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 <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. */
  28static struct eeprom_fixup eeprom_fixups[] = {
  29  {"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  },
  62  {"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  }},
  78  {NULL}};
  79
  80
  81static const char *const block_name[] = {
  82        "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 *
  95 * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
  96 * srom and can not be handled under the fixup routine.  These cards
  97 * still need a valid mediatable entry for correct csr12 setup and
  98 * mii handling.
  99 *
 100 * 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 */
 104static void tulip_build_fake_mediatable(struct tulip_private *tp)
 105{
 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 */
 115                          0x00, 0xe0, /* nway advertisement */
 116                          0x00, 0x05, /* fdx bit map */
 117                          0x00, 0x06  /* ttm bit map */
 118                        };
 119
 120                tp->mtable = kmalloc(sizeof(struct mediatable) +
 121                                     sizeof(struct medialeaf), GFP_KERNEL);
 122
 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        }
 139#endif
 140}
 141
 142void tulip_parse_eeprom(struct net_device *dev)
 143{
 144        /*
 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
 150        /* 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++;
 168                                pr_info("%s: Controller %d of multiport board\n",
 169                                        dev->name, controller_index);
 170                                tp->mtable = last_mediatable;
 171                                ee_data = last_ee_data;
 172                                goto subsequent_board;
 173                        } else
 174                                pr_info("%s: Missing EEPROM, this interface may not work correctly!\n",
 175                                        dev->name);
 176                        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++) {
 180                  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)
 184                          i++;                  /* An Accton EN1207, not an outlaw Maxtech. */
 185                  memcpy(ee_data + 26, eeprom_fixups[i].newtable,
 186                                 sizeof(eeprom_fixups[i].newtable));
 187                  pr_info("%s: Old format EEPROM on '%s' board.  Using substitute media control info\n",
 188                          dev->name, eeprom_fixups[i].name);
 189                  break;
 190                }
 191          }
 192          if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
 193                  pr_info("%s: Old style EEPROM with no media selection information\n",
 194                          dev->name);
 195                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)
 222                                pr_warn("%s: no phy info, aborting mtable build\n",
 223                                        dev->name);
 224                        return;
 225                }
 226
 227                mtable = kmalloc(sizeof(struct mediatable) +
 228                                 count * sizeof(struct medialeaf),
 229                                 GFP_KERNEL);
 230                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
 239                pr_info("%s: EEPROM default media type %s\n",
 240                        dev->name,
 241                        media & 0x0800 ? "Autosense"
 242                                       : medianame[media & MEDIA_MASK]);
 243                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;
 305                                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]);
 310                        }
 311                        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);
 316                }
 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. */
 341int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
 342{
 343        int i;
 344        unsigned retval = 0;
 345        struct tulip_private *tp = netdev_priv(dev);
 346        void __iomem *ee_addr = tp->base_addr + CSR9;
 347        int read_cmd = location | (EE_READ_CMD << addr_len);
 348
 349        /* 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
 355        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
 383