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