xref: /openbmc/u-boot/drivers/i2c/omap24xx_i2c.c (revision 61fb15c5)
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 */
330