Blame view

common/miiphyutil.c 13 KB
c609719b8   wdenk   Initial revision
1
2
3
4
  /*
   * (C) Copyright 2001
   * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
5
   * SPDX-License-Identifier:	GPL-2.0+
c609719b8   wdenk   Initial revision
6
7
8
9
10
11
12
13
14
   */
  
  /*
   * This provides a bit-banged interface to the ethernet MII management
   * channel.
   */
  
  #include <common.h>
  #include <miiphy.h>
5f184715e   Andy Fleming   Create PHY Lib fo...
15
  #include <phy.h>
c609719b8   wdenk   Initial revision
16

63ff004c4   Marian Balakowicz   Add support for m...
17
18
19
20
21
22
  #include <asm/types.h>
  #include <linux/list.h>
  #include <malloc.h>
  #include <net.h>
  
  /* local debug macro */
63ff004c4   Marian Balakowicz   Add support for m...
23
24
25
26
  #undef MII_DEBUG
  
  #undef debug
  #ifdef MII_DEBUG
16a532383   Andy Fleming   miiphy: Fix some ...
27
  #define debug(fmt, args...)	printf(fmt, ##args)
63ff004c4   Marian Balakowicz   Add support for m...
28
  #else
16a532383   Andy Fleming   miiphy: Fix some ...
29
  #define debug(fmt, args...)
63ff004c4   Marian Balakowicz   Add support for m...
30
  #endif /* MII_DEBUG */
63ff004c4   Marian Balakowicz   Add support for m...
31
32
  static struct list_head mii_devs;
  static struct mii_dev *current_mii;
0daac9780   Mike Frysinger   miiphy: unify dev...
33
34
35
  /*
   * Lookup the mii_dev struct by the registered device name.
   */
5f184715e   Andy Fleming   Create PHY Lib fo...
36
  struct mii_dev *miiphy_get_dev_by_name(const char *devname)
