Blame view

common/miiphyutil.c 11.9 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
   */
  
  /*
   * This provides a bit-banged interface to the ethernet MII management
   * channel.
   */
  
  #include <common.h>
c74c8e665   Simon Glass   dm: net: Adjust P...
14
  #include <dm.h>
c609719b8   wdenk   Initial revision
15
  #include <miiphy.h>
5f184715e   Andy Fleming   Create PHY Lib fo...
16
  #include <phy.h>
c609719b8   wdenk   Initial revision
17

63ff004c4   Marian Balakowicz   Add support for m...
18
19
20
21
22
23
  #include <asm/types.h>
  #include <linux/list.h>
  #include <malloc.h>
  #include <net.h>
  
  /* local debug macro */
63ff004c4   Marian Balakowicz   Add support for m...
24
25
26
27
  #undef MII_DEBUG
  
  #undef debug
  #ifdef MII_DEBUG
16a532383   Andy Fleming   miiphy: Fix some ...
28
  #define debug(fmt, args...)	printf(fmt, ##args)
63ff004c4   Marian Balakowicz   Add support for m...
29
  #else
16a532383   Andy Fleming   miiphy: Fix some ...
30
  #define debug(fmt, args...)
63ff004c4   Marian Balakowicz   Add support for m...
31
  #endif /* MII_DEBUG */
63ff004c4   Marian Balakowicz   Add support for m...
32
33
  static struct list_head mii_devs;
  static struct mii_dev *current_mii;
0daac9780   Mike Frysinger   miiphy: unify dev...
34
35
36
  /*
   * Lookup the mii_dev struct by the registered device name.
   */
5f184715e   Andy Fleming   Create PHY Lib fo...
37
  struct mii_dev *miiphy_get_dev_by_name(const char *devname)
0daac9780   Mike Frysinger   miiphy: unify dev...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  {
  	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...
53
54
  	return NULL;
  }
63ff004c4   Marian Balakowicz   Add support for m...
55
56
  /*****************************************************************************
   *
d9785c14b   Marian Balakowicz   Fix miiphy global...
57
58
   * Initialize global data. Need to be called before any other miiphy routine.
   */
5700bb635   Mike Frysinger   miiphy: constify ...
59
  void miiphy_init(void)
d9785c14b   Marian Balakowicz   Fix miiphy global...
60
  {
16a532383   Andy Fleming   miiphy: Fix some ...
61
  	INIT_LIST_HEAD(&mii_devs);
298035df4   Larry Johnson   NET: Cosmetic cha...
62
  	current_mii = NULL;
d9785c14b   Marian Balakowicz   Fix miiphy global...
63
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  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;
  }
cb6baca77   Bin Meng   net: mdio: Add md...
79
80
81
82
  void mdio_free(struct mii_dev *bus)
  {
  	free(bus);
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
83
84
  int mdio_register(struct mii_dev *bus)
  {
d39449b11   Peng Fan   common: miiphyuti...
85
  	if (!bus || !bus->read || !bus->write)
5f184715e   Andy Fleming   Create PHY Lib fo...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  		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;
  }
79e2a6a04   Michal Simek   common: miiphyuti...
104
105
106
107
108
109
110
111
112
113
114
  int mdio_register_seq(struct mii_dev *bus, int seq)
  {
  	int ret;
  
  	/* Setup a unique name for each mdio bus */
  	ret = snprintf(bus->name, MDIO_NAME_LEN, "eth%d", seq);
  	if (ret < 0)
  		return ret;
  
  	return mdio_register(bus);
  }
cb6baca77   Bin Meng   net: mdio: Add md...
115
116
117
118
119
120
121
122
123
124
125
126
127
  int mdio_unregister(struct mii_dev *bus)
  {
  	if (!bus)
  		return 0;
  
  	/* delete it from the list */
  	list_del(&bus->link);
  
  	if (current_mii == bus)
  		current_mii = NULL;
  
  	return 0;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  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) {
15a2acdf8   Michal Simek   common: miiphyuti...
143
  				printf("%x - %s", i, phydev->drv->name);
5f184715e   Andy Fleming   Create PHY Lib fo...
144
145
146
147
148
149
150
151
152
153
154
  
  				if (phydev->dev)
  					printf(" <--> %s
  ", phydev->dev->name);
  				else
  					printf("
  ");
  			}
  		}
  	}
  }
5700bb635   Mike Frysinger   miiphy: constify ...
155
  int miiphy_set_current_dev(const char *devname)
