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 
12 typedef 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
43 static 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 */
65 static 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 */
88 static 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
121 u_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 
read_eprom_byte(virt_addr_t base,u_int8_t offset)161 static 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 
nicstar_init_eprom(virt_addr_t base)206 static 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 
237 static void
nicstar_read_eprom(virt_addr_t base,u_int8_t prom_offset,u_int8_t * buffer,u_int32_t nbytes)238 nicstar_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