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 #define CYCLE_DELAY 5
11 
12 /* This was the original definition
13 #define osp_MicroDelay(microsec) \
14     do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
15 */
16 #define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
17                                   udelay((useconds));}
18 
19 
20 /* The following tables represent the timing diagrams found in
21  * the Data Sheet for the Xicor X25020 EEProm.  The #defines below
22  * represent the bits in the NICStAR's General Purpose register
23  * that must be toggled for the corresponding actions on the EEProm
24  * to occur.
25  */
26 
27 /* Write Data To EEProm from SI line on rising edge of CLK */
28 /* Read Data From EEProm on falling edge of CLK */
29 
30 #define CS_HIGH		0x0002		/* Chip select high */
31 #define CS_LOW		0x0000		/* Chip select low (active low)*/
32 #define CLK_HIGH	0x0004		/* Clock high */
33 #define CLK_LOW		0x0000		/* Clock low  */
34 #define SI_HIGH		0x0001		/* Serial input data high */
35 #define SI_LOW		0x0000		/* Serial input data low */
36 
37 /* Read Status Register = 0000 0101b */
38 static u_int32_t rdsrtab[] =
39 {
40     CS_HIGH | CLK_HIGH,
41     CS_LOW | CLK_LOW,
42     CLK_HIGH,             /* 0 */
43     CLK_LOW,
44     CLK_HIGH,             /* 0 */
45     CLK_LOW,
46     CLK_HIGH,             /* 0 */
47     CLK_LOW,
48     CLK_HIGH,             /* 0 */
49     CLK_LOW,
50     CLK_HIGH,             /* 0 */
51     CLK_LOW | SI_HIGH,
52     CLK_HIGH | SI_HIGH,   /* 1 */
53     CLK_LOW | SI_LOW,
54     CLK_HIGH,             /* 0 */
55     CLK_LOW | SI_HIGH,
56     CLK_HIGH | SI_HIGH   /* 1 */
57 };
58 
59 
60 /* Read from EEPROM = 0000 0011b */
61 static u_int32_t readtab[] =
62 {
63     /*
64     CS_HIGH | CLK_HIGH,
65     */
66     CS_LOW | CLK_LOW,
67     CLK_HIGH,             /* 0 */
68     CLK_LOW,
69     CLK_HIGH,             /* 0 */
70     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 | SI_HIGH,
79     CLK_HIGH | SI_HIGH,   /* 1 */
80     CLK_LOW | SI_HIGH,
81     CLK_HIGH | SI_HIGH    /* 1 */
82 };
83 
84 
85 /* Clock to read from/write to the eeprom */
86 static u_int32_t clocktab[] =
87 {
88     CLK_LOW,
89     CLK_HIGH,
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 };
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 
121 u_int32_t
nicstar_read_eprom_status(virt_addr_t base)122 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<sizeof rdsrtab/sizeof rdsrtab[0]; i++)
132    {
133 	NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
134 		(val | rdsrtab[i]) );
135         osp_MicroDelay( CYCLE_DELAY );
136    }
137 
138    /* Done sending instruction - now pull data off of bit 16, MSB first */
139    /* Data clocked out of eeprom on falling edge of clock */
140 
141    rbyte = 0;
142    for (i=7, j=0; i>=0; i--)
143    {
144 	NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
145 		(val | clocktab[j++]) );
146         rbyte |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE)
147 			& 0x00010000) >> 16) << i);
148 	NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
149 		(val | clocktab[j++]) );
150         osp_MicroDelay( CYCLE_DELAY );
151    }
152    NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 );
153    osp_MicroDelay( CYCLE_DELAY );
154    return rbyte;
155 }
156 
157 
158 /*
159  * This routine will clock the Read_data function into the X2520
160  * eeprom, followed by the address to read from, through the NicSTaR's General
161  * Purpose register.
162  */
163 
164 static u_int8_t
read_eprom_byte(u_int32_t base,u_int8_t offset)165 read_eprom_byte(u_int32_t base, u_int8_t offset)
166 {
167    u_int32_t val = 0;
168    int i,j=0;
169    u_int8_t tempread = 0;
170 
171    val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
172 
173    /* Send READ instruction */
174    for (i=0; i<sizeof readtab/sizeof readtab[0]; i++)
175    {
176 	NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
177 		(val | readtab[i]) );
178         osp_MicroDelay( CYCLE_DELAY );
179    }
180 
181    /* Next, we need to send the byte address to read from */
182    for (i=7; i>=0; i--)
183    {
184       NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
185       		(val | clocktab[j++] | ((offset >> i) & 1) ) );
186       osp_MicroDelay(CYCLE_DELAY);
187       NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
188       		(val | clocktab[j++] | ((offset >> i) & 1) ) );
189       osp_MicroDelay( CYCLE_DELAY );
190    }
191 
192    j = 0;
193 
194    /* Now, we can read data from the eeprom by clocking it in */
195    for (i=7; i>=0; i--)
196    {
197       NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
198       		(val | clocktab[j++]) );
199       osp_MicroDelay( CYCLE_DELAY );
200       tempread |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE )
201 		& 0x00010000) >> 16) << i);
202       NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
203       		(val | clocktab[j++]) );
204       osp_MicroDelay( CYCLE_DELAY );
205    }
206 
207    NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 );
208    osp_MicroDelay( CYCLE_DELAY );
209    return tempread;
210 }
211 
212 
213 void
nicstar_init_eprom(virt_addr_t base)214 nicstar_init_eprom( virt_addr_t base )
215 {
216     u_int32_t val;
217 
218     /*
219      * turn chip select off
220      */
221     val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
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     NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
232     	(val | CS_HIGH | CLK_HIGH));
233     osp_MicroDelay( CYCLE_DELAY );
234 
235     NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
236     	(val | CS_HIGH | CLK_LOW));
237     osp_MicroDelay( CYCLE_DELAY );
238 }
239 
240 
241 /*
242  * This routine will be the interface to the ReadPromByte function
243  * above.
244  */
245 
246 void
nicstar_read_eprom(virt_addr_t base,u_int8_t prom_offset,u_int8_t * buffer,u_int32_t nbytes)247 nicstar_read_eprom(
248     virt_addr_t	base,
249     u_int8_t	prom_offset,
250     u_int8_t	*buffer,
251     u_int32_t	nbytes )
252 {
253     u_int		i;
254 
255     for (i=0; i<nbytes; i++)
256     {
257 	buffer[i] = read_eprom_byte( base, prom_offset );
258 	++prom_offset;
259  	osp_MicroDelay( CYCLE_DELAY );
260     }
261 }
262 
263 
264 /*
265 void osp_MicroDelay(int x) {
266 
267 }
268 */
269 
270