]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | /* |
2 | * (C) Copyright 2002 ELTEC Elektronik AG | |
3 | * Frank Gottschling <fgottschling@eltec.de> | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include "srom.h" | |
26 | ||
27 | /*----------------------------------------------------------------------------*/ | |
28 | /* | |
29 | * START sequence | |
30 | * _ _________ | |
31 | * SCLK _> \____ | |
32 | * _ ____ | |
33 | * SDIO _> \_________ | |
34 | * : : : | |
35 | */ | |
36 | static void eepStart (void) | |
37 | { | |
38 | out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */ | |
39 | out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */ | |
40 | udelay(10); | |
41 | out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */ | |
42 | udelay(10); | |
43 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */ | |
44 | udelay(10); | |
45 | } | |
46 | ||
47 | /*----------------------------------------------------------------------------*/ | |
48 | /* | |
49 | * STOP sequence | |
50 | * _______ | |
51 | * SCLK _____/ | |
52 | * _ ___ | |
53 | * SDIO _>_______/ | |
54 | * : : : | |
55 | */ | |
56 | static void eepStop (void) | |
57 | { | |
58 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */ | |
59 | out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */ | |
60 | udelay(10); | |
61 | out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */ | |
62 | udelay(10); | |
63 | out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */ | |
64 | udelay(10); | |
65 | out8(I2C_BUS_DIR, 0x00); /* reset to input direction */ | |
66 | } | |
67 | ||
68 | /*----------------------------------------------------------------------------*/ | |
69 | /* | |
70 | * Read one byte from EEPROM | |
71 | * ___ ___ ___ ___ ___ ___ ___ ___ | |
72 | * SCLK ___/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \ | |
73 | * _________________________________________________________________ | |
74 | * SDIO > ^ ^ ^ ^ ^ ^ ^ ^ | |
75 | * : : : : : : : : : : : : : : : : : | |
76 | */ | |
77 | static unsigned char eepReadByte (void) | |
78 | { | |
79 | register unsigned char buf = 0x00; | |
80 | register int i; | |
81 | ||
82 | out8(I2C_BUS_DIR, 0x40); | |
83 | ||
84 | for (i = 0; i < 8; i++) | |
85 | { | |
8bde7f77 WD |
86 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ |
87 | udelay(10); | |
88 | out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */ | |
89 | udelay(15); | |
90 | buf <<= 1; | |
91 | buf = (in8(I2C_BUS_DAT) & 0x20) ? (buf | 0x01) : (buf & 0xFE); | |
92 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ | |
93 | udelay(10); | |
c609719b WD |
94 | } |
95 | return(buf); | |
96 | } | |
97 | ||
98 | /*----------------------------------------------------------------------------*/ | |
99 | /* | |
100 | * Write one byte to EEPROM | |
101 | * ___ ___ ___ ___ ___ ___ ___ ___ | |
102 | * SCLK __/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \__ | |
103 | * _______ _______ _______ _______ _______ _______ _______ ________ | |
104 | * SDIO X_______X_______X_______X_______X_______X_______X_______X________ | |
105 | * : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0 | |
106 | */ | |
107 | static void eepWriteByte (register unsigned char buf) | |
108 | { | |
109 | register int i; | |
110 | ||
111 | (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = data */ | |
112 | out8(I2C_BUS_DIR, 0x60); | |
113 | ||
114 | for (i = 7; i >= 0; i--) | |
115 | { | |
8bde7f77 WD |
116 | (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */ |
117 | udelay(10); | |
118 | (buf & 0x80) ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK=high SDIO=data */ | |
119 | udelay(15); | |
120 | (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */ | |
121 | udelay(10); | |
122 | buf <<= 1; | |
c609719b WD |
123 | } |
124 | } | |
125 | ||
126 | /*----------------------------------------------------------------------------*/ | |
127 | /* | |
128 | * Read data acknowledge of EEPROM | |
129 | * _______ | |
130 | * SCLK ____/ \___ | |
131 | * _______________ | |
132 | * SDIO > | |
133 | * : : ^ : | |
134 | */ | |
135 | static int eepReadAck (void) | |
136 | { | |
137 | int retval; | |
138 | ||
139 | out8(I2C_BUS_DIR, 0x40); | |
140 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ | |
141 | udelay(10); | |
142 | out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */ | |
143 | udelay(10); | |
144 | retval = (in8(I2C_BUS_DAT) & 0x20) ? ERROR : 0; | |
145 | udelay(10); | |
146 | out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ | |
147 | udelay(10); | |
148 | ||
149 | return(retval); | |
150 | } | |
151 | ||
152 | /*----------------------------------------------------------------------------*/ | |
153 | /* | |
154 | * Write data acknowledge to EEPROM | |
155 | * _______ | |
156 | * SCLK ____/ \___ | |
157 | * | |
158 | * SDIO >_______________ | |
159 | * : : : | |
160 | */ | |
161 | static void eepWriteAck (unsigned char ack) | |
162 | { | |
163 | ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */ | |
164 | out8(I2C_BUS_DIR, 0x60); | |
165 | udelay(10); | |
166 | ack ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = ack */ | |
167 | udelay(15); | |
168 | ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */ | |
169 | udelay(10); | |
170 | } | |
171 | ||
172 | /*----------------------------------------------------------------------------*/ | |
173 | /* | |
174 | * Read bytes from EEPROM | |
175 | */ | |
176 | int el_srom_load (addr, buf, cnt, device, block) | |
177 | unsigned char addr; | |
178 | unsigned char *buf; | |
179 | int cnt; | |
180 | unsigned char device; | |
181 | unsigned char block; | |
182 | { | |
183 | register int i; | |
184 | ||
185 | for (i=0;i<cnt;i++) | |
186 | { | |
8bde7f77 WD |
187 | eepStart(); |
188 | eepWriteByte(0xA0 | device | block); | |
189 | if (eepReadAck() == ERROR) | |
190 | { | |
191 | eepStop(); | |
192 | return(ERROR); | |
193 | } | |
194 | eepWriteByte(addr++); | |
195 | if (eepReadAck() == ERROR) | |
196 | { | |
197 | eepStop(); | |
198 | return(ERROR); | |
199 | } | |
200 | eepStart(); | |
c609719b | 201 | |
8bde7f77 WD |
202 | eepWriteByte(0xA1 | device | block); |
203 | if (eepReadAck() == ERROR) | |
204 | { | |
205 | eepStop(); | |
206 | return(ERROR); | |
207 | } | |
c609719b | 208 | |
8bde7f77 WD |
209 | *buf++ = eepReadByte(); |
210 | eepWriteAck(1); | |
211 | eepStop(); | |
c609719b | 212 | |
8bde7f77 WD |
213 | if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */ |
214 | { | |
215 | if (block == FIRST_BLOCK) | |
216 | block = SECOND_BLOCK; | |
217 | else | |
218 | return(ERROR); | |
219 | } | |
c609719b WD |
220 | } |
221 | return(cnt); | |
222 | } | |
223 | ||
224 | /*----------------------------------------------------------------------------*/ | |
225 | /* | |
226 | * | |
227 | * Write bytes to EEPROM | |
228 | * | |
229 | */ | |
230 | int el_srom_store (addr, buf, cnt, device, block) | |
231 | unsigned char addr, *buf, device, block; | |
232 | int cnt; | |
233 | { | |
234 | register int i, retVal; | |
235 | ||
236 | for (i=0;i<cnt;i++) | |
237 | { | |
8bde7f77 WD |
238 | retVal = ERROR; |
239 | do | |
240 | { | |
241 | eepStart(); | |
242 | eepWriteByte(0xA0 | device | block); | |
243 | if ((retVal = eepReadAck()) == ERROR) | |
244 | eepStop(); | |
245 | } while (retVal == ERROR); | |
c609719b | 246 | |
8bde7f77 WD |
247 | eepWriteByte(addr++); |
248 | if (eepReadAck() == ERROR) return(ERROR); | |
c609719b | 249 | |
8bde7f77 WD |
250 | if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */ |
251 | { | |
252 | if (block == FIRST_BLOCK) | |
253 | block = SECOND_BLOCK; | |
254 | else | |
255 | return(ERROR); | |
256 | } | |
c609719b | 257 | |
8bde7f77 WD |
258 | eepWriteByte(*buf++); |
259 | if (eepReadAck() == ERROR) | |
260 | return(ERROR); | |
c609719b | 261 | |
8bde7f77 | 262 | eepStop(); |
c609719b WD |
263 | } |
264 | return(cnt); | |
265 | } | |
266 | ||
267 | /*----------------------------------------------------------------------------*/ | |
268 | /* | |
269 | * calculate checksum for ELTEC revision srom | |
270 | */ | |
271 | unsigned long el_srom_checksum (ptr, size) | |
272 | register unsigned char *ptr; | |
273 | unsigned long size; | |
274 | { | |
275 | u_long f, accu = 0; | |
276 | u_int i; | |
277 | u_char byte; | |
278 | ||
279 | for (; size; size--) | |
280 | { | |
8bde7f77 WD |
281 | byte = *ptr++; |
282 | for (i = 8; i; i--) | |
283 | { | |
284 | f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0; | |
285 | accu >>= 1; accu ^= f; | |
286 | byte >>= 1; | |
287 | } | |
c609719b WD |
288 | } |
289 | return(accu); | |
290 | } | |
291 | ||
292 | /*----------------------------------------------------------------------------*/ |