Linux-2.6.12-rc2
[cascardo/linux.git] / 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   {NULL}};
67
68
69 static const char *block_name[] __devinitdata = {
70         "21140 non-MII",
71         "21140 MII PHY",
72         "21142 Serial PHY",
73         "21142 MII PHY",
74         "21143 SYM PHY",
75         "21143 reset method"
76 };
77
78
79 /**
80  * tulip_build_fake_mediatable - Build a fake mediatable entry.
81  * @tp: Ptr to the tulip private data.
82  *
83  * Some cards like the 3x5 HSC cards (J3514A) do not have a standard 
84  * srom and can not be handled under the fixup routine.  These cards
85  * still need a valid mediatable entry for correct csr12 setup and 
86  * mii handling.
87  * 
88  * Since this is currently a parisc-linux specific function, the
89  * #ifdef __hppa__ should completely optimize this function away for
90  * non-parisc hardware.
91  */
92 static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
93 {
94 #ifdef CONFIG_GSC
95         if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
96                 static unsigned char leafdata[] =
97                         { 0x01,       /* phy number */
98                           0x02,       /* gpr setup sequence length */
99                           0x02, 0x00, /* gpr setup sequence */
100                           0x02,       /* phy reset sequence length */
101                           0x01, 0x00, /* phy reset sequence */
102                           0x00, 0x78, /* media capabilities */
103                           0x00, 0xe0, /* nway advertisment */
104                           0x00, 0x05, /* fdx bit map */
105                           0x00, 0x06  /* ttm bit map */
106                         };
107
108                 tp->mtable = (struct mediatable *)
109                         kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
110
111                 if (tp->mtable == NULL)
112                         return; /* Horrible, impossible failure. */
113
114                 tp->mtable->defaultmedia = 0x800;
115                 tp->mtable->leafcount = 1;
116                 tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
117                 tp->mtable->has_nonmii = 0;
118                 tp->mtable->has_reset = 0;
119                 tp->mtable->has_mii = 1;
120                 tp->mtable->csr15dir = tp->mtable->csr15val = 0;
121                 tp->mtable->mleaf[0].type = 1;
122                 tp->mtable->mleaf[0].media = 11;
123                 tp->mtable->mleaf[0].leafdata = &leafdata[0];
124                 tp->flags |= HAS_PHY_IRQ;
125                 tp->csr12_shadow = -1;
126         }
127 #endif 
128 }
129
130 void __devinit tulip_parse_eeprom(struct net_device *dev)
131 {
132         /* The last media info list parsed, for multiport boards.  */
133         static struct mediatable *last_mediatable;
134         static unsigned char *last_ee_data;
135         static int controller_index;
136         struct tulip_private *tp = netdev_priv(dev);
137         unsigned char *ee_data = tp->eeprom;
138         int i;
139
140         tp->mtable = NULL;
141         /* Detect an old-style (SA only) EEPROM layout:
142            memcmp(eedata, eedata+16, 8). */
143         for (i = 0; i < 8; i ++)
144                 if (ee_data[i] != ee_data[16+i])
145                         break;
146         if (i >= 8) {
147                 if (ee_data[0] == 0xff) {
148                         if (last_mediatable) {
149                                 controller_index++;
150                                 printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
151                                            dev->name, controller_index);
152                                 tp->mtable = last_mediatable;
153                                 ee_data = last_ee_data;
154                                 goto subsequent_board;
155                         } else
156                                 printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
157                                            "not work correctly!\n",
158                            dev->name);
159                         return;
160                 }
161           /* Do a fix-up based on the vendor half of the station address prefix. */
162           for (i = 0; eeprom_fixups[i].name; i++) {
163                 if (dev->dev_addr[0] == eeprom_fixups[i].addr0
164                         &&  dev->dev_addr[1] == eeprom_fixups[i].addr1
165                         &&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
166                   if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
167                           i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
168                   memcpy(ee_data + 26, eeprom_fixups[i].newtable,
169                                  sizeof(eeprom_fixups[i].newtable));
170                   printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
171                                  " substitute media control info.\n",
172                                  dev->name, eeprom_fixups[i].name);
173                   break;
174                 }
175           }
176           if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
177                   printk(KERN_INFO "%s: Old style EEPROM with no media selection "
178                                  "information.\n",
179                            dev->name);
180                 return;
181           }
182         }
183
184         controller_index = 0;
185         if (ee_data[19] > 1) {          /* Multiport board. */
186                 last_ee_data = ee_data;
187         }
188 subsequent_board:
189
190         if (ee_data[27] == 0) {         /* No valid media table. */
191                 tulip_build_fake_mediatable(tp);
192         } else {
193                 unsigned char *p = (void *)ee_data + ee_data[27];
194                 unsigned char csr12dir = 0;
195                 int count, new_advertise = 0;
196                 struct mediatable *mtable;
197                 u16 media = get_u16(p);
198
199                 p += 2;
200                 if (tp->flags & CSR12_IN_SROM)
201                         csr12dir = *p++;
202                 count = *p++;
203
204                 /* there is no phy information, don't even try to build mtable */
205                 if (count == 0) {
206                         if (tulip_debug > 0)
207                                 printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
208                         return;
209                 }
210
211                 mtable = (struct mediatable *)
212                         kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
213                                         GFP_KERNEL);
214                 if (mtable == NULL)
215                         return;                         /* Horrible, impossible failure. */
216                 last_mediatable = tp->mtable = mtable;
217                 mtable->defaultmedia = media;
218                 mtable->leafcount = count;
219                 mtable->csr12dir = csr12dir;
220                 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
221                 mtable->csr15dir = mtable->csr15val = 0;
222
223                 printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
224                            media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
225                 for (i = 0; i < count; i++) {
226                         struct medialeaf *leaf = &mtable->mleaf[i];
227
228                         if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
229                                 leaf->type = 0;
230                                 leaf->media = p[0] & 0x3f;
231                                 leaf->leafdata = p;
232                                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
233                                         mtable->has_mii = 1;
234                                 p += 4;
235                         } else {
236                                 leaf->type = p[1];
237                                 if (p[1] == 0x05) {
238                                         mtable->has_reset = i;
239                                         leaf->media = p[2] & 0x0f;
240                                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
241                                         /* Hack to ignore Davicom delay period block */
242                                         mtable->leafcount--;
243                                         count--;
244                                         i--;
245                                         leaf->leafdata = p + 2;
246                                         p += (p[0] & 0x3f) + 1;
247                                         continue;
248                                 } else if (p[1] & 1) {
249                                         int gpr_len, reset_len;
250
251                                         mtable->has_mii = 1;
252                                         leaf->media = 11;
253                                         gpr_len=p[3]*2;
254                                         reset_len=p[4+gpr_len]*2;
255                                         new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
256                                 } else {
257                                         mtable->has_nonmii = 1;
258                                         leaf->media = p[2] & MEDIA_MASK;
259                                         /* Davicom's media number for 100BaseTX is strange */
260                                         if (tp->chip_id == DM910X && leaf->media == 1)
261                                                 leaf->media = 3;
262                                         switch (leaf->media) {
263                                         case 0: new_advertise |= 0x0020; break;
264                                         case 4: new_advertise |= 0x0040; break;
265                                         case 3: new_advertise |= 0x0080; break;
266                                         case 5: new_advertise |= 0x0100; break;
267                                         case 6: new_advertise |= 0x0200; break;
268                                         }
269                                         if (p[1] == 2  &&  leaf->media == 0) {
270                                                 if (p[2] & 0x40) {
271                                                         u32 base15 = get_unaligned((u16*)&p[7]);
272                                                         mtable->csr15dir =
273                                                                 (get_unaligned((u16*)&p[9])<<16) + base15;
274                                                         mtable->csr15val =
275                                                                 (get_unaligned((u16*)&p[11])<<16) + base15;
276                                                 } else {
277                                                         mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
278                                                         mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
279                                                 }
280                                         }
281                                 }
282                                 leaf->leafdata = p + 2;
283                                 p += (p[0] & 0x3f) + 1;
284                         }
285                         if (tulip_debug > 1  &&  leaf->media == 11) {
286                                 unsigned char *bp = leaf->leafdata;
287                                 printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
288                                            "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
289                                            dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
290                                            bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
291                         }
292                         printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
293                                    "by a %s (%d) block.\n",
294                                    dev->name, i, medianame[leaf->media & 15], leaf->media,
295                                    leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
296                                    leaf->type);
297                 }
298                 if (new_advertise)
299                         tp->sym_advertise = new_advertise;
300         }
301 }
302 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
303
304 /*  EEPROM_Ctrl bits. */
305 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
306 #define EE_CS           0x01    /* EEPROM chip select. */
307 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
308 #define EE_WRITE_0      0x01
309 #define EE_WRITE_1      0x05
310 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
311 #define EE_ENB          (0x4800 | EE_CS)
312
313 /* Delay between EEPROM clock transitions.
314    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
315    We add a bus turn-around to insure that this remains true. */
316 #define eeprom_delay()  ioread32(ee_addr)
317
318 /* The EEPROM commands include the alway-set leading bit. */
319 #define EE_READ_CMD             (6)
320
321 /* Note: this routine returns extra data bits for size detection. */
322 int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
323 {
324         int i;
325         unsigned retval = 0;
326         struct tulip_private *tp = dev->priv;
327         void __iomem *ee_addr = tp->base_addr + CSR9;
328         int read_cmd = location | (EE_READ_CMD << addr_len);
329
330         iowrite32(EE_ENB & ~EE_CS, ee_addr);
331         iowrite32(EE_ENB, ee_addr);
332
333         /* Shift the read command bits out. */
334         for (i = 4 + addr_len; i >= 0; i--) {
335                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
336                 iowrite32(EE_ENB | dataval, ee_addr);
337                 eeprom_delay();
338                 iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
339                 eeprom_delay();
340                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
341         }
342         iowrite32(EE_ENB, ee_addr);
343         eeprom_delay();
344
345         for (i = 16; i > 0; i--) {
346                 iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
347                 eeprom_delay();
348                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
349                 iowrite32(EE_ENB, ee_addr);
350                 eeprom_delay();
351         }
352
353         /* Terminate the EEPROM access. */
354         iowrite32(EE_ENB & ~EE_CS, ee_addr);
355         return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
356 }
357