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