63ff004c4   Marian Balakowicz   Add support for m...
156
  {
63ff004c4   Marian Balakowicz   Add support for m...
157
  	struct mii_dev *dev;
5f184715e   Andy Fleming   Create PHY Lib fo...
158
  	dev = miiphy_get_dev_by_name(devname);
0daac9780   Mike Frysinger   miiphy: unify dev...
159
160
161
  	if (dev) {
  		current_mii = dev;
  		return 0;
63ff004c4   Marian Balakowicz   Add support for m...
162
  	}
5f184715e   Andy Fleming   Create PHY Lib fo...
163
164
  	printf("No such device: %s
  ", devname);
63ff004c4   Marian Balakowicz   Add support for m...
165
166
  	return 1;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
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
  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 ...
194
  const char *miiphy_get_current_dev(void)
63ff004c4   Marian Balakowicz   Add support for m...
195
196
197
198
199
200
  {
  	if (current_mii)
  		return current_mii->name;
  
  	return NULL;
  }
ede16ea32   Mike Frysinger   miiphy: leverage ...
201
202
203
204
205
206
207
208
209
210
211
212
213
  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...
214
215
216
217
218
  /*****************************************************************************
   *
   * Read to variable <value> from the PHY attached to device <devname>,
   * use PHY address <addr> and register <reg>.
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
219
220
   * This API is deprecated. Use phy_read on a phy_device found via phy_connect
   *
63ff004c4   Marian Balakowicz   Add support for m...
221
222
223
   * Returns:
   *   0 on success
   */
f915c9316   Wolfgang Denk   Revert "mii: miip...
224
  int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
298035df4   Larry Johnson   NET: Cosmetic cha...
225
  		 unsigned short *value)
63ff004c4   Marian Balakowicz   Add support for m...
226
  {
5f184715e   Andy Fleming   Create PHY Lib fo...
227
  	struct mii_dev *bus;
d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
228
  	int ret;
63ff004c4   Marian Balakowicz   Add support for m...
229

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

d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
234
235
236
237
238
239
  	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...
240
241
242
243
244
245
246
  }
  
  /*****************************************************************************
   *
   * Write <value> to the PHY attached to device <devname>,
   * use PHY address <addr> and register <reg>.
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
247
248
   * This API is deprecated. Use phy_write on a phy_device found by phy_connect
   *
63ff004c4   Marian Balakowicz   Add support for m...
249
250
251
   * Returns:
   *   0 on success
   */
f915c9316   Wolfgang Denk   Revert "mii: miip...
252
  int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
298035df4   Larry Johnson   NET: Cosmetic cha...
253
  		  unsigned short value)
63ff004c4   Marian Balakowicz   Add support for m...
254
  {
5f184715e   Andy Fleming   Create PHY Lib fo...
255
  	struct mii_dev *bus;
63ff004c4   Marian Balakowicz   Add support for m...
256

5f184715e   Andy Fleming   Create PHY Lib fo...
257
258
259
  	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...
260

0daac9780   Mike Frysinger   miiphy: unify dev...
261
  	return 1;
63ff004c4   Marian Balakowicz   Add support for m...
262
263
264
265
266
267
  }
  
  /*****************************************************************************
   *
   * Print out list of registered MII capable devices.
   */
16a532383   Andy Fleming   miiphy: Fix some ...
268
  void miiphy_listdev(void)
