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