]> git.ipfire.org Git - people/ms/u-boot.git/blame - common/miiphyutil.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
[people/ms/u-boot.git] / common / miiphyutil.c
CommitLineData
c609719b
WD
1/*
2 * (C) Copyright 2001
3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24/*
25 * This provides a bit-banged interface to the ethernet MII management
26 * channel.
27 */
28
29#include <common.h>
30#include <miiphy.h>
5f184715 31#include <phy.h>
c609719b 32
63ff004c
MB
33#include <asm/types.h>
34#include <linux/list.h>
35#include <malloc.h>
36#include <net.h>
37
38/* local debug macro */
63ff004c
MB
39#undef MII_DEBUG
40
41#undef debug
42#ifdef MII_DEBUG
16a53238 43#define debug(fmt, args...) printf(fmt, ##args)
63ff004c 44#else
16a53238 45#define debug(fmt, args...)
63ff004c
MB
46#endif /* MII_DEBUG */
47
63ff004c
MB
48static struct list_head mii_devs;
49static struct mii_dev *current_mii;
50
0daac978
MF
51/*
52 * Lookup the mii_dev struct by the registered device name.
53 */
5f184715 54struct mii_dev *miiphy_get_dev_by_name(const char *devname)
0daac978
MF
55{
56 struct list_head *entry;
57 struct mii_dev *dev;
58
59 if (!devname) {
60 printf("NULL device name!\n");
61 return NULL;
62 }
63
64 list_for_each(entry, &mii_devs) {
65 dev = list_entry(entry, struct mii_dev, link);
66 if (strcmp(dev->name, devname) == 0)
67 return dev;
68 }
69
0daac978
MF
70 return NULL;
71}
72
d9785c14
MB
73/*****************************************************************************
74 *
75 * Initialize global data. Need to be called before any other miiphy routine.
76 */
5700bb63 77void miiphy_init(void)
d9785c14 78{
16a53238 79 INIT_LIST_HEAD(&mii_devs);
298035df 80 current_mii = NULL;
d9785c14
MB
81}
82
5f184715
AF
83static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
84{
85 unsigned short val;
86 int ret;
87 struct legacy_mii_dev *ldev = bus->priv;
88
89 ret = ldev->read(bus->name, addr, reg, &val);
90
91 return ret ? -1 : (int)val;
92}
93
94static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
95 int reg, u16 val)
96{
97 struct legacy_mii_dev *ldev = bus->priv;
98
99 return ldev->write(bus->name, addr, reg, val);
100}
101
63ff004c
MB
102/*****************************************************************************
103 *
104 * Register read and write MII access routines for the device <name>.
105 */
5700bb63 106void miiphy_register(const char *name,
16a53238 107 int (*read)(const char *devname, unsigned char addr,
298035df 108 unsigned char reg, unsigned short *value),
16a53238 109 int (*write)(const char *devname, unsigned char addr,
298035df 110 unsigned char reg, unsigned short value))
63ff004c 111{
63ff004c 112 struct mii_dev *new_dev;
5f184715 113 struct legacy_mii_dev *ldev;
63ff004c
MB
114 unsigned int name_len;
115
63ff004c 116 /* check if we have unique name */
5f184715 117 new_dev = miiphy_get_dev_by_name(name);
0daac978
MF
118 if (new_dev) {
119 printf("miiphy_register: non unique device name '%s'\n", name);
120 return;
63ff004c
MB
121 }
122
123 /* allocate memory */
16a53238 124 name_len = strlen(name);
5f184715
AF
125 if (name_len > MDIO_NAME_LEN - 1) {
126 /* Hopefully this won't happen, but if it does, we'll know */
127 printf("miiphy_register: MDIO name was longer than %d\n",
128 MDIO_NAME_LEN);
129 return;
130 }
131
132 new_dev = mdio_alloc();
133 ldev = malloc(sizeof(*ldev));
63ff004c 134
5f184715 135 if (new_dev == NULL || ldev == NULL) {
16a53238 136 printf("miiphy_register: cannot allocate memory for '%s'\n",
298035df 137 name);
63ff004c
MB
138 return;
139 }
63ff004c
MB
140
141 /* initalize mii_dev struct fields */
5f184715
AF
142 new_dev->read = legacy_miiphy_read;
143 new_dev->write = legacy_miiphy_write;
144 sprintf(new_dev->name, name);
145 ldev->read = read;
146 ldev->write = write;
147 new_dev->priv = ldev;
63ff004c 148
16a53238 149 debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
5f184715 150 new_dev->name, ldev->read, ldev->write);
63ff004c
MB
151
152 /* add it to the list */
16a53238 153 list_add_tail(&new_dev->link, &mii_devs);
63ff004c
MB
154
155 if (!current_mii)
156 current_mii = new_dev;
157}
158
5f184715
AF
159struct mii_dev *mdio_alloc(void)
160{
161 struct mii_dev *bus;
162
163 bus = malloc(sizeof(*bus));
164 if (!bus)
165 return bus;
166
167 memset(bus, 0, sizeof(*bus));
168
169 /* initalize mii_dev struct fields */
170 INIT_LIST_HEAD(&bus->link);
171
172 return bus;
173}
174
175int mdio_register(struct mii_dev *bus)
176{
177 if (!bus || !bus->name || !bus->read || !bus->write)
178 return -1;
179
180 /* check if we have unique name */
181 if (miiphy_get_dev_by_name(bus->name)) {
182 printf("mdio_register: non unique device name '%s'\n",
183 bus->name);
184 return -1;
185 }
186
187 /* add it to the list */
188 list_add_tail(&bus->link, &mii_devs);
189
190 if (!current_mii)
191 current_mii = bus;
192
193 return 0;
194}
195
196void mdio_list_devices(void)
197{
198 struct list_head *entry;
199
200 list_for_each(entry, &mii_devs) {
201 int i;
202 struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
203
204 printf("%s:\n", bus->name);
205
206 for (i = 0; i < PHY_MAX_ADDR; i++) {
207 struct phy_device *phydev = bus->phymap[i];
208
209 if (phydev) {
210 printf("%d - %s", i, phydev->drv->name);
211
212 if (phydev->dev)
213 printf(" <--> %s\n", phydev->dev->name);
214 else
215 printf("\n");
216 }
217 }
218 }
219}
220
5700bb63 221int miiphy_set_current_dev(const char *devname)
63ff004c 222{
63ff004c
MB
223 struct mii_dev *dev;
224
5f184715 225 dev = miiphy_get_dev_by_name(devname);
0daac978
MF
226 if (dev) {
227 current_mii = dev;
228 return 0;
63ff004c
MB
229 }
230
5f184715
AF
231 printf("No such device: %s\n", devname);
232
63ff004c
MB
233 return 1;
234}
235
5f184715
AF
236struct mii_dev *mdio_get_current_dev(void)
237{
238 return current_mii;
239}
240
241struct phy_device *mdio_phydev_for_ethname(const char *ethname)
242{
243 struct list_head *entry;
244 struct mii_dev *bus;
245
246 list_for_each(entry, &mii_devs) {
247 int i;
248 bus = list_entry(entry, struct mii_dev, link);
249
250 for (i = 0; i < PHY_MAX_ADDR; i++) {
251 if (!bus->phymap[i] || !bus->phymap[i]->dev)
252 continue;
253
254 if (strcmp(bus->phymap[i]->dev->name, ethname) == 0)
255 return bus->phymap[i];
256 }
257 }
258
259 printf("%s is not a known ethernet\n", ethname);
260 return NULL;
261}
262
5700bb63 263const char *miiphy_get_current_dev(void)
63ff004c
MB
264{
265 if (current_mii)
266 return current_mii->name;
267
268 return NULL;
269}
270
ede16ea3
MF
271static struct mii_dev *miiphy_get_active_dev(const char *devname)
272{
273 /* If the current mii is the one we want, return it */
274 if (current_mii)
275 if (strcmp(current_mii->name, devname) == 0)
276 return current_mii;
277
278 /* Otherwise, set the active one to the one we want */
279 if (miiphy_set_current_dev(devname))
280 return NULL;
281 else
282 return current_mii;
283}
284
63ff004c
MB
285/*****************************************************************************
286 *
287 * Read to variable <value> from the PHY attached to device <devname>,
288 * use PHY address <addr> and register <reg>.
289 *
290 * Returns:
291 * 0 on success
292 */
5700bb63 293int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
298035df 294 unsigned short *value)
63ff004c 295{
5f184715 296 struct mii_dev *bus;
63ff004c 297
5f184715
AF
298 bus = miiphy_get_active_dev(devname);
299 if (bus)
300 *value = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
301 else
302 return 1;
63ff004c 303
5f184715 304 return (*value < 0) ? 1 : 0;
63ff004c
MB
305}
306
307/*****************************************************************************
308 *
309 * Write <value> to the PHY attached to device <devname>,
310 * use PHY address <addr> and register <reg>.
311 *
312 * Returns:
313 * 0 on success
314 */
5700bb63 315int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
298035df 316 unsigned short value)
63ff004c 317{
5f184715 318 struct mii_dev *bus;
63ff004c 319
5f184715
AF
320 bus = miiphy_get_active_dev(devname);
321 if (bus)
322 return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
63ff004c 323
0daac978 324 return 1;
63ff004c
MB
325}
326
327/*****************************************************************************
328 *
329 * Print out list of registered MII capable devices.
330 */
16a53238 331void miiphy_listdev(void)
63ff004c
MB
332{
333 struct list_head *entry;
334 struct mii_dev *dev;
335
16a53238
AF
336 puts("MII devices: ");
337 list_for_each(entry, &mii_devs) {
338 dev = list_entry(entry, struct mii_dev, link);
339 printf("'%s' ", dev->name);
63ff004c 340 }
16a53238 341 puts("\n");
63ff004c
MB
342
343 if (current_mii)
16a53238 344 printf("Current device: '%s'\n", current_mii->name);
63ff004c
MB
345}
346
c609719b
WD
347/*****************************************************************************
348 *
349 * Read the OUI, manufacture's model number, and revision number.
350 *
351 * OUI: 22 bits (unsigned int)
352 * Model: 6 bits (unsigned char)
353 * Revision: 4 bits (unsigned char)
354 *
355 * Returns:
356 * 0 on success
357 */
5700bb63 358int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
c609719b
WD
359 unsigned char *model, unsigned char *rev)
360{
361 unsigned int reg = 0;
8bf3b005 362 unsigned short tmp;
c609719b 363
16a53238
AF
364 if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
365 debug("PHY ID register 2 read failed\n");
366 return -1;
c609719b 367 }
8bf3b005 368 reg = tmp;
c609719b 369
16a53238 370 debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
26c7bab8 371
c609719b
WD
372 if (reg == 0xFFFF) {
373 /* No physical device present at this address */
16a53238 374 return -1;
c609719b
WD
375 }
376
16a53238
AF
377 if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
378 debug("PHY ID register 1 read failed\n");
379 return -1;
c609719b 380 }
8bf3b005 381 reg |= tmp << 16;
16a53238 382 debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
26c7bab8 383
298035df
LJ
384 *oui = (reg >> 10);
385 *model = (unsigned char)((reg >> 4) & 0x0000003F);
386 *rev = (unsigned char)(reg & 0x0000000F);
16a53238 387 return 0;
c609719b
WD
388}
389
5f184715 390#ifndef CONFIG_PHYLIB
c609719b
WD
391/*****************************************************************************
392 *
393 * Reset the PHY.
394 * Returns:
395 * 0 on success
396 */
5700bb63 397int miiphy_reset(const char *devname, unsigned char addr)
c609719b
WD
398{
399 unsigned short reg;
ab5a0dcb 400 int timeout = 500;
c609719b 401
16a53238
AF
402 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
403 debug("PHY status read failed\n");
404 return -1;
f89920c3 405 }
16a53238
AF
406 if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
407 debug("PHY reset failed\n");
408 return -1;
c609719b 409 }
5653fc33 410#ifdef CONFIG_PHY_RESET_DELAY
16a53238 411 udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
5653fc33 412#endif
c609719b
WD
413 /*
414 * Poll the control register for the reset bit to go to 0 (it is
415 * auto-clearing). This should happen within 0.5 seconds per the
416 * IEEE spec.
417 */
c609719b 418 reg = 0x8000;
ab5a0dcb 419 while (((reg & 0x8000) != 0) && timeout--) {
8ef583a0 420 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
ab5a0dcb
SR
421 debug("PHY status read failed\n");
422 return -1;
c609719b 423 }
ab5a0dcb 424 udelay(1000);
c609719b
WD
425 }
426 if ((reg & 0x8000) == 0) {
16a53238 427 return 0;
c609719b 428 } else {
16a53238
AF
429 puts("PHY reset timed out\n");
430 return -1;
c609719b 431 }
16a53238 432 return 0;
c609719b 433}
5f184715 434#endif /* !PHYLIB */
c609719b 435
c609719b
WD
436/*****************************************************************************
437 *
71bc6e64 438 * Determine the ethernet speed (10/100/1000). Return 10 on error.
c609719b 439 */
5700bb63 440int miiphy_speed(const char *devname, unsigned char addr)
c609719b 441{
71bc6e64 442 u16 bmcr, anlpar;
c609719b 443
6fb6af6d 444#if defined(CONFIG_PHY_GIGE)
71bc6e64
LJ
445 u16 btsr;
446
447 /*
448 * Check for 1000BASE-X. If it is supported, then assume that the speed
449 * is 1000.
450 */
16a53238 451 if (miiphy_is_1000base_x(devname, addr))
71bc6e64 452 return _1000BASET;
16a53238 453
71bc6e64
LJ
454 /*
455 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
456 */
457 /* Check for 1000BASE-T. */
16a53238
AF
458 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
459 printf("PHY 1000BT status");
71bc6e64
LJ
460 goto miiphy_read_failed;
461 }
462 if (btsr != 0xFFFF &&
16a53238 463 (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
71bc6e64 464 return _1000BASET;
6fb6af6d 465#endif /* CONFIG_PHY_GIGE */
855a496f 466
a56bd922 467 /* Check Basic Management Control Register first. */
16a53238
AF
468 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
469 printf("PHY speed");
71bc6e64 470 goto miiphy_read_failed;
c609719b 471 }
a56bd922 472 /* Check if auto-negotiation is on. */
8ef583a0 473 if (bmcr & BMCR_ANENABLE) {
a56bd922 474 /* Get auto-negotiation results. */
16a53238
AF
475 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
476 printf("PHY AN speed");
71bc6e64 477 goto miiphy_read_failed;
a56bd922 478 }
8ef583a0 479 return (anlpar & LPA_100) ? _100BASET : _10BASET;
a56bd922
WD
480 }
481 /* Get speed from basic control settings. */
8ef583a0 482 return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
a56bd922 483
5f841959 484miiphy_read_failed:
16a53238 485 printf(" read failed, assuming 10BASE-T\n");
71bc6e64 486 return _10BASET;
c609719b
WD
487}
488
c609719b
WD
489/*****************************************************************************
490 *
71bc6e64 491 * Determine full/half duplex. Return half on error.
c609719b 492 */
5700bb63 493int miiphy_duplex(const char *devname, unsigned char addr)
c609719b 494{
71bc6e64 495 u16 bmcr, anlpar;
c609719b 496
6fb6af6d 497#if defined(CONFIG_PHY_GIGE)
71bc6e64
LJ
498 u16 btsr;
499
500 /* Check for 1000BASE-X. */
16a53238 501 if (miiphy_is_1000base_x(devname, addr)) {
71bc6e64 502 /* 1000BASE-X */
16a53238
AF
503 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
504 printf("1000BASE-X PHY AN duplex");
71bc6e64
LJ
505 goto miiphy_read_failed;
506 }
507 }
508 /*
509 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
510 */
511 /* Check for 1000BASE-T. */
16a53238
AF
512 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
513 printf("PHY 1000BT status");
71bc6e64
LJ
514 goto miiphy_read_failed;
515 }
516 if (btsr != 0xFFFF) {
517 if (btsr & PHY_1000BTSR_1000FD) {
518 return FULL;
519 } else if (btsr & PHY_1000BTSR_1000HD) {
520 return HALF;
855a496f
WD
521 }
522 }
6fb6af6d 523#endif /* CONFIG_PHY_GIGE */
855a496f 524
a56bd922 525 /* Check Basic Management Control Register first. */
16a53238
AF
526 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
527 puts("PHY duplex");
71bc6e64 528 goto miiphy_read_failed;
c609719b 529 }
a56bd922 530 /* Check if auto-negotiation is on. */
8ef583a0 531 if (bmcr & BMCR_ANENABLE) {
a56bd922 532 /* Get auto-negotiation results. */
16a53238
AF
533 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
534 puts("PHY AN duplex");
71bc6e64 535 goto miiphy_read_failed;
a56bd922 536 }
8ef583a0 537 return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
71bc6e64 538 FULL : HALF;
a56bd922
WD
539 }
540 /* Get speed from basic control settings. */
8ef583a0 541 return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
71bc6e64 542
5f841959 543miiphy_read_failed:
16a53238 544 printf(" read failed, assuming half duplex\n");
71bc6e64
LJ
545 return HALF;
546}
a56bd922 547
71bc6e64
LJ
548/*****************************************************************************
549 *
550 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
551 * 1000BASE-T, or on error.
552 */
5700bb63 553int miiphy_is_1000base_x(const char *devname, unsigned char addr)
71bc6e64
LJ
554{
555#if defined(CONFIG_PHY_GIGE)
556 u16 exsr;
557
16a53238
AF
558 if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
559 printf("PHY extended status read failed, assuming no "
71bc6e64
LJ
560 "1000BASE-X\n");
561 return 0;
562 }
8ef583a0 563 return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
71bc6e64
LJ
564#else
565 return 0;
566#endif
c609719b
WD
567}
568
6d0f6bcf 569#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
fc3e2165
WD
570/*****************************************************************************
571 *
572 * Determine link status
573 */
5700bb63 574int miiphy_link(const char *devname, unsigned char addr)
fc3e2165
WD
575{
576 unsigned short reg;
577
a3d991bd 578 /* dummy read; needed to latch some phys */
16a53238
AF
579 (void)miiphy_read(devname, addr, MII_BMSR, &reg);
580 if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
581 puts("MII_BMSR read failed, assuming no link\n");
582 return 0;
fc3e2165
WD
583 }
584
585 /* Determine if a link is active */
8ef583a0 586 if ((reg & BMSR_LSTATUS) != 0) {
16a53238 587 return 1;
fc3e2165 588 } else {
16a53238 589 return 0;
fc3e2165
WD
590 }
591}
592#endif