blob: fbf85d90f546c915b850fed0a914c3ef3c35c1d6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Flemingaecf6fc2011-04-08 02:10:27 -05002/*
3 * Generic PHY Management code
4 *
Andy Flemingaecf6fc2011-04-08 02:10:27 -05005 * Copyright 2011 Freescale Semiconductor, Inc.
6 * author Andy Fleming
7 *
8 * Based loosely off of Linux's PHY Lib
9 */
Simon Glassa73bda42015-11-08 23:47:45 -070010#include <console.h>
Simon Glassdbad3462015-04-05 16:07:39 -060011#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Andy Flemingaecf6fc2011-04-08 02:10:27 -050013#include <malloc.h>
14#include <net.h>
15#include <command.h>
16#include <miiphy.h>
17#include <phy.h>
18#include <errno.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060019#include <asm/global_data.h>
Marek Vasutcf54eeb2024-03-18 15:57:01 +010020#include <asm-generic/gpio.h>
21#include <dm/device_compat.h>
Bin Mengb34ef722021-03-14 20:14:52 +080022#include <dm/of_extra.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060023#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060024#include <linux/delay.h>
Troy Kisky9519bc52012-10-22 16:40:43 +000025#include <linux/err.h>
Shengzhou Liufcfc7862014-04-11 16:14:17 +080026#include <linux/compiler.h>
Andy Flemingaecf6fc2011-04-08 02:10:27 -050027
Michal Simek5f676312015-05-13 13:40:40 +020028DECLARE_GLOBAL_DATA_PTR;
29
Andy Flemingaecf6fc2011-04-08 02:10:27 -050030/* Generic PHY support and helper functions */
31
32/**
Mario Six77577432018-01-15 11:08:27 +010033 * genphy_config_advert - sanitize and advertise auto-negotiation parameters
Andy Flemingaecf6fc2011-04-08 02:10:27 -050034 * @phydev: target phy_device struct
35 *
36 * Description: Writes MII_ADVERTISE with the appropriate values,
37 * after sanitizing the values to make sure we only advertise
38 * what is supported. Returns < 0 on error, 0 if the PHY's advertisement
39 * hasn't changed, and > 0 if it has changed.
40 */
Kim Phillips914b0782012-10-29 13:34:34 +000041static int genphy_config_advert(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -050042{
43 u32 advertise;
Florian Fainelli6c8be842016-01-13 16:59:31 +030044 int oldadv, adv, bmsr;
Andy Flemingaecf6fc2011-04-08 02:10:27 -050045 int err, changed = 0;
46
Florian Fainelli6c8be842016-01-13 16:59:31 +030047 /* Only allow advertising what this PHY supports */
Andy Flemingaecf6fc2011-04-08 02:10:27 -050048 phydev->advertising &= phydev->supported;
49 advertise = phydev->advertising;
50
51 /* Setup standard advertisement */
Florian Fainelli6c8be842016-01-13 16:59:31 +030052 adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
53 oldadv = adv;
Andy Flemingaecf6fc2011-04-08 02:10:27 -050054
55 if (adv < 0)
56 return adv;
57
58 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
59 ADVERTISE_PAUSE_ASYM);
60 if (advertise & ADVERTISED_10baseT_Half)
61 adv |= ADVERTISE_10HALF;
62 if (advertise & ADVERTISED_10baseT_Full)
63 adv |= ADVERTISE_10FULL;
64 if (advertise & ADVERTISED_100baseT_Half)
65 adv |= ADVERTISE_100HALF;
66 if (advertise & ADVERTISED_100baseT_Full)
67 adv |= ADVERTISE_100FULL;
68 if (advertise & ADVERTISED_Pause)
69 adv |= ADVERTISE_PAUSE_CAP;
70 if (advertise & ADVERTISED_Asym_Pause)
71 adv |= ADVERTISE_PAUSE_ASYM;
Charles Coldwell23329412013-02-21 08:25:52 -050072 if (advertise & ADVERTISED_1000baseX_Half)
73 adv |= ADVERTISE_1000XHALF;
74 if (advertise & ADVERTISED_1000baseX_Full)
75 adv |= ADVERTISE_1000XFULL;
Andy Flemingaecf6fc2011-04-08 02:10:27 -050076
77 if (adv != oldadv) {
78 err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv);
79
80 if (err < 0)
81 return err;
82 changed = 1;
83 }
84
Florian Fainelli6c8be842016-01-13 16:59:31 +030085 bmsr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
86 if (bmsr < 0)
87 return bmsr;
88
89 /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all
90 * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a
91 * logical 1.
92 */
93 if (!(bmsr & BMSR_ESTATEN))
94 return changed;
95
Andy Flemingaecf6fc2011-04-08 02:10:27 -050096 /* Configure gigabit if it's supported */
Florian Fainelli6c8be842016-01-13 16:59:31 +030097 adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
98 oldadv = adv;
99
100 if (adv < 0)
101 return adv;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500102
Florian Fainelli6c8be842016-01-13 16:59:31 +0300103 adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500104
Florian Fainelli6c8be842016-01-13 16:59:31 +0300105 if (phydev->supported & (SUPPORTED_1000baseT_Half |
106 SUPPORTED_1000baseT_Full)) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500107 if (advertise & SUPPORTED_1000baseT_Half)
108 adv |= ADVERTISE_1000HALF;
109 if (advertise & SUPPORTED_1000baseT_Full)
110 adv |= ADVERTISE_1000FULL;
Florian Fainelli6c8be842016-01-13 16:59:31 +0300111 }
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500112
Florian Fainelli6c8be842016-01-13 16:59:31 +0300113 if (adv != oldadv)
114 changed = 1;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500115
Florian Fainelli6c8be842016-01-13 16:59:31 +0300116 err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, adv);
117 if (err < 0)
118 return err;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500119
120 return changed;
121}
122
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500123/**
124 * genphy_setup_forced - configures/forces speed/duplex from @phydev
125 * @phydev: target phy_device struct
126 *
127 * Description: Configures MII_BMCR to force speed/duplex
128 * to the values in phydev. Assumes that the values are valid.
129 */
Kim Phillips914b0782012-10-29 13:34:34 +0000130static int genphy_setup_forced(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500131{
132 int err;
Alexandre Messier103a8c42016-01-22 14:16:15 -0500133 int ctl = BMCR_ANRESTART;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500134
Mario Six77577432018-01-15 11:08:27 +0100135 phydev->pause = 0;
136 phydev->asym_pause = 0;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500137
Mario Six77577432018-01-15 11:08:27 +0100138 if (phydev->speed == SPEED_1000)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500139 ctl |= BMCR_SPEED1000;
Mario Six77577432018-01-15 11:08:27 +0100140 else if (phydev->speed == SPEED_100)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500141 ctl |= BMCR_SPEED100;
142
Mario Six77577432018-01-15 11:08:27 +0100143 if (phydev->duplex == DUPLEX_FULL)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500144 ctl |= BMCR_FULLDPLX;
145
146 err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
147
148 return err;
149}
150
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500151/**
152 * genphy_restart_aneg - Enable and Restart Autonegotiation
153 * @phydev: target phy_device struct
154 */
155int genphy_restart_aneg(struct phy_device *phydev)
156{
157 int ctl;
158
159 ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
160
161 if (ctl < 0)
162 return ctl;
163
164 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
165
166 /* Don't isolate the PHY if we're negotiating */
167 ctl &= ~(BMCR_ISOLATE);
168
169 ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
170
171 return ctl;
172}
173
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500174/**
175 * genphy_config_aneg - restart auto-negotiation or write BMCR
176 * @phydev: target phy_device struct
177 *
178 * Description: If auto-negotiation is enabled, we configure the
179 * advertising, and then restart auto-negotiation. If it is not
180 * enabled, then we write the BMCR.
181 */
182int genphy_config_aneg(struct phy_device *phydev)
183{
184 int result;
185
Mario Six77577432018-01-15 11:08:27 +0100186 if (phydev->autoneg != AUTONEG_ENABLE)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500187 return genphy_setup_forced(phydev);
188
189 result = genphy_config_advert(phydev);
190
191 if (result < 0) /* error */
192 return result;
193
194 if (result == 0) {
Mario Six77577432018-01-15 11:08:27 +0100195 /*
196 * Advertisment hasn't changed, but maybe aneg was never on to
197 * begin with? Or maybe phy was isolated?
198 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500199 int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
200
201 if (ctl < 0)
202 return ctl;
203
204 if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
205 result = 1; /* do restart aneg */
206 }
207
Mario Six77577432018-01-15 11:08:27 +0100208 /*
209 * Only restart aneg if we are advertising something different
210 * than we were before.
211 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500212 if (result > 0)
213 result = genphy_restart_aneg(phydev);
214
215 return result;
216}
217
218/**
219 * genphy_update_link - update link status in @phydev
220 * @phydev: target phy_device struct
221 *
222 * Description: Update the value in phydev->link to reflect the
223 * current link value. In order to do this, we need to read
224 * the status register twice, keeping the second value.
225 */
226int genphy_update_link(struct phy_device *phydev)
227{
228 unsigned int mii_reg;
229
230 /*
231 * Wait if the link is up, and autonegotiation is in progress
232 * (ie - we're capable and it's not done)
233 */
234 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
235
236 /*
237 * If we already saw the link up, and it hasn't gone down, then
238 * we don't need to wait for autoneg again
239 */
240 if (phydev->link && mii_reg & BMSR_LSTATUS)
241 return 0;
242
Alexandre Messier010c5ec2016-01-22 14:16:56 -0500243 if ((phydev->autoneg == AUTONEG_ENABLE) &&
244 !(mii_reg & BMSR_ANEGCOMPLETE)) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500245 int i = 0;
246
247 printf("%s Waiting for PHY auto negotiation to complete",
Mario Six77577432018-01-15 11:08:27 +0100248 phydev->dev->name);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500249 while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
250 /*
251 * Timeout reached ?
252 */
Andre Przywara71a6a602020-01-03 22:08:47 +0000253 if (i > (PHY_ANEG_TIMEOUT / 50)) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500254 printf(" TIMEOUT !\n");
255 phydev->link = 0;
Michal Simekcf6677b2016-05-18 12:48:57 +0200256 return -ETIMEDOUT;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500257 }
258
259 if (ctrlc()) {
260 puts("user interrupt!\n");
261 phydev->link = 0;
262 return -EINTR;
263 }
264
Stefan Roese5cf96d12019-09-30 10:26:42 +0200265 if ((i++ % 10) == 0)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500266 printf(".");
267
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500268 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
Stefan Roese5cf96d12019-09-30 10:26:42 +0200269 mdelay(50); /* 50 ms */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500270 }
271 printf(" done\n");
272 phydev->link = 1;
273 } else {
274 /* Read the link a second time to clear the latched state */
275 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
276
277 if (mii_reg & BMSR_LSTATUS)
278 phydev->link = 1;
279 else
280 phydev->link = 0;
281 }
282
283 return 0;
284}
285
286/*
287 * Generic function which updates the speed and duplex. If
288 * autonegotiation is enabled, it uses the AND of the link
289 * partner's advertised capabilities and our advertised
290 * capabilities. If autonegotiation is disabled, we use the
291 * appropriate bits in the control register.
292 *
293 * Stolen from Linux's mii.c and phy_device.c
294 */
Yegor Yefremovc40f5d32012-11-28 11:15:17 +0100295int genphy_parse_link(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500296{
297 int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
298
299 /* We're using autonegotiation */
Alexandre Messier010c5ec2016-01-22 14:16:56 -0500300 if (phydev->autoneg == AUTONEG_ENABLE) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500301 u32 lpa = 0;
Heiko Schocher94c35022013-07-23 15:32:36 +0200302 int gblpa = 0;
Charles Coldwell23329412013-02-21 08:25:52 -0500303 u32 estatus = 0;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500304
305 /* Check for gigabit capability */
David Duecked454232013-11-05 17:23:02 +0100306 if (phydev->supported & (SUPPORTED_1000baseT_Full |
307 SUPPORTED_1000baseT_Half)) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500308 /* We want a list of states supported by
309 * both PHYs in the link
310 */
311 gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
Heiko Schocher94c35022013-07-23 15:32:36 +0200312 if (gblpa < 0) {
Mario Six77577432018-01-15 11:08:27 +0100313 debug("Could not read MII_STAT1000. ");
314 debug("Ignoring gigabit capability\n");
Heiko Schocher94c35022013-07-23 15:32:36 +0200315 gblpa = 0;
316 }
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500317 gblpa &= phy_read(phydev,
318 MDIO_DEVAD_NONE, MII_CTRL1000) << 2;
319 }
320
321 /* Set the baseline so we only have to set them
322 * if they're different
323 */
324 phydev->speed = SPEED_10;
325 phydev->duplex = DUPLEX_HALF;
326
327 /* Check the gigabit fields */
328 if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
329 phydev->speed = SPEED_1000;
330
331 if (gblpa & PHY_1000BTSR_1000FD)
332 phydev->duplex = DUPLEX_FULL;
333
334 /* We're done! */
335 return 0;
336 }
337
338 lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
339 lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
340
Wolfgang Denka7b06ce2011-09-28 21:02:43 +0200341 if (lpa & (LPA_100FULL | LPA_100HALF)) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500342 phydev->speed = SPEED_100;
343
Wolfgang Denka7b06ce2011-09-28 21:02:43 +0200344 if (lpa & LPA_100FULL)
345 phydev->duplex = DUPLEX_FULL;
346
Mario Six77577432018-01-15 11:08:27 +0100347 } else if (lpa & LPA_10FULL) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500348 phydev->duplex = DUPLEX_FULL;
Mario Six77577432018-01-15 11:08:27 +0100349 }
Charles Coldwell23329412013-02-21 08:25:52 -0500350
Sascha Silbe2ac8d302013-07-19 12:25:10 +0200351 /*
352 * Extended status may indicate that the PHY supports
353 * 1000BASE-T/X even though the 1000BASE-T registers
354 * are missing. In this case we can't tell whether the
355 * peer also supports it, so we only check extended
356 * status if the 1000BASE-T registers are actually
357 * missing.
358 */
359 if ((mii_reg & BMSR_ESTATEN) && !(mii_reg & BMSR_ERCAP))
Charles Coldwell23329412013-02-21 08:25:52 -0500360 estatus = phy_read(phydev, MDIO_DEVAD_NONE,
361 MII_ESTATUS);
362
363 if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF |
364 ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) {
365 phydev->speed = SPEED_1000;
366 if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_TFULL))
367 phydev->duplex = DUPLEX_FULL;
368 }
369
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500370 } else {
371 u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
372
373 phydev->speed = SPEED_10;
374 phydev->duplex = DUPLEX_HALF;
375
376 if (bmcr & BMCR_FULLDPLX)
377 phydev->duplex = DUPLEX_FULL;
378
379 if (bmcr & BMCR_SPEED1000)
380 phydev->speed = SPEED_1000;
381 else if (bmcr & BMCR_SPEED100)
382 phydev->speed = SPEED_100;
383 }
384
385 return 0;
386}
387
388int genphy_config(struct phy_device *phydev)
389{
390 int val;
391 u32 features;
392
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500393 features = (SUPPORTED_TP | SUPPORTED_MII
394 | SUPPORTED_AUI | SUPPORTED_FIBRE |
395 SUPPORTED_BNC);
396
397 /* Do we support autonegotiation? */
398 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
399
400 if (val < 0)
401 return val;
402
403 if (val & BMSR_ANEGCAPABLE)
404 features |= SUPPORTED_Autoneg;
405
406 if (val & BMSR_100FULL)
407 features |= SUPPORTED_100baseT_Full;
408 if (val & BMSR_100HALF)
409 features |= SUPPORTED_100baseT_Half;
410 if (val & BMSR_10FULL)
411 features |= SUPPORTED_10baseT_Full;
412 if (val & BMSR_10HALF)
413 features |= SUPPORTED_10baseT_Half;
414
415 if (val & BMSR_ESTATEN) {
416 val = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS);
417
418 if (val < 0)
419 return val;
420
421 if (val & ESTATUS_1000_TFULL)
422 features |= SUPPORTED_1000baseT_Full;
423 if (val & ESTATUS_1000_THALF)
424 features |= SUPPORTED_1000baseT_Half;
Charles Coldwell23329412013-02-21 08:25:52 -0500425 if (val & ESTATUS_1000_XFULL)
426 features |= SUPPORTED_1000baseX_Full;
427 if (val & ESTATUS_1000_XHALF)
Fabio Estevam45d601e2013-07-19 10:01:34 -0300428 features |= SUPPORTED_1000baseX_Half;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500429 }
430
Sascha Hauer6cc1e7d2016-01-13 16:59:32 +0300431 phydev->supported &= features;
432 phydev->advertising &= features;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500433
434 genphy_config_aneg(phydev);
435
436 return 0;
437}
438
439int genphy_startup(struct phy_device *phydev)
440{
Michal Simek5ff89662016-05-18 12:46:12 +0200441 int ret;
442
443 ret = genphy_update_link(phydev);
444 if (ret)
445 return ret;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500446
Michal Simek5ff89662016-05-18 12:46:12 +0200447 return genphy_parse_link(phydev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500448}
449
450int genphy_shutdown(struct phy_device *phydev)
451{
452 return 0;
453}
454
Marek Vasute89158b2023-03-19 18:03:12 +0100455U_BOOT_PHY_DRIVER(genphy) = {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500456 .uid = 0xffffffff,
457 .mask = 0xffffffff,
458 .name = "Generic PHY",
Sascha Hauer6cc1e7d2016-01-13 16:59:32 +0300459 .features = PHY_GBIT_FEATURES | SUPPORTED_MII |
460 SUPPORTED_AUI | SUPPORTED_FIBRE |
461 SUPPORTED_BNC,
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500462 .config = genphy_config,
463 .startup = genphy_startup,
464 .shutdown = genphy_shutdown,
465};
466
Alexey Brodkine476bb22016-01-13 16:59:34 +0300467int phy_set_supported(struct phy_device *phydev, u32 max_speed)
468{
469 /* The default values for phydev->supported are provided by the PHY
470 * driver "features" member, we want to reset to sane defaults first
471 * before supporting higher speeds.
472 */
473 phydev->supported &= PHY_DEFAULT_FEATURES;
474
475 switch (max_speed) {
476 default:
477 return -ENOTSUPP;
478 case SPEED_1000:
479 phydev->supported |= PHY_1000BT_FEATURES;
480 /* fall through */
481 case SPEED_100:
482 phydev->supported |= PHY_100BT_FEATURES;
483 /* fall through */
484 case SPEED_10:
485 phydev->supported |= PHY_10BT_FEATURES;
486 }
487
488 return 0;
489}
490
Kim Phillips914b0782012-10-29 13:34:34 +0000491static int phy_probe(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500492{
493 int err = 0;
494
Mario Six77577432018-01-15 11:08:27 +0100495 phydev->advertising = phydev->drv->features;
496 phydev->supported = phydev->drv->features;
497
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500498 phydev->mmds = phydev->drv->mmds;
499
500 if (phydev->drv->probe)
501 err = phydev->drv->probe(phydev);
502
503 return err;
504}
505
Marek Behún814c6bd2022-04-07 00:33:06 +0200506static struct phy_driver *generic_for_phy(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500507{
508#ifdef CONFIG_PHYLIB_10G
Marek Behún814c6bd2022-04-07 00:33:06 +0200509 if (phydev->is_c45)
Marek Vasutfd37a062023-03-19 18:03:13 +0100510 return ll_entry_get(struct phy_driver, gen10g, phy_driver);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500511#endif
512
Marek Vasute89158b2023-03-19 18:03:12 +0100513 return ll_entry_get(struct phy_driver, genphy, phy_driver);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500514}
515
Marek Behún3927efb2022-04-07 00:33:08 +0200516static struct phy_driver *get_phy_driver(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500517{
Marek Vasut2994e302023-03-19 18:02:42 +0100518 const int ll_n_ents = ll_entry_count(struct phy_driver, phy_driver);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500519 int phy_id = phydev->phy_id;
Marek Vasutfbe4cf22023-03-19 18:03:14 +0100520 struct phy_driver *ll_entry;
521 struct phy_driver *drv;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500522
Marek Vasut2994e302023-03-19 18:02:42 +0100523 ll_entry = ll_entry_start(struct phy_driver, phy_driver);
524 for (drv = ll_entry; drv != ll_entry + ll_n_ents; drv++)
525 if ((drv->uid & drv->mask) == (phy_id & drv->mask))
526 return drv;
527
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500528 /* If we made it here, there's no driver for this PHY */
Marek Behún814c6bd2022-04-07 00:33:06 +0200529 return generic_for_phy(phydev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500530}
531
Michal Simekc1c16032022-02-23 15:45:41 +0100532struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
Marek Behún3927efb2022-04-07 00:33:08 +0200533 u32 phy_id, bool is_c45)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500534{
535 struct phy_device *dev;
536
Mario Six77577432018-01-15 11:08:27 +0100537 /*
538 * We allocate the device, and initialize the
539 * default values
540 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500541 dev = malloc(sizeof(*dev));
542 if (!dev) {
543 printf("Failed to allocate PHY device for %s:%d\n",
Vladimir Olteanfb73b122020-07-16 18:09:08 +0800544 bus ? bus->name : "(null bus)", addr);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500545 return NULL;
546 }
547
548 memset(dev, 0, sizeof(*dev));
549
550 dev->duplex = -1;
Mugunthan V Nbbc97ba2015-09-03 15:50:21 +0530551 dev->link = 0;
Marek Behún3927efb2022-04-07 00:33:08 +0200552 dev->interface = PHY_INTERFACE_MODE_NA;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500553
Grygorii Strashko6189c062018-07-05 12:02:48 -0500554 dev->node = ofnode_null();
Grygorii Strashko6189c062018-07-05 12:02:48 -0500555
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500556 dev->autoneg = AUTONEG_ENABLE;
557
558 dev->addr = addr;
559 dev->phy_id = phy_id;
Pankaj Bansal3c43a482018-11-16 06:26:18 +0000560 dev->is_c45 = is_c45;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500561 dev->bus = bus;
562
Marek Behún3927efb2022-04-07 00:33:08 +0200563 dev->drv = get_phy_driver(dev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500564
Siva Durga Prasad Paladugua7228482019-03-04 16:02:11 +0100565 if (phy_probe(dev)) {
566 printf("%s, PHY probe failed\n", __func__);
567 return NULL;
568 }
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500569
Jacky Chou77cbf0e2024-01-15 18:34:47 +0800570 if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID &&
571 phy_id != PHY_NCSI_ID)
Michal Simek02a99d72018-12-19 16:57:38 +0100572 bus->phymap[addr] = dev;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500573
574 return dev;
575}
576
577/**
578 * get_phy_id - reads the specified addr for its ID.
579 * @bus: the target MII bus
580 * @addr: PHY address on the MII bus
581 * @phy_id: where to store the ID retrieved.
582 *
583 * Description: Reads the ID registers of the PHY at @addr on the
584 * @bus, stores it in @phy_id and returns zero on success.
585 */
Shengzhou Liu072b0fa2015-04-07 18:46:32 +0800586int __weak get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500587{
588 int phy_reg;
589
Mario Six77577432018-01-15 11:08:27 +0100590 /*
591 * Grab the bits from PHYIR1, and put them
592 * in the upper half
593 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500594 phy_reg = bus->read(bus, addr, devad, MII_PHYSID1);
595
596 if (phy_reg < 0)
597 return -EIO;
598
599 *phy_id = (phy_reg & 0xffff) << 16;
600
601 /* Grab the bits from PHYIR2, and put them in the lower half */
602 phy_reg = bus->read(bus, addr, devad, MII_PHYSID2);
603
604 if (phy_reg < 0)
605 return -EIO;
606
607 *phy_id |= (phy_reg & 0xffff);
608
609 return 0;
610}
611
Troy Kisky9519bc52012-10-22 16:40:43 +0000612static struct phy_device *create_phy_by_mask(struct mii_dev *bus,
Marek Behún3927efb2022-04-07 00:33:08 +0200613 uint phy_mask, int devad)
Troy Kisky9519bc52012-10-22 16:40:43 +0000614{
615 u32 phy_id = 0xffffffff;
Pankaj Bansal3c43a482018-11-16 06:26:18 +0000616 bool is_c45;
Mario Six77577432018-01-15 11:08:27 +0100617
Troy Kisky9519bc52012-10-22 16:40:43 +0000618 while (phy_mask) {
619 int addr = ffs(phy_mask) - 1;
620 int r = get_phy_id(bus, addr, devad, &phy_id);
Alex Marginean920fe672019-07-05 12:28:55 +0300621
622 /*
623 * If the PHY ID is flat 0 we ignore it. There are C45 PHYs
624 * that return all 0s for C22 reads (like Aquantia AQR112) and
625 * there are C22 PHYs that return all 0s for C45 reads (like
626 * Atheros AR8035).
627 */
628 if (r == 0 && phy_id == 0)
629 goto next;
630
Troy Kisky9519bc52012-10-22 16:40:43 +0000631 /* If the PHY ID is mostly f's, we didn't find anything */
Pankaj Bansal3c43a482018-11-16 06:26:18 +0000632 if (r == 0 && (phy_id & 0x1fffffff) != 0x1fffffff) {
633 is_c45 = (devad == MDIO_DEVAD_NONE) ? false : true;
Marek Behún3927efb2022-04-07 00:33:08 +0200634 return phy_device_create(bus, addr, phy_id, is_c45);
Pankaj Bansal3c43a482018-11-16 06:26:18 +0000635 }
Alex Marginean920fe672019-07-05 12:28:55 +0300636next:
Troy Kisky9519bc52012-10-22 16:40:43 +0000637 phy_mask &= ~(1 << addr);
638 }
639 return NULL;
640}
641
642static struct phy_device *search_for_existing_phy(struct mii_dev *bus,
Marek Behún3927efb2022-04-07 00:33:08 +0200643 uint phy_mask)
Troy Kisky9519bc52012-10-22 16:40:43 +0000644{
645 /* If we have one, return the existing device, with new interface */
646 while (phy_mask) {
Eugeniu Rosca42388372024-01-04 05:26:23 +0100647 unsigned int addr = ffs(phy_mask) - 1;
Mario Six77577432018-01-15 11:08:27 +0100648
Marek Behún3927efb2022-04-07 00:33:08 +0200649 if (bus->phymap[addr])
Troy Kisky9519bc52012-10-22 16:40:43 +0000650 return bus->phymap[addr];
Marek Behún3927efb2022-04-07 00:33:08 +0200651
Eugeniu Rosca42388372024-01-04 05:26:23 +0100652 phy_mask &= ~(1U << addr);
Troy Kisky9519bc52012-10-22 16:40:43 +0000653 }
654 return NULL;
655}
656
657static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus,
Marek Behún3927efb2022-04-07 00:33:08 +0200658 uint phy_mask)
Troy Kisky9519bc52012-10-22 16:40:43 +0000659{
Troy Kisky9519bc52012-10-22 16:40:43 +0000660 struct phy_device *phydev;
Florin Chiculita0439bee2020-04-29 14:25:48 +0300661 int devad[] = {
662 /* Clause-22 */
663 MDIO_DEVAD_NONE,
664 /* Clause-45 */
665 MDIO_MMD_PMAPMD,
666 MDIO_MMD_WIS,
667 MDIO_MMD_PCS,
668 MDIO_MMD_PHYXS,
669 MDIO_MMD_VEND1,
670 };
671 int i, devad_cnt;
Troy Kisky9519bc52012-10-22 16:40:43 +0000672
Florin Chiculita0439bee2020-04-29 14:25:48 +0300673 devad_cnt = sizeof(devad)/sizeof(int);
Marek Behún3927efb2022-04-07 00:33:08 +0200674 phydev = search_for_existing_phy(bus, phy_mask);
Troy Kisky9519bc52012-10-22 16:40:43 +0000675 if (phydev)
676 return phydev;
Florin Chiculita0439bee2020-04-29 14:25:48 +0300677 /* try different access clauses */
678 for (i = 0; i < devad_cnt; i++) {
Marek Behún3927efb2022-04-07 00:33:08 +0200679 phydev = create_phy_by_mask(bus, phy_mask, devad[i]);
Troy Kisky9519bc52012-10-22 16:40:43 +0000680 if (IS_ERR(phydev))
681 return NULL;
682 if (phydev)
683 return phydev;
684 }
Bin Meng59c6d892015-10-07 21:19:30 -0700685
686 debug("\n%s PHY: ", bus->name);
687 while (phy_mask) {
688 int addr = ffs(phy_mask) - 1;
Mario Six77577432018-01-15 11:08:27 +0100689
Bin Meng59c6d892015-10-07 21:19:30 -0700690 debug("%d ", addr);
691 phy_mask &= ~(1 << addr);
692 }
693 debug("not found\n");
Bin Meng0776c572015-10-07 21:19:29 -0700694
695 return NULL;
Troy Kisky9519bc52012-10-22 16:40:43 +0000696}
697
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500698/**
Mario Six77577432018-01-15 11:08:27 +0100699 * get_phy_device - reads the specified PHY device and returns its
700 * @phy_device struct
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500701 * @bus: the target MII bus
702 * @addr: PHY address on the MII bus
703 *
704 * Description: Reads the ID registers of the PHY at @addr on the
705 * @bus, then allocates and returns the phy_device to represent it.
706 */
Marek Behún3927efb2022-04-07 00:33:08 +0200707static struct phy_device *get_phy_device(struct mii_dev *bus, int addr)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500708{
Marek Behún3927efb2022-04-07 00:33:08 +0200709 return get_phy_device_by_mask(bus, 1 << addr);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500710}
711
712int phy_reset(struct phy_device *phydev)
713{
714 int reg;
715 int timeout = 500;
716 int devad = MDIO_DEVAD_NONE;
717
Shaohui Xie62a7b922016-01-28 15:55:46 +0800718 if (phydev->flags & PHY_FLAG_BROKEN_RESET)
719 return 0;
720
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500721#ifdef CONFIG_PHYLIB_10G
722 /* If it's 10G, we need to issue reset through one of the MMDs */
Marek Behún814c6bd2022-04-07 00:33:06 +0200723 if (phydev->is_c45) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500724 if (!phydev->mmds)
725 gen10g_discover_mmds(phydev);
726
727 devad = ffs(phydev->mmds) - 1;
728 }
729#endif
730
Stefan Agnere64013d2015-12-09 11:21:25 -0800731 if (phy_write(phydev, devad, MII_BMCR, BMCR_RESET) < 0) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500732 debug("PHY reset failed\n");
733 return -1;
734 }
735
Tom Rini6c851512022-03-18 08:38:26 -0400736#if CONFIG_PHY_RESET_DELAY > 0
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500737 udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
738#endif
739 /*
740 * Poll the control register for the reset bit to go to 0 (it is
741 * auto-clearing). This should happen within 0.5 seconds per the
742 * IEEE spec.
743 */
Stefan Agnere64013d2015-12-09 11:21:25 -0800744 reg = phy_read(phydev, devad, MII_BMCR);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500745 while ((reg & BMCR_RESET) && timeout--) {
746 reg = phy_read(phydev, devad, MII_BMCR);
747
748 if (reg < 0) {
749 debug("PHY status read failed\n");
750 return -1;
751 }
752 udelay(1000);
753 }
754
755 if (reg & BMCR_RESET) {
756 puts("PHY reset timed out\n");
757 return -1;
758 }
759
760 return 0;
761}
762
763int miiphy_reset(const char *devname, unsigned char addr)
764{
765 struct mii_dev *bus = miiphy_get_dev_by_name(devname);
766 struct phy_device *phydev;
767
Marek Behún3927efb2022-04-07 00:33:08 +0200768 phydev = get_phy_device(bus, addr);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500769
770 return phy_reset(phydev);
771}
772
Marek Vasutcf54eeb2024-03-18 15:57:01 +0100773#if CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_REAL) && \
774 !IS_ENABLED(CONFIG_DM_ETH_PHY)
775int phy_gpio_reset(struct udevice *dev)
776{
777 struct ofnode_phandle_args phandle_args;
778 struct gpio_desc gpio;
779 u32 assert, deassert;
780 ofnode node;
781 int ret;
782
783 ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
784 &phandle_args);
785 /* No PHY handle is OK */
786 if (ret)
787 return 0;
788
789 node = phandle_args.node;
790 if (!ofnode_valid(node))
791 return -EINVAL;
792
793 ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
794 GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
795 /* No PHY reset GPIO is OK */
796 if (ret)
797 return 0;
798
799 assert = ofnode_read_u32_default(node, "reset-assert-us", 20000);
800 deassert = ofnode_read_u32_default(node, "reset-deassert-us", 1000);
801 ret = dm_gpio_set_value(&gpio, 1);
802 if (ret) {
803 dev_err(dev, "Failed assert gpio, err: %d\n", ret);
804 return ret;
805 }
806
807 udelay(assert);
808
809 ret = dm_gpio_set_value(&gpio, 0);
810 if (ret) {
811 dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
812 return ret;
813 }
814
815 udelay(deassert);
816
817 return 0;
818}
819#else
820int phy_gpio_reset(struct udevice *dev)
821{
822 return 0;
823}
824#endif
825
Marek Behún3927efb2022-04-07 00:33:08 +0200826struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500827{
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500828 /* Reset the bus */
Jörg Krause71b1d862015-07-15 15:18:22 +0200829 if (bus->reset) {
Vladimir Zapolskiy46f10bb2011-09-05 07:24:07 +0000830 bus->reset(bus);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500831
Jörg Krause71b1d862015-07-15 15:18:22 +0200832 /* Wait 15ms to make sure the PHY has come out of hard reset */
Mario Six77577432018-01-15 11:08:27 +0100833 mdelay(15);
Jörg Krause71b1d862015-07-15 15:18:22 +0200834 }
835
Marek Behún3927efb2022-04-07 00:33:08 +0200836 return get_phy_device_by_mask(bus, phy_mask);
Troy Kisky9519bc52012-10-22 16:40:43 +0000837}
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500838
Marek Vasutccc35bd2023-05-31 00:51:25 +0200839static void phy_connect_dev(struct phy_device *phydev, struct udevice *dev,
840 phy_interface_t interface)
Troy Kisky9519bc52012-10-22 16:40:43 +0000841{
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500842 /* Soft Reset the PHY */
843 phy_reset(phydev);
Bin Mengf87a15c2015-10-07 21:19:31 -0700844 if (phydev->dev && phydev->dev != dev) {
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500845 printf("%s:%d is connected to %s. Reconnecting to %s\n",
Mario Six77577432018-01-15 11:08:27 +0100846 phydev->bus->name, phydev->addr,
847 phydev->dev->name, dev->name);
Troy Kisky9519bc52012-10-22 16:40:43 +0000848 }
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500849 phydev->dev = dev;
Marek Behún3927efb2022-04-07 00:33:08 +0200850 phydev->interface = interface;
851 debug("%s connected to %s mode %s\n", dev->name, phydev->drv->name,
852 phy_string_for_interface(interface));
Troy Kisky9519bc52012-10-22 16:40:43 +0000853}
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530854
855#ifdef CONFIG_PHY_XILINX_GMII2RGMII
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530856static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus,
Marek Behún3927efb2022-04-07 00:33:08 +0200857 struct udevice *dev)
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530858{
859 struct phy_device *phydev = NULL;
Michal Simek77272032021-04-26 14:26:48 +0200860 ofnode node;
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530861
Michal Simek77272032021-04-26 14:26:48 +0200862 ofnode_for_each_subnode(node, dev_ofnode(dev)) {
Bin Meng021e7e72021-03-14 20:14:50 +0800863 node = ofnode_by_compatible(node, "xlnx,gmii-to-rgmii-1.0");
864 if (ofnode_valid(node)) {
Tejas Bhumkar1d47cce2023-09-15 10:20:43 +0530865 int gmiirgmii_phyaddr;
866
867 gmiirgmii_phyaddr = ofnode_read_u32_default(node, "reg", 0);
868 phydev = phy_device_create(bus, gmiirgmii_phyaddr,
Marek Behún3927efb2022-04-07 00:33:08 +0200869 PHY_GMII2RGMII_ID, false);
Bin Meng021e7e72021-03-14 20:14:50 +0800870 if (phydev)
871 phydev->node = node;
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530872 break;
873 }
Bin Meng021e7e72021-03-14 20:14:50 +0800874
875 node = ofnode_first_subnode(node);
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530876 }
877
878 return phydev;
879}
880#endif
Troy Kisky9519bc52012-10-22 16:40:43 +0000881
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530882#ifdef CONFIG_PHY_FIXED
Vladimir Oltean8c089f72021-01-25 14:23:52 +0200883/**
884 * fixed_phy_create() - create an unconnected fixed-link pseudo-PHY device
885 * @node: OF node for the container of the fixed-link node
886 *
887 * Description: Creates a struct phy_device based on a fixed-link of_node
888 * description. Can be used without phy_connect by drivers which do not expose
889 * a UCLASS_ETH udevice.
890 */
891struct phy_device *fixed_phy_create(ofnode node)
892{
Vladimir Oltean6ca194a2021-03-14 20:14:48 +0800893 struct phy_device *phydev;
Vladimir Oltean8c089f72021-01-25 14:23:52 +0200894 ofnode subnode;
895
Vladimir Oltean8c089f72021-01-25 14:23:52 +0200896 subnode = ofnode_find_subnode(node, "fixed-link");
897 if (!ofnode_valid(subnode)) {
898 return NULL;
899 }
900
Marek Behún3927efb2022-04-07 00:33:08 +0200901 phydev = phy_device_create(NULL, 0, PHY_FIXED_ID, false);
Heinrich Schuchardt056f40f2022-07-11 19:40:13 +0200902 if (phydev) {
Vladimir Oltean6ca194a2021-03-14 20:14:48 +0800903 phydev->node = subnode;
Heinrich Schuchardt056f40f2022-07-11 19:40:13 +0200904 phydev->interface = ofnode_read_phy_mode(node);
905 }
Marek Behún3927efb2022-04-07 00:33:08 +0200906
Vladimir Oltean6ca194a2021-03-14 20:14:48 +0800907 return phydev;
Vladimir Oltean8c089f72021-01-25 14:23:52 +0200908}
909
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530910static struct phy_device *phy_connect_fixed(struct mii_dev *bus,
Marek Behún3927efb2022-04-07 00:33:08 +0200911 struct udevice *dev)
Troy Kisky9519bc52012-10-22 16:40:43 +0000912{
Vladimir Oltean6ca194a2021-03-14 20:14:48 +0800913 ofnode node = dev_ofnode(dev), subnode;
Bin Mengb34ef722021-03-14 20:14:52 +0800914 struct phy_device *phydev = NULL;
Vladimir Oltean6ca194a2021-03-14 20:14:48 +0800915
Bin Mengb34ef722021-03-14 20:14:52 +0800916 if (ofnode_phy_is_fixed_link(node, &subnode)) {
Marek Behún3927efb2022-04-07 00:33:08 +0200917 phydev = phy_device_create(bus, 0, PHY_FIXED_ID, false);
Bin Mengb34ef722021-03-14 20:14:52 +0800918 if (phydev)
919 phydev->node = subnode;
920 }
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530921
922 return phydev;
923}
Hannes Schmelzerda494602017-03-23 15:11:43 +0100924#endif
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530925
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530926struct phy_device *phy_connect(struct mii_dev *bus, int addr,
927 struct udevice *dev,
928 phy_interface_t interface)
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530929{
930 struct phy_device *phydev = NULL;
Priyanka Jain11691fd2019-11-05 04:05:11 +0000931 uint mask = (addr >= 0) ? (1 << addr) : 0xffffffff;
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530932
933#ifdef CONFIG_PHY_FIXED
Marek Behún3927efb2022-04-07 00:33:08 +0200934 phydev = phy_connect_fixed(bus, dev);
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530935#endif
Samuel Mendoza-Jonasb069c4a2019-06-18 11:37:18 +1000936
937#ifdef CONFIG_PHY_NCSI
Samuel Mendoza-Jonasc8f4ab02022-08-08 21:46:03 +0930938 if (!phydev && interface == PHY_INTERFACE_MODE_NCSI)
Marek Behún3927efb2022-04-07 00:33:08 +0200939 phydev = phy_device_create(bus, 0, PHY_NCSI_ID, false);
Samuel Mendoza-Jonasb069c4a2019-06-18 11:37:18 +1000940#endif
941
Michal Simek488eec52022-02-23 15:45:42 +0100942#ifdef CONFIG_PHY_ETHERNET_ID
943 if (!phydev)
Tom Rini6a25a7e2022-04-15 08:09:52 -0400944 phydev = phy_connect_phy_id(bus, dev, addr);
Michal Simek488eec52022-02-23 15:45:42 +0100945#endif
946
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530947#ifdef CONFIG_PHY_XILINX_GMII2RGMII
948 if (!phydev)
Marek Behún3927efb2022-04-07 00:33:08 +0200949 phydev = phy_connect_gmii2rgmii(bus, dev);
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530950#endif
Siva Durga Prasad Paladugu03f937a2018-11-27 11:49:10 +0530951
Mario Six77577432018-01-15 11:08:27 +0100952 if (!phydev)
Marek Behún3927efb2022-04-07 00:33:08 +0200953 phydev = phy_find_by_mask(bus, mask);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500954
Troy Kisky9519bc52012-10-22 16:40:43 +0000955 if (phydev)
Marek Behún3927efb2022-04-07 00:33:08 +0200956 phy_connect_dev(phydev, dev, interface);
Troy Kisky9519bc52012-10-22 16:40:43 +0000957 else
958 printf("Could not get PHY for %s: addr %d\n", bus->name, addr);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500959 return phydev;
960}
961
Timur Tabi251180b2012-07-05 10:33:18 +0000962/*
963 * Start the PHY. Returns 0 on success, or a negative error code.
964 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500965int phy_startup(struct phy_device *phydev)
966{
967 if (phydev->drv->startup)
Timur Tabi251180b2012-07-05 10:33:18 +0000968 return phydev->drv->startup(phydev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500969
970 return 0;
971}
972
Jeroen Hofsteee4f89472014-10-08 22:57:26 +0200973__weak int board_phy_config(struct phy_device *phydev)
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500974{
Troy Kisky85846412012-02-07 14:08:49 +0000975 if (phydev->drv->config)
976 return phydev->drv->config(phydev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500977 return 0;
978}
979
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500980int phy_config(struct phy_device *phydev)
981{
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500982 /* Invoke an optional board-specific helper */
Michal Simek24ce2322016-05-18 14:37:23 +0200983 return board_phy_config(phydev);
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500984}
985
986int phy_shutdown(struct phy_device *phydev)
987{
988 if (phydev->drv->shutdown)
989 phydev->drv->shutdown(phydev);
990
991 return 0;
992}
Simon Glassdbad3462015-04-05 16:07:39 -0600993
Ariel D'Alessandro9c18c912022-04-12 10:31:36 -0300994/**
995 * phy_modify - Convenience function for modifying a given PHY register
996 * @phydev: the phy_device struct
997 * @devad: The MMD to read from
998 * @regnum: register number to write
999 * @mask: bit mask of bits to clear
1000 * @set: new value of bits set in mask to write to @regnum
1001 */
1002int phy_modify(struct phy_device *phydev, int devad, int regnum, u16 mask,
1003 u16 set)
1004{
1005 int ret;
1006
1007 ret = phy_read(phydev, devad, regnum);
1008 if (ret < 0)
1009 return ret;
1010
1011 return phy_write(phydev, devad, regnum, (ret & ~mask) | set);
1012}
Ramon Fried5d747262022-06-05 03:44:15 +03001013
1014/**
1015 * phy_read - Convenience function for reading a given PHY register
1016 * @phydev: the phy_device struct
1017 * @devad: The MMD to read from
1018 * @regnum: register number to read
1019 * @return: value for success or negative errno for failure
1020 */
1021int phy_read(struct phy_device *phydev, int devad, int regnum)
1022{
1023 struct mii_dev *bus = phydev->bus;
1024
1025 if (!bus || !bus->read) {
1026 debug("%s: No bus configured\n", __func__);
1027 return -1;
1028 }
1029
1030 return bus->read(bus, phydev->addr, devad, regnum);
1031}
1032
1033/**
1034 * phy_write - Convenience function for writing a given PHY register
1035 * @phydev: the phy_device struct
1036 * @devad: The MMD to read from
1037 * @regnum: register number to write
1038 * @val: value to write to @regnum
1039 * @return: 0 for success or negative errno for failure
1040 */
1041int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
1042{
1043 struct mii_dev *bus = phydev->bus;
1044
1045 if (!bus || !bus->write) {
1046 debug("%s: No bus configured\n", __func__);
1047 return -1;
1048 }
1049
1050 return bus->write(bus, phydev->addr, devad, regnum, val);
1051}
1052
1053/**
1054 * phy_mmd_start_indirect - Convenience function for writing MMD registers
1055 * @phydev: the phy_device struct
1056 * @devad: The MMD to read from
1057 * @regnum: register number to write
1058 * @return: None
1059 */
1060void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum)
1061{
1062 /* Write the desired MMD Devad */
1063 phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
1064
1065 /* Write the desired MMD register address */
1066 phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
1067
1068 /* Select the Function : DATA with no post increment */
1069 phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
1070 (devad | MII_MMD_CTRL_NOINCR));
1071}
1072
1073/**
1074 * phy_read_mmd - Convenience function for reading a register
1075 * from an MMD on a given PHY.
1076 * @phydev: The phy_device struct
1077 * @devad: The MMD to read from
1078 * @regnum: The register on the MMD to read
1079 * @return: Value for success or negative errno for failure
1080 */
1081int phy_read_mmd(struct phy_device *phydev, int devad, int regnum)
1082{
1083 struct phy_driver *drv = phydev->drv;
1084
1085 if (regnum > (u16)~0 || devad > 32)
1086 return -EINVAL;
1087
1088 /* driver-specific access */
1089 if (drv->read_mmd)
1090 return drv->read_mmd(phydev, devad, regnum);
1091
1092 /* direct C45 / C22 access */
1093 if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
1094 devad == MDIO_DEVAD_NONE || !devad)
1095 return phy_read(phydev, devad, regnum);
1096
1097 /* indirect C22 access */
1098 phy_mmd_start_indirect(phydev, devad, regnum);
1099
1100 /* Read the content of the MMD's selected register */
1101 return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
1102}
1103
1104/**
1105 * phy_write_mmd - Convenience function for writing a register
1106 * on an MMD on a given PHY.
1107 * @phydev: The phy_device struct
1108 * @devad: The MMD to read from
1109 * @regnum: The register on the MMD to read
1110 * @val: value to write to @regnum
1111 * @return: 0 for success or negative errno for failure
1112 */
1113int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val)
1114{
1115 struct phy_driver *drv = phydev->drv;
1116
1117 if (regnum > (u16)~0 || devad > 32)
1118 return -EINVAL;
1119
1120 /* driver-specific access */
1121 if (drv->write_mmd)
1122 return drv->write_mmd(phydev, devad, regnum, val);
1123
1124 /* direct C45 / C22 access */
1125 if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
1126 devad == MDIO_DEVAD_NONE || !devad)
1127 return phy_write(phydev, devad, regnum, val);
1128
1129 /* indirect C22 access */
1130 phy_mmd_start_indirect(phydev, devad, regnum);
1131
1132 /* Write the data into MMD's selected register */
1133 return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
1134}
1135
1136/**
1137 * phy_set_bits_mmd - Convenience function for setting bits in a register
1138 * on MMD
1139 * @phydev: the phy_device struct
1140 * @devad: the MMD containing register to modify
1141 * @regnum: register number to modify
1142 * @val: bits to set
1143 * @return: 0 for success or negative errno for failure
1144 */
1145int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
1146{
1147 int value, ret;
1148
1149 value = phy_read_mmd(phydev, devad, regnum);
1150 if (value < 0)
1151 return value;
1152
1153 value |= val;
1154
1155 ret = phy_write_mmd(phydev, devad, regnum, value);
1156 if (ret < 0)
1157 return ret;
1158
1159 return 0;
1160}
1161
1162/**
1163 * phy_clear_bits_mmd - Convenience function for clearing bits in a register
1164 * on MMD
1165 * @phydev: the phy_device struct
1166 * @devad: the MMD containing register to modify
1167 * @regnum: register number to modify
1168 * @val: bits to clear
1169 * @return: 0 for success or negative errno for failure
1170 */
1171int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
1172{
1173 int value, ret;
1174
1175 value = phy_read_mmd(phydev, devad, regnum);
1176 if (value < 0)
1177 return value;
1178
1179 value &= ~val;
1180
1181 ret = phy_write_mmd(phydev, devad, regnum, value);
1182 if (ret < 0)
1183 return ret;
1184
1185 return 0;
1186}
Samuel Mendoza-Jonasc8f4ab02022-08-08 21:46:03 +09301187
Marek Vasut9cd9d222023-03-19 18:08:07 +01001188/**
1189 * phy_modify_mmd_changed - Function for modifying a register on MMD
1190 * @phydev: the phy_device struct
1191 * @devad: the MMD containing register to modify
1192 * @regnum: register number to modify
1193 * @mask: bit mask of bits to clear
1194 * @set: new value of bits set in mask to write to @regnum
1195 *
1196 * NOTE: MUST NOT be called from interrupt context,
1197 * because the bus read/write functions may wait for an interrupt
1198 * to conclude the operation.
1199 *
1200 * Returns negative errno, 0 if there was no change, and 1 in case of change
1201 */
1202int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
1203 u16 mask, u16 set)
1204{
1205 int new, ret;
1206
1207 ret = phy_read_mmd(phydev, devad, regnum);
1208 if (ret < 0)
1209 return ret;
1210
1211 new = (ret & ~mask) | set;
1212 if (new == ret)
1213 return 0;
1214
1215 ret = phy_write_mmd(phydev, devad, regnum, new);
1216
1217 return ret < 0 ? ret : 1;
1218}
1219
1220/**
1221 * phy_modify_mmd - Convenience function for modifying a register on MMD
1222 * @phydev: the phy_device struct
1223 * @devad: the MMD containing register to modify
1224 * @regnum: register number to modify
1225 * @mask: bit mask of bits to clear
1226 * @set: new value of bits set in mask to write to @regnum
1227 *
1228 * NOTE: MUST NOT be called from interrupt context,
1229 * because the bus read/write functions may wait for an interrupt
1230 * to conclude the operation.
1231 */
1232int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
1233 u16 mask, u16 set)
1234{
1235 int ret;
1236
1237 ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
1238
1239 return ret < 0 ? ret : 0;
1240}
1241
Samuel Mendoza-Jonasc8f4ab02022-08-08 21:46:03 +09301242bool phy_interface_is_ncsi(void)
1243{
Marek Vasutadc3fdc2023-03-21 18:25:54 +01001244#ifdef CONFIG_PHY_NCSI
Samuel Mendoza-Jonasc8f4ab02022-08-08 21:46:03 +09301245 struct eth_pdata *pdata = dev_get_plat(eth_get_dev());
1246
1247 return pdata->phy_interface == PHY_INTERFACE_MODE_NCSI;
Marek Vasutadc3fdc2023-03-21 18:25:54 +01001248#else
1249 return 0;
1250#endif
Samuel Mendoza-Jonasc8f4ab02022-08-08 21:46:03 +09301251}