1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
3 
4 #include <linux/ethtool.h>
5 #include <linux/iopoll.h>
6 #include <linux/pci.h>
7 #include <linux/phy.h>
8 
9 #include "../libwx/wx_type.h"
10 #include "../libwx/wx_hw.h"
11 #include "ngbe_type.h"
12 #include "ngbe_mdio.h"
13 
14 static int ngbe_phy_read_reg_internal(struct mii_bus *bus, int phy_addr, int regnum)
15 {
16 	struct wx *wx = bus->priv;
17 
18 	if (phy_addr != 0)
19 		return 0xffff;
20 	return (u16)rd32(wx, NGBE_PHY_CONFIG(regnum));
21 }
22 
23 static int ngbe_phy_write_reg_internal(struct mii_bus *bus, int phy_addr, int regnum, u16 value)
24 {
25 	struct wx *wx = bus->priv;
26 
27 	if (phy_addr == 0)
28 		wr32(wx, NGBE_PHY_CONFIG(regnum), value);
29 	return 0;
30 }
31 
32 static int ngbe_phy_read_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regnum)
33 {
34 	u32 command, val, device_type = 0;
35 	struct wx *wx = bus->priv;
36 	int ret;
37 
38 	wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF);
39 	/* setup and write the address cycle command */
40 	command = WX_MSCA_RA(regnum) |
41 		  WX_MSCA_PA(phy_addr) |
42 		  WX_MSCA_DA(device_type);
43 	wr32(wx, WX_MSCA, command);
44 	command = WX_MSCC_CMD(WX_MSCA_CMD_READ) |
45 		  WX_MSCC_BUSY |
46 		  WX_MDIO_CLK(6);
47 	wr32(wx, WX_MSCC, command);
48 
49 	/* wait to complete */
50 	ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000,
51 				100000, false, wx, WX_MSCC);
52 	if (ret) {
53 		wx_err(wx, "Mdio read c22 command did not complete.\n");
54 		return ret;
55 	}
56 
57 	return (u16)rd32(wx, WX_MSCC);
58 }
59 
60 static int ngbe_phy_write_reg_mdi_c22(struct mii_bus *bus, int phy_addr, int regnum, u16 value)
61 {
62 	u32 command, val, device_type = 0;
63 	struct wx *wx = bus->priv;
64 	int ret;
65 
66 	wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0xF);
67 	/* setup and write the address cycle command */
68 	command = WX_MSCA_RA(regnum) |
69 		  WX_MSCA_PA(phy_addr) |
70 		  WX_MSCA_DA(device_type);
71 	wr32(wx, WX_MSCA, command);
72 	command = value |
73 		  WX_MSCC_CMD(WX_MSCA_CMD_WRITE) |
74 		  WX_MSCC_BUSY |
75 		  WX_MDIO_CLK(6);
76 	wr32(wx, WX_MSCC, command);
77 
78 	/* wait to complete */
79 	ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000,
80 				100000, false, wx, WX_MSCC);
81 	if (ret)
82 		wx_err(wx, "Mdio write c22 command did not complete.\n");
83 
84 	return ret;
85 }
86 
87 static int ngbe_phy_read_reg_mdi_c45(struct mii_bus *bus, int phy_addr, int devnum, int regnum)
88 {
89 	struct wx *wx = bus->priv;
90 	u32 val, command;
91 	int ret;
92 
93 	wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0);
94 	/* setup and write the address cycle command */
95 	command = WX_MSCA_RA(regnum) |
96 		  WX_MSCA_PA(phy_addr) |
97 		  WX_MSCA_DA(devnum);
98 	wr32(wx, WX_MSCA, command);
99 	command = WX_MSCC_CMD(WX_MSCA_CMD_READ) |
100 		  WX_MSCC_BUSY |
101 		  WX_MDIO_CLK(6);
102 	wr32(wx, WX_MSCC, command);
103 
104 	/* wait to complete */
105 	ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000,
106 				100000, false, wx, WX_MSCC);
107 	if (ret) {
108 		wx_err(wx, "Mdio read c45 command did not complete.\n");
109 		return ret;
110 	}
111 
112 	return (u16)rd32(wx, WX_MSCC);
113 }
114 
115 static int ngbe_phy_write_reg_mdi_c45(struct mii_bus *bus, int phy_addr,
116 				      int devnum, int regnum, u16 value)
117 {
118 	struct wx *wx = bus->priv;
119 	int ret, command;
120 	u16 val;
121 
122 	wr32(wx, NGBE_MDIO_CLAUSE_SELECT, 0x0);
123 	/* setup and write the address cycle command */
124 	command = WX_MSCA_RA(regnum) |
125 		  WX_MSCA_PA(phy_addr) |
126 		  WX_MSCA_DA(devnum);
127 	wr32(wx, WX_MSCA, command);
128 	command = value |
129 		  WX_MSCC_CMD(WX_MSCA_CMD_WRITE) |
130 		  WX_MSCC_BUSY |
131 		  WX_MDIO_CLK(6);
132 	wr32(wx, WX_MSCC, command);
133 
134 	/* wait to complete */
135 	ret = read_poll_timeout(rd32, val, !(val & WX_MSCC_BUSY), 1000,
136 				100000, false, wx, WX_MSCC);
137 	if (ret)
138 		wx_err(wx, "Mdio write c45 command did not complete.\n");
139 
140 	return ret;
141 }
142 
143 static int ngbe_phy_read_reg_c22(struct mii_bus *bus, int phy_addr, int regnum)
144 {
145 	struct wx *wx = bus->priv;
146 	u16 phy_data;
147 
148 	if (wx->mac_type == em_mac_type_mdi)
149 		phy_data = ngbe_phy_read_reg_internal(bus, phy_addr, regnum);
150 	else
151 		phy_data = ngbe_phy_read_reg_mdi_c22(bus, phy_addr, regnum);
152 
153 	return phy_data;
154 }
155 
156 static int ngbe_phy_write_reg_c22(struct mii_bus *bus, int phy_addr,
157 				  int regnum, u16 value)
158 {
159 	struct wx *wx = bus->priv;
160 	int ret;
161 
162 	if (wx->mac_type == em_mac_type_mdi)
163 		ret = ngbe_phy_write_reg_internal(bus, phy_addr, regnum, value);
164 	else
165 		ret = ngbe_phy_write_reg_mdi_c22(bus, phy_addr, regnum, value);
166 
167 	return ret;
168 }
169 
170 static void ngbe_handle_link_change(struct net_device *dev)
171 {
172 	struct wx *wx = netdev_priv(dev);
173 	struct phy_device *phydev;
174 	u32 lan_speed, reg;
175 
176 	phydev = wx->phydev;
177 	if (!(wx->link != phydev->link ||
178 	      wx->speed != phydev->speed ||
179 	      wx->duplex != phydev->duplex))
180 		return;
181 
182 	wx->link = phydev->link;
183 	wx->speed = phydev->speed;
184 	wx->duplex = phydev->duplex;
185 	switch (phydev->speed) {
186 	case SPEED_10:
187 		lan_speed = 0;
188 		break;
189 	case SPEED_100:
190 		lan_speed = 1;
191 		break;
192 	case SPEED_1000:
193 	default:
194 		lan_speed = 2;
195 		break;
196 	}
197 	wr32m(wx, NGBE_CFG_LAN_SPEED, 0x3, lan_speed);
198 
199 	if (phydev->link) {
200 		reg = rd32(wx, WX_MAC_TX_CFG);
201 		reg &= ~WX_MAC_TX_CFG_SPEED_MASK;
202 		reg |= WX_MAC_TX_CFG_SPEED_1G | WX_MAC_TX_CFG_TE;
203 		wr32(wx, WX_MAC_TX_CFG, reg);
204 		/* Re configure MAC RX */
205 		reg = rd32(wx, WX_MAC_RX_CFG);
206 		wr32(wx, WX_MAC_RX_CFG, reg);
207 		wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR);
208 		reg = rd32(wx, WX_MAC_WDG_TIMEOUT);
209 		wr32(wx, WX_MAC_WDG_TIMEOUT, reg);
210 	}
211 	phy_print_status(phydev);
212 }
213 
214 int ngbe_phy_connect(struct wx *wx)
215 {
216 	int ret;
217 
218 	/* The MAC only has add the Tx delay and it can not be modified.
219 	 * So just disable TX delay in PHY, and it is does not matter to
220 	 * internal phy.
221 	 */
222 	ret = phy_connect_direct(wx->netdev,
223 				 wx->phydev,
224 				 ngbe_handle_link_change,
225 				 PHY_INTERFACE_MODE_RGMII_RXID);
226 	if (ret) {
227 		wx_err(wx, "PHY connect failed.\n");
228 		return ret;
229 	}
230 
231 	return 0;
232 }
233 
234 static void ngbe_phy_fixup(struct wx *wx)
235 {
236 	struct phy_device *phydev = wx->phydev;
237 	struct ethtool_eee eee;
238 
239 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
240 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
241 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
242 
243 	phydev->mac_managed_pm = true;
244 	if (wx->mac_type != em_mac_type_mdi)
245 		return;
246 	/* disable EEE, internal phy does not support eee */
247 	memset(&eee, 0, sizeof(eee));
248 	phy_ethtool_set_eee(phydev, &eee);
249 }
250 
251 int ngbe_mdio_init(struct wx *wx)
252 {
253 	struct pci_dev *pdev = wx->pdev;
254 	struct mii_bus *mii_bus;
255 	int ret;
256 
257 	mii_bus = devm_mdiobus_alloc(&pdev->dev);
258 	if (!mii_bus)
259 		return -ENOMEM;
260 
261 	mii_bus->name = "ngbe_mii_bus";
262 	mii_bus->read = ngbe_phy_read_reg_c22;
263 	mii_bus->write = ngbe_phy_write_reg_c22;
264 	mii_bus->phy_mask = GENMASK(31, 4);
265 	mii_bus->parent = &pdev->dev;
266 	mii_bus->priv = wx;
267 
268 	if (wx->mac_type == em_mac_type_rgmii) {
269 		mii_bus->read_c45 = ngbe_phy_read_reg_mdi_c45;
270 		mii_bus->write_c45 = ngbe_phy_write_reg_mdi_c45;
271 	}
272 
273 	snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", pci_dev_id(pdev));
274 	ret = devm_mdiobus_register(&pdev->dev, mii_bus);
275 	if (ret)
276 		return ret;
277 
278 	wx->phydev = phy_find_first(mii_bus);
279 	if (!wx->phydev)
280 		return -ENODEV;
281 
282 	phy_attached_info(wx->phydev);
283 	ngbe_phy_fixup(wx);
284 
285 	wx->link = 0;
286 	wx->speed = 0;
287 	wx->duplex = 0;
288 
289 	return 0;
290 }
291