linux/drivers/atm/nicstarmac.c
<<
>>
Prefs
   1/*
   2 * this file included by nicstar.c
   3 */
   4
   5/*
   6 * nicstarmac.c
   7 * Read this ForeRunner's MAC address from eprom/eeprom
   8 */
   9
  10#include <linux/kernel.h>
  11
  12typedef void __iomem *virt_addr_t;
  13
  14#define CYCLE_DELAY 5
  15
  16/*
  17   This was the original definition
  18#define osp_MicroDelay(microsec) \
  19    do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
  20*/
  21#define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
  22                                  udelay((useconds));}
  23/*
  24 * The following tables represent the timing diagrams found in
  25 * the Data Sheet for the Xicor X25020 EEProm.  The #defines below
  26 * represent the bits in the NICStAR's General Purpose register
  27 * that must be toggled for the corresponding actions on the EEProm
  28 * to occur.
  29 */
  30
  31/* Write Data To EEProm from SI line on rising edge of CLK */
  32/* Read Data From EEProm on falling edge of CLK */
  33
  34#define CS_HIGH         0x0002  /* Chip select high */
  35#define CS_LOW          0x0000  /* Chip select low (active low) */
  36#define CLK_HIGH        0x0004  /* Clock high */
  37#define CLK_LOW         0x0000  /* Clock low  */
  38#define SI_HIGH         0x0001  /* Serial input data high */
  39#define SI_LOW          0x0000  /* Serial input data low */
  40
  41/* Read Status Register = 0000 0101b */
  42#if 0
  43static u_int32_t rdsrtab[] = {
  44        CS_HIGH | CLK_HIGH,
  45        CS_LOW | CLK_LOW,
  46        CLK_HIGH,               /* 0 */
  47        CLK_LOW,
  48        CLK_HIGH,               /* 0 */
  49        CLK_LOW,
  50        CLK_HIGH,               /* 0 */
  51        CLK_LOW,
  52        CLK_HIGH,               /* 0 */
  53        CLK_LOW,
  54        CLK_HIGH,               /* 0 */
  55        CLK_LOW | SI_HIGH,
  56        CLK_HIGH | SI_HIGH,     /* 1 */
  57        CLK_LOW | SI_LOW,
  58        CLK_HIGH,               /* 0 */
  59        CLK_LOW | SI_HIGH,
  60        CLK_HIGH | SI_HIGH      /* 1 */
  61};
  62#endif /*  0  */
  63
  64/* Read from EEPROM = 0000 0011b */
  65static u_int32_t readtab[] = {
  66        /*
  67           CS_HIGH | CLK_HIGH,
  68         */
  69        CS_LOW | CLK_LOW,
  70        CLK_HIGH,               /* 0 */
  71        CLK_LOW,
  72        CLK_HIGH,               /* 0 */
  73        CLK_LOW,
  74        CLK_HIGH,               /* 0 */
  75        CLK_LOW,
  76        CLK_HIGH,               /* 0 */
  77        CLK_LOW,
  78        CLK_HIGH,               /* 0 */
  79        CLK_LOW,
  80        CLK_HIGH,               /* 0 */
  81        CLK_LOW | SI_HIGH,
  82        CLK_HIGH | SI_HIGH,     /* 1 */
  83        CLK_LOW | SI_HIGH,
  84        CLK_HIGH | SI_HIGH      /* 1 */
  85};
  86
  87/* Clock to read from/write to the eeprom */
  88static u_int32_t clocktab[] = {
  89        CLK_LOW,
  90        CLK_HIGH,
  91        CLK_LOW,
  92        CLK_HIGH,
  93        CLK_LOW,
  94        CLK_HIGH,
  95        CLK_LOW,
  96        CLK_HIGH,
  97        CLK_LOW,
  98        CLK_HIGH,
  99        CLK_LOW,
 100        CLK_HIGH,
 101        CLK_LOW,
 102        CLK_HIGH,
 103        CLK_LOW,
 104        CLK_HIGH,
 105        CLK_LOW
 106};
 107
 108#define NICSTAR_REG_WRITE(bs, reg, val) \
 109        while ( readl(bs + STAT) & 0x0200 ) ; \
 110        writel((val),(base)+(reg))
 111#define NICSTAR_REG_READ(bs, reg) \
 112        readl((base)+(reg))
 113#define NICSTAR_REG_GENERAL_PURPOSE GP
 114
 115/*
 116 * This routine will clock the Read_Status_reg function into the X2520
 117 * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose 
 118 * register.  
 119 */
 120#if 0
 121u_int32_t nicstar_read_eprom_status(virt_addr_t base)
 122{
 123        u_int32_t val;
 124        u_int32_t rbyte;
 125        int32_t i, j;
 126
 127        /* Send read instruction */
 128        val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
 129
 130        for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
 131                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 132                                  (val | rdsrtab[i]));
 133                osp_MicroDelay(CYCLE_DELAY);
 134        }
 135
 136        /* Done sending instruction - now pull data off of bit 16, MSB first */
 137        /* Data clocked out of eeprom on falling edge of clock */
 138
 139        rbyte = 0;
 140        for (i = 7, j = 0; i >= 0; i--) {
 141                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 142                                  (val | clocktab[j++]));
 143                rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
 144                            & 0x00010000) >> 16) << i);
 145                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 146                                  (val | clocktab[j++]));
 147                osp_MicroDelay(CYCLE_DELAY);
 148        }
 149        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
 150        osp_MicroDelay(CYCLE_DELAY);
 151        return rbyte;
 152}
 153#endif /*  0  */
 154
 155/*
 156 * This routine will clock the Read_data function into the X2520
 157 * eeprom, followed by the address to read from, through the NicSTaR's General
 158 * Purpose register.  
 159 */
 160
 161static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset)
 162{
 163        u_int32_t val = 0;
 164        int i, j = 0;
 165        u_int8_t tempread = 0;
 166
 167        val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
 168
 169        /* Send READ instruction */
 170        for (i = 0; i < ARRAY_SIZE(readtab); i++) {
 171                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 172                                  (val | readtab[i]));
 173                osp_MicroDelay(CYCLE_DELAY);
 174        }
 175
 176        /* Next, we need to send the byte address to read from */
 177        for (i = 7; i >= 0; i--) {
 178                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 179                                  (val | clocktab[j++] | ((offset >> i) & 1)));
 180                osp_MicroDelay(CYCLE_DELAY);
 181                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 182                                  (val | clocktab[j++] | ((offset >> i) & 1)));
 183                osp_MicroDelay(CYCLE_DELAY);
 184        }
 185
 186        j = 0;
 187
 188        /* Now, we can read data from the eeprom by clocking it in */
 189        for (i = 7; i >= 0; i--) {
 190                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 191                                  (val | clocktab[j++]));
 192                osp_MicroDelay(CYCLE_DELAY);
 193                tempread |=
 194                    (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
 195                       & 0x00010000) >> 16) << i);
 196                NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 197                                  (val | clocktab[j++]));
 198                osp_MicroDelay(CYCLE_DELAY);
 199        }
 200
 201        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
 202        osp_MicroDelay(CYCLE_DELAY);
 203        return tempread;
 204}
 205
 206static void nicstar_init_eprom(virt_addr_t base)
 207{
 208        u_int32_t val;
 209
 210        /*
 211         * turn chip select off
 212         */
 213        val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
 214
 215        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 216                          (val | CS_HIGH | CLK_HIGH));
 217        osp_MicroDelay(CYCLE_DELAY);
 218
 219        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 220                          (val | CS_HIGH | CLK_LOW));
 221        osp_MicroDelay(CYCLE_DELAY);
 222
 223        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 224                          (val | CS_HIGH | CLK_HIGH));
 225        osp_MicroDelay(CYCLE_DELAY);
 226
 227        NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
 228                          (val | CS_HIGH | CLK_LOW));
 229        osp_MicroDelay(CYCLE_DELAY);
 230}
 231
 232/*
 233 * This routine will be the interface to the ReadPromByte function
 234 * above.
 235 */
 236
 237static void
 238nicstar_read_eprom(virt_addr_t base,
 239                   u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes)
 240{
 241        u_int i;
 242
 243        for (i = 0; i < nbytes; i++) {
 244                buffer[i] = read_eprom_byte(base, prom_offset);
 245                ++prom_offset;
 246                osp_MicroDelay(CYCLE_DELAY);
 247        }
 248}
 249