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