0daac9780   Mike Frysinger   miiphy: unify dev...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  {
  	struct list_head *entry;
  	struct mii_dev *dev;
  
  	if (!devname) {
  		printf("NULL device name!
  ");
  		return NULL;
  	}
  
  	list_for_each(entry, &mii_devs) {
  		dev = list_entry(entry, struct mii_dev, link);
  		if (strcmp(dev->name, devname) == 0)
  			return dev;
  	}
0daac9780   Mike Frysinger   miiphy: unify dev...
52
53
  	return NULL;
  }
63ff004c4   Marian Balakowicz   Add support for m...
54
55
  /*****************************************************************************
   *
d9785c14b   Marian Balakowicz   Fix miiphy global...
56
57
   * Initialize global data. Need to be called before any other miiphy routine.
   */
5700bb635   Mike Frysinger   miiphy: constify ...
58
  void miiphy_init(void)
d9785c14b   Marian Balakowicz   Fix miiphy global...
59
  {
16a532383   Andy Fleming   miiphy: Fix some ...
60
  	INIT_LIST_HEAD(&mii_devs);
298035df4   Larry Johnson   NET: Cosmetic cha...
61
  	current_mii = NULL;
d9785c14b   Marian Balakowicz   Fix miiphy global...
62
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
  {
  	unsigned short val;
  	int ret;
  	struct legacy_mii_dev *ldev = bus->priv;
  
  	ret = ldev->read(bus->name, addr, reg, &val);
  
  	return ret ? -1 : (int)val;
  }
  
  static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
  				int reg, u16 val)
  {
  	struct legacy_mii_dev *ldev = bus->priv;
  
  	return ldev->write(bus->name, addr, reg, val);
  }
d9785c14b   Marian Balakowicz   Fix miiphy global...
81
82
  /*****************************************************************************
   *
63ff004c4   Marian Balakowicz   Add support for m...
83
   * Register read and write MII access routines for the device <name>.
1cdabc4bc   Andy Fleming   miiphy: Note that...
84
   * This API is now deprecated. Please use mdio_alloc and mdio_register, instead.
63ff004c4   Marian Balakowicz   Add support for m...
85
   */
5700bb635   Mike Frysinger   miiphy: constify ...
86
  void miiphy_register(const char *name,
16a532383   Andy Fleming   miiphy: Fix some ...
87
  		      int (*read)(const char *devname, unsigned char addr,
f915c9316   Wolfgang Denk   Revert "mii: miip...
88
  				   unsigned char reg, unsigned short *value),
16a532383   Andy Fleming   miiphy: Fix some ...
89
  		      int (*write)(const char *devname, unsigned char addr,
f915c9316   Wolfgang Denk   Revert "mii: miip...
90
  				    unsigned char reg, unsigned short value))
63ff004c4   Marian Balakowicz   Add support for m...
91
  {
63ff004c4   Marian Balakowicz   Add support for m...
92
  	struct mii_dev *new_dev;
5f184715e   Andy Fleming   Create PHY Lib fo...
93
  	struct legacy_mii_dev *ldev;
07c07635b   Laurence Withers   miiphy: use strnc...
94
95
  
  	BUG_ON(strlen(name) >= MDIO_NAME_LEN);
63ff004c4   Marian Balakowicz   Add support for m...
96

63ff004c4   Marian Balakowicz   Add support for m...
97
  	/* check if we have unique name */
5f184715e   Andy Fleming   Create PHY Lib fo...
98
  	new_dev = miiphy_get_dev_by_name(name);
0daac9780   Mike Frysinger   miiphy: unify dev...
99
100
101
102
  	if (new_dev) {
  		printf("miiphy_register: non unique device name '%s'
  ", name);
  		return;
63ff004c4   Marian Balakowicz   Add support for m...
103
104
105
  	}
  
  	/* allocate memory */
5f184715e   Andy Fleming   Create PHY Lib fo...
106
107
  	new_dev = mdio_alloc();
  	ldev = malloc(sizeof(*ldev));
63ff004c4   Marian Balakowicz   Add support for m...
108

5f184715e   Andy Fleming   Create PHY Lib fo...
109
  	if (new_dev == NULL || ldev == NULL) {
16a532383   Andy Fleming   miiphy: Fix some ...
110
111
  		printf("miiphy_register: cannot allocate memory for '%s'
  ",
298035df4   Larry Johnson   NET: Cosmetic cha...
112
  			name);
63ff004c4   Marian Balakowicz   Add support for m...
113
114
  		return;
  	}
63ff004c4   Marian Balakowicz   Add support for m...
115
116
  
  	/* initalize mii_dev struct fields */
5f184715e   Andy Fleming   Create PHY Lib fo...
117
118
  	new_dev->read = legacy_miiphy_read;
  	new_dev->write = legacy_miiphy_write;
07c07635b   Laurence Withers   miiphy: use strnc...
119
120
  	strncpy(new_dev->name, name, MDIO_NAME_LEN);
  	new_dev->name[MDIO_NAME_LEN - 1] = 0;
5f184715e   Andy Fleming   Create PHY Lib fo...
121
122
123
  	ldev->read = read;
  	ldev->write = write;
  	new_dev->priv = ldev;
63ff004c4   Marian Balakowicz   Add support for m...
124

16a532383   Andy Fleming   miiphy: Fix some ...
125
126
  	debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx
  ",
5f184715e   Andy Fleming   Create PHY Lib fo...
127
  	       new_dev->name, ldev->read, ldev->write);
63ff004c4   Marian Balakowicz   Add support for m...
128
129
  
  	/* add it to the list */
16a532383   Andy Fleming   miiphy: Fix some ...
130
  	list_add_tail(&new_dev->link, &mii_devs);
63ff004c4   Marian Balakowicz   Add support for m...
131
132
133
134
  
  	if (!current_mii)
  		current_mii = new_dev;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  struct mii_dev *mdio_alloc(void)
  {
  	struct mii_dev *bus;
  
  	bus = malloc(sizeof(*bus));
  	if (!bus)
  		return bus;
  
  	memset(bus, 0, sizeof(*bus));
  
  	/* initalize mii_dev struct fields */
  	INIT_LIST_HEAD(&bus->link);
  
  	return bus;
  }
  
  int mdio_register(struct mii_dev *bus)
  {
  	if (!bus || !bus->name || !bus->read || !bus->write)
  		return -1;
  
  	/* check if we have unique name */
  	if (miiphy_get_dev_by_name(bus->name)) {
  		printf("mdio_register: non unique device name '%s'
  ",
  			bus->name);
  		return -1;
  	}
  
  	/* add it to the list */
  	list_add_tail(&bus->link, &mii_devs);
  
  	if (!current_mii)
  		current_mii = bus;
  
  	return 0;
  }
  
  void mdio_list_devices(void)
  {
  	struct list_head *entry;
  
  	list_for_each(entry, &mii_devs) {
  		int i;
  		struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
  
  		printf("%s:
  ", bus->name);
  
  		for (i = 0; i < PHY_MAX_ADDR; i++) {
  			struct phy_device *phydev = bus->phymap[i];
  
  			if (phydev) {
  				printf("%d - %s", i, phydev->drv->name);
  
  				if (phydev->dev)
  					printf(" <--> %s
  ", phydev->dev->name);
  				else
  					printf("
  ");
  			}
  		}
  	}
  }
5700bb635   Mike Frysinger   miiphy: constify ...
200
  int miiphy_set_current_dev(const char *devname)
63ff004c4   Marian Balakowicz   Add support for m...
201
  {
63ff004c4   Marian Balakowicz   Add support for m...
202
  	struct mii_dev *dev;
5f184715e   Andy Fleming   Create PHY Lib fo...
203
  	dev = miiphy_get_dev_by_name(devname);
0daac9780   Mike Frysinger   miiphy: unify dev...
204
205
206
  	if (dev) {
  		current_mii = dev;
  		return 0;
63ff004c4   Marian Balakowicz   Add support for m...
207
  	}
5f184715e   Andy Fleming   Create PHY Lib fo...
208
209
  	printf("No such device: %s
  ", devname);
63ff004c4   Marian Balakowicz   Add support for m...
210
211
  	return 1;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  struct mii_dev *mdio_get_current_dev(void)
  {
  	return current_mii;
  }
  
  struct phy_device *mdio_phydev_for_ethname(const char *ethname)
  {
  	struct list_head *entry;
  	struct mii_dev *bus;
  
  	list_for_each(entry, &mii_devs) {
  		int i;
  		bus = list_entry(entry, struct mii_dev, link);
  
  		for (i = 0; i < PHY_MAX_ADDR; i++) {
  			if (!bus->phymap[i] || !bus->phymap[i]->dev)
  				continue;
  
  			if (strcmp(bus->phymap[i]->dev->name, ethname) == 0)
  				return bus->phymap[i];
  		}
  	}
  
  	printf("%s is not a known ethernet
  ", ethname);
  	return NULL;
  }
5700bb635   Mike Frysinger   miiphy: constify ...
239
  const char *miiphy_get_current_dev(void)
63ff004c4   Marian Balakowicz   Add support for m...
240
241
242
243
244
245
  {
  	if (current_mii)
  		return current_mii->name;
  
  	return NULL;
  }
ede16ea32   Mike Frysinger   miiphy: leverage ...
246
247
248
249
250
251
252
253
254
255
256
257
258
  static struct mii_dev *miiphy_get_active_dev(const char *devname)
  {
  	/* If the current mii is the one we want, return it */
  	if (current_mii)
  		if (strcmp(current_mii->name, devname) == 0)
  			return current_mii;
  
  	/* Otherwise, set the active one to the one we want */
  	if (miiphy_set_current_dev(devname))
  		return NULL;
  	else
  		return current_mii;
  }
63ff004c4   Marian Balakowicz   Add support for m...
259
260
261
262
263
  /*****************************************************************************
   *
   * Read to variable <value> from the PHY attached to device <devname>,
   * use PHY address <addr> and register <reg>.
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
264
265
   * This API is deprecated. Use phy_read on a phy_device found via phy_connect
   *
63ff004c4   Marian Balakowicz   Add support for m...
266
267
268
   * Returns:
   *   0 on success
   */
f915c9316   Wolfgang Denk   Revert "mii: miip...
269
  int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
298035df4   Larry Johnson   NET: Cosmetic cha...
270
  		 unsigned short *value)
63ff004c4   Marian Balakowicz   Add support for m...
271
  {
5f184715e   Andy Fleming   Create PHY Lib fo...
272
  	struct mii_dev *bus;
d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
273
  	int ret;
63ff004c4   Marian Balakowicz   Add support for m...
274

5f184715e   Andy Fleming   Create PHY Lib fo...
275
  	bus = miiphy_get_active_dev(devname);
d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
276
  	if (!bus)
5f184715e   Andy Fleming   Create PHY Lib fo...
277
  		return 1;
63ff004c4   Marian Balakowicz   Add support for m...
278

d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
279
280
281
282
283
284
  	ret = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
  	if (ret < 0)
  		return 1;
  
  	*value = (unsigned short)ret;
  	return 0;
63ff004c4   Marian Balakowicz   Add support for m...
285
286
287
288
289
290
291
  }
  
  /*****************************************************************************
   *
   * Write <value> to the PHY attached to device <devname>,
   * use PHY address <addr> and register <reg>.
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
292
293
   * This API is deprecated. Use phy_write on a phy_device found by phy_connect
   *
63ff004c4   Marian Balakowicz   Add support for m...
294
295
296
   * Returns:
   *   0 on success
   */
f915c9316   Wolfgang Denk   Revert "mii: miip...
297
  int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
298035df4   Larry Johnson   NET: Cosmetic cha...
298
  		  unsigned short value)
63ff004c4   Marian Balakowicz   Add support for m...
299
  {
5f184715e   Andy Fleming   Create PHY Lib fo...
300
  	struct mii_dev *bus;
63ff004c4   Marian Balakowicz   Add support for m...
301

5f184715e   Andy Fleming   Create PHY Lib fo...
302
303
304
  	bus = miiphy_get_active_dev(devname);
  	if (bus)
  		return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
63ff004c4   Marian Balakowicz   Add support for m...
305

0daac9780   Mike Frysinger   miiphy: unify dev...
306
  	return 1;
63ff004c4   Marian Balakowicz   Add support for m...
307
308
309
310
311
312
  }
  
  /*****************************************************************************
   *
   * Print out list of registered MII capable devices.
   */
16a532383   Andy Fleming   miiphy: Fix some ...
313
  void miiphy_listdev(void)
63ff004c4   Marian Balakowicz   Add support for m...
314
315
316
  {
  	struct list_head *entry;
  	struct mii_dev *dev;
16a532383   Andy Fleming   miiphy: Fix some ...
317
318
319
320
  	puts("MII devices: ");
  	list_for_each(entry, &mii_devs) {
  		dev = list_entry(entry, struct mii_dev, link);
  		printf("'%s' ", dev->name);
63ff004c4   Marian Balakowicz   Add support for m...
321
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
322
323
  	puts("
  ");
63ff004c4   Marian Balakowicz   Add support for m...
324
325
  
  	if (current_mii)
16a532383   Andy Fleming   miiphy: Fix some ...
326
327
  		printf("Current device: '%s'
  ", current_mii->name);
63ff004c4   Marian Balakowicz   Add support for m...
328
  }
c609719b8   wdenk   Initial revision
329
330
331
332
333
334
335
336
  /*****************************************************************************
   *
   * Read the OUI, manufacture's model number, and revision number.
   *
   * OUI:     22 bits (unsigned int)
   * Model:    6 bits (unsigned char)
   * Revision: 4 bits (unsigned char)
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
337
338
   * This API is deprecated.
   *
c609719b8   wdenk   Initial revision
339
340
341
   * Returns:
   *   0 on success
   */
5700bb635   Mike Frysinger   miiphy: constify ...
342
  int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
c609719b8   wdenk   Initial revision
343
344
345
  		 unsigned char *model, unsigned char *rev)
  {
  	unsigned int reg = 0;
8bf3b005d   wdenk   * Patches by Step...
346
  	unsigned short tmp;
c609719b8   wdenk   Initial revision
347

16a532383   Andy Fleming   miiphy: Fix some ...
348
349
350
351
  	if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
  		debug("PHY ID register 2 read failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
352
  	}
8bf3b005d   wdenk   * Patches by Step...
353
  	reg = tmp;
c609719b8   wdenk   Initial revision
354

16a532383   Andy Fleming   miiphy: Fix some ...
355
356
  	debug("MII_PHYSID2 @ 0x%x = 0x%04x
  ", addr, reg);
26c7bab81   Shinya Kuribayashi   common/miiphyutil...
357

c609719b8   wdenk   Initial revision
358
359
  	if (reg == 0xFFFF) {
  		/* No physical device present at this address */
16a532383   Andy Fleming   miiphy: Fix some ...
360
  		return -1;
c609719b8   wdenk   Initial revision
361
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
362
363
364
365
  	if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
  		debug("PHY ID register 1 read failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
366
  	}
8bf3b005d   wdenk   * Patches by Step...
367
  	reg |= tmp << 16;
16a532383   Andy Fleming   miiphy: Fix some ...
368
369
  	debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x
  ", addr, reg);
26c7bab81   Shinya Kuribayashi   common/miiphyutil...
370

298035df4   Larry Johnson   NET: Cosmetic cha...
371
372
373
  	*oui = (reg >> 10);
  	*model = (unsigned char)((reg >> 4) & 0x0000003F);
  	*rev = (unsigned char)(reg & 0x0000000F);
16a532383   Andy Fleming   miiphy: Fix some ...
374
  	return 0;
c609719b8   wdenk   Initial revision
375
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
376
  #ifndef CONFIG_PHYLIB
c609719b8   wdenk   Initial revision
377
378
379
  /*****************************************************************************
   *
   * Reset the PHY.
1cdabc4bc   Andy Fleming   miiphy: Note that...
380
381
382
   *
   * This API is deprecated. Use PHYLIB.
   *
c609719b8   wdenk   Initial revision
383
384
385
   * Returns:
   *   0 on success
   */
5700bb635   Mike Frysinger   miiphy: constify ...
386
  int miiphy_reset(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
387
388
  {
  	unsigned short reg;
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
389
  	int timeout = 500;
c609719b8   wdenk   Initial revision
390

16a532383   Andy Fleming   miiphy: Fix some ...
391
392
393
394
  	if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
  		debug("PHY status read failed
  ");
  		return -1;
f89920c3e   Wolfgang Denk   Preserve PHY_BMCR...
395
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
396
397
398
399
  	if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
  		debug("PHY reset failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
400
  	}
5653fc335   wdenk   * Patch by Yuli B...
401
  #ifdef CONFIG_PHY_RESET_DELAY
16a532383   Andy Fleming   miiphy: Fix some ...
402
  	udelay(CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */
5653fc335   wdenk   * Patch by Yuli B...
403
  #endif
c609719b8   wdenk   Initial revision
404
405
406
407
408
  	/*
  	 * Poll the control register for the reset bit to go to 0 (it is
  	 * auto-clearing).  This should happen within 0.5 seconds per the
  	 * IEEE spec.
  	 */
c609719b8   wdenk   Initial revision
409
  	reg = 0x8000;
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
410
  	while (((reg & 0x8000) != 0) && timeout--) {
8ef583a03   Mike Frysinger   miiphy: convert t...
411
  		if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
412
413
414
  			debug("PHY status read failed
  ");
  			return -1;
c609719b8   wdenk   Initial revision
415
  		}
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
416
  		udelay(1000);
c609719b8   wdenk   Initial revision
417
418
  	}
  	if ((reg & 0x8000) == 0) {
16a532383   Andy Fleming   miiphy: Fix some ...
419
  		return 0;
c609719b8   wdenk   Initial revision
420
  	} else {
16a532383   Andy Fleming   miiphy: Fix some ...
421
422
423
  		puts("PHY reset timed out
  ");
  		return -1;
c609719b8   wdenk   Initial revision
424
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
425
  	return 0;
c609719b8   wdenk   Initial revision
426
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
427
  #endif /* !PHYLIB */
c609719b8   wdenk   Initial revision
428

c609719b8   wdenk   Initial revision
429
430
  /*****************************************************************************
   *
71bc6e647   Larry Johnson   NET: Add Ethernet...
431
   * Determine the ethernet speed (10/100/1000).  Return 10 on error.
c609719b8   wdenk   Initial revision
432
   */
5700bb635   Mike Frysinger   miiphy: constify ...
433
  int miiphy_speed(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
434
  {
71bc6e647   Larry Johnson   NET: Add Ethernet...
435
  	u16 bmcr, anlpar;
c609719b8   wdenk   Initial revision
436

6fb6af6dc   wdenk   * Patch by Stephe...
437
  #if defined(CONFIG_PHY_GIGE)
71bc6e647   Larry Johnson   NET: Add Ethernet...
438
439
440
441
442
443
  	u16 btsr;
  
  	/*
  	 * Check for 1000BASE-X.  If it is supported, then assume that the speed
  	 * is 1000.
  	 */
16a532383   Andy Fleming   miiphy: Fix some ...
444
  	if (miiphy_is_1000base_x(devname, addr))
71bc6e647   Larry Johnson   NET: Add Ethernet...
445
  		return _1000BASET;
16a532383   Andy Fleming   miiphy: Fix some ...
446

71bc6e647   Larry Johnson   NET: Add Ethernet...
447
448
449
450
  	/*
  	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
  	 */
  	/* Check for 1000BASE-T. */
16a532383   Andy Fleming   miiphy: Fix some ...
451
452
  	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  		printf("PHY 1000BT status");
71bc6e647   Larry Johnson   NET: Add Ethernet...
453
454
455
  		goto miiphy_read_failed;
  	}
  	if (btsr != 0xFFFF &&
16a532383   Andy Fleming   miiphy: Fix some ...
456
  			(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
71bc6e647   Larry Johnson   NET: Add Ethernet...
457
  		return _1000BASET;
6fb6af6dc   wdenk   * Patch by Stephe...
458
  #endif /* CONFIG_PHY_GIGE */
855a496fe   wdenk   * Patches by Trav...
459

a56bd9228   wdenk   * Patch by Dave P...
460
  	/* Check Basic Management Control Register first. */
16a532383   Andy Fleming   miiphy: Fix some ...
461
462
  	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  		printf("PHY speed");
71bc6e647   Larry Johnson   NET: Add Ethernet...
463
  		goto miiphy_read_failed;
c609719b8   wdenk   Initial revision
464
  	}
a56bd9228   wdenk   * Patch by Dave P...
465
  	/* Check if auto-negotiation is on. */
8ef583a03   Mike Frysinger   miiphy: convert t...
466
  	if (bmcr & BMCR_ANENABLE) {
a56bd9228   wdenk   * Patch by Dave P...
467
  		/* Get auto-negotiation results. */
16a532383   Andy Fleming   miiphy: Fix some ...
468
469
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			printf("PHY AN speed");
71bc6e647   Larry Johnson   NET: Add Ethernet...
470
  			goto miiphy_read_failed;
a56bd9228   wdenk   * Patch by Dave P...
471
  		}
8ef583a03   Mike Frysinger   miiphy: convert t...
472
  		return (anlpar & LPA_100) ? _100BASET : _10BASET;
a56bd9228   wdenk   * Patch by Dave P...
473
474
  	}
  	/* Get speed from basic control settings. */
8ef583a03   Mike Frysinger   miiphy: convert t...
475
  	return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
a56bd9228   wdenk   * Patch by Dave P...
476

5f8419597   Michael Zaidman   Cosmetic change -...
477
  miiphy_read_failed:
16a532383   Andy Fleming   miiphy: Fix some ...
478
479
  	printf(" read failed, assuming 10BASE-T
  ");
71bc6e647   Larry Johnson   NET: Add Ethernet...
480
  	return _10BASET;
c609719b8   wdenk   Initial revision
481
  }
c609719b8   wdenk   Initial revision
482
483
  /*****************************************************************************
   *
71bc6e647   Larry Johnson   NET: Add Ethernet...
484
   * Determine full/half duplex.  Return half on error.
c609719b8   wdenk   Initial revision
485
   */
5700bb635   Mike Frysinger   miiphy: constify ...
486
  int miiphy_duplex(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
487
  {
71bc6e647   Larry Johnson   NET: Add Ethernet...
488
  	u16 bmcr, anlpar;
c609719b8   wdenk   Initial revision
489

6fb6af6dc   wdenk   * Patch by Stephe...
490
  #if defined(CONFIG_PHY_GIGE)
71bc6e647   Larry Johnson   NET: Add Ethernet...
491
492
493
  	u16 btsr;
  
  	/* Check for 1000BASE-X. */
16a532383   Andy Fleming   miiphy: Fix some ...
494
  	if (miiphy_is_1000base_x(devname, addr)) {
71bc6e647   Larry Johnson   NET: Add Ethernet...
495
  		/* 1000BASE-X */
16a532383   Andy Fleming   miiphy: Fix some ...
496
497
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			printf("1000BASE-X PHY AN duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
498
499
500
501
502
503
504
  			goto miiphy_read_failed;
  		}
  	}
  	/*
  	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
  	 */
  	/* Check for 1000BASE-T. */
16a532383   Andy Fleming   miiphy: Fix some ...
505
506
  	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  		printf("PHY 1000BT status");
71bc6e647   Larry Johnson   NET: Add Ethernet...
507
508
509
510
511
512
513
  		goto miiphy_read_failed;
  	}
  	if (btsr != 0xFFFF) {
  		if (btsr & PHY_1000BTSR_1000FD) {
  			return FULL;
  		} else if (btsr & PHY_1000BTSR_1000HD) {
  			return HALF;
855a496fe   wdenk   * Patches by Trav...
514
515
  		}
  	}
6fb6af6dc   wdenk   * Patch by Stephe...
516
  #endif /* CONFIG_PHY_GIGE */
855a496fe   wdenk   * Patches by Trav...
517

a56bd9228   wdenk   * Patch by Dave P...
518
  	/* Check Basic Management Control Register first. */
16a532383   Andy Fleming   miiphy: Fix some ...
519
520
  	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  		puts("PHY duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
521
  		goto miiphy_read_failed;
c609719b8   wdenk   Initial revision
522
  	}
a56bd9228   wdenk   * Patch by Dave P...
523
  	/* Check if auto-negotiation is on. */
8ef583a03   Mike Frysinger   miiphy: convert t...
524
  	if (bmcr & BMCR_ANENABLE) {
a56bd9228   wdenk   * Patch by Dave P...
525
  		/* Get auto-negotiation results. */
16a532383   Andy Fleming   miiphy: Fix some ...
526
527
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			puts("PHY AN duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
528
  			goto miiphy_read_failed;
a56bd9228   wdenk   * Patch by Dave P...
529
  		}
8ef583a03   Mike Frysinger   miiphy: convert t...
530
  		return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
71bc6e647   Larry Johnson   NET: Add Ethernet...
531
  		    FULL : HALF;
a56bd9228   wdenk   * Patch by Dave P...
532
533
  	}
  	/* Get speed from basic control settings. */
8ef583a03   Mike Frysinger   miiphy: convert t...
534
  	return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
71bc6e647   Larry Johnson   NET: Add Ethernet...
535

5f8419597   Michael Zaidman   Cosmetic change -...
536
  miiphy_read_failed:
16a532383   Andy Fleming   miiphy: Fix some ...
537
538
  	printf(" read failed, assuming half duplex
  ");
71bc6e647   Larry Johnson   NET: Add Ethernet...
539
540
  	return HALF;
  }
a56bd9228   wdenk   * Patch by Dave P...
541

71bc6e647   Larry Johnson   NET: Add Ethernet...
542
543
544
545
546
  /*****************************************************************************
   *
   * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
   * 1000BASE-T, or on error.
   */
5700bb635   Mike Frysinger   miiphy: constify ...
547
  int miiphy_is_1000base_x(const char *devname, unsigned char addr)
71bc6e647   Larry Johnson   NET: Add Ethernet...
548
549
550
  {
  #if defined(CONFIG_PHY_GIGE)
  	u16 exsr;
16a532383   Andy Fleming   miiphy: Fix some ...
551
552
  	if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
  		printf("PHY extended status read failed, assuming no "
71bc6e647   Larry Johnson   NET: Add Ethernet...
553
554
555
556
  			"1000BASE-X
  ");
  		return 0;
  	}
8ef583a03   Mike Frysinger   miiphy: convert t...
557
  	return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
71bc6e647   Larry Johnson   NET: Add Ethernet...
558
559
560
  #else
  	return 0;
  #endif
c609719b8   wdenk   Initial revision
561
  }
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
562
  #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
fc3e2165e   wdenk   * Patch by Sangmo...
563
564
565
566
  /*****************************************************************************
   *
   * Determine link status
   */
5700bb635   Mike Frysinger   miiphy: constify ...
567
  int miiphy_link(const char *devname, unsigned char addr)
fc3e2165e   wdenk   * Patch by Sangmo...
568
569
  {
  	unsigned short reg;
a3d991bd0   wdenk   Patches by Pantel...
570
  	/* dummy read; needed to latch some phys */
16a532383   Andy Fleming   miiphy: Fix some ...
571
572
573
574
575
  	(void)miiphy_read(devname, addr, MII_BMSR, &reg);
  	if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
  		puts("MII_BMSR read failed, assuming no link
  ");
  		return 0;
fc3e2165e   wdenk   * Patch by Sangmo...
576
577
578
  	}
  
  	/* Determine if a link is active */
8ef583a03   Mike Frysinger   miiphy: convert t...
579
  	if ((reg & BMSR_LSTATUS) != 0) {
16a532383   Andy Fleming   miiphy: Fix some ...
580
  		return 1;
fc3e2165e   wdenk   * Patch by Sangmo...
581
  	} else {
16a532383   Andy Fleming   miiphy: Fix some ...
582
  		return 0;
fc3e2165e   wdenk   * Patch by Sangmo...
583
584
585
  	}
  }
  #endif