49f05d1431f5c6a67b3ffdff698e6866010ed259
[linux-flexiantxendom0-3.2.10.git] / 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         /*
147           dev is not registered at this point, so logging messages can't
148           use dev_<level> or netdev_<level> but dev->name is good via a
149           hack in the caller
150         */
151
152         /* The last media info list parsed, for multiport boards.  */
153         static struct mediatable *last_mediatable;
154         static unsigned char *last_ee_data;
155         static int controller_index;
156         struct tulip_private *tp = netdev_priv(dev);
157         unsigned char *ee_data = tp->eeprom;
158         int i;
159
160         tp->mtable = NULL;
161         /* Detect an old-style (SA only) EEPROM layout:
162            memcmp(eedata, eedata+16, 8). */
163         for (i = 0; i < 8; i ++)
164                 if (ee_data[i] != ee_data[16+i])
165                         break;
166         if (i >= 8) {
167                 if (ee_data[0] == 0xff) {
168                         if (last_mediatable) {
169                                 controller_index++;
170                                 pr_info("%s: Controller %d of multiport board\n",
171                                         dev->name, controller_index);
172                                 tp->mtable = last_mediatable;
173                                 ee_data = last_ee_data;
174                                 goto subsequent_board;
175                         } else
176                                 pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
177                                         dev->name);
178                         return;
179                 }
180           /* Do a fix-up based on the vendor half of the station address prefix. */
181           for (i = 0; eeprom_fixups[i].name; i++) {
182                   if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
183                       dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
184                       dev->dev_addr[2] == eeprom_fixups[i].addr2) {
185                   if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
186                           i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
187                   memcpy(ee_data + 26, eeprom_fixups[i].newtable,
188                                  sizeof(eeprom_fixups[i].newtable));
189                   pr_info("%s: Old format EEPROM on '%s' board.  Using substitute media control info\n",
190                           dev->name, eeprom_fixups[i].name);
191                   break;
192                 }
193           }
194           if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
195                   pr_info("%s: Old style EEPROM with no media selection information\n",
196                           dev->name);
197                 return;
198           }
199         }
200
201         controller_index = 0;
202         if (ee_data[19] > 1) {          /* Multiport board. */
203                 last_ee_data = ee_data;
204         }
205 subsequent_board:
206
207         if (ee_data[27] == 0) {         /* No valid media table. */
208                 tulip_build_fake_mediatable(tp);
209         } else {
210                 unsigned char *p = (void *)ee_data + ee_data[27];
211                 unsigned char csr12dir = 0;
212                 int count, new_advertise = 0;
213                 struct mediatable *mtable;
214                 u16 media = get_u16(p);
215
216                 p += 2;
217                 if (tp->flags & CSR12_IN_SROM)
218                         csr12dir = *p++;
219                 count = *p++;
220
221                 /* there is no phy information, don't even try to build mtable */
222                 if (count == 0) {
223                         if (tulip_debug > 0)
224                                 pr_warning("%s: no phy info, aborting mtable build\n",
225                                            dev->name);
226                         return;
227                 }
228
229                 mtable = (struct mediatable *)
230                         kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
231                                         GFP_KERNEL);
232                 if (mtable == NULL)
233                         return;                         /* Horrible, impossible failure. */
234                 last_mediatable = tp->mtable = mtable;
235                 mtable->defaultmedia = media;
236                 mtable->leafcount = count;
237                 mtable->csr12dir = csr12dir;
238                 mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
239                 mtable->csr15dir = mtable->csr15val = 0;
240
241                 pr_info("%s: EEPROM default media type %s\n",
242                         dev->name,
243                         media & 0x0800 ? "Autosense"
244                                        : medianame[media & MEDIA_MASK]);
245                 for (i = 0; i < count; i++) {
246                         struct medialeaf *leaf = &mtable->mleaf[i];
247
248                         if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
249                                 leaf->type = 0;
250                                 leaf->media = p[0] & 0x3f;
251                                 leaf->leafdata = p;
252                                 if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
253                                         mtable->has_mii = 1;
254                                 p += 4;
255                         } else {
256                                 leaf->type = p[1];
257                                 if (p[1] == 0x05) {
258                                         mtable->has_reset = i;
259                                         leaf->media = p[2] & 0x0f;
260                                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
261                                         /* Hack to ignore Davicom delay period block */
262                                         mtable->leafcount--;
263                                         count--;
264                                         i--;
265                                         leaf->leafdata = p + 2;
266                                         p += (p[0] & 0x3f) + 1;
267                                         continue;
268                                 } else if (p[1] & 1) {
269                                         int gpr_len, reset_len;
270
271                                         mtable->has_mii = 1;
272                                         leaf->media = 11;
273                                         gpr_len=p[3]*2;
274                                         reset_len=p[4+gpr_len]*2;
275                                         new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
276                                 } else {
277                                         mtable->has_nonmii = 1;
278                                         leaf->media = p[2] & MEDIA_MASK;
279                                         /* Davicom's media number for 100BaseTX is strange */
280                                         if (tp->chip_id == DM910X && leaf->media == 1)
281                                                 leaf->media = 3;
282                                         switch (leaf->media) {
283                                         case 0: new_advertise |= 0x0020; break;
284                                         case 4: new_advertise |= 0x0040; break;
285                                         case 3: new_advertise |= 0x0080; break;
286                                         case 5: new_advertise |= 0x0100; break;
287                                         case 6: new_advertise |= 0x0200; break;
288                                         }
289                                         if (p[1] == 2  &&  leaf->media == 0) {
290                                                 if (p[2] & 0x40) {
291                                                         u32 base15 = get_unaligned((u16*)&p[7]);
292                                                         mtable->csr15dir =
293                                                                 (get_unaligned((u16*)&p[9])<<16) + base15;
294                                                         mtable->csr15val =
295                                                                 (get_unaligned((u16*)&p[11])<<16) + base15;
296                                                 } else {
297                                                         mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
298                                                         mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
299                                                 }
300                                         }
301                                 }
302                                 leaf->leafdata = p + 2;
303                                 p += (p[0] & 0x3f) + 1;
304                         }
305                         if (tulip_debug > 1  &&  leaf->media == 11) {
306                                 unsigned char *bp = leaf->leafdata;
307                                 pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
308                                         dev->name,
309                                         bp[0], bp[1], bp[2 + bp[1]*2],
310                                         bp[5 + bp[2 + bp[1]*2]*2],
311                                         bp[4 + bp[2 + bp[1]*2]*2]);
312                         }
313                         pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
314                                 dev->name,
315                                 i, medianame[leaf->media & 15], leaf->media,
316                                 leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
317                                 leaf->type);
318                 }
319                 if (new_advertise)
320                         tp->sym_advertise = new_advertise;
321         }
322 }
323 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
324
325 /*  EEPROM_Ctrl bits. */
326 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
327 #define EE_CS           0x01    /* EEPROM chip select. */
328 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
329 #define EE_WRITE_0      0x01
330 #define EE_WRITE_1      0x05
331 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
332 #define EE_ENB          (0x4800 | EE_CS)
333
334 /* Delay between EEPROM clock transitions.
335    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
336    We add a bus turn-around to insure that this remains true. */
337 #define eeprom_delay()  ioread32(ee_addr)
338
339 /* The EEPROM commands include the alway-set leading bit. */
340 #define EE_READ_CMD             (6)
341
342 /* Note: this routine returns extra data bits for size detection. */
343 int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
344 {
345         int i;
346         unsigned retval = 0;
347         struct tulip_private *tp = netdev_priv(dev);
348         void __iomem *ee_addr = tp->base_addr + CSR9;
349         int read_cmd = location | (EE_READ_CMD << addr_len);
350
351         /* If location is past the end of what we can address, don't
352          * read some other location (ie truncate). Just return zero.
353          */
354         if (location > (1 << addr_len) - 1)
355                 return 0;
356
357         iowrite32(EE_ENB & ~EE_CS, ee_addr);
358         iowrite32(EE_ENB, ee_addr);
359
360         /* Shift the read command bits out. */
361         for (i = 4 + addr_len; i >= 0; i--) {
362                 short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
363                 iowrite32(EE_ENB | dataval, ee_addr);
364                 eeprom_delay();
365                 iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
366                 eeprom_delay();
367                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
368         }
369         iowrite32(EE_ENB, ee_addr);
370         eeprom_delay();
371
372         for (i = 16; i > 0; i--) {
373                 iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
374                 eeprom_delay();
375                 retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
376                 iowrite32(EE_ENB, ee_addr);
377                 eeprom_delay();
378         }
379
380         /* Terminate the EEPROM access. */
381         iowrite32(EE_ENB & ~EE_CS, ee_addr);
382         return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
383 }
384