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 
ngbe_phy_read_reg_internal(struct mii_bus * bus,int phy_addr,int regnum)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 
ngbe_phy_write_reg_internal(struct mii_bus * bus,int phy_addr,int regnum,u16 value)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 
ngbe_phy_read_reg_mdi_c22(struct mii_bus * bus,int phy_addr,int regnum)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 
ngbe_phy_write_reg_mdi_c22(struct mii_bus * bus,int phy_addr,int regnum,u16 value)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 
ngbe_phy_read_reg_mdi_c45(struct mii_bus * bus,int phy_addr,int devnum,int regnum)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 
ngbe_phy_write_reg_mdi_c45(struct mii_bus * bus,int phy_addr,int devnum,int regnum,u16 value)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 
ngbe_phy_read_reg_c22(struct mii_bus * bus,int phy_addr,int regnum)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 
ngbe_phy_write_reg_c22(struct mii_bus * bus,int phy_addr,int regnum,u16 value)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 
ngbe_handle_link_change(struct net_device * dev)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 
ngbe_phy_connect(struct wx * wx)214 int ngbe_phy_connect(struct wx *wx)
215 {
216 	int ret;
217 
218 	ret = phy_connect_direct(wx->netdev,
219 				 wx->phydev,
220 				 ngbe_handle_link_change,
221 				 PHY_INTERFACE_MODE_RGMII_ID);
222 	if (ret) {
223 		wx_err(wx, "PHY connect failed.\n");
224 		return ret;
225 	}
226 
227 	return 0;
228 }
229 
ngbe_phy_fixup(struct wx * wx)230 static void ngbe_phy_fixup(struct wx *wx)
231 {
232 	struct phy_device *phydev = wx->phydev;
233 	struct ethtool_eee eee;
234 
235 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
236 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
237 	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
238 
239 	phydev->mac_managed_pm = true;
240 	if (wx->mac_type != em_mac_type_mdi)
241 		return;
242 	/* disable EEE, internal phy does not support eee */
243 	memset(&eee, 0, sizeof(eee));
244 	phy_ethtool_set_eee(phydev, &eee);
245 }
246 
ngbe_mdio_init(struct wx * wx)247 int ngbe_mdio_init(struct wx *wx)
248 {
249 	struct pci_dev *pdev = wx->pdev;
250 	struct mii_bus *mii_bus;
251 	int ret;
252 
253 	mii_bus = devm_mdiobus_alloc(&pdev->dev);
254 	if (!mii_bus)
255 		return -ENOMEM;
256 
257 	mii_bus->name = "ngbe_mii_bus";
258 	mii_bus->read = ngbe_phy_read_reg_c22;
259 	mii_bus->write = ngbe_phy_write_reg_c22;
260 	mii_bus->phy_mask = GENMASK(31, 4);
261 	mii_bus->parent = &pdev->dev;
262 	mii_bus->priv = wx;
263 
264 	if (wx->mac_type == em_mac_type_rgmii) {
265 		mii_bus->read_c45 = ngbe_phy_read_reg_mdi_c45;
266 		mii_bus->write_c45 = ngbe_phy_write_reg_mdi_c45;
267 	}
268 
269 	snprintf(mii_bus->id, MII_BUS_ID_SIZE, "ngbe-%x", pci_dev_id(pdev));
270 	ret = devm_mdiobus_register(&pdev->dev, mii_bus);
271 	if (ret)
272 		return ret;
273 
274 	wx->phydev = phy_find_first(mii_bus);
275 	if (!wx->phydev)
276 		return -ENODEV;
277 
278 	phy_attached_info(wx->phydev);
279 	ngbe_phy_fixup(wx);
280 
281 	wx->link = 0;
282 	wx->speed = 0;
283 	wx->duplex = 0;
284 
285 	return 0;
286 }
287