Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / drivers / net / tulip / eeprom.c
1 /*
2         drivers/net/tulip/eeprom.c
3
4         Maintained by Jeff Garzik <jgarzik@pobox.com>
5         Copyright 2000,2001  The Linux Kernel Team
6         Written/copyright 1994-2001 by Donald Becker.
7
8         This software may be used and distributed according to the terms
9         of the GNU General Public License, incorporated herein by reference.
10
11         Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
12         for more information on this driver, or visit the project
13         Web page at http://sourceforge.net/projects/tulip/
14
15 */
16
17 #include <linux/pci.h>
18 #include "tulip.h"
19 #include <linux/init.h>
20 #include <asm/unaligned.h>
21
22
23
24 /* Serial EEPROM section. */
25 /* The main routine to parse the very complicated SROM structure.
26    Search www.digital.com for "21X4 SROM" to get details.
27    This code is very complex, and will require changes to support
28    additional cards, so I'll be verbose about what is going on.
29    */
30
31 /* Known cards that have old-style EEPROMs. */
32 static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
33   {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
34                           0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
35   {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
36                            0x0000, 0x009E, /* 10baseT */
37                            0x0004, 0x009E, /* 10baseT-FD */
38                            0x0903, 0x006D, /* 100baseTx */
39                            0x0905, 0x006D, /* 100baseTx-FD */ }},
40   {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
41                                  0x0107, 0x8021, /* 100baseFx */
42                                  0x0108, 0x8021, /* 100baseFx-FD */
43                                  0x0100, 0x009E, /* 10baseT */
44                                  0x0104, 0x009E, /* 10baseT-FD */
45                                  0x0103, 0x006D, /* 100baseTx */
46                                  0x0105, 0x006D, /* 100baseTx-FD */ }},
47   {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
48                                    0x1001, 0x009E, /* 10base2, CSR12 0x10*/
49                                    0x0000, 0x009E, /* 10baseT */
50                                    0x0004, 0x009E, /* 10baseT-FD */
51                                    0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
52                                    0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
53   {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
54                                   0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
55                                   0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
56                                   0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
57                                   0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
58                                   0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
59    }},
60   {"NetWinder", 0x00, 0x10, 0x57,
61         /* Default media = MII
62          * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
63          */
64         { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
65   },
66   {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset     */
67                                          0x0000, /* 0 == high offset, 0 == gap          */
68                                          0x0800, /* Default Autoselect                  */
69                                          0x8001, /* 1 leaf, extended type, bogus len    */
70                                          0x0003, /* Type 3 (MII), PHY #0                */
71                                          0x0400, /* 0 init instr, 4 reset instr         */
72                                          0x0801, /* Set control mode, GP0 output        */
73                                          0x0000, /* Drive GP0 Low (RST is active low)   */
74                                          0x0800, /* control mode, GP0 input (undriven)  */
75                                          0x0000, /* clear control mode                  */
76                                          0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX     */
77                                          0x01e0, /* Advertise all above                 */
78                                          0x5000, /* FDX all above                       */
79                                          0x1800, /* Set fast TTM in 100bt modes         */
80                                          0x0000, /* PHY cannot be unplugged             */
81   }},
82   {NULL}};
83
84
85 static const char *block_name[] __devinitdata = {
86         "21140 non-MII",
87         "21140 MII PHY",
88         "21142 Serial PHY",
89         "21142 MII PHY",
90         "21143 SYM PHY",
91         "21143 reset method"
92 };
93
94
95 /**
96  * tulip_build_fake_mediatable - Build a fake mediatable entry.
97  * @tp: Ptr to the tulip private data.
98  *
99  * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
100  * srom and can not be handled under the fixup routine.  These cards
101  * still need a valid mediatable entry for correct csr12 setup and
102  * mii handling.
103  *
104  * Since this is currently a parisc-linux specific function, the
105  * #ifdef __hppa__ should completely optimize this function away for
106  * non-parisc hardware.
107  */
108 static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
109 {
110 #ifdef CONFIG_GSC
111         if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
112                 static unsigned char leafdata[] =
113                         { 0x01,       /* phy number */
114                           0x02,       /* gpr setup sequence length */
115                           0x02, 0x00, /* gpr setup sequence */
116                           0x02,       /* phy reset sequence length */
117                           0x01, 0x00, /* phy reset sequence */
118                           0x00, 0x78, /* media capabilities */
119                           0x00, 0xe0, /* nway advertisment */
120                           0x00, 0x05, /* fdx bit map */
121                           0x00, 0x06  /* ttm bit map */
122                         };
123
124                 tp->mtable = (struct mediatable *)
125                         kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
126
127                 if (tp->mtable == NULL)
128                         return; /* Horrible, impossible failure. */
129
130                 tp->mtable->defaultmedia = 0x800;
131                 tp->mtable->leafcount = 1;
132                 tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
133                 tp->mtable->has_nonmii = 0;
134                 tp->mtable->has_reset = 0;
135                 tp->mtable->has_mii = 1;
136                 tp->mtable->csr15dir = tp->mtable->csr15val = 0;
137                 tp->mtable->mleaf[0].type = 1;
138                 tp->mtable->mleaf[0].media = 11;
139                 tp->mtable->mleaf[0].leafdata = &leafdata[0];
140                 tp->flags |= HAS_PHY_IRQ;
141                 tp->csr12_shadow = -1;
142         }
143 #endif
144 }
145
146 void __devinit tulip_parse_eeprom(struct net_device *dev)
147 {
148         /* The last media info list parsed, for multiport boards.  */
149         static struct mediatable *last_mediatable;
150         static unsigned char *last_ee_data;
151         static int controller_index;
152         struct tulip_private *tp = netdev_priv(dev);
153         unsigned char *ee_data = tp->eeprom;
154         int i;
155
156         tp->mtable = NULL;
157         /* Detect an old-style (SA only) EEPROM layout:
158            memcmp(eedata, eedata+16, 8). */
159         for (i = 0; i < 8; i ++)
160                 if (ee_data[i] != ee_data[16+i])
161                         break;
162         if (i >= 8) {
163                 if (ee_data[0] == 0xff) {
164                         if (last_mediatable) {
165                                 controller_index++;
166                                 printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
167                                            dev->name, controller_index);
168                                 tp->mtable = last_mediatable;
169                                 ee_data = last_ee_data;
170                                 goto subsequent_board;
171                         } else
172                                 printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
173                                            "not work correctly!\n",
174                            dev->name);
175                         return;
176                 }
177           /* Do a fix-up based on the vendor half of the station address prefix. */
178           for (i = 0; eeprom_fixups[i].name; i++) {
179                 if (dev->dev_addr[0] == eeprom_fixups[i].addr0
180                         &&  dev->dev_addr[1] == eeprom_fixups[i].addr1
181                         &&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
182                   if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
183                           i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
184                   memcpy(ee_data + 26, eeprom_fixups[i].newtable,
185                                  sizeof(eeprom_fixups[i].newtable));
186                   printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
187                                  " substitute media control info.\n",
188                                  dev->name, eeprom_fixups[i].name);
189                   break;
190                 }
191           }
192           if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
193                   printk(KERN_INFO "%s: Old style EEPROM with no media selection "
194                                  "information.\n",
195                            dev->name);
196                 return;
197           }
198         }
199
200         controller_index = 0;
201         if (ee_data[19] > 1) {          /* Multiport board. */
202                 last_ee_data = ee_data;
203         }
204 subsequent_board:
205
206         if (ee_data[27] == 0) {         /* No valid media table. */
207                 tulip_build_fake_mediatable(tp);
208         } else {
209                 unsigned char *p = (void *)ee_data + ee_data[27];
210                 unsigned char csr12dir = 0;
211                 int count, new_advertise = 0;
212                 struct mediatable *mtable;
213                 u16 media = get_u16(p);
214
215                 p += 2;
216                 if (tp->flags & CSR12_IN_SROM)
217                         csr12dir = *p++;
218                 count = *p++;
219
220                 /* there is no phy information, don't even try to build mtable */
221                 if (count == 0) {
222                         if (tulip_debug > 0)
223                                 printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
224                         return;
225                 }
226
227                 mtable = (struct mediatable *)
228                         kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
229                                         GFP_KERNEL);
230                 if (mtable == NULL)
231                         return;                         /* Horrible, impossible failure. */
232                 last_mediatable = tp->mtable = mtable;
233                 mtable->defaultmedia = media;
234                 mtable->leafcount = count;
235                 mtable->csr12dir = csr12dir;
236                 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
237                 mtable->csr15dir = mtable->csr15val = 0;
238
239                 printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
240                            media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
241                 for (i = 0; i < count; i++) {
242                         struct medialeaf *leaf = &mtable->mleaf[i];
243
244                         if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
245                                 leaf->type = 0;
246                                 leaf->media = p[0] & 0x3f;
247                                 leaf->leafdata = p;
248                                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
249                                         mtable->has_mii = 1;
250                                 p += 4;
251                         } else {
252                                 leaf->type = p[1];
253                                 if (p[1] == 0x05) {
254                                         mtable->has_reset = i;
255                                         leaf->media = p[2] & 0x0f;
256                                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
257                                         /* Hack to ignore Davicom delay period block */
258                                         mtable->leafcount--;
259                                         count--;
260                                         i--;
261                                         leaf->leafdata = p + 2;
262                                         p += (p[0] & 0x3f) + 1;
263                                         continue;
264                                 } else if (p[1] & 1) {
265                                         int gpr_len, reset_len;
266
267                                         mtable->has_mii = 1;
268                                         leaf->media = 11;
269                                         gpr_len=p[3]*2;
270                                         reset_len=p[4+gpr_len]*2;
271                                         new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
272                                 } else {
273                                         mtable->has_nonmii = 1;
274                                         leaf->media = p[2] & MEDIA_MASK;
275                                         /* Davicom's media number for 100BaseTX is strange */
276                                         if (tp->chip_id == DM910X && leaf->media == 1)
277                                                 leaf->media = 3;
278                                         switch (leaf->media) {
279                                         case 0: new_advertise |= 0x0020; break;
280                                         case 4: new_advertise |= 0x0040; break;
281                                         case 3: new_advertise |= 0x0080; break;
282                                         case 5: new_advertise |= 0x0100; break;
283                                         case 6: new_advertise |= 0x0200; break;
284                                         }
285                                         if (p[1] == 2  &&  leaf->media == 0) {
286                                                 if (p[2] & 0x40) {
287                                                         u32 base15 = get_unaligned((u16*)&p[7]);
288                                                         mtable->csr15dir =
289                                                                 (get_unaligned((u16*)&p[9])<<16) + base15;
290                                                         mtable->csr15val =
291                                                                 (get_unaligned((u16*)&p[11])<<16) + base15;
292                                                 } else {
293                                                         mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
294                                                         mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
295                                                 }
296                                         }
297                                 }
298                                 leaf->leafdata = p + 2;
299                                 p += (p[0] & 0x3f) + 1;
300                         }
301                         if (tulip_debug > 1  &&  leaf->media == 11) {
302                                 unsigned char *bp = leaf->leafdata;
303                                 printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
304                                            "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
305                                            dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
306                                            bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
307                         }
308                         printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
309                                    "by a %s (%d) block.\n",
310                                    dev->name, i, medianame[leaf->media & 15], leaf->media,
311                                    leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
312                                    leaf->type);
313                 }
314                 if (new_advertise)
315                         tp->sym_advertise = new_advertise;
316         }
317 }
318 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
319
320 /*  EEPROM_Ctrl bits. */
321 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
322 #define EE_CS           0x01    /* EEPROM chip select. */
323 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
324 #define EE_WRITE_0      0x01
325 #define EE_WRITE_1      0x05
326 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
327 #define EE_ENB          (0x4800 | EE_CS)
328
329 /* Delay between EEPROM clock transitions.
330    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
331    We add a bus turn-around to insure that this remains true. */
332 #define eeprom_delay()  ioread32(ee_addr)
333
334 /* The EEPROM commands include the alway-set leading bit. */
335 #define EE_READ_CMD             (6)
336
337 /* Note: this routine returns extra data bits for size detection. */
338 int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
339 {
340         int i;
341         unsigned retval = 0;
342         struct tulip_private *tp = dev->priv;
343         void __iomem *ee_addr = tp->base_addr + CSR9;
344         int read_cmd = location | (EE_READ_CMD << addr_len);
345
346         iowrite32(EE_ENB & ~EE_CS, ee_addr);
347         iowrite32(EE_ENB, ee_addr);
348
349         /* Shift the read command bits out. */
350         for (i = 4 + addr_len; i >= 0; i--) {
351                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
352                 iowrite32(EE_ENB | dataval, ee_addr);
353                 eeprom_delay();
354                 iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
355                 eeprom_delay();
356                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
357         }
358         iowrite32(EE_ENB, ee_addr);
359         eeprom_delay();
360
361         for (i = 16; i > 0; i--) {
362                 iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
363                 eeprom_delay();
364                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
365                 iowrite32(EE_ENB, ee_addr);
366                 eeprom_delay();
367         }
368
369         /* Terminate the EEPROM access. */
370         iowrite32(EE_ENB & ~EE_CS, ee_addr);
371         return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
372 }
373