Import upstream u-boot 1.1.4
[u-boot.git] / board / eltec / elppc / mpc107_i2c.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 /* includes */
25 #include <common.h>
26 #include "srom.h"
27
28 /* locals */
29 static unsigned long mpc107_eumb_addr = 0;
30
31 /*----------------------------------------------------------------------------*/
32
33 /*
34  * calculate checksum for ELTEC revision srom
35  */
36 unsigned long el_srom_checksum (ptr, size)
37 register unsigned char *ptr;
38 unsigned long size;
39 {
40     u_long f, accu = 0;
41     u_int  i;
42     u_char byte;
43
44     for (; size; size--)
45     {
46         byte = *ptr++;
47         for (i = 8; i; i--)
48         {
49             f =  ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
50             accu >>= 1; accu ^= f;
51             byte >>= 1;
52         }
53     }
54     return(accu);
55 }
56
57 /*----------------------------------------------------------------------------*/
58
59 static int mpc107_i2c_wait ( unsigned long timeout )
60 {
61     unsigned long x;
62
63     while (((x = in32r(MPC107_I2CSR)) & 0x82) != 0x82)
64     {
65         if (!timeout--)
66             return -1;
67     }
68
69     if (x & 0x10)
70     {
71         return -1;
72     }
73     out32r(MPC107_I2CSR, 0);
74
75     return 0;
76 }
77
78 /*----------------------------------------------------------------------------*/
79
80 static int mpc107_i2c_wait_idle ( unsigned long timeout )
81 {
82     while (in32r(MPC107_I2CSR) & 0x20)
83     {
84         if (!timeout--)
85             return -1;
86     }
87     return 0;
88 }
89
90
91 /*----------------------------------------------------------------------------*/
92
93 int mpc107_i2c_read_byte (
94     unsigned char device,
95     unsigned char block,
96     unsigned char offset )
97 {
98     unsigned long timeout = MPC107_I2C_TIMEOUT;
99     int data;
100
101     if (!mpc107_eumb_addr)
102         return -6;
103
104     mpc107_i2c_wait_idle (timeout);
105
106     /* Start with MEN */
107     out32r(MPC107_I2CCR, 0x80);
108
109     /* Start as master */
110     out32r(MPC107_I2CCR, 0xB0);
111     out32r(MPC107_I2CDR, (0xA0 | device | block));
112
113     if (mpc107_i2c_wait(timeout) < 0)
114     {
115         printf("mpc107_i2c_read Error 1\n");
116         return -2;
117     }
118
119     if (in32r(MPC107_I2CSR)&0x1)
120     {
121         /* Generate STOP condition; device busy or not existing */
122         out32r(MPC107_I2CCR, 0x80);
123         return -1;
124     }
125
126     /* Data address */
127     out32r(MPC107_I2CDR, offset);
128
129     if (mpc107_i2c_wait(timeout) < 0)
130     {
131         printf("mpc107_i2c_read Error 2\n");
132         return -3;
133     }
134
135     /* Switch to read - restart */
136     out32r(MPC107_I2CCR, 0xB4);
137     out32r(MPC107_I2CDR, (0xA1 | device | block));
138
139     if (mpc107_i2c_wait(timeout) < 0)
140     {
141         printf("mpc107_i2c_read Error 3\n");
142         return -4;
143     }
144
145     out32r(MPC107_I2CCR, 0xA8); /* no ACK */
146     in32r(MPC107_I2CDR);
147
148     if (mpc107_i2c_wait(timeout) < 0)
149     {
150         printf("mpc107_i2c_read Error 4\n");
151         return -5;
152     }
153     /* Generate STOP condition */
154     out32r(MPC107_I2CCR, 0x88);
155
156     /* read */
157     data = in32r(MPC107_I2CDR);
158
159     return (data);
160 }
161
162 /*----------------------------------------------------------------------------*/
163
164 int mpc107_i2c_write_byte (
165     unsigned char device,
166     unsigned char block,
167     unsigned char offset,
168     unsigned char val )
169 {
170
171     unsigned long timeout = MPC107_I2C_TIMEOUT;
172
173     if (!mpc107_eumb_addr)
174         return -6;
175
176     mpc107_i2c_wait_idle(timeout);
177
178     /* Start with MEN */
179     out32r(MPC107_I2CCR, 0x80);
180
181     /* Start as master */
182     out32r(MPC107_I2CCR, 0xB0);
183     out32r(MPC107_I2CDR, (0xA0 | device | block));
184
185     if (mpc107_i2c_wait(timeout) < 0)
186     {
187         printf("mpc107_i2c_write Error 1\n");
188         return -1;
189     }
190
191     /* Data address */
192     out32r(MPC107_I2CDR, offset);
193
194     if (mpc107_i2c_wait(timeout) < 0)
195     {
196         printf("mpc107_i2c_write Error 2\n");
197         return -1;
198     }
199
200     /* Write */
201     out32r(MPC107_I2CDR, val);
202     if (mpc107_i2c_wait(timeout) < 0)
203     {
204         printf("mpc107_i2c_write Error 3\n");
205         return -1;
206     }
207
208     /* Generate Stop Condition */
209     out32r(MPC107_I2CCR, 0x80);
210
211     /* Return ACK or no ACK */
212     return (in32r(MPC107_I2CSR) & 0x01);
213 }
214
215 /*----------------------------------------------------------------------------*/
216
217 int mpc107_srom_load (
218     unsigned char addr,
219     unsigned char *pBuf,
220     int          cnt,
221     unsigned char device,
222     unsigned char block )
223 {
224     register int i;
225     int val;
226     int timeout;
227
228     for (i = 0; i < cnt; i++)
229     {
230         timeout=100;
231         do
232         {
233             val = mpc107_i2c_read_byte (device, block, addr);
234             if (val < -1)
235             {
236             printf("i2c_read_error %d at dev %x block %x addr %x\n",
237                    val, device, block, addr);
238             return -1;
239             }
240             else if (timeout==0)
241             {
242                 printf ("i2c_read_error: timeout at dev %x block %x addr %x\n",
243                         device, block, addr);
244                 return -1;
245             }
246             timeout--;
247         } while (val == -1); /* if no ack: try again! */
248
249         *pBuf++ = (unsigned char)val;
250         addr++;
251
252         if ((addr == 0) && (i != cnt-1))    /* is it the same block ? */
253         {
254             if (block == FIRST_BLOCK)
255                 block = SECOND_BLOCK;
256             else
257             {
258                 printf ("ic2_read_error: read beyond 2. block !\n");
259                 return -1;
260             }
261         }
262     }
263     udelay(100000);
264     return (cnt);
265 }
266
267 /*----------------------------------------------------------------------------*/
268
269 int mpc107_srom_store (
270     unsigned char addr,
271     unsigned char *pBuf,
272     int          cnt,
273     unsigned char device,
274     unsigned char block )
275 {
276     register int i;
277
278     for (i = 0; i < cnt; i++)
279     {
280         while (mpc107_i2c_write_byte (device,block,addr,*pBuf) == 1);
281         addr++;
282         pBuf++;
283
284         if ((addr == 0) && (i != cnt-1))     /* is it the same block ? */
285         {
286             if (block == FIRST_BLOCK)
287                 block = SECOND_BLOCK;
288             else
289             {
290                 printf ("ic2_write_error: write beyond 2. block !\n");
291                 return -1;
292             }
293         }
294     }
295     udelay(100000);
296     return(cnt);
297 }
298
299 /*----------------------------------------------------------------------------*/
300
301 int mpc107_i2c_init ( unsigned long eumb_addr, unsigned long divider )
302 {
303     unsigned long x;
304
305     if (eumb_addr)
306         mpc107_eumb_addr = eumb_addr;
307     else
308         return -1;
309
310     /* Set I2C clock */
311     x = in32r(MPC107_I2CFDR) & 0xffffff00;
312     out32r(MPC107_I2CFDR, (x | divider));
313
314     /* Clear arbitration */
315     out32r(MPC107_I2CSR, 0);
316
317     return mpc107_eumb_addr;
318 }
319
320 /*----------------------------------------------------------------------------*/