1
2
3
4
5
6
7
8
9
10#include <linux/etherdevice.h>
11#include <linux/kernel.h>
12
13#include "hclge_cmd.h"
14#include "hclge_main.h"
15#include "hclge_mdio.h"
16
17#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \
18 SUPPORTED_TP | \
19 PHY_10BT_FEATURES | \
20 PHY_100BT_FEATURES | \
21 PHY_1000BT_FEATURES)
22
23enum hclge_mdio_c22_op_seq {
24 HCLGE_MDIO_C22_WRITE = 1,
25 HCLGE_MDIO_C22_READ = 2
26};
27
28#define HCLGE_MDIO_CTRL_START_B 0
29#define HCLGE_MDIO_CTRL_ST_S 1
30#define HCLGE_MDIO_CTRL_ST_M (0x3 << HCLGE_MDIO_CTRL_ST_S)
31#define HCLGE_MDIO_CTRL_OP_S 3
32#define HCLGE_MDIO_CTRL_OP_M (0x3 << HCLGE_MDIO_CTRL_OP_S)
33
34#define HCLGE_MDIO_PHYID_S 0
35#define HCLGE_MDIO_PHYID_M (0x1f << HCLGE_MDIO_PHYID_S)
36
37#define HCLGE_MDIO_PHYREG_S 0
38#define HCLGE_MDIO_PHYREG_M (0x1f << HCLGE_MDIO_PHYREG_S)
39
40#define HCLGE_MDIO_STA_B 0
41
42struct hclge_mdio_cfg_cmd {
43 u8 ctrl_bit;
44 u8 phyid;
45 u8 phyad;
46 u8 rsvd;
47 __le16 reserve;
48 __le16 data_wr;
49 __le16 data_rd;
50 __le16 sta;
51};
52
53static int hclge_mdio_write(struct mii_bus *bus, int phyid, int regnum,
54 u16 data)
55{
56 struct hclge_mdio_cfg_cmd *mdio_cmd;
57 struct hclge_dev *hdev = bus->priv;
58 struct hclge_desc desc;
59 int ret;
60
61 if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
62 return 0;
63
64 hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, false);
65
66 mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
67
68 hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
69 HCLGE_MDIO_PHYID_S, phyid);
70 hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
71 HCLGE_MDIO_PHYREG_S, regnum);
72
73 hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
74 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
75 HCLGE_MDIO_CTRL_ST_S, 1);
76 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
77 HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_WRITE);
78
79 mdio_cmd->data_wr = cpu_to_le16(data);
80
81 ret = hclge_cmd_send(&hdev->hw, &desc, 1);
82 if (ret) {
83 dev_err(&hdev->pdev->dev,
84 "mdio write fail when sending cmd, status is %d.\n",
85 ret);
86 return ret;
87 }
88
89 return 0;
90}
91
92static int hclge_mdio_read(struct mii_bus *bus, int phyid, int regnum)
93{
94 struct hclge_mdio_cfg_cmd *mdio_cmd;
95 struct hclge_dev *hdev = bus->priv;
96 struct hclge_desc desc;
97 int ret;
98
99 if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
100 return 0;
101
102 hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MDIO_CONFIG, true);
103
104 mdio_cmd = (struct hclge_mdio_cfg_cmd *)desc.data;
105
106 hnae3_set_field(mdio_cmd->phyid, HCLGE_MDIO_PHYID_M,
107 HCLGE_MDIO_PHYID_S, phyid);
108 hnae3_set_field(mdio_cmd->phyad, HCLGE_MDIO_PHYREG_M,
109 HCLGE_MDIO_PHYREG_S, regnum);
110
111 hnae3_set_bit(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_START_B, 1);
112 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_ST_M,
113 HCLGE_MDIO_CTRL_ST_S, 1);
114 hnae3_set_field(mdio_cmd->ctrl_bit, HCLGE_MDIO_CTRL_OP_M,
115 HCLGE_MDIO_CTRL_OP_S, HCLGE_MDIO_C22_READ);
116
117
118 ret = hclge_cmd_send(&hdev->hw, &desc, 1);
119 if (ret) {
120 dev_err(&hdev->pdev->dev,
121 "mdio read fail when get data, status is %d.\n",
122 ret);
123 return ret;
124 }
125
126 if (hnae3_get_bit(le16_to_cpu(mdio_cmd->sta), HCLGE_MDIO_STA_B)) {
127 dev_err(&hdev->pdev->dev, "mdio read data error\n");
128 return -EIO;
129 }
130
131 return le16_to_cpu(mdio_cmd->data_rd);
132}
133
134int hclge_mac_mdio_config(struct hclge_dev *hdev)
135{
136 struct hclge_mac *mac = &hdev->hw.mac;
137 struct phy_device *phydev;
138 struct mii_bus *mdio_bus;
139 int ret;
140
141 if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR) {
142 dev_err(&hdev->pdev->dev, "phy_addr(%d) is too large.\n",
143 hdev->hw.mac.phy_addr);
144 return -EINVAL;
145 }
146
147 mdio_bus = devm_mdiobus_alloc(&hdev->pdev->dev);
148 if (!mdio_bus)
149 return -ENOMEM;
150
151 mdio_bus->name = "hisilicon MII bus";
152 mdio_bus->read = hclge_mdio_read;
153 mdio_bus->write = hclge_mdio_write;
154 snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "mii",
155 dev_name(&hdev->pdev->dev));
156
157 mdio_bus->parent = &hdev->pdev->dev;
158 mdio_bus->priv = hdev;
159 mdio_bus->phy_mask = ~(1 << mac->phy_addr);
160 ret = mdiobus_register(mdio_bus);
161 if (ret) {
162 dev_err(mdio_bus->parent,
163 "Failed to register MDIO bus ret = %#x\n", ret);
164 return ret;
165 }
166
167 phydev = mdiobus_get_phy(mdio_bus, mac->phy_addr);
168 if (!phydev) {
169 dev_err(mdio_bus->parent, "Failed to get phy device\n");
170 mdiobus_unregister(mdio_bus);
171 return -EIO;
172 }
173
174 mac->phydev = phydev;
175 mac->mdio_bus = mdio_bus;
176
177 return 0;
178}
179
180static void hclge_mac_adjust_link(struct net_device *netdev)
181{
182 struct hnae3_handle *h = *((void **)netdev_priv(netdev));
183 struct hclge_vport *vport = hclge_get_vport(h);
184 struct hclge_dev *hdev = vport->back;
185 int duplex, speed;
186 int ret;
187
188 speed = netdev->phydev->speed;
189 duplex = netdev->phydev->duplex;
190
191 ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
192 if (ret)
193 netdev_err(netdev, "failed to adjust link.\n");
194
195 ret = hclge_cfg_flowctrl(hdev);
196 if (ret)
197 netdev_err(netdev, "failed to configure flow control.\n");
198}
199
200int hclge_mac_connect_phy(struct hnae3_handle *handle)
201{
202 struct hclge_vport *vport = hclge_get_vport(handle);
203 struct hclge_dev *hdev = vport->back;
204 struct net_device *netdev = hdev->vport[0].nic.netdev;
205 struct phy_device *phydev = hdev->hw.mac.phydev;
206 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
207 int ret;
208
209 if (!phydev)
210 return 0;
211
212 linkmode_clear_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
213
214 ret = phy_connect_direct(netdev, phydev,
215 hclge_mac_adjust_link,
216 PHY_INTERFACE_MODE_SGMII);
217 if (ret) {
218 netdev_err(netdev, "phy_connect_direct err.\n");
219 return ret;
220 }
221
222 linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask);
223 linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask);
224 linkmode_set_bit_array(phy_10_100_features_array,
225 ARRAY_SIZE(phy_10_100_features_array),
226 mask);
227 linkmode_set_bit_array(phy_gbit_features_array,
228 ARRAY_SIZE(phy_gbit_features_array),
229 mask);
230 linkmode_and(phydev->supported, phydev->supported, mask);
231 phy_support_asym_pause(phydev);
232
233 return 0;
234}
235
236void hclge_mac_disconnect_phy(struct hnae3_handle *handle)
237{
238 struct hclge_vport *vport = hclge_get_vport(handle);
239 struct hclge_dev *hdev = vport->back;
240 struct phy_device *phydev = hdev->hw.mac.phydev;
241
242 if (!phydev)
243 return;
244
245 phy_disconnect(phydev);
246}
247
248void hclge_mac_start_phy(struct hclge_dev *hdev)
249{
250 struct phy_device *phydev = hdev->hw.mac.phydev;
251
252 if (!phydev)
253 return;
254
255 phy_start(phydev);
256}
257
258void hclge_mac_stop_phy(struct hclge_dev *hdev)
259{
260 struct net_device *netdev = hdev->vport[0].nic.netdev;
261 struct phy_device *phydev = netdev->phydev;
262
263 if (!phydev)
264 return;
265
266 phy_stop(phydev);
267}
268