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(struct_size(mtable, mleaf, count), GFP_KERNEL);
 228                if (mtable == NULL)
 229                        return;                         /* Horrible, impossible failure. */
 230                last_mediatable = tp->mtable = mtable;
 231                mtable->defaultmedia = media;
 232                mtable->leafcount = count;
 233                mtable->csr12dir = csr12dir;
 234                mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
 235                mtable->csr15dir = mtable->csr15val = 0;
 236
 237                pr_info("%s: EEPROM default media type %s\n",
 238                        dev->name,
 239                        media & 0x0800 ? "Autosense"
 240                                       : medianame[media & MEDIA_MASK]);
 241                for (i = 0; i < count; i++) {
 242                        struct medialeaf *leaf = &mtable->mleaf[i];
 243
 244                        if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
 245                                leaf->type = 0;
 246                                leaf->media = p[0] & 0x3f;
 247                                leaf->leafdata = p;
 248                                if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */
 249                                        mtable->has_mii = 1;
 250                                p += 4;
 251                        } else {
 252                                leaf->type = p[1];
 253                                if (p[1] == 0x05) {
 254                                        mtable->has_reset = i;
 255                                        leaf->media = p[2] & 0x0f;
 256                                } else if (tp->chip_id == DM910X && p[1] == 0x80) {
 257                                        /* Hack to ignore Davicom delay period block */
 258                                        mtable->leafcount--;
 259                                        count--;
 260                                        i--;
 261                                        leaf->leafdata = p + 2;
 262                                        p += (p[0] & 0x3f) + 1;
 263                                        continue;
 264                                } else if (p[1] & 1) {
 265                                        int gpr_len, reset_len;
 266
 267                                        mtable->has_mii = 1;
 268                                        leaf->media = 11;
 269                                        gpr_len=p[3]*2;
 270                                        reset_len=p[4+gpr_len]*2;
 271                                        new_advertise |= get_u16(&p[7+gpr_len+reset_len]);
 272                                } else {
 273                                        mtable->has_nonmii = 1;
 274                                        leaf->media = p[2] & MEDIA_MASK;
 275                                        /* Davicom's media number for 100BaseTX is strange */
 276                                        if (tp->chip_id == DM910X && leaf->media == 1)
 277                                                leaf->media = 3;
 278                                        switch (leaf->media) {
 279                                        case 0: new_advertise |= 0x0020; break;
 280                                        case 4: new_advertise |= 0x0040; break;
 281                                        case 3: new_advertise |= 0x0080; break;
 282                                        case 5: new_advertise |= 0x0100; break;
 283                                        case 6: new_advertise |= 0x0200; break;
 284                                        }
 285                                        if (p[1] == 2  &&  leaf->media == 0) {
 286                                                if (p[2] & 0x40) {
 287                                                        u32 base15 = get_unaligned((u16*)&p[7]);
 288                                                        mtable->csr15dir =
 289                                                                (get_unaligned((u16*)&p[9])<<16) + base15;
 290                                                        mtable->csr15val =
 291                                                                (get_unaligned((u16*)&p[11])<<16) + base15;
 292                                                } else {
 293                                                        mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
 294                                                        mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
 295                                                }
 296                                        }
 297                                }
 298                                leaf->leafdata = p + 2;
 299                                p += (p[0] & 0x3f) + 1;
 300                        }
 301                        if (tulip_debug > 1  &&  leaf->media == 11) {
 302                                unsigned char *bp = leaf->leafdata;
 303                                pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n",
 304                                        dev->name,
 305                                        bp[0], bp[1], bp[2 + bp[1]*2],
 306                                        bp[5 + bp[2 + bp[1]*2]*2],
 307                                        bp[4 + bp[2 + bp[1]*2]*2]);
 308                        }
 309                        pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n",
 310                                dev->name,
 311                                i, medianame[leaf->media & 15], leaf->media,
 312                                leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>",
 313                                leaf->type);
 314                }
 315                if (new_advertise)
 316                        tp->sym_advertise = new_advertise;
 317        }
 318}
 319/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
 320
 321/*  EEPROM_Ctrl bits. */
 322#define EE_SHIFT_CLK    0x02    /* EEPROM shift clock. */
 323#define EE_CS           0x01    /* EEPROM chip select. */
 324#define EE_DATA_WRITE   0x04    /* Data from the Tulip to EEPROM. */
 325#define EE_WRITE_0      0x01
 326#define EE_WRITE_1      0x05
 327#define EE_DATA_READ    0x08    /* Data from the EEPROM chip. */
 328#define EE_ENB          (0x4800 | EE_CS)
 329
 330/* Delay between EEPROM clock transitions.
 331   Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
 332   We add a bus turn-around to insure that this remains true. */
 333#define eeprom_delay()  ioread32(ee_addr)
 334
 335/* The EEPROM commands include the alway-set leading bit. */
 336#define EE_READ_CMD             (6)
 337
 338/* Note: this routine returns extra data bits for size detection. */
 339int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
 340{
 341        int i;
 342        unsigned retval = 0;
 343        struct tulip_private *tp = netdev_priv(dev);
 344        void __iomem *ee_addr = tp->base_addr + CSR9;
 345        int read_cmd = location | (EE_READ_CMD << addr_len);
 346
 347        /* If location is past the end of what we can address, don't
 348         * read some other location (ie truncate). Just return zero.
 349         */
 350        if (location > (1 << addr_len) - 1)
 351                return 0;
 352
 353        iowrite32(EE_ENB & ~EE_CS, ee_addr);
 354        iowrite32(EE_ENB, ee_addr);
 355
 356        /* Shift the read command bits out. */
 357        for (i = 4 + addr_len; i >= 0; i--) {
 358                short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 359                iowrite32(EE_ENB | dataval, ee_addr);
 360                eeprom_delay();
 361                iowrite32(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
 362                eeprom_delay();
 363                retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
 364        }
 365        iowrite32(EE_ENB, ee_addr);
 366        eeprom_delay();
 367
 368        for (i = 16; i > 0; i--) {
 369                iowrite32(EE_ENB | EE_SHIFT_CLK, ee_addr);
 370                eeprom_delay();
 371                retval = (retval << 1) | ((ioread32(ee_addr) & EE_DATA_READ) ? 1 : 0);
 372                iowrite32(EE_ENB, ee_addr);
 373                eeprom_delay();
 374        }
 375
 376        /* Terminate the EEPROM access. */
 377        iowrite32(EE_ENB & ~EE_CS, ee_addr);
 378        return (tp->flags & HAS_SWAPPED_SEEPROM) ? swab16(retval) : retval;
 379}
 380
 381