1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /******************************************************************************* |
3 | STMMAC Ethernet Driver -- MDIO bus implementation |
4 | Provides Bus interface for MII registers |
5 | |
6 | Copyright (C) 2007-2009 STMicroelectronics Ltd |
7 | |
8 | |
9 | Author: Carl Shaw <carl.shaw@st.com> |
10 | Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com> |
11 | *******************************************************************************/ |
12 | |
13 | #include <linux/gpio/consumer.h> |
14 | #include <linux/io.h> |
15 | #include <linux/iopoll.h> |
16 | #include <linux/mii.h> |
17 | #include <linux/of_mdio.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/phy.h> |
20 | #include <linux/property.h> |
21 | #include <linux/slab.h> |
22 | |
23 | #include "dwxgmac2.h" |
24 | #include "stmmac.h" |
25 | |
26 | #define MII_BUSY 0x00000001 |
27 | #define MII_WRITE 0x00000002 |
28 | #define MII_DATA_MASK GENMASK(15, 0) |
29 | |
30 | /* GMAC4 defines */ |
31 | #define MII_GMAC4_GOC_SHIFT 2 |
32 | #define MII_GMAC4_REG_ADDR_SHIFT 16 |
33 | #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) |
34 | #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) |
35 | #define MII_GMAC4_C45E BIT(1) |
36 | |
37 | /* XGMAC defines */ |
38 | #define MII_XGMAC_SADDR BIT(18) |
39 | #define MII_XGMAC_CMD_SHIFT 16 |
40 | #define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT) |
41 | #define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT) |
42 | #define MII_XGMAC_BUSY BIT(22) |
43 | #define MII_XGMAC_MAX_C22ADDR 3 |
44 | #define MII_XGMAC_C22P_MASK GENMASK(MII_XGMAC_MAX_C22ADDR, 0) |
45 | #define MII_XGMAC_PA_SHIFT 16 |
46 | #define MII_XGMAC_DA_SHIFT 21 |
47 | |
48 | static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr, |
49 | int devad, int phyreg, u32 *hw_addr) |
50 | { |
51 | u32 tmp; |
52 | |
53 | /* Set port as Clause 45 */ |
54 | tmp = readl(addr: priv->ioaddr + XGMAC_MDIO_C22P); |
55 | tmp &= ~BIT(phyaddr); |
56 | writel(val: tmp, addr: priv->ioaddr + XGMAC_MDIO_C22P); |
57 | |
58 | *hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0xffff); |
59 | *hw_addr |= devad << MII_XGMAC_DA_SHIFT; |
60 | } |
61 | |
62 | static void stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr, |
63 | int phyreg, u32 *hw_addr) |
64 | { |
65 | u32 tmp = 0; |
66 | |
67 | if (priv->synopsys_id < DWXGMAC_CORE_2_20) { |
68 | /* Until ver 2.20 XGMAC does not support C22 addr >= 4. Those |
69 | * bits above bit 3 of XGMAC_MDIO_C22P register are reserved. |
70 | */ |
71 | tmp = readl(addr: priv->ioaddr + XGMAC_MDIO_C22P); |
72 | tmp &= ~MII_XGMAC_C22P_MASK; |
73 | } |
74 | /* Set port as Clause 22 */ |
75 | tmp |= BIT(phyaddr); |
76 | writel(val: tmp, addr: priv->ioaddr + XGMAC_MDIO_C22P); |
77 | |
78 | *hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0x1f); |
79 | } |
80 | |
81 | static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, |
82 | u32 value) |
83 | { |
84 | unsigned int mii_address = priv->hw->mii.addr; |
85 | unsigned int mii_data = priv->hw->mii.data; |
86 | u32 tmp; |
87 | int ret; |
88 | |
89 | ret = pm_runtime_resume_and_get(dev: priv->device); |
90 | if (ret < 0) |
91 | return ret; |
92 | |
93 | /* Wait until any existing MII operation is complete */ |
94 | if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
95 | !(tmp & MII_XGMAC_BUSY), 100, 10000)) { |
96 | ret = -EBUSY; |
97 | goto err_disable_clks; |
98 | } |
99 | |
100 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
101 | & priv->hw->mii.clk_csr_mask; |
102 | value |= MII_XGMAC_READ; |
103 | |
104 | /* Wait until any existing MII operation is complete */ |
105 | if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
106 | !(tmp & MII_XGMAC_BUSY), 100, 10000)) { |
107 | ret = -EBUSY; |
108 | goto err_disable_clks; |
109 | } |
110 | |
111 | /* Set the MII address register to read */ |
112 | writel(val: addr, addr: priv->ioaddr + mii_address); |
113 | writel(val: value, addr: priv->ioaddr + mii_data); |
114 | |
115 | /* Wait until any existing MII operation is complete */ |
116 | if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
117 | !(tmp & MII_XGMAC_BUSY), 100, 10000)) { |
118 | ret = -EBUSY; |
119 | goto err_disable_clks; |
120 | } |
121 | |
122 | /* Read the data from the MII data register */ |
123 | ret = (int)readl(addr: priv->ioaddr + mii_data) & GENMASK(15, 0); |
124 | |
125 | err_disable_clks: |
126 | pm_runtime_put(dev: priv->device); |
127 | |
128 | return ret; |
129 | } |
130 | |
131 | static int stmmac_xgmac2_mdio_read_c22(struct mii_bus *bus, int phyaddr, |
132 | int phyreg) |
133 | { |
134 | struct net_device *ndev = bus->priv; |
135 | struct stmmac_priv *priv; |
136 | u32 addr; |
137 | |
138 | priv = netdev_priv(dev: ndev); |
139 | |
140 | /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */ |
141 | if (priv->synopsys_id < DWXGMAC_CORE_2_20 && |
142 | phyaddr > MII_XGMAC_MAX_C22ADDR) |
143 | return -ENODEV; |
144 | |
145 | stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, hw_addr: &addr); |
146 | |
147 | return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY); |
148 | } |
149 | |
150 | static int stmmac_xgmac2_mdio_read_c45(struct mii_bus *bus, int phyaddr, |
151 | int devad, int phyreg) |
152 | { |
153 | struct net_device *ndev = bus->priv; |
154 | struct stmmac_priv *priv; |
155 | u32 addr; |
156 | |
157 | priv = netdev_priv(dev: ndev); |
158 | |
159 | stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, hw_addr: &addr); |
160 | |
161 | return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY); |
162 | } |
163 | |
164 | static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, |
165 | u32 value, u16 phydata) |
166 | { |
167 | unsigned int mii_address = priv->hw->mii.addr; |
168 | unsigned int mii_data = priv->hw->mii.data; |
169 | u32 tmp; |
170 | int ret; |
171 | |
172 | ret = pm_runtime_resume_and_get(dev: priv->device); |
173 | if (ret < 0) |
174 | return ret; |
175 | |
176 | /* Wait until any existing MII operation is complete */ |
177 | if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
178 | !(tmp & MII_XGMAC_BUSY), 100, 10000)) { |
179 | ret = -EBUSY; |
180 | goto err_disable_clks; |
181 | } |
182 | |
183 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
184 | & priv->hw->mii.clk_csr_mask; |
185 | value |= phydata; |
186 | value |= MII_XGMAC_WRITE; |
187 | |
188 | /* Wait until any existing MII operation is complete */ |
189 | if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
190 | !(tmp & MII_XGMAC_BUSY), 100, 10000)) { |
191 | ret = -EBUSY; |
192 | goto err_disable_clks; |
193 | } |
194 | |
195 | /* Set the MII address register to write */ |
196 | writel(val: addr, addr: priv->ioaddr + mii_address); |
197 | writel(val: value, addr: priv->ioaddr + mii_data); |
198 | |
199 | /* Wait until any existing MII operation is complete */ |
200 | ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp, |
201 | !(tmp & MII_XGMAC_BUSY), 100, 10000); |
202 | |
203 | err_disable_clks: |
204 | pm_runtime_put(dev: priv->device); |
205 | |
206 | return ret; |
207 | } |
208 | |
209 | static int stmmac_xgmac2_mdio_write_c22(struct mii_bus *bus, int phyaddr, |
210 | int phyreg, u16 phydata) |
211 | { |
212 | struct net_device *ndev = bus->priv; |
213 | struct stmmac_priv *priv; |
214 | u32 addr; |
215 | |
216 | priv = netdev_priv(dev: ndev); |
217 | |
218 | /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */ |
219 | if (priv->synopsys_id < DWXGMAC_CORE_2_20 && |
220 | phyaddr > MII_XGMAC_MAX_C22ADDR) |
221 | return -ENODEV; |
222 | |
223 | stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, hw_addr: &addr); |
224 | |
225 | return stmmac_xgmac2_mdio_write(priv, addr, |
226 | MII_XGMAC_BUSY | MII_XGMAC_SADDR, phydata); |
227 | } |
228 | |
229 | static int stmmac_xgmac2_mdio_write_c45(struct mii_bus *bus, int phyaddr, |
230 | int devad, int phyreg, u16 phydata) |
231 | { |
232 | struct net_device *ndev = bus->priv; |
233 | struct stmmac_priv *priv; |
234 | u32 addr; |
235 | |
236 | priv = netdev_priv(dev: ndev); |
237 | |
238 | stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, hw_addr: &addr); |
239 | |
240 | return stmmac_xgmac2_mdio_write(priv, addr, MII_XGMAC_BUSY, |
241 | phydata); |
242 | } |
243 | |
244 | static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) |
245 | { |
246 | unsigned int mii_address = priv->hw->mii.addr; |
247 | unsigned int mii_data = priv->hw->mii.data; |
248 | u32 v; |
249 | |
250 | if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), |
251 | 100, 10000)) |
252 | return -EBUSY; |
253 | |
254 | writel(val: data, addr: priv->ioaddr + mii_data); |
255 | writel(val: value, addr: priv->ioaddr + mii_address); |
256 | |
257 | if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), |
258 | 100, 10000)) |
259 | return -EBUSY; |
260 | |
261 | /* Read the data from the MII data register */ |
262 | return readl(addr: priv->ioaddr + mii_data) & MII_DATA_MASK; |
263 | } |
264 | |
265 | /** |
266 | * stmmac_mdio_read_c22 |
267 | * @bus: points to the mii_bus structure |
268 | * @phyaddr: MII addr |
269 | * @phyreg: MII reg |
270 | * Description: it reads data from the MII register from within the phy device. |
271 | * For the 7111 GMAC, we must set the bit 0 in the MII address register while |
272 | * accessing the PHY registers. |
273 | * Fortunately, it seems this has no drawback for the 7109 MAC. |
274 | */ |
275 | static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) |
276 | { |
277 | struct net_device *ndev = bus->priv; |
278 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
279 | u32 value = MII_BUSY; |
280 | int data = 0; |
281 | |
282 | data = pm_runtime_resume_and_get(dev: priv->device); |
283 | if (data < 0) |
284 | return data; |
285 | |
286 | value |= (phyaddr << priv->hw->mii.addr_shift) |
287 | & priv->hw->mii.addr_mask; |
288 | value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
289 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
290 | & priv->hw->mii.clk_csr_mask; |
291 | if (priv->plat->has_gmac4) |
292 | value |= MII_GMAC4_READ; |
293 | |
294 | data = stmmac_mdio_read(priv, data, value); |
295 | |
296 | pm_runtime_put(dev: priv->device); |
297 | |
298 | return data; |
299 | } |
300 | |
301 | /** |
302 | * stmmac_mdio_read_c45 |
303 | * @bus: points to the mii_bus structure |
304 | * @phyaddr: MII addr |
305 | * @devad: device address to read |
306 | * @phyreg: MII reg |
307 | * Description: it reads data from the MII register from within the phy device. |
308 | * For the 7111 GMAC, we must set the bit 0 in the MII address register while |
309 | * accessing the PHY registers. |
310 | * Fortunately, it seems this has no drawback for the 7109 MAC. |
311 | */ |
312 | static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, |
313 | int phyreg) |
314 | { |
315 | struct net_device *ndev = bus->priv; |
316 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
317 | u32 value = MII_BUSY; |
318 | int data = 0; |
319 | |
320 | data = pm_runtime_get_sync(dev: priv->device); |
321 | if (data < 0) { |
322 | pm_runtime_put_noidle(dev: priv->device); |
323 | return data; |
324 | } |
325 | |
326 | value |= (phyaddr << priv->hw->mii.addr_shift) |
327 | & priv->hw->mii.addr_mask; |
328 | value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
329 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
330 | & priv->hw->mii.clk_csr_mask; |
331 | value |= MII_GMAC4_READ; |
332 | value |= MII_GMAC4_C45E; |
333 | value &= ~priv->hw->mii.reg_mask; |
334 | value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
335 | |
336 | data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; |
337 | |
338 | data = stmmac_mdio_read(priv, data, value); |
339 | |
340 | pm_runtime_put(dev: priv->device); |
341 | |
342 | return data; |
343 | } |
344 | |
345 | static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value) |
346 | { |
347 | unsigned int mii_address = priv->hw->mii.addr; |
348 | unsigned int mii_data = priv->hw->mii.data; |
349 | u32 v; |
350 | |
351 | /* Wait until any existing MII operation is complete */ |
352 | if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), |
353 | 100, 10000)) |
354 | return -EBUSY; |
355 | |
356 | /* Set the MII address register to write */ |
357 | writel(val: data, addr: priv->ioaddr + mii_data); |
358 | writel(val: value, addr: priv->ioaddr + mii_address); |
359 | |
360 | /* Wait until any existing MII operation is complete */ |
361 | return readl_poll_timeout(priv->ioaddr + mii_address, v, |
362 | !(v & MII_BUSY), 100, 10000); |
363 | } |
364 | |
365 | /** |
366 | * stmmac_mdio_write_c22 |
367 | * @bus: points to the mii_bus structure |
368 | * @phyaddr: MII addr |
369 | * @phyreg: MII reg |
370 | * @phydata: phy data |
371 | * Description: it writes the data into the MII register from within the device. |
372 | */ |
373 | static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, |
374 | u16 phydata) |
375 | { |
376 | struct net_device *ndev = bus->priv; |
377 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
378 | int ret, data = phydata; |
379 | u32 value = MII_BUSY; |
380 | |
381 | ret = pm_runtime_resume_and_get(dev: priv->device); |
382 | if (ret < 0) |
383 | return ret; |
384 | |
385 | value |= (phyaddr << priv->hw->mii.addr_shift) |
386 | & priv->hw->mii.addr_mask; |
387 | value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
388 | |
389 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
390 | & priv->hw->mii.clk_csr_mask; |
391 | if (priv->plat->has_gmac4) |
392 | value |= MII_GMAC4_WRITE; |
393 | else |
394 | value |= MII_WRITE; |
395 | |
396 | ret = stmmac_mdio_write(priv, data, value); |
397 | |
398 | pm_runtime_put(dev: priv->device); |
399 | |
400 | return ret; |
401 | } |
402 | |
403 | /** |
404 | * stmmac_mdio_write_c45 |
405 | * @bus: points to the mii_bus structure |
406 | * @phyaddr: MII addr |
407 | * @phyreg: MII reg |
408 | * @devad: device address to read |
409 | * @phydata: phy data |
410 | * Description: it writes the data into the MII register from within the device. |
411 | */ |
412 | static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr, |
413 | int devad, int phyreg, u16 phydata) |
414 | { |
415 | struct net_device *ndev = bus->priv; |
416 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
417 | int ret, data = phydata; |
418 | u32 value = MII_BUSY; |
419 | |
420 | ret = pm_runtime_get_sync(dev: priv->device); |
421 | if (ret < 0) { |
422 | pm_runtime_put_noidle(dev: priv->device); |
423 | return ret; |
424 | } |
425 | |
426 | value |= (phyaddr << priv->hw->mii.addr_shift) |
427 | & priv->hw->mii.addr_mask; |
428 | value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
429 | |
430 | value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) |
431 | & priv->hw->mii.clk_csr_mask; |
432 | |
433 | value |= MII_GMAC4_WRITE; |
434 | value |= MII_GMAC4_C45E; |
435 | value &= ~priv->hw->mii.reg_mask; |
436 | value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; |
437 | |
438 | data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; |
439 | |
440 | ret = stmmac_mdio_write(priv, data, value); |
441 | |
442 | pm_runtime_put(dev: priv->device); |
443 | |
444 | return ret; |
445 | } |
446 | |
447 | /** |
448 | * stmmac_mdio_reset |
449 | * @bus: points to the mii_bus structure |
450 | * Description: reset the MII bus |
451 | */ |
452 | int stmmac_mdio_reset(struct mii_bus *bus) |
453 | { |
454 | #if IS_ENABLED(CONFIG_STMMAC_PLATFORM) |
455 | struct net_device *ndev = bus->priv; |
456 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
457 | unsigned int mii_address = priv->hw->mii.addr; |
458 | |
459 | #ifdef CONFIG_OF |
460 | if (priv->device->of_node) { |
461 | struct gpio_desc *reset_gpio; |
462 | u32 delays[3] = { 0, 0, 0 }; |
463 | |
464 | reset_gpio = devm_gpiod_get_optional(dev: priv->device, |
465 | con_id: "snps,reset" , |
466 | flags: GPIOD_OUT_LOW); |
467 | if (IS_ERR(ptr: reset_gpio)) |
468 | return PTR_ERR(ptr: reset_gpio); |
469 | |
470 | device_property_read_u32_array(dev: priv->device, |
471 | propname: "snps,reset-delays-us" , |
472 | val: delays, ARRAY_SIZE(delays)); |
473 | |
474 | if (delays[0]) |
475 | msleep(DIV_ROUND_UP(delays[0], 1000)); |
476 | |
477 | gpiod_set_value_cansleep(desc: reset_gpio, value: 1); |
478 | if (delays[1]) |
479 | msleep(DIV_ROUND_UP(delays[1], 1000)); |
480 | |
481 | gpiod_set_value_cansleep(desc: reset_gpio, value: 0); |
482 | if (delays[2]) |
483 | msleep(DIV_ROUND_UP(delays[2], 1000)); |
484 | } |
485 | #endif |
486 | |
487 | /* This is a workaround for problems with the STE101P PHY. |
488 | * It doesn't complete its reset until at least one clock cycle |
489 | * on MDC, so perform a dummy mdio read. To be updated for GMAC4 |
490 | * if needed. |
491 | */ |
492 | if (!priv->plat->has_gmac4) |
493 | writel(val: 0, addr: priv->ioaddr + mii_address); |
494 | #endif |
495 | return 0; |
496 | } |
497 | |
498 | int stmmac_xpcs_setup(struct mii_bus *bus) |
499 | { |
500 | struct net_device *ndev = bus->priv; |
501 | struct stmmac_priv *priv; |
502 | struct dw_xpcs *xpcs; |
503 | int mode, addr; |
504 | |
505 | priv = netdev_priv(dev: ndev); |
506 | mode = priv->plat->phy_interface; |
507 | |
508 | /* Try to probe the XPCS by scanning all addresses. */ |
509 | for (addr = 0; addr < PHY_MAX_ADDR; addr++) { |
510 | xpcs = xpcs_create_mdiodev(bus, addr, interface: mode); |
511 | if (IS_ERR(ptr: xpcs)) |
512 | continue; |
513 | |
514 | priv->hw->xpcs = xpcs; |
515 | break; |
516 | } |
517 | |
518 | if (!priv->hw->xpcs) { |
519 | dev_warn(priv->device, "No xPCS found\n" ); |
520 | return -ENODEV; |
521 | } |
522 | |
523 | return 0; |
524 | } |
525 | |
526 | /** |
527 | * stmmac_mdio_register |
528 | * @ndev: net device structure |
529 | * Description: it registers the MII bus |
530 | */ |
531 | int stmmac_mdio_register(struct net_device *ndev) |
532 | { |
533 | int err = 0; |
534 | struct mii_bus *new_bus; |
535 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
536 | struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; |
537 | struct device_node *mdio_node = priv->plat->mdio_node; |
538 | struct device *dev = ndev->dev.parent; |
539 | struct fwnode_handle *fixed_node; |
540 | struct fwnode_handle *fwnode; |
541 | int addr, found, max_addr; |
542 | |
543 | if (!mdio_bus_data) |
544 | return 0; |
545 | |
546 | new_bus = mdiobus_alloc(); |
547 | if (!new_bus) |
548 | return -ENOMEM; |
549 | |
550 | if (mdio_bus_data->irqs) |
551 | memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq)); |
552 | |
553 | new_bus->name = "stmmac" ; |
554 | |
555 | if (priv->plat->has_xgmac) { |
556 | new_bus->read = &stmmac_xgmac2_mdio_read_c22; |
557 | new_bus->write = &stmmac_xgmac2_mdio_write_c22; |
558 | new_bus->read_c45 = &stmmac_xgmac2_mdio_read_c45; |
559 | new_bus->write_c45 = &stmmac_xgmac2_mdio_write_c45; |
560 | |
561 | if (priv->synopsys_id < DWXGMAC_CORE_2_20) { |
562 | /* Right now only C22 phys are supported */ |
563 | max_addr = MII_XGMAC_MAX_C22ADDR + 1; |
564 | |
565 | /* Check if DT specified an unsupported phy addr */ |
566 | if (priv->plat->phy_addr > MII_XGMAC_MAX_C22ADDR) |
567 | dev_err(dev, "Unsupported phy_addr (max=%d)\n" , |
568 | MII_XGMAC_MAX_C22ADDR); |
569 | } else { |
570 | /* XGMAC version 2.20 onwards support 32 phy addr */ |
571 | max_addr = PHY_MAX_ADDR; |
572 | } |
573 | } else { |
574 | new_bus->read = &stmmac_mdio_read_c22; |
575 | new_bus->write = &stmmac_mdio_write_c22; |
576 | if (priv->plat->has_gmac4) { |
577 | new_bus->read_c45 = &stmmac_mdio_read_c45; |
578 | new_bus->write_c45 = &stmmac_mdio_write_c45; |
579 | } |
580 | |
581 | max_addr = PHY_MAX_ADDR; |
582 | } |
583 | |
584 | if (mdio_bus_data->needs_reset) |
585 | new_bus->reset = &stmmac_mdio_reset; |
586 | |
587 | snprintf(buf: new_bus->id, MII_BUS_ID_SIZE, fmt: "%s-%x" , |
588 | new_bus->name, priv->plat->bus_id); |
589 | new_bus->priv = ndev; |
590 | new_bus->phy_mask = mdio_bus_data->phy_mask; |
591 | new_bus->parent = priv->device; |
592 | |
593 | err = of_mdiobus_register(mdio: new_bus, np: mdio_node); |
594 | if (err == -ENODEV) { |
595 | err = 0; |
596 | dev_info(dev, "MDIO bus is disabled\n" ); |
597 | goto bus_register_fail; |
598 | } else if (err) { |
599 | dev_err_probe(dev, err, fmt: "Cannot register the MDIO bus\n" ); |
600 | goto bus_register_fail; |
601 | } |
602 | |
603 | /* Looks like we need a dummy read for XGMAC only and C45 PHYs */ |
604 | if (priv->plat->has_xgmac) |
605 | stmmac_xgmac2_mdio_read_c45(bus: new_bus, phyaddr: 0, devad: 0, phyreg: 0); |
606 | |
607 | /* If fixed-link is set, skip PHY scanning */ |
608 | fwnode = priv->plat->port_node; |
609 | if (!fwnode) |
610 | fwnode = dev_fwnode(priv->device); |
611 | |
612 | if (fwnode) { |
613 | fixed_node = fwnode_get_named_child_node(fwnode, childname: "fixed-link" ); |
614 | if (fixed_node) { |
615 | fwnode_handle_put(fwnode: fixed_node); |
616 | goto bus_register_done; |
617 | } |
618 | } |
619 | |
620 | if (priv->plat->phy_node || mdio_node) |
621 | goto bus_register_done; |
622 | |
623 | found = 0; |
624 | for (addr = 0; addr < max_addr; addr++) { |
625 | struct phy_device *phydev = mdiobus_get_phy(bus: new_bus, addr); |
626 | |
627 | if (!phydev) |
628 | continue; |
629 | |
630 | /* |
631 | * If an IRQ was provided to be assigned after |
632 | * the bus probe, do it here. |
633 | */ |
634 | if (!mdio_bus_data->irqs && |
635 | (mdio_bus_data->probed_phy_irq > 0)) { |
636 | new_bus->irq[addr] = mdio_bus_data->probed_phy_irq; |
637 | phydev->irq = mdio_bus_data->probed_phy_irq; |
638 | } |
639 | |
640 | /* |
641 | * If we're going to bind the MAC to this PHY bus, |
642 | * and no PHY number was provided to the MAC, |
643 | * use the one probed here. |
644 | */ |
645 | if (priv->plat->phy_addr == -1) |
646 | priv->plat->phy_addr = addr; |
647 | |
648 | phy_attached_info(phydev); |
649 | found = 1; |
650 | } |
651 | |
652 | if (!found && !mdio_node) { |
653 | dev_warn(dev, "No PHY found\n" ); |
654 | err = -ENODEV; |
655 | goto no_phy_found; |
656 | } |
657 | |
658 | bus_register_done: |
659 | priv->mii = new_bus; |
660 | |
661 | return 0; |
662 | |
663 | no_phy_found: |
664 | mdiobus_unregister(bus: new_bus); |
665 | bus_register_fail: |
666 | mdiobus_free(bus: new_bus); |
667 | return err; |
668 | } |
669 | |
670 | /** |
671 | * stmmac_mdio_unregister |
672 | * @ndev: net device structure |
673 | * Description: it unregisters the MII bus |
674 | */ |
675 | int stmmac_mdio_unregister(struct net_device *ndev) |
676 | { |
677 | struct stmmac_priv *priv = netdev_priv(dev: ndev); |
678 | |
679 | if (!priv->mii) |
680 | return 0; |
681 | |
682 | if (priv->hw->xpcs) |
683 | xpcs_destroy(xpcs: priv->hw->xpcs); |
684 | |
685 | mdiobus_unregister(bus: priv->mii); |
686 | priv->mii->priv = NULL; |
687 | mdiobus_free(bus: priv->mii); |
688 | priv->mii = NULL; |
689 | |
690 | return 0; |
691 | } |
692 | |