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