[go: nahoru, domu]

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