]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/omap1510_i2c.c
Add support for Siemens SX1 mobile phone;
[karo-tx-uboot.git] / drivers / omap1510_i2c.c
1 /*
2  * Basic I2C functions
3  *
4  * Copyright (c) 2003 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  */
20
21 #include <common.h>
22
23 #ifdef CONFIG_DRIVER_OMAP1510_I2C
24
25 static void wait_for_bb (void);
26 static u16 wait_for_pin (void);
27
28 void i2c_init (int speed, int slaveadd)
29 {
30         u16 scl;
31
32         if (inw (I2C_CON) & I2C_CON_EN) {
33                 outw (0, I2C_CON);
34                 udelay (5000);
35         }
36
37         /* 12Mhz I2C module clock */
38         outw (0, I2C_PSC);
39         outw (I2C_CON_EN, I2C_CON);
40         outw (0, I2C_SYSTEST);
41         /* have to enable intrrupts or OMAP i2c module doesn't work */
42         outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
43               I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
44         scl = (12000000 / 2) / speed - 6;
45         outw (scl, I2C_SCLL);
46         outw (scl, I2C_SCLH);
47         /* own address */
48         outw (slaveadd, I2C_OA);
49         outw (0, I2C_CNT);
50         udelay (1000);
51 }
52
53 static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
54 {
55         int i2c_error = 0;
56         u16 status;
57
58         /* wait until bus not busy */
59         wait_for_bb ();
60
61         /* one byte only */
62         outw (1, I2C_CNT);
63         /* set slave address */
64         outw (devaddr, I2C_SA);
65         /* no stop bit needed here */
66         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
67
68         status = wait_for_pin ();
69
70         if (status & I2C_STAT_XRDY) {
71                 /* Important: have to use byte access */
72                 *(volatile u8 *) (I2C_DATA) = regoffset;
73                 udelay (20000);
74                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
75                         i2c_error = 1;
76                 }
77         } else {
78                 i2c_error = 1;
79         }
80
81         if (!i2c_error) {
82                 /* free bus, otherwise we can't use a combined transction */
83                 outw (0, I2C_CON);
84                 while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
85                         udelay (10000);
86                         /* Have to clear pending interrupt to clear I2C_STAT */
87                         inw (I2C_IV);
88                 }
89
90                 wait_for_bb ();
91                 /* set slave address */
92                 outw (devaddr, I2C_SA);
93                 /* read one byte from slave */
94                 outw (1, I2C_CNT);
95                 /* need stop bit here */
96                 outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
97                       I2C_CON);
98
99                 status = wait_for_pin ();
100                 if (status & I2C_STAT_RRDY) {
101                         *value = inw (I2C_DATA);
102                         udelay (20000);
103                 } else {
104                         i2c_error = 1;
105                 }
106
107                 if (!i2c_error) {
108                         outw (I2C_CON_EN, I2C_CON);
109                         while (inw (I2C_STAT)
110                                || (inw (I2C_CON) & I2C_CON_MST)) {
111                                 udelay (10000);
112                                 inw (I2C_IV);
113                         }
114                 }
115         }
116
117         return i2c_error;
118 }
119
120 static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
121 {
122         int i2c_error = 0;
123         u16 status;
124
125         /* wait until bus not busy */
126         wait_for_bb ();
127
128         /* two bytes */
129         outw (2, I2C_CNT);
130         /* set slave address */
131         outw (devaddr, I2C_SA);
132         /* stop bit needed here */
133         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
134               I2C_CON_STP, I2C_CON);
135
136         /* wait until state change */
137         status = wait_for_pin ();
138
139         if (status & I2C_STAT_XRDY) {
140                 /* send out two bytes */
141                 outw ((value << 8) + regoffset, I2C_DATA);
142                 /* must have enough delay to allow BB bit to go low */
143                 udelay (30000);
144                 if (inw (I2C_STAT) & I2C_STAT_NACK) {
145                         i2c_error = 1;
146                 }
147         } else {
148                 i2c_error = 1;
149         }
150
151         if (!i2c_error) {
152                 outw (I2C_CON_EN, I2C_CON);
153                 while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
154                         udelay (1000);
155                         /* have to read to clear intrrupt */
156                         inw (I2C_IV);
157                 }
158         }
159
160         return i2c_error;
161 }
162
163 int i2c_probe (uchar chip)
164 {
165         int res = 1;
166
167         if (chip == inw (I2C_OA)) {
168                 return res;
169         }
170
171         /* wait until bus not busy */
172         wait_for_bb ();
173
174         /* try to read one byte */
175         outw (1, I2C_CNT);
176         /* set slave address */
177         outw (chip, I2C_SA);
178         /* stop bit needed here */
179         outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
180         /* enough delay for the NACK bit set */
181         udelay (2000);
182         if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
183                 res = 0;
184         } else {
185                 outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON);
186                 udelay (20);
187                 wait_for_bb ();
188         }
189
190         return res;
191 }
192
193 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
194 {
195         int i;
196
197         if (alen > 1) {
198                 printf ("I2C read: addr len %d not supported\n", alen);
199                 return 1;
200         }
201
202         if (addr + len > 256) {
203                 printf ("I2C read: address out of range\n");
204                 return 1;
205         }
206
207         for (i = 0; i < len; i++) {
208                 if (i2c_read_byte (chip, addr + i, &buffer[i])) {
209                         printf ("I2C read: I/O error\n");
210                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
211                         return 1;
212                 }
213         }
214
215         return 0;
216 }
217
218 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
219 {
220         int i;
221
222         if (alen > 1) {
223                 printf ("I2C read: addr len %d not supported\n", alen);
224                 return 1;
225         }
226
227         if (addr + len > 256) {
228                 printf ("I2C read: address out of range\n");
229                 return 1;
230         }
231
232         for (i = 0; i < len; i++) {
233                 if (i2c_write_byte (chip, addr + i, buffer[i])) {
234                         printf ("I2C read: I/O error\n");
235                         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
236                         return 1;
237                 }
238         }
239
240         return 0;
241 }
242
243 static void wait_for_bb (void)
244 {
245         int timeout = 10;
246
247         while ((inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
248                 inw (I2C_IV);
249                 udelay (1000);
250         }
251
252         if (timeout <= 0) {
253                 printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
254                         inw (I2C_STAT));
255         }
256 }
257
258 static u16 wait_for_pin (void)
259 {
260         u16 status, iv;
261         int timeout = 10;
262
263         do {
264                 udelay (1000);
265                 status = inw (I2C_STAT);
266                 iv = inw (I2C_IV);
267         } while (!iv &&
268                  !(status &
269                    (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
270                     I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
271                     I2C_STAT_AL)) && timeout--);
272
273         if (timeout <= 0) {
274                 printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
275                         inw (I2C_STAT));
276         }
277
278         return status;
279 }
280
281 #endif /* CONFIG_DRIVER_OMAP1510_I2C */