Blame view

common/miiphyutil.c 11.9 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
c609719b8   wdenk   Initial revision
2
3
4
  /*
   * (C) Copyright 2001
   * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
c609719b8   wdenk   Initial revision
5
6
7
8
9
10
11
12
   */
  
  /*
   * This provides a bit-banged interface to the ethernet MII management
   * channel.
   */
  
  #include <common.h>
c74c8e665   Simon Glass   dm: net: Adjust P...
13
  #include <dm.h>
c609719b8   wdenk   Initial revision
14
  #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
  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...
78
79
80
81
  void mdio_free(struct mii_dev *bus)
  {
  	free(bus);
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
82
83
  int mdio_register(struct mii_dev *bus)
  {
d39449b11   Peng Fan   common: miiphyuti...
84
  	if (!bus || !bus->read || !bus->write)
5f184715e   Andy Fleming   Create PHY Lib fo...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  		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...
103
104
105
106
107
108
109
110
111
112
113
  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...
114
115
116
117
118
119
120
121
122
123
124
125
126
  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...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
  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...
142
  				printf("%x - %s", i, phydev->drv->name);
5f184715e   Andy Fleming   Create PHY Lib fo...
143
144
145
146
147
148
149
150
151
152
153
  
  				if (phydev->dev)
  					printf(" <--> %s
  ", phydev->dev->name);
  				else
  					printf("
  ");
  			}
  		}
  	}
  }
5700bb635   Mike Frysinger   miiphy: constify ...
154
  int miiphy_set_current_dev(const char *devname)
63ff004c4   Marian Balakowicz   Add support for m...
155
  {
63ff004c4   Marian Balakowicz   Add support for m...
156
  	struct mii_dev *dev;
5f184715e   Andy Fleming   Create PHY Lib fo...
157
  	dev = miiphy_get_dev_by_name(devname);
0daac9780   Mike Frysinger   miiphy: unify dev...
158
159
160
  	if (dev) {
  		current_mii = dev;
  		return 0;
63ff004c4   Marian Balakowicz   Add support for m...
161
  	}
5f184715e   Andy Fleming   Create PHY Lib fo...
162
163
  	printf("No such device: %s
  ", devname);
63ff004c4   Marian Balakowicz   Add support for m...
164
165
  	return 1;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
166
167
168
169
  struct mii_dev *mdio_get_current_dev(void)
  {
  	return current_mii;
  }
9215bb1f3   Pankaj Bansal   miiphy: Add funct...
170
171
172
173
  struct list_head *mdio_get_list_head(void)
  {
  	return &mii_devs;
  }
5f184715e   Andy Fleming   Create PHY Lib fo...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  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 ...
196
  const char *miiphy_get_current_dev(void)
63ff004c4   Marian Balakowicz   Add support for m...
197
198
199
200
201
202
  {
  	if (current_mii)
  		return current_mii->name;
  
  	return NULL;
  }
ede16ea32   Mike Frysinger   miiphy: leverage ...
203
204
205
206
207
208
209
210
211
212
213
214
215
  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...
216
217
218
219
220
  /*****************************************************************************
   *
   * Read to variable <value> from the PHY attached to device <devname>,
   * use PHY address <addr> and register <reg>.
   *
1cdabc4bc   Andy Fleming   miiphy: Note that...
221
222
   * This API is deprecated. Use phy_read on a phy_device found via phy_connect
   *
63ff004c4   Marian Balakowicz   Add support for m...
223
224
225
   * Returns:
   *   0 on success
   */
f915c9316   Wolfgang Denk   Revert "mii: miip...
226
  int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
298035df4   Larry Johnson   NET: Cosmetic cha...
227
  		 unsigned short *value)
63ff004c4   Marian Balakowicz   Add support for m...
228
  {
5f184715e   Andy Fleming   Create PHY Lib fo...
229
  	struct mii_dev *bus;
d67d5d529   Anatolij Gustschin   miiphy: miiphyuti...
230
  	int ret;
63ff004c4   Marian Balakowicz   Add support for m...
231

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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