Back to home page

OSCL-LXR

 
 

    


0001 /*
0002     drivers/net/ethernet/dec/tulip/eeprom.c
0003 
0004     Copyright 2000,2001  The Linux Kernel Team
0005     Written/copyright 1994-2001 by Donald Becker.
0006 
0007     This software may be used and distributed according to the terms
0008     of the GNU General Public License, incorporated herein by reference.
0009 
0010     Please submit bug reports to http://bugzilla.kernel.org/.
0011 */
0012 
0013 #include <linux/pci.h>
0014 #include <linux/slab.h>
0015 #include "tulip.h"
0016 #include <asm/unaligned.h>
0017 
0018 
0019 
0020 /* Serial EEPROM section. */
0021 /* The main routine to parse the very complicated SROM structure.
0022    Search www.digital.com for "21X4 SROM" to get details.
0023    This code is very complex, and will require changes to support
0024    additional cards, so I'll be verbose about what is going on.
0025    */
0026 
0027 /* Known cards that have old-style EEPROMs. */
0028 static struct eeprom_fixup eeprom_fixups[] = {
0029   {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
0030               0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
0031   {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
0032                0x0000, 0x009E, /* 10baseT */
0033                0x0004, 0x009E, /* 10baseT-FD */
0034                0x0903, 0x006D, /* 100baseTx */
0035                0x0905, 0x006D, /* 100baseTx-FD */ }},
0036   {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
0037                  0x0107, 0x8021, /* 100baseFx */
0038                  0x0108, 0x8021, /* 100baseFx-FD */
0039                  0x0100, 0x009E, /* 10baseT */
0040                  0x0104, 0x009E, /* 10baseT-FD */
0041                  0x0103, 0x006D, /* 100baseTx */
0042                  0x0105, 0x006D, /* 100baseTx-FD */ }},
0043   {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
0044                    0x1001, 0x009E, /* 10base2, CSR12 0x10*/
0045                    0x0000, 0x009E, /* 10baseT */
0046                    0x0004, 0x009E, /* 10baseT-FD */
0047                    0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
0048                    0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
0049   {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
0050                   0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
0051                   0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
0052                   0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
0053                   0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
0054                   0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
0055    }},
0056   {"NetWinder", 0x00, 0x10, 0x57,
0057     /* Default media = MII
0058      * MII block, reset sequence (3) = 0x0821 0x0000 0x0001, capabilities 0x01e1
0059      */
0060     { 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
0061   },
0062   {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset */
0063                      0x0000, /* 0 == high offset, 0 == gap      */
0064                      0x0800, /* Default Autoselect          */
0065                      0x8001, /* 1 leaf, extended type, bogus len    */
0066                      0x0003, /* Type 3 (MII), PHY #0        */
0067                      0x0400, /* 0 init instr, 4 reset instr     */
0068                      0x0801, /* Set control mode, GP0 output    */
0069                      0x0000, /* Drive GP0 Low (RST is active low)   */
0070                      0x0800, /* control mode, GP0 input (undriven)  */
0071                      0x0000, /* clear control mode          */
0072                      0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX */
0073                      0x01e0, /* Advertise all above         */
0074                      0x5000, /* FDX all above           */
0075                      0x1800, /* Set fast TTM in 100bt modes     */
0076                      0x0000, /* PHY cannot be unplugged     */
0077   }},
0078   {NULL}};
0079 
0080 
0081 static const char *const block_name[] = {
0082     "21140 non-MII",
0083     "21140 MII PHY",
0084     "21142 Serial PHY",
0085     "21142 MII PHY",
0086     "21143 SYM PHY",
0087     "21143 reset method"
0088 };
0089 
0090 
0091 /**
0092  * tulip_build_fake_mediatable - Build a fake mediatable entry.
0093  * @tp: Ptr to the tulip private data.
0094  *
0095  * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
0096  * srom and can not be handled under the fixup routine.  These cards
0097  * still need a valid mediatable entry for correct csr12 setup and
0098  * mii handling.
0099  *
0100  * Since this is currently a parisc-linux specific function, the
0101  * #ifdef __hppa__ should completely optimize this function away for
0102  * non-parisc hardware.
0103  */
0104 static void tulip_build_fake_mediatable(struct tulip_private *tp)
0105 {
0106 #ifdef CONFIG_GSC
0107     if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
0108         static unsigned char leafdata[] =
0109             { 0x01,       /* phy number */
0110               0x02,       /* gpr setup sequence length */
0111               0x02, 0x00, /* gpr setup sequence */
0112               0x02,       /* phy reset sequence length */
0113               0x01, 0x00, /* phy reset sequence */
0114               0x00, 0x78, /* media capabilities */
0115               0x00, 0xe0, /* nway advertisement */
0116               0x00, 0x05, /* fdx bit map */
0117               0x00, 0x06  /* ttm bit map */
0118             };
0119 
0120         tp->mtable = devm_kmalloc(&tp->pdev->dev, sizeof(struct mediatable) +
0121                       sizeof(struct medialeaf), GFP_KERNEL);
0122 
0123         if (tp->mtable == NULL)
0124             return; /* Horrible, impossible failure. */
0125 
0126         tp->mtable->defaultmedia = 0x800;
0127         tp->mtable->leafcount = 1;
0128         tp->mtable->csr12dir = 0x3f; /* inputs on bit7 for hsc-pci, bit6 for pci-fx */
0129         tp->mtable->has_nonmii = 0;
0130         tp->mtable->has_reset = 0;
0131         tp->mtable->has_mii = 1;
0132         tp->mtable->csr15dir = tp->mtable->csr15val = 0;
0133         tp->mtable->mleaf[0].type = 1;
0134         tp->mtable->mleaf[0].media = 11;
0135         tp->mtable->mleaf[0].leafdata = &leafdata[0];
0136         tp->flags |= HAS_PHY_IRQ;
0137         tp->csr12_shadow = -1;
0138     }
0139 #endif
0140 }
0141 
0142 void tulip_parse_eeprom(struct net_device *dev)
0143 {
0144     /*
0145       dev is not registered at this point, so logging messages can't
0146       use dev_<level> or netdev_<level> but dev->name is good via a
0147       hack in the caller
0148     */
0149 
0150     /* The last media info list parsed, for multiport boards.  */
0151     static struct mediatable *last_mediatable;
0152     static unsigned char *last_ee_data;
0153     static int controller_index;
0154     struct tulip_private *tp = netdev_priv(dev);
0155     unsigned char *ee_data = tp->eeprom;
0156     int i;
0157 
0158     tp->mtable = NULL;
0159     /* Detect an old-style (SA only) EEPROM layout:
0160        memcmp(eedata, eedata+16, 8). */
0161     for (i = 0; i < 8; i ++)
0162         if (ee_data[i] != ee_data[16+i])
0163             break;
0164     if (i >= 8) {
0165         if (ee_data[0] == 0xff) {
0166             if (last_mediatable) {
0167                 controller_index++;
0168                 pr_info("%s: Controller %d of multiport board\n",
0169                     dev->name, controller_index);
0170                 tp->mtable = last_mediatable;
0171                 ee_data = last_ee_data;
0172                 goto subsequent_board;
0173             } else
0174                 pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
0175                     dev->name);
0176             return;
0177         }
0178       /* Do a fix-up based on the vendor half of the station address prefix. */
0179       for (i = 0; eeprom_fixups[i].name; i++) {
0180           if (dev->dev_addr[0] == eeprom_fixups[i].addr0 &&
0181               dev->dev_addr[1] == eeprom_fixups[i].addr1 &&
0182               dev->dev_addr[2] == eeprom_fixups[i].addr2) {
0183           if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55)
0184               i++;          /* An Accton EN1207, not an outlaw Maxtech. */
0185           memcpy(ee_data + 26, eeprom_fixups[i].newtable,
0186                  sizeof(eeprom_fixups[i].newtable));
0187           pr_info("%s: Old format EEPROM on '%s' board.  Using substitute media control info\n",
0188               dev->name, eeprom_fixups[i].name);
0189           break;
0190         }
0191       }
0192       if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
0193           pr_info("%s: Old style EEPROM with no media selection information\n",
0194               dev->name);
0195         return;
0196       }
0197     }
0198 
0199     controller_index = 0;
0200     if (ee_data[19] > 1) {      /* Multiport board. */
0201         last_ee_data = ee_data;
0202     }
0203 subsequent_board:
0204 
0205     if (ee_data[27] == 0) {     /* No valid media table. */
0206         tulip_build_fake_mediatable(tp);
0207     } else {
0208         unsigned char *p = (void *)ee_data + ee_data[27];
0209         unsigned char csr12dir = 0;
0210         int count, new_advertise = 0;
0211         struct mediatable *mtable;
0212         u16 media = get_u16(p);
0213 
0214         p += 2;
0215         if (tp->flags & CSR12_IN_SROM)
0216             csr12dir = *p++;
0217         count = *p++;
0218 
0219             /* there is no phy information, don't even try to build mtable */
0220             if (count == 0) {
0221             if (tulip_debug > 0)
0222                 pr_warn("%s: no phy info, aborting mtable build\n",
0223                     dev->name);
0224                 return;
0225         }
0226 
0227         mtable = devm_kmalloc(&tp->pdev->dev, struct_size(mtable, mleaf, count),
0228                       GFP_KERNEL);
0229         if (mtable == NULL)
0230             return;             /* Horrible, impossible failure. */
0231         last_mediatable = tp->mtable = mtable;
0232         mtable->defaultmedia = media;
0233         mtable->leafcount = count;
0234         mtable->csr12dir = csr12dir;
0235         mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
0236         mtable->csr15dir = mtable->csr15val = 0;
0237 
0238         pr_info("%s: EEPROM default media type %s\n",
0239             dev->name,
0240             media & 0x0800 ? "Autosense"
0241                        : medianame[media & MEDIA_MASK]);
0242         for (i = 0; i < count; i++) {
0243             struct medialeaf *leaf = &mtable->mleaf[i];
0244 
0245             if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
0246                 leaf->type = 0;
0247                 leaf->media = p[0] & 0x3f;
0248                 leaf->leafdata = p;
0249                 if ((p[2] & 0x61) == 0x01)  /* Bogus, but Znyx boards do it. */
0250                     mtable->has_mii = 1;
0251                 p += 4;
0252             } else {
0253                 leaf->type = p[1];
0254                 if (p[1] == 0x05) {
0255                     mtable->has_reset = i;
0256                     leaf->media = p[2] & 0x0f;
0257                 } else if (tp->chip_id == DM910X && p[1] == 0x80) {
0258                     /* Hack to ignore Davicom delay period block */
0259                     mtable->leafcount--;
0260                     count--;
0261                     i--;
0262                     leaf->leafdata = p + 2;
0263                     p += (p[0] & 0x3f) + 1;
0264                     continue;
0265                 } else if (p[1] & 1) {
0266                     int gpr_len, reset_len;
0267 
0268                     mtable->has_mii = 1;
0269                     leaf->media = 11;
0270                     gpr_len=p[3]*2;
0271                     reset_len=p[4+gpr_len]*2;
0272                     new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
0273                 } else {
0274                     mtable->has_nonmii = 1;
0275                     leaf->media = p[2] & MEDIA_MASK;
0276                     /* Davicom's media number for 100BaseTX is strange */
0277                     if (tp->chip_id == DM910X && leaf->media == 1)
0278                         leaf->media = 3;
0279                     switch (leaf->media) {
0280                     case 0: new_advertise |= 0x0020; break;
0281                     case 4: new_advertise |= 0x0040; break;
0282                     case 3: new_advertise |= 0x0080; break;
0283                     case 5: new_advertise |= 0x0100; break;
0284                     case 6: new_advertise |= 0x0200; break;
0285                     }
0286                     if (p[1] == 2  &&  leaf->media == 0) {
0287                         if (p[2] & 0x40) {
0288                             u32 base15 = get_unaligned((u16*)&p[7]);
0289                             mtable->csr15dir =
0290                                 (get_unaligned((u16*)&p[9])<<16) + base15;
0291                             mtable->csr15val =
0292                                 (get_unaligned((u16*)&p[11])<<16) + base15;
0293                         } else {
0294                             mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
0295                             mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
0296                         }
0297                     }
0298                 }
0299                 leaf->leafdata = p + 2;
0300                 p += (p[0] & 0x3f) + 1;
0301             }
0302             if (tulip_debug > 1  &&  leaf->media == 11) {
0303                 unsigned char *bp = leaf->leafdata;
0304                 pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
0305                     dev->name,
0306                     bp[0], bp[1], bp[2 + bp[1]*2],
0307                     bp[5 + bp[2 + bp[1]*2]*2],
0308                     bp[4 + bp[2 + bp[1]*2]*2]);
0309             }
0310             pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
0311                 dev->name,
0312                 i, medianame[leaf->media & 15], leaf->media,
0313                 leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
0314                 leaf->type);
0315         }
0316         if (new_advertise)
0317             tp->sym_advertise = new_advertise;
0318     }
0319 }
0320 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
0321 
0322 /*  EEPROM_Ctrl bits. */
0323 #define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
0324 #define EE_CS       0x01    /* EEPROM chip select. */
0325 #define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
0326 #define EE_WRITE_0  0x01
0327 #define EE_WRITE_1  0x05
0328 #define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
0329 #define EE_ENB      (0x4800 | EE_CS)
0330 
0331 /* Delay between EEPROM clock transitions.
0332    Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
0333    We add a bus turn-around to insure that this remains true. */
0334 #define eeprom_delay()  ioread32(ee_addr)
0335 
0336 /* The EEPROM commands include the alway-set leading bit. */
0337 #define EE_READ_CMD     (6)
0338 
0339 /* Note: this routine returns extra data bits for size detection. */
0340 int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
0341 {
0342     int i;
0343     unsigned retval = 0;
0344     struct tulip_private *tp = netdev_priv(dev);
0345     void __iomem *ee_addr = tp->base_addr + CSR9;
0346     int read_cmd = location | (EE_READ_CMD << addr_len);
0347 
0348     /* If location is past the end of what we can address, don't
0349      * read some other location (ie truncate). Just return zero.
0350      */
0351     if (location > (1 << addr_len) - 1)
0352         return 0;
0353 
0354     iowrite32(EE_ENB & ~EE_CS, ee_addr);
0355     iowrite32(EE_ENB, ee_addr);
0356 
0357     /* Shift the read command bits out. */
0358     for (i = 4 + addr_len; i >= 0; i--) {
0359         short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
0360         iowrite32(EE_ENB | dataval, ee_addr);
0361         eeprom_delay();
0362         iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
0363         eeprom_delay();
0364         retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
0365     }
0366     iowrite32(EE_ENB, ee_addr);
0367     eeprom_delay();
0368 
0369     for (i = 16; i > 0; i--) {
0370         iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
0371         eeprom_delay();
0372         retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
0373         iowrite32(EE_ENB, ee_addr);
0374         eeprom_delay();
0375     }
0376 
0377     /* Terminate the EEPROM access. */
0378     iowrite32(EE_ENB & ~EE_CS, ee_addr);
0379     return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
0380 }
0381