63ff004c4   Marian Balakowicz   Add support for m...
269
270
271
  {
  	struct list_head *entry;
  	struct mii_dev *dev;
16a532383   Andy Fleming   miiphy: Fix some ...
272
273
274
275
  	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...
276
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
277
278
  	puts("
  ");
63ff004c4   Marian Balakowicz   Add support for m...
279
280
  
  	if (current_mii)
16a532383   Andy Fleming   miiphy: Fix some ...
281
282
  		printf("Current device: '%s'
  ", current_mii->name);
63ff004c4   Marian Balakowicz   Add support for m...
283
  }
c609719b8   wdenk   Initial revision
284
285
286
287
288
289
290
291
  /*****************************************************************************
   *
   * 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...
292
293
   * This API is deprecated.
   *
c609719b8   wdenk   Initial revision
294
295
296
   * Returns:
   *   0 on success
   */
5700bb635   Mike Frysinger   miiphy: constify ...
297
  int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
c609719b8   wdenk   Initial revision
298
299
300
  		 unsigned char *model, unsigned char *rev)
  {
  	unsigned int reg = 0;
8bf3b005d   wdenk   * Patches by Step...
301
  	unsigned short tmp;
c609719b8   wdenk   Initial revision
302

16a532383   Andy Fleming   miiphy: Fix some ...
303
304
305
306
  	if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
  		debug("PHY ID register 2 read failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
307
  	}
8bf3b005d   wdenk   * Patches by Step...
308
  	reg = tmp;
c609719b8   wdenk   Initial revision
309

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

c609719b8   wdenk   Initial revision
313
314
  	if (reg == 0xFFFF) {
  		/* No physical device present at this address */
16a532383   Andy Fleming   miiphy: Fix some ...
315
  		return -1;
c609719b8   wdenk   Initial revision
316
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
317
318
319
320
  	if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
  		debug("PHY ID register 1 read failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
321
  	}
8bf3b005d   wdenk   * Patches by Step...
322
  	reg |= tmp << 16;
16a532383   Andy Fleming   miiphy: Fix some ...
323
324
  	debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x
  ", addr, reg);
26c7bab81   Shinya Kuribayashi   common/miiphyutil...
325

298035df4   Larry Johnson   NET: Cosmetic cha...
326
327
328
  	*oui = (reg >> 10);
  	*model = (unsigned char)((reg >> 4) & 0x0000003F);
  	*rev = (unsigned char)(reg & 0x0000000F);
16a532383   Andy Fleming   miiphy: Fix some ...
329
  	return 0;
c609719b8   wdenk   Initial revision
330
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
331
  #ifndef CONFIG_PHYLIB
c609719b8   wdenk   Initial revision
332
333
334
  /*****************************************************************************
   *
   * Reset the PHY.
1cdabc4bc   Andy Fleming   miiphy: Note that...
335
336
337
   *
   * This API is deprecated. Use PHYLIB.
   *
c609719b8   wdenk   Initial revision
338
339
340
   * Returns:
   *   0 on success
   */
5700bb635   Mike Frysinger   miiphy: constify ...
341
  int miiphy_reset(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
342
343
  {
  	unsigned short reg;
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
344
  	int timeout = 500;
c609719b8   wdenk   Initial revision
345

16a532383   Andy Fleming   miiphy: Fix some ...
346
347
348
349
  	if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
  		debug("PHY status read failed
  ");
  		return -1;
f89920c3e   Wolfgang Denk   Preserve PHY_BMCR...
350
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
351
352
353
354
  	if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
  		debug("PHY reset failed
  ");
  		return -1;
c609719b8   wdenk   Initial revision
355
  	}
5653fc335   wdenk   * Patch by Yuli B...
356
  #ifdef CONFIG_PHY_RESET_DELAY
16a532383   Andy Fleming   miiphy: Fix some ...
357
  	udelay(CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */
5653fc335   wdenk   * Patch by Yuli B...
358
  #endif
c609719b8   wdenk   Initial revision
359
360
361
362
363
  	/*
  	 * 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
364
  	reg = 0x8000;
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
365
  	while (((reg & 0x8000) != 0) && timeout--) {
8ef583a03   Mike Frysinger   miiphy: convert t...
366
  		if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
367
368
369
  			debug("PHY status read failed
  ");
  			return -1;
c609719b8   wdenk   Initial revision
370
  		}
ab5a0dcb9   Stefan Roese   net: Use 0.5 sec ...
371
  		udelay(1000);
c609719b8   wdenk   Initial revision
372
373
  	}
  	if ((reg & 0x8000) == 0) {
16a532383   Andy Fleming   miiphy: Fix some ...
374
  		return 0;
c609719b8   wdenk   Initial revision
375
  	} else {
16a532383   Andy Fleming   miiphy: Fix some ...
376
377
378
  		puts("PHY reset timed out
  ");
  		return -1;
c609719b8   wdenk   Initial revision
379
  	}
16a532383   Andy Fleming   miiphy: Fix some ...
380
  	return 0;
c609719b8   wdenk   Initial revision
381
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
382
  #endif /* !PHYLIB */
c609719b8   wdenk   Initial revision
383

c609719b8   wdenk   Initial revision
384
385
  /*****************************************************************************
   *
71bc6e647   Larry Johnson   NET: Add Ethernet...
386
   * Determine the ethernet speed (10/100/1000).  Return 10 on error.
c609719b8   wdenk   Initial revision
387
   */
5700bb635   Mike Frysinger   miiphy: constify ...
388
  int miiphy_speed(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
389
  {
8c83c0303   Dongpo Li   net: mii: check p...
390
  	u16 bmcr, anlpar, adv;
c609719b8   wdenk   Initial revision
391

6fb6af6dc   wdenk   * Patch by Stephe...
392
  #if defined(CONFIG_PHY_GIGE)
71bc6e647   Larry Johnson   NET: Add Ethernet...
393
394
395
396
397
398
  	u16 btsr;
  
  	/*
  	 * Check for 1000BASE-X.  If it is supported, then assume that the speed
  	 * is 1000.
  	 */
16a532383   Andy Fleming   miiphy: Fix some ...
399
  	if (miiphy_is_1000base_x(devname, addr))
71bc6e647   Larry Johnson   NET: Add Ethernet...
400
  		return _1000BASET;
16a532383   Andy Fleming   miiphy: Fix some ...
401

71bc6e647   Larry Johnson   NET: Add Ethernet...
402
403
404
405
  	/*
  	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
  	 */
  	/* Check for 1000BASE-T. */
16a532383   Andy Fleming   miiphy: Fix some ...
406
407
  	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  		printf("PHY 1000BT status");
71bc6e647   Larry Johnson   NET: Add Ethernet...
408
409
410
  		goto miiphy_read_failed;
  	}
  	if (btsr != 0xFFFF &&
16a532383   Andy Fleming   miiphy: Fix some ...
411
  			(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
71bc6e647   Larry Johnson   NET: Add Ethernet...
412
  		return _1000BASET;
6fb6af6dc   wdenk   * Patch by Stephe...
413
  #endif /* CONFIG_PHY_GIGE */
855a496fe   wdenk   * Patches by Trav...
414

a56bd9228   wdenk   * Patch by Dave P...
415
  	/* Check Basic Management Control Register first. */
16a532383   Andy Fleming   miiphy: Fix some ...
416
417
  	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  		printf("PHY speed");
71bc6e647   Larry Johnson   NET: Add Ethernet...
418
  		goto miiphy_read_failed;
c609719b8   wdenk   Initial revision
419
  	}
a56bd9228   wdenk   * Patch by Dave P...
420
  	/* Check if auto-negotiation is on. */
8ef583a03   Mike Frysinger   miiphy: convert t...
421
  	if (bmcr & BMCR_ANENABLE) {
a56bd9228   wdenk   * Patch by Dave P...
422
  		/* Get auto-negotiation results. */
16a532383   Andy Fleming   miiphy: Fix some ...
423
424
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			printf("PHY AN speed");
71bc6e647   Larry Johnson   NET: Add Ethernet...
425
  			goto miiphy_read_failed;
a56bd9228   wdenk   * Patch by Dave P...
426
  		}
8c83c0303   Dongpo Li   net: mii: check p...
427
428
429
430
431
432
  
  		if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) {
  			puts("PHY AN adv speed");
  			goto miiphy_read_failed;
  		}
  		return ((anlpar & adv) & LPA_100) ? _100BASET : _10BASET;
a56bd9228   wdenk   * Patch by Dave P...
433
434
  	}
  	/* Get speed from basic control settings. */
8ef583a03   Mike Frysinger   miiphy: convert t...
435
  	return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
a56bd9228   wdenk   * Patch by Dave P...
436

5f8419597   Michael Zaidman   Cosmetic change -...
437
  miiphy_read_failed:
16a532383   Andy Fleming   miiphy: Fix some ...
438
439
  	printf(" read failed, assuming 10BASE-T
  ");
71bc6e647   Larry Johnson   NET: Add Ethernet...
440
  	return _10BASET;
c609719b8   wdenk   Initial revision
441
  }
c609719b8   wdenk   Initial revision
442
443
  /*****************************************************************************
   *
71bc6e647   Larry Johnson   NET: Add Ethernet...
444
   * Determine full/half duplex.  Return half on error.
c609719b8   wdenk   Initial revision
445
   */
5700bb635   Mike Frysinger   miiphy: constify ...
446
  int miiphy_duplex(const char *devname, unsigned char addr)
c609719b8   wdenk   Initial revision
447
  {
8c83c0303   Dongpo Li   net: mii: check p...
448
  	u16 bmcr, anlpar, adv;
c609719b8   wdenk   Initial revision
449

6fb6af6dc   wdenk   * Patch by Stephe...
450
  #if defined(CONFIG_PHY_GIGE)
71bc6e647   Larry Johnson   NET: Add Ethernet...
451
452
453
  	u16 btsr;
  
  	/* Check for 1000BASE-X. */
16a532383   Andy Fleming   miiphy: Fix some ...
454
  	if (miiphy_is_1000base_x(devname, addr)) {
71bc6e647   Larry Johnson   NET: Add Ethernet...
455
  		/* 1000BASE-X */
16a532383   Andy Fleming   miiphy: Fix some ...
456
457
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			printf("1000BASE-X PHY AN duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
458
459
460
461
462
463
464
  			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 ...
465
466
  	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
  		printf("PHY 1000BT status");
71bc6e647   Larry Johnson   NET: Add Ethernet...
467
468
469
470
471
472
473
  		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...
474
475
  		}
  	}
6fb6af6dc   wdenk   * Patch by Stephe...
476
  #endif /* CONFIG_PHY_GIGE */
855a496fe   wdenk   * Patches by Trav...
477

a56bd9228   wdenk   * Patch by Dave P...
478
  	/* Check Basic Management Control Register first. */
16a532383   Andy Fleming   miiphy: Fix some ...
479
480
  	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
  		puts("PHY duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
481
  		goto miiphy_read_failed;
c609719b8   wdenk   Initial revision
482
  	}
a56bd9228   wdenk   * Patch by Dave P...
483
  	/* Check if auto-negotiation is on. */
8ef583a03   Mike Frysinger   miiphy: convert t...
484
  	if (bmcr & BMCR_ANENABLE) {
a56bd9228   wdenk   * Patch by Dave P...
485
  		/* Get auto-negotiation results. */
16a532383   Andy Fleming   miiphy: Fix some ...
486
487
  		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
  			puts("PHY AN duplex");
71bc6e647   Larry Johnson   NET: Add Ethernet...
488
  			goto miiphy_read_failed;
a56bd9228   wdenk   * Patch by Dave P...
489
  		}
8c83c0303   Dongpo Li   net: mii: check p...
490
491
492
493
494
495
  
  		if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) {
  			puts("PHY AN adv duplex");
  			goto miiphy_read_failed;
  		}
  		return ((anlpar & adv) & (LPA_10FULL | LPA_100FULL)) ?
71bc6e647   Larry Johnson   NET: Add Ethernet...
496
  		    FULL : HALF;
a56bd9228   wdenk   * Patch by Dave P...
497
498
  	}
  	/* Get speed from basic control settings. */
8ef583a03   Mike Frysinger   miiphy: convert t...
499
  	return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
71bc6e647   Larry Johnson   NET: Add Ethernet...
500

5f8419597   Michael Zaidman   Cosmetic change -...
501
  miiphy_read_failed:
16a532383   Andy Fleming   miiphy: Fix some ...
502
503
  	printf(" read failed, assuming half duplex
  ");
71bc6e647   Larry Johnson   NET: Add Ethernet...
504
505
  	return HALF;
  }
a56bd9228   wdenk   * Patch by Dave P...
506

71bc6e647   Larry Johnson   NET: Add Ethernet...
507
508
509
510
511
  /*****************************************************************************
   *
   * 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 ...
512
  int miiphy_is_1000base_x(const char *devname, unsigned char addr)
71bc6e647   Larry Johnson   NET: Add Ethernet...
513
514
515
  {
  #if defined(CONFIG_PHY_GIGE)
  	u16 exsr;
16a532383   Andy Fleming   miiphy: Fix some ...
516
517
  	if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
  		printf("PHY extended status read failed, assuming no "
71bc6e647   Larry Johnson   NET: Add Ethernet...
518
519
520
521
  			"1000BASE-X
  ");
  		return 0;
  	}
8ef583a03   Mike Frysinger   miiphy: convert t...
522
  	return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH));
71bc6e647   Larry Johnson   NET: Add Ethernet...
523
524
525
  #else
  	return 0;
  #endif
c609719b8   wdenk   Initial revision
526
  }
6d0f6bcf3   Jean-Christophe PLAGNIOL-VILLARD   rename CFG_ macro...
527
  #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
fc3e2165e   wdenk   * Patch by Sangmo...
528
529
530
531
  /*****************************************************************************
   *
   * Determine link status
   */
5700bb635   Mike Frysinger   miiphy: constify ...
532
  int miiphy_link(const char *devname, unsigned char addr)
fc3e2165e   wdenk   * Patch by Sangmo...
533
534
  {
  	unsigned short reg;
a3d991bd0   wdenk   Patches by Pantel...
535
  	/* dummy read; needed to latch some phys */
16a532383   Andy Fleming   miiphy: Fix some ...
536
537
538
539
540
  	(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...
541
542
543
  	}
  
  	/* Determine if a link is active */
8ef583a03   Mike Frysinger   miiphy: convert t...
544
  	if ((reg & BMSR_LSTATUS) != 0) {
16a532383   Andy Fleming   miiphy: Fix some ...
545
  		return 1;
fc3e2165e   wdenk   * Patch by Sangmo...
546
  	} else {
16a532383   Andy Fleming   miiphy: Fix some ...
547
  		return 0;
fc3e2165e   wdenk   * Patch by Sangmo...
548
549
550
  	}
  }
  #endif