blob: 243cae97a468111c68b3b155541b73a13e00877d [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 Flemingaecf6fc2011-04-08 02:10:27 -050031#include <phy.h>
wdenkc6097192002-11-03 00:24:07 +000032
Marian Balakowiczaab8c492005-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 Balakowiczaab8c492005-10-28 22:30:33 +020039#undef MII_DEBUG
40
41#undef debug
42#ifdef MII_DEBUG
Andy Flemingaea0c3e2011-04-07 14:38:35 -050043#define debug(fmt, args...) printf(fmt, ##args)
Marian Balakowiczaab8c492005-10-28 22:30:33 +020044#else
Andy Flemingaea0c3e2011-04-07 14:38:35 -050045#define debug(fmt, args...)
Marian Balakowiczaab8c492005-10-28 22:30:33 +020046#endif /* MII_DEBUG */
47
Marian Balakowiczaab8c492005-10-28 22:30:33 +020048static struct list_head mii_devs;
49static struct mii_dev *current_mii;
50
Mike Frysinger24a90082010-07-27 18:35:09 -040051/*
52 * Lookup the mii_dev struct by the registered device name.
53 */
Andy Flemingaecf6fc2011-04-08 02:10:27 -050054struct mii_dev *miiphy_get_dev_by_name(const char *devname)
Mike Frysinger24a90082010-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 Frysinger24a90082010-07-27 18:35:09 -040070 return NULL;
71}
72
Marian Balakowiczaab8c492005-10-28 22:30:33 +020073/*****************************************************************************
74 *
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +010075 * Initialize global data. Need to be called before any other miiphy routine.
76 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -040077void miiphy_init(void)
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +010078{
Andy Flemingaea0c3e2011-04-07 14:38:35 -050079 INIT_LIST_HEAD(&mii_devs);
Larry Johnson81b974b2007-10-31 11:21:29 -050080 current_mii = NULL;
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +010081}
82
Andy Flemingaecf6fc2011-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 Balakowiczcbdd1c82005-11-30 18:06:04 +0100102/*****************************************************************************
103 *
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200104 * Register read and write MII access routines for the device <name>.
105 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400106void miiphy_register(const char *name,
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500107 int (*read)(const char *devname, unsigned char addr,
Larry Johnson81b974b2007-10-31 11:21:29 -0500108 unsigned char reg, unsigned short *value),
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500109 int (*write)(const char *devname, unsigned char addr,
Larry Johnson81b974b2007-10-31 11:21:29 -0500110 unsigned char reg, unsigned short value))
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200111{
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200112 struct mii_dev *new_dev;
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500113 struct legacy_mii_dev *ldev;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200114 unsigned int name_len;
115
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200116 /* check if we have unique name */
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500117 new_dev = miiphy_get_dev_by_name(name);
Mike Frysinger24a90082010-07-27 18:35:09 -0400118 if (new_dev) {
119 printf("miiphy_register: non unique device name '%s'\n", name);
120 return;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200121 }
122
123 /* allocate memory */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500124 name_len = strlen(name);
Andy Flemingaecf6fc2011-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 }
131
132 new_dev = mdio_alloc();
133 ldev = malloc(sizeof(*ldev));
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200134
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500135 if (new_dev == NULL || ldev == NULL) {
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500136 printf("miiphy_register: cannot allocate memory for '%s'\n",
Larry Johnson81b974b2007-10-31 11:21:29 -0500137 name);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200138 return;
139 }
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200140
141 /* initalize mii_dev struct fields */
Andy Flemingaecf6fc2011-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 Balakowiczaab8c492005-10-28 22:30:33 +0200148
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500149 debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500150 new_dev->name, ldev->read, ldev->write);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200151
152 /* add it to the list */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500153 list_add_tail(&new_dev->link, &mii_devs);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200154
155 if (!current_mii)
156 current_mii = new_dev;
157}
158
Andy Flemingaecf6fc2011-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 Frysinger5ff5fdb2010-07-27 18:35:08 -0400221int miiphy_set_current_dev(const char *devname)
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200222{
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200223 struct mii_dev *dev;
224
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500225 dev = miiphy_get_dev_by_name(devname);
Mike Frysinger24a90082010-07-27 18:35:09 -0400226 if (dev) {
227 current_mii = dev;
228 return 0;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200229 }
230
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500231 printf("No such device: %s\n", devname);
232
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200233 return 1;
234}
235
Andy Flemingaecf6fc2011-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 Frysinger5ff5fdb2010-07-27 18:35:08 -0400263const char *miiphy_get_current_dev(void)
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200264{
265 if (current_mii)
266 return current_mii->name;
267
268 return NULL;
269}
270
Mike Frysingerbd17e7a2010-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 Balakowiczaab8c492005-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 Frysinger5ff5fdb2010-07-27 18:35:08 -0400293int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
Larry Johnson81b974b2007-10-31 11:21:29 -0500294 unsigned short *value)
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200295{
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500296 struct mii_dev *bus;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200297
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500298 bus = miiphy_get_active_dev(devname);
299 if (bus)
300 *value = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
301 else
302 return 1;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200303
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500304 return (*value < 0) ? 1 : 0;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200305}
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 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400315int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
Larry Johnson81b974b2007-10-31 11:21:29 -0500316 unsigned short value)
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200317{
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500318 struct mii_dev *bus;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200319
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500320 bus = miiphy_get_active_dev(devname);
321 if (bus)
322 return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200323
Mike Frysinger24a90082010-07-27 18:35:09 -0400324 return 1;
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200325}
326
327/*****************************************************************************
328 *
329 * Print out list of registered MII capable devices.
330 */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500331void miiphy_listdev(void)
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200332{
333 struct list_head *entry;
334 struct mii_dev *dev;
335
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500336 puts("MII devices: ");
337 list_for_each(entry, &mii_devs) {
338 dev = list_entry(entry, struct mii_dev, link);
339 printf("'%s' ", dev->name);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200340 }
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500341 puts("\n");
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200342
343 if (current_mii)
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500344 printf("Current device: '%s'\n", current_mii->name);
Marian Balakowiczaab8c492005-10-28 22:30:33 +0200345}
346
wdenkc6097192002-11-03 00:24:07 +0000347/*****************************************************************************
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 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400358int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
wdenkc6097192002-11-03 00:24:07 +0000359 unsigned char *model, unsigned char *rev)
360{
361 unsigned int reg = 0;
wdenkf4cec3f2003-12-06 23:20:41 +0000362 unsigned short tmp;
wdenkc6097192002-11-03 00:24:07 +0000363
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500364 if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
365 debug("PHY ID register 2 read failed\n");
366 return -1;
wdenkc6097192002-11-03 00:24:07 +0000367 }
wdenkf4cec3f2003-12-06 23:20:41 +0000368 reg = tmp;
wdenkc6097192002-11-03 00:24:07 +0000369
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500370 debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
Shinya Kuribayashi49e42af2008-01-19 10:25:59 +0900371
wdenkc6097192002-11-03 00:24:07 +0000372 if (reg == 0xFFFF) {
373 /* No physical device present at this address */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500374 return -1;
wdenkc6097192002-11-03 00:24:07 +0000375 }
376
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500377 if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
378 debug("PHY ID register 1 read failed\n");
379 return -1;
wdenkc6097192002-11-03 00:24:07 +0000380 }
wdenkf4cec3f2003-12-06 23:20:41 +0000381 reg |= tmp << 16;
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500382 debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
Shinya Kuribayashi49e42af2008-01-19 10:25:59 +0900383
Larry Johnson81b974b2007-10-31 11:21:29 -0500384 *oui = (reg >> 10);
385 *model = (unsigned char)((reg >> 4) & 0x0000003F);
386 *rev = (unsigned char)(reg & 0x0000000F);
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500387 return 0;
wdenkc6097192002-11-03 00:24:07 +0000388}
389
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500390#ifndef CONFIG_PHYLIB
wdenkc6097192002-11-03 00:24:07 +0000391/*****************************************************************************
392 *
393 * Reset the PHY.
394 * Returns:
395 * 0 on success
396 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400397int miiphy_reset(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000398{
399 unsigned short reg;
Stefan Roese2e536362010-02-02 13:43:48 +0100400 int timeout = 500;
wdenkc6097192002-11-03 00:24:07 +0000401
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500402 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
403 debug("PHY status read failed\n");
404 return -1;
Wolfgang Denk8ff63c22005-08-12 23:15:53 +0200405 }
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500406 if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
407 debug("PHY reset failed\n");
408 return -1;
wdenkc6097192002-11-03 00:24:07 +0000409 }
wdenk2cefd152004-02-08 22:55:38 +0000410#ifdef CONFIG_PHY_RESET_DELAY
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500411 udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
wdenk2cefd152004-02-08 22:55:38 +0000412#endif
wdenkc6097192002-11-03 00:24:07 +0000413 /*
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 */
wdenkc6097192002-11-03 00:24:07 +0000418 reg = 0x8000;
Stefan Roese2e536362010-02-02 13:43:48 +0100419 while (((reg & 0x8000) != 0) && timeout--) {
Mike Frysingerd63ee712010-12-23 15:40:12 -0500420 if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
Stefan Roese2e536362010-02-02 13:43:48 +0100421 debug("PHY status read failed\n");
422 return -1;
wdenkc6097192002-11-03 00:24:07 +0000423 }
Stefan Roese2e536362010-02-02 13:43:48 +0100424 udelay(1000);
wdenkc6097192002-11-03 00:24:07 +0000425 }
426 if ((reg & 0x8000) == 0) {
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500427 return 0;
wdenkc6097192002-11-03 00:24:07 +0000428 } else {
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500429 puts("PHY reset timed out\n");
430 return -1;
wdenkc6097192002-11-03 00:24:07 +0000431 }
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500432 return 0;
wdenkc6097192002-11-03 00:24:07 +0000433}
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500434#endif /* !PHYLIB */
wdenkc6097192002-11-03 00:24:07 +0000435
wdenkc6097192002-11-03 00:24:07 +0000436/*****************************************************************************
437 *
Larry Johnson966a80b2007-11-01 08:46:50 -0500438 * Determine the ethernet speed (10/100/1000). Return 10 on error.
wdenkc6097192002-11-03 00:24:07 +0000439 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400440int miiphy_speed(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000441{
Larry Johnson966a80b2007-11-01 08:46:50 -0500442 u16 bmcr, anlpar;
wdenkc6097192002-11-03 00:24:07 +0000443
wdenkeec9a3d2004-03-23 23:20:24 +0000444#if defined(CONFIG_PHY_GIGE)
Larry Johnson966a80b2007-11-01 08:46:50 -0500445 u16 btsr;
446
447 /*
448 * Check for 1000BASE-X. If it is supported, then assume that the speed
449 * is 1000.
450 */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500451 if (miiphy_is_1000base_x(devname, addr))
Larry Johnson966a80b2007-11-01 08:46:50 -0500452 return _1000BASET;
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500453
Larry Johnson966a80b2007-11-01 08:46:50 -0500454 /*
455 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
456 */
457 /* Check for 1000BASE-T. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500458 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
459 printf("PHY 1000BT status");
Larry Johnson966a80b2007-11-01 08:46:50 -0500460 goto miiphy_read_failed;
461 }
462 if (btsr != 0xFFFF &&
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500463 (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
Larry Johnson966a80b2007-11-01 08:46:50 -0500464 return _1000BASET;
wdenkeec9a3d2004-03-23 23:20:24 +0000465#endif /* CONFIG_PHY_GIGE */
wdenked2ac4b2004-03-14 18:23:55 +0000466
wdenke3a06802004-06-06 23:13:55 +0000467 /* Check Basic Management Control Register first. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500468 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
469 printf("PHY speed");
Larry Johnson966a80b2007-11-01 08:46:50 -0500470 goto miiphy_read_failed;
wdenkc6097192002-11-03 00:24:07 +0000471 }
wdenke3a06802004-06-06 23:13:55 +0000472 /* Check if auto-negotiation is on. */
Mike Frysingerd63ee712010-12-23 15:40:12 -0500473 if (bmcr & BMCR_ANENABLE) {
wdenke3a06802004-06-06 23:13:55 +0000474 /* Get auto-negotiation results. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500475 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
476 printf("PHY AN speed");
Larry Johnson966a80b2007-11-01 08:46:50 -0500477 goto miiphy_read_failed;
wdenke3a06802004-06-06 23:13:55 +0000478 }
Mike Frysingerd63ee712010-12-23 15:40:12 -0500479 return (anlpar & LPA_100) ? _100BASET : _10BASET;
wdenke3a06802004-06-06 23:13:55 +0000480 }
481 /* Get speed from basic control settings. */
Mike Frysingerd63ee712010-12-23 15:40:12 -0500482 return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
wdenke3a06802004-06-06 23:13:55 +0000483
Michael Zaidman6dbca5f2010-02-28 16:28:25 +0200484miiphy_read_failed:
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500485 printf(" read failed, assuming 10BASE-T\n");
Larry Johnson966a80b2007-11-01 08:46:50 -0500486 return _10BASET;
wdenkc6097192002-11-03 00:24:07 +0000487}
488
wdenkc6097192002-11-03 00:24:07 +0000489/*****************************************************************************
490 *
Larry Johnson966a80b2007-11-01 08:46:50 -0500491 * Determine full/half duplex. Return half on error.
wdenkc6097192002-11-03 00:24:07 +0000492 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400493int miiphy_duplex(const char *devname, unsigned char addr)
wdenkc6097192002-11-03 00:24:07 +0000494{
Larry Johnson966a80b2007-11-01 08:46:50 -0500495 u16 bmcr, anlpar;
wdenkc6097192002-11-03 00:24:07 +0000496
wdenkeec9a3d2004-03-23 23:20:24 +0000497#if defined(CONFIG_PHY_GIGE)
Larry Johnson966a80b2007-11-01 08:46:50 -0500498 u16 btsr;
499
500 /* Check for 1000BASE-X. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500501 if (miiphy_is_1000base_x(devname, addr)) {
Larry Johnson966a80b2007-11-01 08:46:50 -0500502 /* 1000BASE-X */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500503 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
504 printf("1000BASE-X PHY AN duplex");
Larry Johnson966a80b2007-11-01 08:46:50 -0500505 goto miiphy_read_failed;
wdenked2ac4b2004-03-14 18:23:55 +0000506 }
507 }
Larry Johnson966a80b2007-11-01 08:46:50 -0500508 /*
509 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
510 */
511 /* Check for 1000BASE-T. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500512 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
513 printf("PHY 1000BT status");
Larry Johnson966a80b2007-11-01 08:46:50 -0500514 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;
521 }
522 }
wdenkeec9a3d2004-03-23 23:20:24 +0000523#endif /* CONFIG_PHY_GIGE */
wdenked2ac4b2004-03-14 18:23:55 +0000524
wdenke3a06802004-06-06 23:13:55 +0000525 /* Check Basic Management Control Register first. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500526 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
527 puts("PHY duplex");
Larry Johnson966a80b2007-11-01 08:46:50 -0500528 goto miiphy_read_failed;
wdenkc6097192002-11-03 00:24:07 +0000529 }
wdenke3a06802004-06-06 23:13:55 +0000530 /* Check if auto-negotiation is on. */
Mike Frysingerd63ee712010-12-23 15:40:12 -0500531 if (bmcr & BMCR_ANENABLE) {
wdenke3a06802004-06-06 23:13:55 +0000532 /* Get auto-negotiation results. */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500533 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
534 puts("PHY AN duplex");
Larry Johnson966a80b2007-11-01 08:46:50 -0500535 goto miiphy_read_failed;
wdenke3a06802004-06-06 23:13:55 +0000536 }
Mike Frysingerd63ee712010-12-23 15:40:12 -0500537 return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
Larry Johnson966a80b2007-11-01 08:46:50 -0500538 FULL : HALF;
wdenke3a06802004-06-06 23:13:55 +0000539 }
540 /* Get speed from basic control settings. */
Mike Frysingerd63ee712010-12-23 15:40:12 -0500541 return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
Larry Johnson966a80b2007-11-01 08:46:50 -0500542
Michael Zaidman6dbca5f2010-02-28 16:28:25 +0200543miiphy_read_failed:
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500544 printf(" read failed, assuming half duplex\n");
Larry Johnson966a80b2007-11-01 08:46:50 -0500545 return HALF;
546}
wdenke3a06802004-06-06 23:13:55 +0000547
Larry Johnson966a80b2007-11-01 08:46:50 -0500548/*****************************************************************************
549 *
550 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
551 * 1000BASE-T, or on error.
552 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400553int miiphy_is_1000base_x(const char *devname, unsigned char addr)
Larry Johnson966a80b2007-11-01 08:46:50 -0500554{
555#if defined(CONFIG_PHY_GIGE)
556 u16 exsr;
557
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500558 if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
559 printf("PHY extended status read failed, assuming no "
Larry Johnson966a80b2007-11-01 08:46:50 -0500560 "1000BASE-X\n");
561 return 0;
562 }
Mike Frysingerd63ee712010-12-23 15:40:12 -0500563 return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
Larry Johnson966a80b2007-11-01 08:46:50 -0500564#else
565 return 0;
566#endif
wdenkc6097192002-11-03 00:24:07 +0000567}
568
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200569#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
wdenk49c3f672003-10-08 22:33:00 +0000570/*****************************************************************************
571 *
572 * Determine link status
573 */
Mike Frysinger5ff5fdb2010-07-27 18:35:08 -0400574int miiphy_link(const char *devname, unsigned char addr)
wdenk49c3f672003-10-08 22:33:00 +0000575{
576 unsigned short reg;
577
wdenk145d2c12004-04-15 21:48:45 +0000578 /* dummy read; needed to latch some phys */
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500579 (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;
wdenk49c3f672003-10-08 22:33:00 +0000583 }
584
585 /* Determine if a link is active */
Mike Frysingerd63ee712010-12-23 15:40:12 -0500586 if ((reg & BMSR_LSTATUS) != 0) {
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500587 return 1;
wdenk49c3f672003-10-08 22:33:00 +0000588 } else {
Andy Flemingaea0c3e2011-04-07 14:38:35 -0500589 return 0;
wdenk49c3f672003-10-08 22:33:00 +0000590 }
591}
592#endif