]> git.sur5r.net Git - u-boot/blob - drivers/omap24xx_i2c.c
* Patch by Yuli Barcohen, 08 Nov 2004:
[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 void flush_fifo(void);
36
37 void i2c_init (int speed, int slaveadd)
38 {
39         u16 scl;
40
41         if (inw (I2C_CON) & I2C_CON_EN) {
42                 outw (0, I2C_CON);
43                 udelay (50000);
44         }
45
46         /* 12Mhz I2C module clock */
47         outw (0, I2C_PSC);
48         speed = speed/1000;                 /* 100 or 400 */
49         scl = ((12000/(speed*2)) - 7);  /* use 7 when PSC = 0 */
50         outw (scl, I2C_SCLL);
51         outw (scl, I2C_SCLH);
52         /* own address */
53         outw (slaveadd, I2C_OA);
54         outw (I2C_CON_EN, I2C_CON);
55         outw (0, I2C_CNT);
56         /* have to enable intrrupts or OMAP i2c module doesn't work */
57         outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
58               I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
59         udelay (1000);
60 }
61
62 static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
63 {
64         int i2c_error = 0;
65         u16 status;
66
67         /* wait until bus not busy */
68         wait_for_bb ();
69
70         /* one byte only */
71         outw (1, I2C_CNT);
72         /* set slave address */
73         outw (devaddr, I2C_SA);
74         /* no stop bit needed here */
75         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
76
77         status = wait_for_pin ();
78
79         if (status & I2C_STAT_XRDY) {
80                 /* Important: have to use byte access */
81                 *(volatile u8 *) (I2C_DATA) = regoffset;
82                 udelay (20000);
83                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
84                         i2c_error = 1;
85                 }
86         } else {
87                 i2c_error = 1;
88         }
89
90         if (!i2c_error) {
91                 /* free bus, otherwise we can't use a combined transction */
92                 outw (0, I2C_CON);
93                 while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
94                         udelay (10000);
95                         /* Have to clear pending interrupt to clear I2C_STAT */
96                         outw (0xFFFF, I2C_STAT);
97                 }
98
99                 wait_for_bb ();
100                 /* set slave address */
101                 outw (devaddr, I2C_SA);
102                 /* read one byte from slave */
103                 outw (1, I2C_CNT);
104                 /* need stop bit here */
105                 outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
106                       I2C_CON);
107
108                 status = wait_for_pin ();
109                 if (status & I2C_STAT_RRDY) {
110                         *value = inw (I2C_DATA);
111                         udelay (20000);
112                 } else {
113                         i2c_error = 1;
114                 }
115
116                 if (!i2c_error) {
117                         outw (I2C_CON_EN, I2C_CON);
118                         while (inw (I2C_STAT)
119                                || (inw (I2C_CON) & I2C_CON_MST)) {
120                                 udelay (10000);
121                                 outw (0xFFFF, I2C_STAT);
122                         }
123                 }
124         }
125         flush_fifo();
126         outw (0xFFFF, I2C_STAT);
127         outw (0, I2C_CNT);
128         return i2c_error;
129 }
130
131 static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
132 {
133         int i2c_error = 0;
134         u16 status, stat;
135
136         /* wait until bus not busy */
137         wait_for_bb ();
138
139         /* two bytes */
140         outw (2, I2C_CNT);
141         /* set slave address */
142         outw (devaddr, I2C_SA);
143         /* stop bit needed here */
144         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
145               I2C_CON_STP, I2C_CON);
146
147         /* wait until state change */
148         status = wait_for_pin ();
149
150         if (status & I2C_STAT_XRDY) {
151                 /* send out two bytes */
152                 outw ((value << 8) + regoffset, I2C_DATA);
153                 /* must have enough delay to allow BB bit to go low */
154                 udelay (50000);
155                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
156                         i2c_error = 1;
157                 }
158         } else {
159                 i2c_error = 1;
160         }
161
162         if (!i2c_error) {
163                 outw (I2C_CON_EN, I2C_CON);
164                 while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) {
165                         udelay (1000);
166                         /* have to read to clear intrrupt */
167                         outw (0xFFFF, I2C_STAT);
168                 }
169         }
170         flush_fifo();
171         outw (0xFFFF, I2C_STAT);
172         outw (0, I2C_CNT);
173         return i2c_error;
174 }
175
176 void flush_fifo(void)
177 {       u16 stat;
178
179         /* note: if you try and read data when its not there or ready
180          * you get a bus error
181          */
182         while(1){
183                 stat = inw(I2C_STAT);
184                 if(stat == I2C_STAT_RRDY){
185                         inw(I2C_DATA);
186                         outw(I2C_STAT_RRDY,I2C_STAT);
187                         udelay(1000);
188                 }else
189                         break;
190         }
191 }
192
193 int i2c_probe (uchar chip)
194 {
195         int res = 1; /* default = fail */
196
197         if (chip == inw (I2C_OA)) {
198                 return res;
199         }
200
201         /* wait until bus not busy */
202         wait_for_bb ();
203
204         /* try to read one byte */
205         outw (1, I2C_CNT);
206         /* set slave address */
207         outw (chip, I2C_SA);
208         /* stop bit needed here */
209         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
210         /* enough delay for the NACK bit set */
211         udelay (50000);
212
213         if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
214                 res = 0;      /* success case */
215                 flush_fifo();
216                 outw(0xFFFF, I2C_STAT);
217         } else {
218                 outw(0xFFFF, I2C_STAT);  /* failue, clear sources*/
219                 outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
220                 udelay(20000);
221                 wait_for_bb ();
222         }
223         flush_fifo();
224         outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
225         outw(0xFFFF, I2C_STAT);
226         return res;
227 }
228
229 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
230 {
231         int i;
232
233         if (alen > 1) {
234                 printf ("I2C read: addr len %d not supported\n", alen);
235                 return 1;
236         }
237
238         if (addr + len > 256) {
239                 printf ("I2C read: address out of range\n");
240                 return 1;
241         }
242
243         for (i = 0; i < len; i++) {
244                 if (i2c_read_byte (chip, addr + i, &buffer[i])) {
245                         printf ("I2C read: I/O error\n");
246                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
247                         return 1;
248                 }
249         }
250
251         return 0;
252 }
253
254 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
255 {
256         int i;
257
258         if (alen > 1) {
259                 printf ("I2C read: addr len %d not supported\n", alen);
260                 return 1;
261         }
262
263         if (addr + len > 256) {
264                 printf ("I2C read: address out of range\n");
265                 return 1;
266         }
267
268         for (i = 0; i < len; i++) {
269                 if (i2c_write_byte (chip, addr + i, buffer[i])) {
270                         printf ("I2C read: I/O error\n");
271                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
272                         return 1;
273                 }
274         }
275
276         return 0;
277 }
278
279 static void wait_for_bb (void)
280 {
281         int timeout = 10;
282         u16 stat;
283
284         outw(0xFFFF, I2C_STAT);  /* clear current interruts...*/
285         while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
286                 outw (stat, I2C_STAT);
287                 udelay (50000);
288         }
289
290         if (timeout <= 0) {
291                 printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
292                         inw (I2C_STAT));
293         }
294         outw(0xFFFF, I2C_STAT);  /* clear delayed stuff*/
295 }
296
297 static u16 wait_for_pin (void)
298 {
299         u16 status;
300         int timeout = 10;
301
302         do {
303                 udelay (1000);
304                 status = inw (I2C_STAT);
305         } while (  !(status &
306                    (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
307                     I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
308                     I2C_STAT_AL)) && timeout--);
309
310         if (timeout <= 0) {
311                 printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
312                         inw (I2C_STAT));
313                         outw(0xFFFF, I2C_STAT);
314 }
315         return status;
316 }
317
318 #endif /* CONFIG_DRIVER_OMAP24XX_I2C */