]> git.sur5r.net Git - u-boot/blob - drivers/omap24xx_i2c.c
ppc4xx: Update 44x_spd_ddr2 code (440SP/440SPe)
[u-boot] / drivers / omap24xx_i2c.c
1 /*
2  * Basic I2C functions
3  *
4  * Copyright (c) 2004 Texas Instruments
5  *
6  * This package is free software;  you can redistribute it and/or
7  * modify it under the terms of the license found in the file
8  * named COPYING that should have accompanied this file.
9  *
10  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * Author: Jian Zhang jzhang@ti.com, Texas Instruments
15  *
16  * Copyright (c) 2003 Wolfgang Denk, wd@denx.de
17  * Rewritten to fit into the current U-Boot framework
18  *
19  * Adapted for OMAP2420 I2C, r-woodruff2@ti.com
20  *
21  */
22
23 #include <common.h>
24
25 #ifdef CONFIG_DRIVER_OMAP24XX_I2C
26
27 #include <asm/arch/i2c.h>
28 #include <asm/io.h>
29
30 #define inw(a) __raw_readw(a)
31 #define outw(a,v) __raw_writew(a,v)
32
33 static void wait_for_bb (void);
34 static u16 wait_for_pin (void);
35 static void flush_fifo(void);
36
37 void i2c_init (int speed, int slaveadd)
38 {
39         u16 scl;
40
41         outw(0x2, I2C_SYSC); /* for ES2 after soft reset */
42         udelay(1000);
43         outw(0x0, I2C_SYSC); /* will probably self clear but */
44
45         if (inw (I2C_CON) & I2C_CON_EN) {
46                 outw (0, I2C_CON);
47                 udelay (50000);
48         }
49
50         /* 12Mhz I2C module clock */
51         outw (0, I2C_PSC);
52         speed = speed/1000;                 /* 100 or 400 */
53         scl = ((12000/(speed*2)) - 7);  /* use 7 when PSC = 0 */
54         outw (scl, I2C_SCLL);
55         outw (scl, I2C_SCLH);
56         /* own address */
57         outw (slaveadd, I2C_OA);
58         outw (I2C_CON_EN, I2C_CON);
59
60         /* have to enable intrrupts or OMAP i2c module doesn't work */
61         outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
62               I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
63         udelay (1000);
64         flush_fifo();
65         outw (0xFFFF, I2C_STAT);
66         outw (0, I2C_CNT);
67 }
68
69 static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
70 {
71         int i2c_error = 0;
72         u16 status;
73
74         /* wait until bus not busy */
75         wait_for_bb ();
76
77         /* one byte only */
78         outw (1, I2C_CNT);
79         /* set slave address */
80         outw (devaddr, I2C_SA);
81         /* no stop bit needed here */
82         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
83
84         status = wait_for_pin ();
85
86         if (status & I2C_STAT_XRDY) {
87                 /* Important: have to use byte access */
88                 *(volatile u8 *) (I2C_DATA) = regoffset;
89                 udelay (20000);
90                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
91                         i2c_error = 1;
92                 }
93         } else {
94                 i2c_error = 1;
95         }
96
97         if (!i2c_error) {
98                 /* free bus, otherwise we can't use a combined transction */
99                 outw (0, I2C_CON);
100                 while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
101                         udelay (10000);
102                         /* Have to clear pending interrupt to clear I2C_STAT */
103                         outw (0xFFFF, I2C_STAT);
104                 }
105
106                 wait_for_bb ();
107                 /* set slave address */
108                 outw (devaddr, I2C_SA);
109                 /* read one byte from slave */
110                 outw (1, I2C_CNT);
111                 /* need stop bit here */
112                 outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
113                       I2C_CON);
114
115                 status = wait_for_pin ();
116                 if (status & I2C_STAT_RRDY) {
117                         *value = inw (I2C_DATA);
118                         udelay (20000);
119                 } else {
120                         i2c_error = 1;
121                 }
122
123                 if (!i2c_error) {
124                         outw (I2C_CON_EN, I2C_CON);
125                         while (inw (I2C_STAT)
126                                || (inw (I2C_CON) & I2C_CON_MST)) {
127                                 udelay (10000);
128                                 outw (0xFFFF, I2C_STAT);
129                         }
130                 }
131         }
132         flush_fifo();
133         outw (0xFFFF, I2C_STAT);
134         outw (0, I2C_CNT);
135         return i2c_error;
136 }
137
138 static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
139 {
140         int i2c_error = 0;
141         u16 status, stat;
142
143         /* wait until bus not busy */
144         wait_for_bb ();
145
146         /* two bytes */
147         outw (2, I2C_CNT);
148         /* set slave address */
149         outw (devaddr, I2C_SA);
150         /* stop bit needed here */
151         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
152               I2C_CON_STP, I2C_CON);
153
154         /* wait until state change */
155         status = wait_for_pin ();
156
157         if (status & I2C_STAT_XRDY) {
158                 /* send out two bytes */
159                 outw ((value << 8) + regoffset, I2C_DATA);
160                 /* must have enough delay to allow BB bit to go low */
161                 udelay (50000);
162                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
163                         i2c_error = 1;
164                 }
165         } else {
166                 i2c_error = 1;
167         }
168
169         if (!i2c_error) {
170                 int eout = 200;
171
172                 outw (I2C_CON_EN, I2C_CON);
173                 while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) {
174                         udelay (1000);
175                         /* have to read to clear intrrupt */
176                         outw (0xFFFF, I2C_STAT);
177                         if(--eout == 0) /* better leave with error than hang */
178                                 break;
179                 }
180         }
181         flush_fifo();
182         outw (0xFFFF, I2C_STAT);
183         outw (0, I2C_CNT);
184         return i2c_error;
185 }
186
187 static void flush_fifo(void)
188 {       u16 stat;
189
190         /* note: if you try and read data when its not there or ready
191          * you get a bus error
192          */
193         while(1){
194                 stat = inw(I2C_STAT);
195                 if(stat == I2C_STAT_RRDY){
196                         inw(I2C_DATA);
197                         outw(I2C_STAT_RRDY,I2C_STAT);
198                         udelay(1000);
199                 }else
200                         break;
201         }
202 }
203
204 int i2c_probe (uchar chip)
205 {
206         int res = 1; /* default = fail */
207
208         if (chip == inw (I2C_OA)) {
209                 return res;
210         }
211
212         /* wait until bus not busy */
213         wait_for_bb ();
214
215         /* try to read one byte */
216         outw (1, I2C_CNT);
217         /* set slave address */
218         outw (chip, I2C_SA);
219         /* stop bit needed here */
220         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
221         /* enough delay for the NACK bit set */
222         udelay (50000);
223
224         if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
225                 res = 0;      /* success case */
226                 flush_fifo();
227                 outw(0xFFFF, I2C_STAT);
228         } else {
229                 outw(0xFFFF, I2C_STAT);  /* failue, clear sources*/
230                 outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
231                 udelay(20000);
232                 wait_for_bb ();
233         }
234         flush_fifo();
235         outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
236         outw(0xFFFF, I2C_STAT);
237         return res;
238 }
239
240 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
241 {
242         int i;
243
244         if (alen > 1) {
245                 printf ("I2C read: addr len %d not supported\n", alen);
246                 return 1;
247         }
248
249         if (addr + len > 256) {
250                 printf ("I2C read: address out of range\n");
251                 return 1;
252         }
253
254         for (i = 0; i < len; i++) {
255                 if (i2c_read_byte (chip, addr + i, &buffer[i])) {
256                         printf ("I2C read: I/O error\n");
257                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
258                         return 1;
259                 }
260         }
261
262         return 0;
263 }
264
265 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
266 {
267         int i;
268
269         if (alen > 1) {
270                 printf ("I2C read: addr len %d not supported\n", alen);
271                 return 1;
272         }
273
274         if (addr + len > 256) {
275                 printf ("I2C read: address out of range\n");
276                 return 1;
277         }
278
279         for (i = 0; i < len; i++) {
280                 if (i2c_write_byte (chip, addr + i, buffer[i])) {
281                         printf ("I2C read: I/O error\n");
282                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
283                         return 1;
284                 }
285         }
286
287         return 0;
288 }
289
290 static void wait_for_bb (void)
291 {
292         int timeout = 10;
293         u16 stat;
294
295         outw(0xFFFF, I2C_STAT);  /* clear current interruts...*/
296         while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
297                 outw (stat, I2C_STAT);
298                 udelay (50000);
299         }
300
301         if (timeout <= 0) {
302                 printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
303                         inw (I2C_STAT));
304         }
305         outw(0xFFFF, I2C_STAT);  /* clear delayed stuff*/
306 }
307
308 static u16 wait_for_pin (void)
309 {
310         u16 status;
311         int timeout = 10;
312
313         do {
314                 udelay (1000);
315                 status = inw (I2C_STAT);
316         } while (  !(status &
317                    (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
318                     I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
319                     I2C_STAT_AL)) && timeout--);
320
321         if (timeout <= 0) {
322                 printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
323                         inw (I2C_STAT));
324                         outw(0xFFFF, I2C_STAT);
325 }
326         return status;
327 }
328
329 #endif /* CONFIG_DRIVER_OMAP24XX_I2C */