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