]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/eltec/bab7xx/el_srom.c
Initial revision
[karo-tx-uboot.git] / board / eltec / bab7xx / el_srom.c
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     {
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);
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     {
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;
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     {
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();
201
202         eepWriteByte(0xA1 | device | block);
203         if (eepReadAck() == ERROR)
204         {
205             eepStop();
206             return(ERROR);
207         }
208
209         *buf++ = eepReadByte();
210         eepWriteAck(1);
211         eepStop();
212
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         }
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     {
238         retVal = ERROR;
239         do
240         {
241             eepStart();
242             eepWriteByte(0xA0 | device | block);
243             if ((retVal = eepReadAck()) == ERROR)
244                 eepStop();
245         } while (retVal == ERROR);
246
247         eepWriteByte(addr++);
248         if (eepReadAck() == ERROR)  return(ERROR);
249
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         }
257
258         eepWriteByte(*buf++);
259         if (eepReadAck() == ERROR)
260             return(ERROR);
261
262         eepStop();
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     {
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         }
288     }
289     return(accu);
290 }
291
292 /*----------------------------------------------------------------------------*/