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 43/* Read from EEPROM = 0000 0011b */ 44static u_int32_t readtab[] = { 45 /* 46 CS_HIGH | CLK_HIGH, 47 */ 48 CS_LOW | 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, 57 CLK_HIGH, /* 0 */ 58 CLK_LOW, 59 CLK_HIGH, /* 0 */ 60 CLK_LOW | SI_HIGH, 61 CLK_HIGH | SI_HIGH, /* 1 */ 62 CLK_LOW | SI_HIGH, 63 CLK_HIGH | SI_HIGH /* 1 */ 64}; 65 66/* Clock to read from/write to the eeprom */ 67static u_int32_t clocktab[] = { 68 CLK_LOW, 69 CLK_HIGH, 70 CLK_LOW, 71 CLK_HIGH, 72 CLK_LOW, 73 CLK_HIGH, 74 CLK_LOW, 75 CLK_HIGH, 76 CLK_LOW, 77 CLK_HIGH, 78 CLK_LOW, 79 CLK_HIGH, 80 CLK_LOW, 81 CLK_HIGH, 82 CLK_LOW, 83 CLK_HIGH, 84 CLK_LOW 85}; 86 87#define NICSTAR_REG_WRITE(bs, reg, val) \ 88 while ( readl(bs + STAT) & 0x0200 ) ; \ 89 writel((val),(base)+(reg)) 90#define NICSTAR_REG_READ(bs, reg) \ 91 readl((base)+(reg)) 92#define NICSTAR_REG_GENERAL_PURPOSE GP 93 94/* 95 * This routine will clock the Read_Status_reg function into the X2520 96 * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose 97 * register. 98 */ 99 100/* 101 * This routine will clock the Read_data function into the X2520 102 * eeprom, followed by the address to read from, through the NicSTaR's General 103 * Purpose register. 104 */ 105 106static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset) 107{ 108 u_int32_t val = 0; 109 int i, j = 0; 110 u_int8_t tempread = 0; 111 112 val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; 113 114 /* Send READ instruction */ 115 for (i = 0; i < ARRAY_SIZE(readtab); i++) { 116 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 117 (val | readtab[i])); 118 osp_MicroDelay(CYCLE_DELAY); 119 } 120 121 /* Next, we need to send the byte address to read from */ 122 for (i = 7; i >= 0; i--) { 123 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 124 (val | clocktab[j++] | ((offset >> i) & 1))); 125 osp_MicroDelay(CYCLE_DELAY); 126 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 127 (val | clocktab[j++] | ((offset >> i) & 1))); 128 osp_MicroDelay(CYCLE_DELAY); 129 } 130 131 j = 0; 132 133 /* Now, we can read data from the eeprom by clocking it in */ 134 for (i = 7; i >= 0; i--) { 135 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 136 (val | clocktab[j++])); 137 osp_MicroDelay(CYCLE_DELAY); 138 tempread |= 139 (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) 140 & 0x00010000) >> 16) << i); 141 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 142 (val | clocktab[j++])); 143 osp_MicroDelay(CYCLE_DELAY); 144 } 145 146 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2); 147 osp_MicroDelay(CYCLE_DELAY); 148 return tempread; 149} 150 151static void nicstar_init_eprom(virt_addr_t base) 152{ 153 u_int32_t val; 154 155 /* 156 * turn chip select off 157 */ 158 val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0; 159 160 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 161 (val | CS_HIGH | CLK_HIGH)); 162 osp_MicroDelay(CYCLE_DELAY); 163 164 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 165 (val | CS_HIGH | CLK_LOW)); 166 osp_MicroDelay(CYCLE_DELAY); 167 168 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 169 (val | CS_HIGH | CLK_HIGH)); 170 osp_MicroDelay(CYCLE_DELAY); 171 172 NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 173 (val | CS_HIGH | CLK_LOW)); 174 osp_MicroDelay(CYCLE_DELAY); 175} 176 177/* 178 * This routine will be the interface to the ReadPromByte function 179 * above. 180 */ 181 182static void 183nicstar_read_eprom(virt_addr_t base, 184 u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes) 185{ 186 u_int i; 187 188 for (i = 0; i < nbytes; i++) { 189 buffer[i] = read_eprom_byte(base, prom_offset); 190 ++prom_offset; 191 osp_MicroDelay(CYCLE_DELAY); 192 } 193} 194