OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [net/] [tulip/] [eeprom.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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.{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 "tulip.h"
18
#include <linux/init.h>
19
#include <asm/unaligned.h>
20
 
21
 
22
 
23
/* Serial EEPROM section. */
24
/* The main routine to parse the very complicated SROM structure.
25
   Search www.digital.com for "21X4 SROM" to get details.
26
   This code is very complex, and will require changes to support
27
   additional cards, so I'll be verbose about what is going on.
28
   */
29
 
30
/* Known cards that have old-style EEPROMs. */
31
static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
32
  {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
33
                          0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
34
  {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
35
                           0x0000, 0x009E, /* 10baseT */
36
                           0x0004, 0x009E, /* 10baseT-FD */
37
                           0x0903, 0x006D, /* 100baseTx */
38
                           0x0905, 0x006D, /* 100baseTx-FD */ }},
39
  {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
40
                                 0x0107, 0x8021, /* 100baseFx */
41
                                 0x0108, 0x8021, /* 100baseFx-FD */
42
                                 0x0100, 0x009E, /* 10baseT */
43
                                 0x0104, 0x009E, /* 10baseT-FD */
44
                                 0x0103, 0x006D, /* 100baseTx */
45
                                 0x0105, 0x006D, /* 100baseTx-FD */ }},
46
  {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
47
                                   0x1001, 0x009E, /* 10base2, CSR12 0x10*/
48
                                   0x0000, 0x009E, /* 10baseT */
49
                                   0x0004, 0x009E, /* 10baseT-FD */
50
                                   0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
51
                                   0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
52
  {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
53
                                  0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
54
                                  0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
55
                                  0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
56
                                  0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
57
                                  0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
58
   }},
59
  {"NetWinder", 0x00, 0x10, 0x57,
60
        /* Default media = MII
61
         * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
62
         */
63
        { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
64
  },
65
  {0, 0, 0, 0, {}}};
66
 
67
 
68
static const char *block_name[] __devinitdata = {
69
        "21140 non-MII",
70
        "21140 MII PHY",
71
        "21142 Serial PHY",
72
        "21142 MII PHY",
73
        "21143 SYM PHY",
74
        "21143 reset method"
75
};
76
 
77
 
78
/**
79
 * tulip_build_fake_mediatable - Build a fake mediatable entry.
80
 * @tp: Ptr to the tulip private data.
81
 *
82
 * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
83
 * srom and can not be handled under the fixup routine.  These cards
84
 * still need a valid mediatable entry for correct csr12 setup and
85
 * mii handling.
86
 *
87
 * Since this is currently a parisc-linux specific function, the
88
 * #ifdef __hppa__ should completely optimize this function away for
89
 * non-parisc hardware.
90
 */
91
static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
92
{
93
#ifdef __hppa__
94
        unsigned char *ee_data = tp->eeprom;
95
 
96
        if (ee_data[0] == 0x3c && ee_data[1] == 0x10 &&
97
                (ee_data[2] == 0x63 || ee_data[2] == 0x61) && ee_data[3] == 0x10) {
98
 
99
                static unsigned char leafdata[] =
100
                        { 0x01,       /* phy number */
101
                          0x02,       /* gpr setup sequence length */
102
                          0x02, 0x00, /* gpr setup sequence */
103
                          0x02,       /* phy reset sequence length */
104
                          0x01, 0x00, /* phy reset sequence */
105
                          0x00, 0x78, /* media capabilities */
106
                          0x00, 0xe0, /* nway advertisment */
107
                          0x00, 0x05, /* fdx bit map */
108
                          0x00, 0x06  /* ttm bit map */
109
                        };
110
 
111
                tp->mtable = (struct mediatable *)
112
                        kmalloc(sizeof(struct mediatable) + sizeof(struct medialeaf), GFP_KERNEL);
113
 
114
                if (tp->mtable == NULL)
115
                        return; /* Horrible, impossible failure. */
116
 
117
                tp->mtable->defaultmedia = 0x800;
118
                tp->mtable->leafcount = 1;
119
                tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
120
                tp->mtable->has_nonmii = 0;
121
                tp->mtable->has_reset = 0;
122
                tp->mtable->has_mii = 1;
123
                tp->mtable->csr15dir = tp->mtable->csr15val = 0;
124
                tp->mtable->mleaf[0].type = 1;
125
                tp->mtable->mleaf[0].media = 11;
126
                tp->mtable->mleaf[0].leafdata = &leafdata[0];
127
                tp->flags |= HAS_PHY_IRQ;
128
                tp->csr12_shadow = -1;
129
        }
130
#endif 
131
}
132
 
133
void __devinit tulip_parse_eeprom(struct net_device *dev)
134
{
135
        /* The last media info list parsed, for multiport boards.  */
136
        static struct mediatable *last_mediatable;
137
        static unsigned char *last_ee_data;
138
        static int controller_index;
139
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
140
        unsigned char *ee_data = tp->eeprom;
141
        int i;
142
 
143
        tp->mtable = 0;
144
        /* Detect an old-style (SA only) EEPROM layout:
145
           memcmp(eedata, eedata+16, 8). */
146
        for (i = 0; i < 8; i ++)
147
                if (ee_data[i] != ee_data[16+i])
148
                        break;
149
        if (i >= 8) {
150
                if (ee_data[0] == 0xff) {
151
                        if (last_mediatable) {
152
                                controller_index++;
153
                                printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
154
                                           dev->name, controller_index);
155
                                tp->mtable = last_mediatable;
156
                                ee_data = last_ee_data;
157
                                goto subsequent_board;
158
                        } else
159
                                printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
160
                                           "not work correctly!\n",
161
                           dev->name);
162
                        return;
163
                }
164
          /* Do a fix-up based on the vendor half of the station address prefix. */
165
          for (i = 0; eeprom_fixups[i].name; i++) {
166
                if (dev->dev_addr[0] == eeprom_fixups[i].addr0
167
                        &&  dev->dev_addr[1] == eeprom_fixups[i].addr1
168
                        &&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
169
                  if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
170
                          i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
171
                  memcpy(ee_data + 26, eeprom_fixups[i].newtable,
172
                                 sizeof(eeprom_fixups[i].newtable));
173
                  printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
174
                                 " substitute media control info.\n",
175
                                 dev->name, eeprom_fixups[i].name);
176
                  break;
177
                }
178
          }
