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