linux/drivers/net/ethernet/dec/tulip/eeprom.c
<<
>>
Prefs
   1/*
   2        drivers/net/ethernet/dec/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. */
  29static struct eeprom_fixup eeprom_fixups[] = {
  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
  82static const char *const block_name[] = {
  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 */
 105static void 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
 143void 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        }
 204subsequent_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. */
 342int 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
 384