aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tulip/eeprom.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/tulip/eeprom.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/net/tulip/eeprom.c')
-rw-r--r--drivers/net/tulip/eeprom.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
new file mode 100644
index 000000000000..ac5bf49ff60f
--- /dev/null
+++ b/drivers/net/tulip/eeprom.c
@@ -0,0 +1,357 @@
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. */
32static 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
69static 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 */
92static 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
130void __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 }
188subsequent_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. */
322int __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