179
          if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
180
                  printk(KERN_INFO "%s: Old style EEPROM with no media selection "
181
                                 "information.\n",
182
                           dev->name);
183
                return;
184
          }
185
        }
186
 
187
        controller_index = 0;
188
        if (ee_data[19] > 1) {          /* Multiport board. */
189
                last_ee_data = ee_data;
190
        }
191
subsequent_board:
192
 
193
        if (ee_data[27] == 0) {          /* No valid media table. */
194
                tulip_build_fake_mediatable(tp);
195
        } else if (tp->chip_id == DC21041) {
196
                unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];
197
                int media = get_u16(p);
198
                int count = p[2];
199
                p += 3;
200
 
201
                printk(KERN_INFO "%s: 21041 Media table, default media %4.4x (%s).\n",
202
                           dev->name, media,
203
                           media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);
204
                for (i = 0; i < count; i++) {
205
                        unsigned char media_block = *p++;
206
                        int media_code = media_block & MEDIA_MASK;
207
                        if (media_block & 0x40)
208
                                p += 6;
209
                        printk(KERN_INFO "%s:  21041 media #%d, %s.\n",
210
                                   dev->name, media_code, medianame[media_code]);
211
                }
212
        } else {
213
                unsigned char *p = (void *)ee_data + ee_data[27];
214
                unsigned char csr12dir = 0;
215
                int count, new_advertise = 0;
216
                struct mediatable *mtable;
217
                u16 media = get_u16(p);
218
 
219
                p += 2;
220
                if (tp->flags & CSR12_IN_SROM)
221
                        csr12dir = *p++;
222
                count = *p++;
223
 
224
                /* there is no phy information, don't even try to build mtable */
225
                if (count == 0) {
226
                        if (tulip_debug > 0)
227
                                printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
228
                        return;
229
                }
230
 
231
                mtable = (struct mediatable *)
232
                        kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
233
                                        GFP_KERNEL);
234
                if (mtable == NULL)
235
                        return;                         /* Horrible, impossible failure. */
236
                last_mediatable = tp->mtable = mtable;
237
                mtable->defaultmedia = media;
238
                mtable->leafcount = count;
239
                mtable->csr12dir = csr12dir;
240
                mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
241
                mtable->csr15dir = mtable->csr15val = 0;
242
 
243
                printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
244
                           media & 0x0800 ? "Autosense" : 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
                                printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
308
                                           "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
309
                                           dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
310
                                           bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
311
                        }
312
                        printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
313
                                   "by a %s (%d) block.\n",
314
                                   dev->name, 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()  inl(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(long ioaddr, int location, int addr_len)
343
{
344
        int i;
345
        unsigned retval = 0;
346
        long ee_addr = ioaddr + CSR9;
347
        int read_cmd = location | (EE_READ_CMD << addr_len);
348
 
349
        outl(EE_ENB & ~EE_CS, ee_addr);
350
        outl(EE_ENB, ee_addr);
351
 
352
        /* Shift the read command bits out. */
353
        for (i = 4 + addr_len; i >= 0; i--) {
354
                short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
355
                outl(EE_ENB | dataval, ee_addr);
356
                eeprom_delay();
357
                outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
358
                eeprom_delay();
359
                retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
360
        }
361
        outl(EE_ENB, ee_addr);
362
        eeprom_delay();
363
 
364
        for (i = 16; i > 0; i--) {
365
                outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
366
                eeprom_delay();
367
                retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
368
                outl(EE_ENB, ee_addr);
369
                eeprom_delay();
370
        }
371
 
372
        /* Terminate the EEPROM access. */
373
        outl(EE_ENB & ~EE_CS, ee_addr);
374
        return retval;
375
}
376
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.