xref: /openbmc/u-boot/common/miiphyutil.c (revision 33b1d3f4)
1 /*
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>
31 
32 #include <asm/types.h>
33 #include <linux/list.h>
34 #include <malloc.h>
35 #include <net.h>
36 
37 /* local debug macro */
38 #undef MII_DEBUG
39 
40 #undef debug
41 #ifdef MII_DEBUG
42 #define debug(fmt,args...)	printf (fmt ,##args)
43 #else
44 #define debug(fmt,args...)
45 #endif /* MII_DEBUG */
46 
47 struct mii_dev {
48 	struct list_head link;
49 	char *name;
50 	int (*read) (char *devname, unsigned char addr,
51 		     unsigned char reg, unsigned short *value);
52 	int (*write) (char *devname, unsigned char addr,
53 		      unsigned char reg, unsigned short value);
54 };
55 
56 static struct list_head mii_devs;
57 static struct mii_dev *current_mii;
58 
59 /*****************************************************************************
60  *
61  * Initialize global data. Need to be called before any other miiphy routine.
62  */
63 void miiphy_init ()
64 {
65 	INIT_LIST_HEAD (&mii_devs);
66 	current_mii = NULL;
67 }
68 
69 /*****************************************************************************
70  *
71  * Register read and write MII access routines for the device <name>.
72  */
73 void miiphy_register (char *name,
74 		      int (*read) (char *devname, unsigned char addr,
75 				   unsigned char reg, unsigned short *value),
76 		      int (*write) (char *devname, unsigned char addr,
77 				    unsigned char reg, unsigned short value))
78 {
79 	struct list_head *entry;
80 	struct mii_dev *new_dev;
81 	struct mii_dev *miidev;
82 	unsigned int name_len;
83 
84 	/* check if we have unique name */
85 	list_for_each (entry, &mii_devs) {
86 		miidev = list_entry (entry, struct mii_dev, link);
87 		if (strcmp (miidev->name, name) == 0) {
88 			printf ("miiphy_register: non unique device name "
89 				"'%s'\n", name);
90 			return;
91 		}
92 	}
93 
94 	/* allocate memory */
95 	name_len = strlen (name);
96 	new_dev =
97 	    (struct mii_dev *)malloc (sizeof (struct mii_dev) + name_len + 1);
98 
99 	if (new_dev == NULL) {
100 		printf ("miiphy_register: cannot allocate memory for '%s'\n",
101 			name);
102 		return;
103 	}
104 	memset (new_dev, 0, sizeof (struct mii_dev) + name_len);
105 
106 	/* initalize mii_dev struct fields */
107 	INIT_LIST_HEAD (&new_dev->link);
108 	new_dev->read = read;
109 	new_dev->write = write;
110 	new_dev->name = (char *)(new_dev + 1);
111 	strncpy (new_dev->name, name, name_len);
112 	new_dev->name[name_len] = '\0';
113 
114 	debug ("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
115 	       new_dev->name, new_dev->read, new_dev->write);
116 
117 	/* add it to the list */
118 	list_add_tail (&new_dev->link, &mii_devs);
119 
120 	if (!current_mii)
121 		current_mii = new_dev;
122 }
123 
124 int miiphy_set_current_dev (char *devname)
125 {
126 	struct list_head *entry;
127 	struct mii_dev *dev;
128 
129 	list_for_each (entry, &mii_devs) {
130 		dev = list_entry (entry, struct mii_dev, link);
131 
132 		if (strcmp (devname, dev->name) == 0) {
133 			current_mii = dev;
134 			return 0;
135 		}
136 	}
137 
138 	printf ("No such device: %s\n", devname);
139 	return 1;
140 }
141 
142 char *miiphy_get_current_dev ()
143 {
144 	if (current_mii)
145 		return current_mii->name;
146 
147 	return NULL;
148 }
149 
150 /*****************************************************************************
151  *
152  * Read to variable <value> from the PHY attached to device <devname>,
153  * use PHY address <addr> and register <reg>.
154  *
155  * Returns:
156  *   0 on success
157  */
158 int miiphy_read (char *devname, unsigned char addr, unsigned char reg,
159 		 unsigned short *value)
160 {
161 	struct list_head *entry;
162 	struct mii_dev *dev;
163 	int found_dev = 0;
164 	int read_ret = 0;
165 
166 	if (!devname) {
167 		printf ("NULL device name!\n");
168 		return 1;
169 	}
170 
171 	list_for_each (entry, &mii_devs) {
172 		dev = list_entry (entry, struct mii_dev, link);
173 
174 		if (strcmp (devname, dev->name) == 0) {
175 			found_dev = 1;
176 			read_ret = dev->read (devname, addr, reg, value);
177 			break;
178 		}
179 	}
180 
181 	if (found_dev == 0)
182 		printf ("No such device: %s\n", devname);
183 
184 	return ((found_dev) ? read_ret : 1);
185 }
186 
187 /*****************************************************************************
188  *
189  * Write <value> to the PHY attached to device <devname>,
190  * use PHY address <addr> and register <reg>.
191  *
192  * Returns:
193  *   0 on success
194  */
195 int miiphy_write (char *devname, unsigned char addr, unsigned char reg,
196 		  unsigned short value)
197 {
198 	struct list_head *entry;
199 	struct mii_dev *dev;
200 	int found_dev = 0;
201 	int write_ret = 0;
202 
203 	if (!devname) {
204 		printf ("NULL device name!\n");
205 		return 1;
206 	}
207 
208 	list_for_each (entry, &mii_devs) {
209 		dev = list_entry (entry, struct mii_dev, link);
210 
211 		if (strcmp (devname, dev->name) == 0) {
212 			found_dev = 1;
213 			write_ret = dev->write (devname, addr, reg, value);
214 			break;
215 		}
216 	}
217 
218 	if (found_dev == 0)
219 		printf ("No such device: %s\n", devname);
220 
221 	return ((found_dev) ? write_ret : 1);
222 }
223 
224 /*****************************************************************************
225  *
226  * Print out list of registered MII capable devices.
227  */
228 void miiphy_listdev (void)
229 {
230 	struct list_head *entry;
231 	struct mii_dev *dev;
232 
233 	puts ("MII devices: ");
234 	list_for_each (entry, &mii_devs) {
235 		dev = list_entry (entry, struct mii_dev, link);
236 		printf ("'%s' ", dev->name);
237 	}
238 	puts ("\n");
239 
240 	if (current_mii)
241 		printf ("Current device: '%s'\n", current_mii->name);
242 }
243 
244 /*****************************************************************************
245  *
246  * Read the OUI, manufacture's model number, and revision number.
247  *
248  * OUI:     22 bits (unsigned int)
249  * Model:    6 bits (unsigned char)
250  * Revision: 4 bits (unsigned char)
251  *
252  * Returns:
253  *   0 on success
254  */
255 int miiphy_info (char *devname, unsigned char addr, unsigned int *oui,
256 		 unsigned char *model, unsigned char *rev)
257 {
258 	unsigned int reg = 0;
259 	unsigned short tmp;
260 
261 	if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) {
262 		debug ("PHY ID register 2 read failed\n");
263 		return (-1);
264 	}
265 	reg = tmp;
266 
267 	debug ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg);
268 
269 	if (reg == 0xFFFF) {
270 		/* No physical device present at this address */
271 		return (-1);
272 	}
273 
274 	if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) {
275 		debug ("PHY ID register 1 read failed\n");
276 		return (-1);
277 	}
278 	reg |= tmp << 16;
279 	debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
280 
281 	*oui = (reg >> 10);
282 	*model = (unsigned char)((reg >> 4) & 0x0000003F);
283 	*rev = (unsigned char)(reg & 0x0000000F);
284 	return (0);
285 }
286 
287 /*****************************************************************************
288  *
289  * Reset the PHY.
290  * Returns:
291  *   0 on success
292  */
293 int miiphy_reset (char *devname, unsigned char addr)
294 {
295 	unsigned short reg;
296 	int loop_cnt;
297 
298 	if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
299 		debug ("PHY status read failed\n");
300 		return (-1);
301 	}
302 	if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) {
303 		debug ("PHY reset failed\n");
304 		return (-1);
305 	}
306 #ifdef CONFIG_PHY_RESET_DELAY
307 	udelay (CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */
308 #endif
309 	/*
310 	 * Poll the control register for the reset bit to go to 0 (it is
311 	 * auto-clearing).  This should happen within 0.5 seconds per the
312 	 * IEEE spec.
313 	 */
314 	loop_cnt = 0;
315 	reg = 0x8000;
316 	while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) {
317 		if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
318 			debug ("PHY status read failed\n");
319 			return (-1);
320 		}
321 	}
322 	if ((reg & 0x8000) == 0) {
323 		return (0);
324 	} else {
325 		puts ("PHY reset timed out\n");
326 		return (-1);
327 	}
328 	return (0);
329 }
330 
331 /*****************************************************************************
332  *
333  * Determine the ethernet speed (10/100/1000).  Return 10 on error.
334  */
335 int miiphy_speed (char *devname, unsigned char addr)
336 {
337 	u16 bmcr, anlpar;
338 
339 #if defined(CONFIG_PHY_GIGE)
340 	u16 btsr;
341 
342 	/*
343 	 * Check for 1000BASE-X.  If it is supported, then assume that the speed
344 	 * is 1000.
345 	 */
346 	if (miiphy_is_1000base_x (devname, addr)) {
347 		return _1000BASET;
348 	}
349 	/*
350 	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
351 	 */
352 	/* Check for 1000BASE-T. */
353 	if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
354 		printf ("PHY 1000BT status");
355 		goto miiphy_read_failed;
356 	}
357 	if (btsr != 0xFFFF &&
358 	    (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
359 		return _1000BASET;
360 	}
361 #endif /* CONFIG_PHY_GIGE */
362 
363 	/* Check Basic Management Control Register first. */
364 	if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
365 		printf ("PHY speed");
366 		goto miiphy_read_failed;
367 	}
368 	/* Check if auto-negotiation is on. */
369 	if (bmcr & PHY_BMCR_AUTON) {
370 		/* Get auto-negotiation results. */
371 		if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
372 			printf ("PHY AN speed");
373 			goto miiphy_read_failed;
374 		}
375 		return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
376 	}
377 	/* Get speed from basic control settings. */
378 	return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;
379 
380       miiphy_read_failed:
381 	printf (" read failed, assuming 10BASE-T\n");
382 	return _10BASET;
383 }
384 
385 /*****************************************************************************
386  *
387  * Determine full/half duplex.  Return half on error.
388  */
389 int miiphy_duplex (char *devname, unsigned char addr)
390 {
391 	u16 bmcr, anlpar;
392 
393 #if defined(CONFIG_PHY_GIGE)
394 	u16 btsr;
395 
396 	/* Check for 1000BASE-X. */
397 	if (miiphy_is_1000base_x (devname, addr)) {
398 		/* 1000BASE-X */
399 		if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
400 			printf ("1000BASE-X PHY AN duplex");
401 			goto miiphy_read_failed;
402 		}
403 	}
404 	/*
405 	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
406 	 */
407 	/* Check for 1000BASE-T. */
408 	if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
409 		printf ("PHY 1000BT status");
410 		goto miiphy_read_failed;
411 	}
412 	if (btsr != 0xFFFF) {
413 		if (btsr & PHY_1000BTSR_1000FD) {
414 			return FULL;
415 		} else if (btsr & PHY_1000BTSR_1000HD) {
416 			return HALF;
417 		}
418 	}
419 #endif /* CONFIG_PHY_GIGE */
420 
421 	/* Check Basic Management Control Register first. */
422 	if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
423 		puts ("PHY duplex");
424 		goto miiphy_read_failed;
425 	}
426 	/* Check if auto-negotiation is on. */
427 	if (bmcr & PHY_BMCR_AUTON) {
428 		/* Get auto-negotiation results. */
429 		if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
430 			puts ("PHY AN duplex");
431 			goto miiphy_read_failed;
432 		}
433 		return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
434 		    FULL : HALF;
435 	}
436 	/* Get speed from basic control settings. */
437 	return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;
438 
439       miiphy_read_failed:
440 	printf (" read failed, assuming half duplex\n");
441 	return HALF;
442 }
443 
444 /*****************************************************************************
445  *
446  * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
447  * 1000BASE-T, or on error.
448  */
449 int miiphy_is_1000base_x (char *devname, unsigned char addr)
450 {
451 #if defined(CONFIG_PHY_GIGE)
452 	u16 exsr;
453 
454 	if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
455 		printf ("PHY extended status read failed, assuming no "
456 			"1000BASE-X\n");
457 		return 0;
458 	}
459 	return 0 != (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH));
460 #else
461 	return 0;
462 #endif
463 }
464 
465 #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
466 /*****************************************************************************
467  *
468  * Determine link status
469  */
470 int miiphy_link (char *devname, unsigned char addr)
471 {
472 	unsigned short reg;
473 
474 	/* dummy read; needed to latch some phys */
475 	(void)miiphy_read (devname, addr, PHY_BMSR, &reg);
476 	if (miiphy_read (devname, addr, PHY_BMSR, &reg)) {
477 		puts ("PHY_BMSR read failed, assuming no link\n");
478 		return (0);
479 	}
480 
481 	/* Determine if a link is active */
482 	if ((reg & PHY_BMSR_LS) != 0) {
483 		return (1);
484 	} else {
485 		return (0);
486 	}
487 }
488 #endif
489