File: /usr/src/linux/drivers/atm/nicstarmac.c

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
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 
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
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
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