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