]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/i2c/omap24xx_i2c.c
OMAP I2C Fix the sampling clock.
[karo-tx-uboot.git] / drivers / i2c / 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 #include <asm/arch/i2c.h>
26 #include <asm/io.h>
27
28 static void wait_for_bb (void);
29 static u16 wait_for_pin (void);
30 static void flush_fifo(void);
31
32 void i2c_init (int speed, int slaveadd)
33 {
34         int psc, fsscll, fssclh;
35         int hsscll = 0, hssclh = 0;
36         u32 scll, sclh;
37
38         /* Only handle standard, fast and high speeds */
39         if ((speed != OMAP_I2C_STANDARD) &&
40             (speed != OMAP_I2C_FAST_MODE) &&
41             (speed != OMAP_I2C_HIGH_SPEED)) {
42                 printf("Error : I2C unsupported speed %d\n", speed);
43                 return;
44         }
45
46         psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
47         psc -= 1;
48         if (psc < I2C_PSC_MIN) {
49                 printf("Error : I2C unsupported prescalar %d\n", psc);
50                 return;
51         }
52
53         if (speed == OMAP_I2C_HIGH_SPEED) {
54                 /* High speed */
55
56                 /* For first phase of HS mode */
57                 fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
58                         (2 * OMAP_I2C_FAST_MODE);
59
60                 fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
61                 fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
62                 if (((fsscll < 0) || (fssclh < 0)) ||
63                     ((fsscll > 255) || (fssclh > 255))) {
64                         printf("Error : I2C initializing first phase clock\n");
65                         return;
66                 }
67
68                 /* For second phase of HS mode */
69                 hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
70
71                 hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
72                 hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
73                 if (((fsscll < 0) || (fssclh < 0)) ||
74                     ((fsscll > 255) || (fssclh > 255))) {
75                         printf("Error : I2C initializing second phase clock\n");
76                         return;
77                 }
78
79                 scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
80                 sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh;
81
82         } else {
83                 /* Standard and fast speed */
84                 fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
85
86                 fsscll -= I2C_FASTSPEED_SCLL_TRIM;
87                 fssclh -= I2C_FASTSPEED_SCLH_TRIM;
88                 if (((fsscll < 0) || (fssclh < 0)) ||
89                     ((fsscll > 255) || (fssclh > 255))) {
90                         printf("Error : I2C initializing clock\n");
91                         return;
92                 }
93
94                 scll = (unsigned int)fsscll;
95                 sclh = (unsigned int)fssclh;
96         }
97
98         writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
99         udelay(1000);
100         writew(0x0, I2C_SYSC); /* will probably self clear but */
101
102         if (readw (I2C_CON) & I2C_CON_EN) {
103                 writew (0, I2C_CON);
104                 udelay (50000);
105         }
106
107         writew(psc, I2C_PSC);
108         writew(scll, I2C_SCLL);
109         writew(sclh, I2C_SCLH);
110
111         /* own address */
112         writew (slaveadd, I2C_OA);
113         writew (I2C_CON_EN, I2C_CON);
114
115         /* have to enable intrrupts or OMAP i2c module doesn't work */
116         writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
117                 I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
118         udelay (1000);
119         flush_fifo();
120         writew (0xFFFF, I2C_STAT);
121         writew (0, I2C_CNT);
122 }
123
124 static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
125 {
126         int i2c_error = 0;
127         u16 status;
128
129         /* wait until bus not busy */
130         wait_for_bb ();
131
132         /* one byte only */
133         writew (1, I2C_CNT);
134         /* set slave address */
135         writew (devaddr, I2C_SA);
136         /* no stop bit needed here */
137         writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
138
139         status = wait_for_pin ();
140
141         if (status & I2C_STAT_XRDY) {
142                 /* Important: have to use byte access */
143                 writeb (regoffset, I2C_DATA);
144                 udelay (20000);
145                 if (readw (I2C_STAT) & I2C_STAT_NACK) {
146                         i2c_error = 1;
147                 }
148         } else {
149                 i2c_error = 1;
150         }
151
152         if (!i2c_error) {
153                 /* free bus, otherwise we can't use a combined transction */
154                 writew (0, I2C_CON);
155                 while (readw (I2C_STAT) || (readw (I2C_CON) & I2C_CON_MST)) {
156                         udelay (10000);
157                         /* Have to clear pending interrupt to clear I2C_STAT */
158                         writew (0xFFFF, I2C_STAT);
159                 }
160
161                 wait_for_bb ();
162                 /* set slave address */
163                 writew (devaddr, I2C_SA);
164                 /* read one byte from slave */
165                 writew (1, I2C_CNT);
166                 /* need stop bit here */
167                 writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
168                         I2C_CON);
169
170                 status = wait_for_pin ();
171                 if (status & I2C_STAT_RRDY) {
172 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
173                         *value = readb (I2C_DATA);
174 #else
175                         *value = readw (I2C_DATA);
176 #endif
177                         udelay (20000);
178                 } else {
179                         i2c_error = 1;
180                 }
181
182                 if (!i2c_error) {
183                         writew (I2C_CON_EN, I2C_CON);
184                         while (readw (I2C_STAT)
185                                || (readw (I2C_CON) & I2C_CON_MST)) {
186                                 udelay (10000);
187                                 writew (0xFFFF, I2C_STAT);
188                         }
189                 }
190         }
191         flush_fifo();
192         writew (0xFFFF, I2C_STAT);
193         writew (0, I2C_CNT);
194         return i2c_error;
195 }
196
197 static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
198 {
199         int i2c_error = 0;
200         u16 status, stat;
201
202         /* wait until bus not busy */
203         wait_for_bb ();
204
205         /* two bytes */
206         writew (2, I2C_CNT);
207         /* set slave address */
208         writew (devaddr, I2C_SA);
209         /* stop bit needed here */
210         writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
211                 I2C_CON_STP, I2C_CON);
212
213         /* wait until state change */
214         status = wait_for_pin ();
215
216         if (status & I2C_STAT_XRDY) {
217 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
218                 /* send out 1 byte */
219                 writeb (regoffset, I2C_DATA);
220                 writew (I2C_STAT_XRDY, I2C_STAT);
221
222                 status = wait_for_pin ();
223                 if ((status & I2C_STAT_XRDY)) {
224                         /* send out next 1 byte */
225                         writeb (value, I2C_DATA);
226                         writew (I2C_STAT_XRDY, I2C_STAT);
227                 } else {
228                         i2c_error = 1;
229                 }
230 #else
231                 /* send out two bytes */
232                 writew ((value << 8) + regoffset, I2C_DATA);
233 #endif
234                 /* must have enough delay to allow BB bit to go low */
235                 udelay (50000);
236                 if (readw (I2C_STAT) & I2C_STAT_NACK) {
237                         i2c_error = 1;
238                 }
239         } else {
240                 i2c_error = 1;
241         }
242
243         if (!i2c_error) {
244                 int eout = 200;
245
246                 writew (I2C_CON_EN, I2C_CON);
247                 while ((stat = readw (I2C_STAT)) || (readw (I2C_CON) & I2C_CON_MST)) {
248                         udelay (1000);
249                         /* have to read to clear intrrupt */
250                         writew (0xFFFF, I2C_STAT);
251                         if(--eout == 0) /* better leave with error than hang */
252                                 break;
253                 }
254         }
255         flush_fifo();
256         writew (0xFFFF, I2C_STAT);
257         writew (0, I2C_CNT);
258         return i2c_error;
259 }
260
261 static void flush_fifo(void)
262 {       u16 stat;
263
264         /* note: if you try and read data when its not there or ready
265          * you get a bus error
266          */
267         while(1){
268                 stat = readw(I2C_STAT);
269                 if(stat == I2C_STAT_RRDY){
270 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
271                         readb(I2C_DATA);
272 #else
273                         readw(I2C_DATA);
274 #endif
275                         writew(I2C_STAT_RRDY,I2C_STAT);
276                         udelay(1000);
277                 }else
278                         break;
279         }
280 }
281
282 int i2c_probe (uchar chip)
283 {
284         int res = 1; /* default = fail */
285
286         if (chip == readw (I2C_OA)) {
287                 return res;
288         }
289
290         /* wait until bus not busy */
291         wait_for_bb ();
292
293         /* try to read one byte */
294         writew (1, I2C_CNT);
295         /* set slave address */
296         writew (chip, I2C_SA);
297         /* stop bit needed here */
298         writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
299         /* enough delay for the NACK bit set */
300         udelay (50000);
301
302         if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
303                 res = 0;      /* success case */
304                 flush_fifo();
305                 writew(0xFFFF, I2C_STAT);
306         } else {
307                 writew(0xFFFF, I2C_STAT);        /* failue, clear sources*/
308                 writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
309                 udelay(20000);
310                 wait_for_bb ();
311         }
312         flush_fifo();
313         writew (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
314         writew(0xFFFF, I2C_STAT);
315         return res;
316 }
317
318 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
319 {
320         int i;
321
322         if (alen > 1) {
323                 printf ("I2C read: addr len %d not supported\n", alen);
324                 return 1;
325         }
326
327         if (addr + len > 256) {
328                 printf ("I2C read: address out of range\n");
329                 return 1;
330         }
331
332         for (i = 0; i < len; i++) {
333                 if (i2c_read_byte (chip, addr + i, &buffer[i])) {
334                         printf ("I2C read: I/O error\n");
335                         i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
336                         return 1;
337                 }
338         }
339
340         return 0;
341 }
342
343 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
344 {
345         int i;
346
347         if (alen > 1) {
348                 printf ("I2C read: addr len %d not supported\n", alen);
349                 return 1;
350         }
351
352         if (addr + len > 256) {
353                 printf ("I2C read: address out of range\n");
354                 return 1;
355         }
356
357         for (i = 0; i < len; i++) {
358                 if (i2c_write_byte (chip, addr + i, buffer[i])) {
359                         printf ("I2C read: I/O error\n");
360                         i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
361                         return 1;
362                 }
363         }
364
365         return 0;
366 }
367
368 static void wait_for_bb (void)
369 {
370         int timeout = 10;
371         u16 stat;
372
373         writew(0xFFFF, I2C_STAT);        /* clear current interruts...*/
374         while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
375                 writew (stat, I2C_STAT);
376                 udelay (50000);
377         }
378
379         if (timeout <= 0) {
380                 printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
381                         readw (I2C_STAT));
382         }
383         writew(0xFFFF, I2C_STAT);        /* clear delayed stuff*/
384 }
385
386 static u16 wait_for_pin (void)
387 {
388         u16 status;
389         int timeout = 10;
390
391         do {
392                 udelay (1000);
393                 status = readw (I2C_STAT);
394         } while (  !(status &
395                    (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
396                     I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
397                     I2C_STAT_AL)) && timeout--);
398
399         if (timeout <= 0) {
400                 printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
401                         readw (I2C_STAT));
402                         writew(0xFFFF, I2C_STAT);
403 }
404         return status;
405 }