blob: bcab74e73a9d769d9631310aea0791a834d447bc [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
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>
Andy Fleming5f184712011-04-08 02:10:27 -050031#include <phy.h>
wdenkc6097192002-11-03 00:24:07 +000032
Marian Balakowicz63ff0042005-10-28 22:30:33 +020033#include <asm/types.h>
34#include <linux/list.h>
35#include <malloc.h>
36#include <net.h>
37
38/* local debug macro */
Marian Balakowicz63ff0042005-10-28 22:30:33 +020039#undef MII_DEBUG
40
41#undef debug
42#ifdef MII_DEBUG
Andy Fleming16a53232011-04-07 14:38:35 -050043#define debug(fmt, args...) printf(fmt, ##args)
Marian Balakowicz63ff0042005-10-28 22:30:33 +020044#else
Andy Fleming16a53232011-04-07 14:38:35 -050045#define debug(fmt, args...)
Marian Balakowicz63ff0042005-10-28 22:30:33 +020046#endif /* MII_DEBUG */
47
Marian Balakowicz63ff0042005-10-28 22:30:33 +020048static struct list_head mii_devs;
49static struct mii_dev *current_mii;
50
Mike Frysinger0daac972010-07-27 18:35:09 -040051/*
52 * Lookup the mii_dev struct by the registered device name.
53 */
Andy Fleming5f184712011-04-08 02:10:27 -050054struct mii_dev *miiphy_get_dev_by_name(const char *devname)
Mike Frysinger0daac972010-07-27 18:35:09 -040055{
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
Mike Frysinger0daac972010-07-27 18:35:09 -040070 return NULL;
71}
72
Marian Balakowicz63ff0042005-10-28 22:30:33 +020073/*****************************************************************************
74 *
Marian Balakowiczd9785c12005-11-30 18:06:04 +010075 * Initialize global data. Need to be called before any other miiphy routine.
76 */
Mike Frysinger5700bb62010-07-27 18:35:08 -040077void miiphy_init(void)
Marian Balakowiczd9785c12005-11-30 18:06:04 +010078{
Andy Fleming16a53232011-04-07 14:38:35 -050079 INIT_LIST_HEAD(&mii_devs);
Larry Johnson298035d2007-10-31 11:21:29 -050080 current_mii = NULL;
Marian Balakowiczd9785c12005-11-30 18:06:04 +010081}
82
Andy Fleming5f184712011-04-08 02:10:27 -050083static 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
Marian Balakowiczd9785c12005-11-30 18:06:04 +0100102/*****************************************************************************
103 *
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200104 * Register read and write MII access routines for the device <name>.
105 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400106void miiphy_register(const char *name,
Andy Fleming16a53232011-04-07 14:38:35 -0500107 int (*read)(const char *devname, unsigned char addr,
Larry Johnson298035d2007-10-31 11:21:29 -0500108 unsigned char reg, unsigned short *value),
Andy Fleming16a53232011-04-07 14:38:35 -0500109 int (*write)(const char *devname, unsigned char addr,
Larry Johnson298035d2007-10-31 11:21:29 -0500110 unsigned char reg, unsigned short value))
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200111{
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200112 struct mii_dev *new_dev;
Andy Fleming5f184712011-04-08 02:10:27 -0500113 struct legacy_mii_dev *ldev;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200114 unsigned int name_len;
115
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200116 /* check if we have unique name */
Andy Fleming5f184712011-04-08 02:10:27 -0500117 new_dev = miiphy_get_dev_by_name(name);
Mike Frysinger0daac972010-07-27 18:35:09 -0400118 if (new_dev) {
119 printf("miiphy_register: non unique device name '%s'\n", name);
120 return;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200121 }
122
123 /* allocate memory */
Andy Fleming16a53232011-04-07 14:38:35 -0500124 name_len = strlen(name);
Andy Fleming5f184712011-04-08 02:10:27 -0500125 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 }
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200131
Andy Fleming5f184712011-04-08 02:10:27 -0500132 new_dev = mdio_alloc();
133 ldev = malloc(sizeof(*ldev));
134
135 if (new_dev == NULL || ldev == NULL) {
Andy Fleming16a53232011-04-07 14:38:35 -0500136 printf("miiphy_register: cannot allocate memory for '%s'\n",
Larry Johnson298035d2007-10-31 11:21:29 -0500137 name);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200138 return;
139 }
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200140
141 /* initalize mii_dev struct fields */
Andy Fleming5f184712011-04-08 02:10:27 -0500142 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;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200148
Andy Fleming16a53232011-04-07 14:38:35 -0500149 debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
Andy Fleming5f184712011-04-08 02:10:27 -0500150 new_dev->name, ldev->read, ldev->write);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200151
152 /* add it to the list */
Andy Fleming16a53232011-04-07 14:38:35 -0500153 list_add_tail(&new_dev->link, &mii_devs);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200154
155 if (!current_mii)
156 current_mii = new_dev;
157}
158
Andy Fleming5f184712011-04-08 02:10:27 -0500159struct 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
Mike Frysinger5700bb62010-07-27 18:35:08 -0400221int miiphy_set_current_dev(const char *devname)
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200222{
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200223 struct mii_dev *dev;
224
Andy Fleming5f184712011-04-08 02:10:27 -0500225 dev = miiphy_get_dev_by_name(devname);
Mike Frysinger0daac972010-07-27 18:35:09 -0400226 if (dev) {
227 current_mii = dev;
228 return 0;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200229 }
230
Andy Fleming5f184712011-04-08 02:10:27 -0500231 printf("No such device: %s\n", devname);
232
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200233 return 1;
234}
235
Andy Fleming5f184712011-04-08 02:10:27 -0500236struct 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
Mike Frysinger5700bb62010-07-27 18:35:08 -0400263const char *miiphy_get_current_dev(void)
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200264{
265 if (current_mii)
266 return current_mii->name;
267
268 return NULL;
269}
270
Mike Frysingerede16ea2010-07-27 18:35:10 -0400271static 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
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200285/*****************************************************************************
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 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400293int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
Larry Johnson298035d2007-10-31 11:21:29 -0500294 unsigned short *value)
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200295{
Andy Fleming5f184712011-04-08 02:10:27 -0500296 struct mii_dev *bus;
Anatolij Gustschind67d5d52011-04-30 02:17:44 +0000297 int ret;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200298
Andy Fleming5f184712011-04-08 02:10:27 -0500299 bus = miiphy_get_active_dev(devname);
Anatolij Gustschind67d5d52011-04-30 02:17:44 +0000300 if (!bus)
Andy Fleming5f184712011-04-08 02:10:27 -0500301 return 1;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200302
Anatolij Gustschind67d5d52011-04-30 02:17:44 +0000303 ret = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
304 if (ret < 0)
305 return 1;
306
307 *value = (unsigned short)ret;
308 return 0;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200309}
310
311/*****************************************************************************
312 *
313 * Write <value> to the PHY attached to device <devname>,
314 * use PHY address <addr> and register <reg>.
315 *
316 * Returns:
317 * 0 on success
318 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400319int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
Larry Johnson298035d2007-10-31 11:21:29 -0500320 unsigned short value)
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200321{
Andy Fleming5f184712011-04-08 02:10:27 -0500322 struct mii_dev *bus;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200323
Andy Fleming5f184712011-04-08 02:10:27 -0500324 bus = miiphy_get_active_dev(devname);
325 if (bus)
326 return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200327
Mike Frysinger0daac972010-07-27 18:35:09 -0400328 return 1;
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200329}
330
331/*****************************************************************************
332 *
333 * Print out list of registered MII capable devices.
334 */
Andy Fleming16a53232011-04-07 14:38:35 -0500335void miiphy_listdev(void)
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200336{
337 struct list_head *entry;
338 struct mii_dev *dev;
339
Andy Fleming16a53232011-04-07 14:38:35 -0500340 puts("MII devices: ");
341 list_for_each(entry, &mii_devs) {
342 dev = list_entry(entry, struct mii_dev, link);
343 printf("'%s' ", dev->name);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200344 }
Andy Fleming16a53232011-04-07 14:38:35 -0500345 puts("\n");
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200346
347 if (current_mii)
Andy Fleming16a53232011-04-07 14:38:35 -0500348 printf("Current device: '%s'\n", current_mii->name);
Marian Balakowicz63ff0042005-10-28 22:30:33 +0200349}
350
wdenkc6097192002-11-03 00:24:07 +0000351/*****************************************************************************
352 *
353 * Read the OUI, manufacture's model number, and revision number.
354 *
355 * OUI: 22 bits (unsigned int)
356 * Model: 6 bits (unsigned char)
357 * Revision: 4 bits (unsigned char)
358 *
359 * Returns:
360 * 0 on success
361 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400362int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
wdenkc6097192002-11-03 00:24:07 +0000363 unsigned char *model, unsigned char *rev)
364{
365 unsigned int reg = 0;
wdenk8bf3b002003-12-06 23:20:41 +0000366 unsigned short tmp;
wdenkc6097192002-11-03 00:24:07 +0000367
Andy Fleming16a53232011-04-07 14:38:35 -0500368 if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
369 debug("PHY ID register 2 read failed\n");
370 return -1;
wdenkc6097192002-11-03 00:24:07 +0000371 }
wdenk8bf3b002003-12-06 23:20:41 +0000372 reg = tmp;
wdenkc6097192002-11-03 00:24:07 +0000373
Andy Fleming16a53232011-04-07 14:38:35 -0500374 debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
Shinya Kuribayashi26c7bab2008-01-19 10:25:59 +0900375
wdenkc6097192002-11-03 00:24:07 +0000376 if (reg == 0xFFFF) {
377 /* No physical device present at this address */
Andy Fleming16a53232011-04-07 14:38:35 -0500378 return -1;
wdenkc6097192002-11-03 00:24:07 +0000379 }
380
Andy Fleming16a53232011-04-07 14:38:35 -0500381 if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
382 debug("PHY ID register 1 read failed\n");
383 return -1;
wdenkc6097192002-11-03 00:24:07 +0000384 }
wdenk8bf3b002003-12-06 23:20:41 +0000385 reg |= tmp << 16;
Andy Fleming16a53232011-04-07 14:38:35 -0500386 debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
Shinya Kuribayashi26c7bab2008-01-19 10:25:59 +0900387
Larry Johnson298035d2007-10-31 11:21:29 -0500388 *oui = (reg >> 10);
389 *model = (unsigned char)((reg >> 4) & 0x0000003F);
390 *rev = (unsigned char)(reg & 0x0000000F);
Andy Fleming16a53232011-04-07 14:38:35 -0500391 return 0;
wdenkc6097192002-11-03 00:24:07 +0000392}
393
Andy Fleming5f184712011-04-08 02:10:27 -0500394#ifndef CONFIG_PHYLIB
wdenkc6097192002-11-03 00:24:07 +0000395/*****************************************************************************
396 *
397 * Reset the PHY.
398 * Returns:
399 * 0 on success
400 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400401int miiphy_reset(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000402{
403 unsigned short reg;
Stefan Roeseab5a0dc2010-02-02 13:43:48 +0100404 int timeout = 500;
wdenkc6097192002-11-03 00:24:07 +0000405
Andy Fleming16a53232011-04-07 14:38:35 -0500406 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
407 debug("PHY status read failed\n");
408 return -1;
Wolfgang Denkf89920c2005-08-12 23:15:53 +0200409 }
Andy Fleming16a53232011-04-07 14:38:35 -0500410 if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
411 debug("PHY reset failed\n");
412 return -1;
wdenkc6097192002-11-03 00:24:07 +0000413 }
wdenk5653fc32004-02-08 22:55:38 +0000414#ifdef CONFIG_PHY_RESET_DELAY
Andy Fleming16a53232011-04-07 14:38:35 -0500415 udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
wdenk5653fc32004-02-08 22:55:38 +0000416#endif
wdenkc6097192002-11-03 00:24:07 +0000417 /*
418 * Poll the control register for the reset bit to go to 0 (it is
419 * auto-clearing). This should happen within 0.5 seconds per the
420 * IEEE spec.
421 */
wdenkc6097192002-11-03 00:24:07 +0000422 reg = 0x8000;
Stefan Roeseab5a0dc2010-02-02 13:43:48 +0100423 while (((reg & 0x8000) != 0) && timeout--) {
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500424 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
Stefan Roeseab5a0dc2010-02-02 13:43:48 +0100425 debug("PHY status read failed\n");
426 return -1;
wdenkc6097192002-11-03 00:24:07 +0000427 }
Stefan Roeseab5a0dc2010-02-02 13:43:48 +0100428 udelay(1000);
wdenkc6097192002-11-03 00:24:07 +0000429 }
430 if ((reg & 0x8000) == 0) {
Andy Fleming16a53232011-04-07 14:38:35 -0500431 return 0;
wdenkc6097192002-11-03 00:24:07 +0000432 } else {
Andy Fleming16a53232011-04-07 14:38:35 -0500433 puts("PHY reset timed out\n");
434 return -1;
wdenkc6097192002-11-03 00:24:07 +0000435 }
Andy Fleming16a53232011-04-07 14:38:35 -0500436 return 0;
wdenkc6097192002-11-03 00:24:07 +0000437}
Andy Fleming5f184712011-04-08 02:10:27 -0500438#endif /* !PHYLIB */
wdenkc6097192002-11-03 00:24:07 +0000439
wdenkc6097192002-11-03 00:24:07 +0000440/*****************************************************************************
441 *
Larry Johnson71bc6e62007-11-01 08:46:50 -0500442 * Determine the ethernet speed (10/100/1000). Return 10 on error.
wdenkc6097192002-11-03 00:24:07 +0000443 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400444int miiphy_speed(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000445{
Larry Johnson71bc6e62007-11-01 08:46:50 -0500446 u16 bmcr, anlpar;
wdenkc6097192002-11-03 00:24:07 +0000447
wdenk6fb6af62004-03-23 23:20:24 +0000448#if defined(CONFIG_PHY_GIGE)
Larry Johnson71bc6e62007-11-01 08:46:50 -0500449 u16 btsr;
450
451 /*
452 * Check for 1000BASE-X. If it is supported, then assume that the speed
453 * is 1000.
454 */
Andy Fleming16a53232011-04-07 14:38:35 -0500455 if (miiphy_is_1000base_x(devname, addr))
Larry Johnson71bc6e62007-11-01 08:46:50 -0500456 return _1000BASET;
Andy Fleming16a53232011-04-07 14:38:35 -0500457
Larry Johnson71bc6e62007-11-01 08:46:50 -0500458 /*
459 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
460 */
461 /* Check for 1000BASE-T. */
Andy Fleming16a53232011-04-07 14:38:35 -0500462 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
463 printf("PHY 1000BT status");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500464 goto miiphy_read_failed;
465 }
466 if (btsr != 0xFFFF &&
Andy Fleming16a53232011-04-07 14:38:35 -0500467 (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
Larry Johnson71bc6e62007-11-01 08:46:50 -0500468 return _1000BASET;
wdenk6fb6af62004-03-23 23:20:24 +0000469#endif /* CONFIG_PHY_GIGE */
wdenk855a4962004-03-14 18:23:55 +0000470
wdenka56bd922004-06-06 23:13:55 +0000471 /* Check Basic Management Control Register first. */
Andy Fleming16a53232011-04-07 14:38:35 -0500472 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
473 printf("PHY speed");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500474 goto miiphy_read_failed;
wdenkc6097192002-11-03 00:24:07 +0000475 }
wdenka56bd922004-06-06 23:13:55 +0000476 /* Check if auto-negotiation is on. */
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500477 if (bmcr & BMCR_ANENABLE) {
wdenka56bd922004-06-06 23:13:55 +0000478 /* Get auto-negotiation results. */
Andy Fleming16a53232011-04-07 14:38:35 -0500479 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
480 printf("PHY AN speed");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500481 goto miiphy_read_failed;
wdenka56bd922004-06-06 23:13:55 +0000482 }
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500483 return (anlpar & LPA_100) ? _100BASET : _10BASET;
wdenka56bd922004-06-06 23:13:55 +0000484 }
485 /* Get speed from basic control settings. */
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500486 return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
wdenka56bd922004-06-06 23:13:55 +0000487
Michael Zaidman5f841952010-02-28 16:28:25 +0200488miiphy_read_failed:
Andy Fleming16a53232011-04-07 14:38:35 -0500489 printf(" read failed, assuming 10BASE-T\n");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500490 return _10BASET;
wdenkc6097192002-11-03 00:24:07 +0000491}
492
wdenkc6097192002-11-03 00:24:07 +0000493/*****************************************************************************
494 *
Larry Johnson71bc6e62007-11-01 08:46:50 -0500495 * Determine full/half duplex. Return half on error.
wdenkc6097192002-11-03 00:24:07 +0000496 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400497int miiphy_duplex(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000498{
Larry Johnson71bc6e62007-11-01 08:46:50 -0500499 u16 bmcr, anlpar;
wdenkc6097192002-11-03 00:24:07 +0000500
wdenk6fb6af62004-03-23 23:20:24 +0000501#if defined(CONFIG_PHY_GIGE)
Larry Johnson71bc6e62007-11-01 08:46:50 -0500502 u16 btsr;
503
504 /* Check for 1000BASE-X. */
Andy Fleming16a53232011-04-07 14:38:35 -0500505 if (miiphy_is_1000base_x(devname, addr)) {
Larry Johnson71bc6e62007-11-01 08:46:50 -0500506 /* 1000BASE-X */
Andy Fleming16a53232011-04-07 14:38:35 -0500507 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
508 printf("1000BASE-X PHY AN duplex");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500509 goto miiphy_read_failed;
510 }
511 }
512 /*
513 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
514 */
515 /* Check for 1000BASE-T. */
Andy Fleming16a53232011-04-07 14:38:35 -0500516 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
517 printf("PHY 1000BT status");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500518 goto miiphy_read_failed;
519 }
520 if (btsr != 0xFFFF) {
521 if (btsr & PHY_1000BTSR_1000FD) {
522 return FULL;
523 } else if (btsr & PHY_1000BTSR_1000HD) {
524 return HALF;
wdenk855a4962004-03-14 18:23:55 +0000525 }
526 }
wdenk6fb6af62004-03-23 23:20:24 +0000527#endif /* CONFIG_PHY_GIGE */
wdenk855a4962004-03-14 18:23:55 +0000528
wdenka56bd922004-06-06 23:13:55 +0000529 /* Check Basic Management Control Register first. */
Andy Fleming16a53232011-04-07 14:38:35 -0500530 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
531 puts("PHY duplex");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500532 goto miiphy_read_failed;
wdenkc6097192002-11-03 00:24:07 +0000533 }
wdenka56bd922004-06-06 23:13:55 +0000534 /* Check if auto-negotiation is on. */
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500535 if (bmcr & BMCR_ANENABLE) {
wdenka56bd922004-06-06 23:13:55 +0000536 /* Get auto-negotiation results. */
Andy Fleming16a53232011-04-07 14:38:35 -0500537 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
538 puts("PHY AN duplex");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500539 goto miiphy_read_failed;
wdenka56bd922004-06-06 23:13:55 +0000540 }
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500541 return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
Larry Johnson71bc6e62007-11-01 08:46:50 -0500542 FULL : HALF;
wdenka56bd922004-06-06 23:13:55 +0000543 }
544 /* Get speed from basic control settings. */
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500545 return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
wdenka56bd922004-06-06 23:13:55 +0000546
Michael Zaidman5f841952010-02-28 16:28:25 +0200547miiphy_read_failed:
Andy Fleming16a53232011-04-07 14:38:35 -0500548 printf(" read failed, assuming half duplex\n");
Larry Johnson71bc6e62007-11-01 08:46:50 -0500549 return HALF;
550}
551
552/*****************************************************************************
553 *
554 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
555 * 1000BASE-T, or on error.
556 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400557int miiphy_is_1000base_x(const char *devname, unsigned char addr)
Larry Johnson71bc6e62007-11-01 08:46:50 -0500558{
559#if defined(CONFIG_PHY_GIGE)
560 u16 exsr;
561
Andy Fleming16a53232011-04-07 14:38:35 -0500562 if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
563 printf("PHY extended status read failed, assuming no "
Larry Johnson71bc6e62007-11-01 08:46:50 -0500564 "1000BASE-X\n");
565 return 0;
566 }
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500567 return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
Larry Johnson71bc6e62007-11-01 08:46:50 -0500568#else
569 return 0;
570#endif
wdenkc6097192002-11-03 00:24:07 +0000571}
572
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200573#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
wdenkfc3e2162003-10-08 22:33:00 +0000574/*****************************************************************************
575 *
576 * Determine link status
577 */
Mike Frysinger5700bb62010-07-27 18:35:08 -0400578int miiphy_link(const char *devname, unsigned char addr)
wdenkfc3e2162003-10-08 22:33:00 +0000579{
580 unsigned short reg;
581
wdenka3d991b2004-04-15 21:48:45 +0000582 /* dummy read; needed to latch some phys */
Andy Fleming16a53232011-04-07 14:38:35 -0500583 (void)miiphy_read(devname, addr, MII_BMSR, &reg);
584 if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
585 puts("MII_BMSR read failed, assuming no link\n");
586 return 0;
wdenkfc3e2162003-10-08 22:33:00 +0000587 }
588
589 /* Determine if a link is active */
Mike Frysinger8ef583a2010-12-23 15:40:12 -0500590 if ((reg & BMSR_LSTATUS) != 0) {
Andy Fleming16a53232011-04-07 14:38:35 -0500591 return 1;
wdenkfc3e2162003-10-08 22:33:00 +0000592 } else {
Andy Fleming16a53232011-04-07 14:38:35 -0500593 return 0;
wdenkfc3e2162003-10-08 22:33:00 +0000594 }
595}
596#endif