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