2 * Copyright (c) 2016~2017 Hisilicon Limited.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
10 #include <linux/etherdevice.h>
11 #include <linux/kernel.h>
13 #include "hclge_cmd.h"
14 #include "hclge_main.h"
15 #include "hclge_mdio.h"
17 #define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
20 SUPPORTED_Asym_Pause | \
22 PHY_100BT_FEATURES | \
25 enum hclge_mdio_c22_op_seq
{
26 HCLGE_MDIO_C22_WRITE
= 1,
27 HCLGE_MDIO_C22_READ
= 2
30 #define HCLGE_MDIO_CTRL_START_B 0
31 #define HCLGE_MDIO_CTRL_ST_S 1
32 #define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S)
33 #define HCLGE_MDIO_CTRL_OP_S 3
34 #define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S)
36 #define HCLGE_MDIO_PHYID_S 0
37 #define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S)
39 #define HCLGE_MDIO_PHYREG_S 0
40 #define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S)
42 #define HCLGE_MDIO_STA_B 0
44 struct hclge_mdio_cfg_cmd
{
55 static int hclge_mdio_write(struct mii_bus
*bus
, int phyid
, int regnum
,
58 struct hclge_mdio_cfg_cmd
*mdio_cmd
;
59 struct hclge_dev
*hdev
= bus
->priv
;
60 struct hclge_desc desc
;
63 hclge_cmd_setup_basic_desc(&desc
, HCLGE_OPC_MDIO_CONFIG
, false);
65 mdio_cmd
= (struct hclge_mdio_cfg_cmd
*)desc
.data
;
67 hnae_set_field(mdio_cmd
->phyid
, HCLGE_MDIO_PHYID_M
,
68 HCLGE_MDIO_PHYID_S
, phyid
);
69 hnae_set_field(mdio_cmd
->phyad
, HCLGE_MDIO_PHYREG_M
,
70 HCLGE_MDIO_PHYREG_S
, regnum
);
72 hnae_set_bit(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_START_B
, 1);
73 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_ST_M
,
74 HCLGE_MDIO_CTRL_ST_S
, 1);
75 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_OP_M
,
76 HCLGE_MDIO_CTRL_OP_S
, HCLGE_MDIO_C22_WRITE
);
78 mdio_cmd
->data_wr
= cpu_to_le16(data
);
80 ret
= hclge_cmd_send(&hdev
->hw
, &desc
, 1);
82 dev_err(&hdev
->pdev
->dev
,
83 "mdio write fail when sending cmd, status is %d.\n",
91 static int hclge_mdio_read(struct mii_bus
*bus
, int phyid
, int regnum
)
93 struct hclge_mdio_cfg_cmd
*mdio_cmd
;
94 struct hclge_dev
*hdev
= bus
->priv
;
95 struct hclge_desc desc
;
98 hclge_cmd_setup_basic_desc(&desc
, HCLGE_OPC_MDIO_CONFIG
, true);
100 mdio_cmd
= (struct hclge_mdio_cfg_cmd
*)desc
.data
;
102 hnae_set_field(mdio_cmd
->phyid
, HCLGE_MDIO_PHYID_M
,
103 HCLGE_MDIO_PHYID_S
, phyid
);
104 hnae_set_field(mdio_cmd
->phyad
, HCLGE_MDIO_PHYREG_M
,
105 HCLGE_MDIO_PHYREG_S
, regnum
);
107 hnae_set_bit(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_START_B
, 1);
108 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_ST_M
,
109 HCLGE_MDIO_CTRL_ST_S
, 1);
110 hnae_set_field(mdio_cmd
->ctrl_bit
, HCLGE_MDIO_CTRL_OP_M
,
111 HCLGE_MDIO_CTRL_OP_S
, HCLGE_MDIO_C22_READ
);
113 /* Read out phy data */
114 ret
= hclge_cmd_send(&hdev
->hw
, &desc
, 1);
116 dev_err(&hdev
->pdev
->dev
,
117 "mdio read fail when get data, status is %d.\n",
122 if (hnae_get_bit(le16_to_cpu(mdio_cmd
->sta
), HCLGE_MDIO_STA_B
)) {
123 dev_err(&hdev
->pdev
->dev
, "mdio read data error\n");
127 return le16_to_cpu(mdio_cmd
->data_rd
);
130 int hclge_mac_mdio_config(struct hclge_dev
*hdev
)
132 struct hclge_mac
*mac
= &hdev
->hw
.mac
;
133 struct phy_device
*phydev
;
134 struct mii_bus
*mdio_bus
;
137 if (hdev
->hw
.mac
.phy_addr
>= PHY_MAX_ADDR
)
140 mdio_bus
= devm_mdiobus_alloc(&hdev
->pdev
->dev
);
144 mdio_bus
->name
= "hisilicon MII bus";
145 mdio_bus
->read
= hclge_mdio_read
;
146 mdio_bus
->write
= hclge_mdio_write
;
147 snprintf(mdio_bus
->id
, MII_BUS_ID_SIZE
, "%s-%s", "mii",
148 dev_name(&hdev
->pdev
->dev
));
150 mdio_bus
->parent
= &hdev
->pdev
->dev
;
151 mdio_bus
->priv
= hdev
;
152 mdio_bus
->phy_mask
= ~(1 << mac
->phy_addr
);
153 ret
= mdiobus_register(mdio_bus
);
155 dev_err(mdio_bus
->parent
,
156 "Failed to register MDIO bus ret = %#x\n", ret
);
160 phydev
= mdiobus_get_phy(mdio_bus
, mac
->phy_addr
);
162 dev_err(mdio_bus
->parent
, "Failed to get phy device\n");
163 mdiobus_unregister(mdio_bus
);
167 mac
->phydev
= phydev
;
168 mac
->mdio_bus
= mdio_bus
;
173 static void hclge_mac_adjust_link(struct net_device
*netdev
)
175 struct hnae3_handle
*h
= *((void **)netdev_priv(netdev
));
176 struct hclge_vport
*vport
= hclge_get_vport(h
);
177 struct hclge_dev
*hdev
= vport
->back
;
181 speed
= netdev
->phydev
->speed
;
182 duplex
= netdev
->phydev
->duplex
;
184 ret
= hclge_cfg_mac_speed_dup(hdev
, speed
, duplex
);
186 netdev_err(netdev
, "failed to adjust link.\n");
188 ret
= hclge_cfg_flowctrl(hdev
);
190 netdev_err(netdev
, "failed to configure flow control.\n");
193 int hclge_mac_start_phy(struct hclge_dev
*hdev
)
195 struct net_device
*netdev
= hdev
->vport
[0].nic
.netdev
;
196 struct phy_device
*phydev
= hdev
->hw
.mac
.phydev
;
202 ret
= phy_connect_direct(netdev
, phydev
,
203 hclge_mac_adjust_link
,
204 PHY_INTERFACE_MODE_SGMII
);
206 netdev_err(netdev
, "phy_connect_direct err.\n");
210 phydev
->supported
&= HCLGE_PHY_SUPPORTED_FEATURES
;
211 phydev
->advertising
= phydev
->supported
;
218 void hclge_mac_stop_phy(struct hclge_dev
*hdev
)
220 struct net_device
*netdev
= hdev
->vport
[0].nic
.netdev
;
221 struct phy_device
*phydev
= netdev
->phydev
;
227 phy_disconnect(phydev
);