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