]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/miiphyutil.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / common / miiphyutil.c
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 timeout = 500;
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 | PHY_BMCR_RESET) != 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         reg = 0x8000;
315         while (((reg & 0x8000) != 0) && timeout--) {
316                 if (miiphy_read(devname, addr, PHY_BMCR, &reg) != 0) {
317                         debug("PHY status read failed\n");
318                         return -1;
319                 }
320                 udelay(1000);
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