xref: /rk3399_rockchip-uboot/drivers/i2c/omap24xx_i2c.c (revision 8ed44d91c8122d00368523b0b746691c895d3b3c)
1080c646dSJean-Christophe PLAGNIOL-VILLARD /*
2080c646dSJean-Christophe PLAGNIOL-VILLARD  * Basic I2C functions
3080c646dSJean-Christophe PLAGNIOL-VILLARD  *
4080c646dSJean-Christophe PLAGNIOL-VILLARD  * Copyright (c) 2004 Texas Instruments
5080c646dSJean-Christophe PLAGNIOL-VILLARD  *
6080c646dSJean-Christophe PLAGNIOL-VILLARD  * This package is free software;  you can redistribute it and/or
7080c646dSJean-Christophe PLAGNIOL-VILLARD  * modify it under the terms of the license found in the file
8080c646dSJean-Christophe PLAGNIOL-VILLARD  * named COPYING that should have accompanied this file.
9080c646dSJean-Christophe PLAGNIOL-VILLARD  *
10080c646dSJean-Christophe PLAGNIOL-VILLARD  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11080c646dSJean-Christophe PLAGNIOL-VILLARD  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
12080c646dSJean-Christophe PLAGNIOL-VILLARD  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13080c646dSJean-Christophe PLAGNIOL-VILLARD  *
14080c646dSJean-Christophe PLAGNIOL-VILLARD  * Author: Jian Zhang jzhang@ti.com, Texas Instruments
15080c646dSJean-Christophe PLAGNIOL-VILLARD  *
16080c646dSJean-Christophe PLAGNIOL-VILLARD  * Copyright (c) 2003 Wolfgang Denk, wd@denx.de
17080c646dSJean-Christophe PLAGNIOL-VILLARD  * Rewritten to fit into the current U-Boot framework
18080c646dSJean-Christophe PLAGNIOL-VILLARD  *
19080c646dSJean-Christophe PLAGNIOL-VILLARD  * Adapted for OMAP2420 I2C, r-woodruff2@ti.com
20080c646dSJean-Christophe PLAGNIOL-VILLARD  *
21080c646dSJean-Christophe PLAGNIOL-VILLARD  */
22080c646dSJean-Christophe PLAGNIOL-VILLARD 
23080c646dSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
24080c646dSJean-Christophe PLAGNIOL-VILLARD 
25080c646dSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/i2c.h>
26080c646dSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
27080c646dSJean-Christophe PLAGNIOL-VILLARD 
28080c646dSJean-Christophe PLAGNIOL-VILLARD #define inw(a) __raw_readw(a)
29080c646dSJean-Christophe PLAGNIOL-VILLARD #define outw(a,v) __raw_writew(a,v)
30080c646dSJean-Christophe PLAGNIOL-VILLARD 
31080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void);
32080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void);
33080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void);
34080c646dSJean-Christophe PLAGNIOL-VILLARD 
35080c646dSJean-Christophe PLAGNIOL-VILLARD void i2c_init (int speed, int slaveadd)
36080c646dSJean-Christophe PLAGNIOL-VILLARD {
37080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 scl;
38080c646dSJean-Christophe PLAGNIOL-VILLARD 
39080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw(0x2, I2C_SYSC); /* for ES2 after soft reset */
40080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay(1000);
41080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw(0x0, I2C_SYSC); /* will probably self clear but */
42080c646dSJean-Christophe PLAGNIOL-VILLARD 
43080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (inw (I2C_CON) & I2C_CON_EN) {
44080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (0, I2C_CON);
45080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
46080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
47080c646dSJean-Christophe PLAGNIOL-VILLARD 
48*8ed44d91SWolfgang Denk 	/* 12MHz I2C module clock */
49080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0, I2C_PSC);
50080c646dSJean-Christophe PLAGNIOL-VILLARD 	speed = speed/1000;		    /* 100 or 400 */
51080c646dSJean-Christophe PLAGNIOL-VILLARD 	scl = ((12000/(speed*2)) - 7);	/* use 7 when PSC = 0 */
52080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (scl, I2C_SCLL);
53080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (scl, I2C_SCLH);
54080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* own address */
55080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (slaveadd, I2C_OA);
56080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (I2C_CON_EN, I2C_CON);
57080c646dSJean-Christophe PLAGNIOL-VILLARD 
58080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* have to enable intrrupts or OMAP i2c module doesn't work */
59080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
60080c646dSJean-Christophe PLAGNIOL-VILLARD 	      I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
61080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (1000);
62080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
63080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0xFFFF, I2C_STAT);
64080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0, I2C_CNT);
65080c646dSJean-Christophe PLAGNIOL-VILLARD }
66080c646dSJean-Christophe PLAGNIOL-VILLARD 
67080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
68080c646dSJean-Christophe PLAGNIOL-VILLARD {
69080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
70080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
71080c646dSJean-Christophe PLAGNIOL-VILLARD 
72080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
73080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
74080c646dSJean-Christophe PLAGNIOL-VILLARD 
75080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* one byte only */
76080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (1, I2C_CNT);
77080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
78080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (devaddr, I2C_SA);
79080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* no stop bit needed here */
80080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
81080c646dSJean-Christophe PLAGNIOL-VILLARD 
82080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
83080c646dSJean-Christophe PLAGNIOL-VILLARD 
84080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
85080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* Important: have to use byte access */
86080c646dSJean-Christophe PLAGNIOL-VILLARD 		*(volatile u8 *) (I2C_DATA) = regoffset;
87080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (20000);
88080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (inw (I2C_STAT) & I2C_STAT_NACK) {
89080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
90080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
91080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
92080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
93080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
94080c646dSJean-Christophe PLAGNIOL-VILLARD 
95080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
96080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* free bus, otherwise we can't use a combined transction */
97080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (0, I2C_CON);
98080c646dSJean-Christophe PLAGNIOL-VILLARD 		while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
99080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (10000);
100080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* Have to clear pending interrupt to clear I2C_STAT */
101080c646dSJean-Christophe PLAGNIOL-VILLARD 			outw (0xFFFF, I2C_STAT);
102080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
103080c646dSJean-Christophe PLAGNIOL-VILLARD 
104080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
105080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* set slave address */
106080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (devaddr, I2C_SA);
107080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* read one byte from slave */
108080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (1, I2C_CNT);
109080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* need stop bit here */
110080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
111080c646dSJean-Christophe PLAGNIOL-VILLARD 		      I2C_CON);
112080c646dSJean-Christophe PLAGNIOL-VILLARD 
113080c646dSJean-Christophe PLAGNIOL-VILLARD 		status = wait_for_pin ();
114080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (status & I2C_STAT_RRDY) {
115080c646dSJean-Christophe PLAGNIOL-VILLARD 			*value = inw (I2C_DATA);
116080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (20000);
117080c646dSJean-Christophe PLAGNIOL-VILLARD 		} else {
118080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
119080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
120080c646dSJean-Christophe PLAGNIOL-VILLARD 
121080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (!i2c_error) {
122080c646dSJean-Christophe PLAGNIOL-VILLARD 			outw (I2C_CON_EN, I2C_CON);
123080c646dSJean-Christophe PLAGNIOL-VILLARD 			while (inw (I2C_STAT)
124080c646dSJean-Christophe PLAGNIOL-VILLARD 			       || (inw (I2C_CON) & I2C_CON_MST)) {
125080c646dSJean-Christophe PLAGNIOL-VILLARD 				udelay (10000);
126080c646dSJean-Christophe PLAGNIOL-VILLARD 				outw (0xFFFF, I2C_STAT);
127080c646dSJean-Christophe PLAGNIOL-VILLARD 			}
128080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
129080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
130080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
131080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0xFFFF, I2C_STAT);
132080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0, I2C_CNT);
133080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
134080c646dSJean-Christophe PLAGNIOL-VILLARD }
135080c646dSJean-Christophe PLAGNIOL-VILLARD 
136080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
137080c646dSJean-Christophe PLAGNIOL-VILLARD {
138080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
139080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status, stat;
140080c646dSJean-Christophe PLAGNIOL-VILLARD 
141080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
142080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
143080c646dSJean-Christophe PLAGNIOL-VILLARD 
144080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* two bytes */
145080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (2, I2C_CNT);
146080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
147080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (devaddr, I2C_SA);
148080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
149080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
150080c646dSJean-Christophe PLAGNIOL-VILLARD 	      I2C_CON_STP, I2C_CON);
151080c646dSJean-Christophe PLAGNIOL-VILLARD 
152080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until state change */
153080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
154080c646dSJean-Christophe PLAGNIOL-VILLARD 
155080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
156080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* send out two bytes */
157080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw ((value << 8) + regoffset, I2C_DATA);
158080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* must have enough delay to allow BB bit to go low */
159080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
160080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (inw (I2C_STAT) & I2C_STAT_NACK) {
161080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
162080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
163080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
164080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
165080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
166080c646dSJean-Christophe PLAGNIOL-VILLARD 
167080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
168080c646dSJean-Christophe PLAGNIOL-VILLARD 		int eout = 200;
169080c646dSJean-Christophe PLAGNIOL-VILLARD 
170080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (I2C_CON_EN, I2C_CON);
171080c646dSJean-Christophe PLAGNIOL-VILLARD 		while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) {
172080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (1000);
173080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* have to read to clear intrrupt */
174080c646dSJean-Christophe PLAGNIOL-VILLARD 			outw (0xFFFF, I2C_STAT);
175080c646dSJean-Christophe PLAGNIOL-VILLARD 			if(--eout == 0) /* better leave with error than hang */
176080c646dSJean-Christophe PLAGNIOL-VILLARD 				break;
177080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
178080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
179080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
180080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0xFFFF, I2C_STAT);
181080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0, I2C_CNT);
182080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
183080c646dSJean-Christophe PLAGNIOL-VILLARD }
184080c646dSJean-Christophe PLAGNIOL-VILLARD 
185080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void)
186080c646dSJean-Christophe PLAGNIOL-VILLARD {	u16 stat;
187080c646dSJean-Christophe PLAGNIOL-VILLARD 
188080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* note: if you try and read data when its not there or ready
189080c646dSJean-Christophe PLAGNIOL-VILLARD 	 * you get a bus error
190080c646dSJean-Christophe PLAGNIOL-VILLARD 	 */
191080c646dSJean-Christophe PLAGNIOL-VILLARD 	while(1){
192080c646dSJean-Christophe PLAGNIOL-VILLARD 		stat = inw(I2C_STAT);
193080c646dSJean-Christophe PLAGNIOL-VILLARD 		if(stat == I2C_STAT_RRDY){
194080c646dSJean-Christophe PLAGNIOL-VILLARD 			inw(I2C_DATA);
195080c646dSJean-Christophe PLAGNIOL-VILLARD 			outw(I2C_STAT_RRDY,I2C_STAT);
196080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
197080c646dSJean-Christophe PLAGNIOL-VILLARD 		}else
198080c646dSJean-Christophe PLAGNIOL-VILLARD 			break;
199080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
200080c646dSJean-Christophe PLAGNIOL-VILLARD }
201080c646dSJean-Christophe PLAGNIOL-VILLARD 
202080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip)
203080c646dSJean-Christophe PLAGNIOL-VILLARD {
204080c646dSJean-Christophe PLAGNIOL-VILLARD 	int res = 1; /* default = fail */
205080c646dSJean-Christophe PLAGNIOL-VILLARD 
206080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (chip == inw (I2C_OA)) {
207080c646dSJean-Christophe PLAGNIOL-VILLARD 		return res;
208080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
209080c646dSJean-Christophe PLAGNIOL-VILLARD 
210080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
211080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
212080c646dSJean-Christophe PLAGNIOL-VILLARD 
213080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* try to read one byte */
214080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (1, I2C_CNT);
215080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
216080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (chip, I2C_SA);
217080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
218080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
219080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* enough delay for the NACK bit set */
220080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (50000);
221080c646dSJean-Christophe PLAGNIOL-VILLARD 
222080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
223080c646dSJean-Christophe PLAGNIOL-VILLARD 		res = 0;      /* success case */
224080c646dSJean-Christophe PLAGNIOL-VILLARD 		flush_fifo();
225080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw(0xFFFF, I2C_STAT);
226080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
227080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw(0xFFFF, I2C_STAT);	 /* failue, clear sources*/
228080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
229080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay(20000);
230080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
231080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
232080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
233080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
234080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw(0xFFFF, I2C_STAT);
235080c646dSJean-Christophe PLAGNIOL-VILLARD 	return res;
236080c646dSJean-Christophe PLAGNIOL-VILLARD }
237080c646dSJean-Christophe PLAGNIOL-VILLARD 
238080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
239080c646dSJean-Christophe PLAGNIOL-VILLARD {
240080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
241080c646dSJean-Christophe PLAGNIOL-VILLARD 
242080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
243080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
244080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
245080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
246080c646dSJean-Christophe PLAGNIOL-VILLARD 
247080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
248080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
249080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
250080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
251080c646dSJean-Christophe PLAGNIOL-VILLARD 
252080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
253080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_read_byte (chip, addr + i, &buffer[i])) {
254080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
2556d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
256080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
257080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
258080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
259080c646dSJean-Christophe PLAGNIOL-VILLARD 
260080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
261080c646dSJean-Christophe PLAGNIOL-VILLARD }
262080c646dSJean-Christophe PLAGNIOL-VILLARD 
263080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
264080c646dSJean-Christophe PLAGNIOL-VILLARD {
265080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
266080c646dSJean-Christophe PLAGNIOL-VILLARD 
267080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
268080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
269080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
270080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
271080c646dSJean-Christophe PLAGNIOL-VILLARD 
272080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
273080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
274080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
275080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
276080c646dSJean-Christophe PLAGNIOL-VILLARD 
277080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
278080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_write_byte (chip, addr + i, buffer[i])) {
279080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
2806d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
281080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
282080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
283080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
284080c646dSJean-Christophe PLAGNIOL-VILLARD 
285080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
286080c646dSJean-Christophe PLAGNIOL-VILLARD }
287080c646dSJean-Christophe PLAGNIOL-VILLARD 
288080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void)
289080c646dSJean-Christophe PLAGNIOL-VILLARD {
290080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
291080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 stat;
292080c646dSJean-Christophe PLAGNIOL-VILLARD 
293080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw(0xFFFF, I2C_STAT);	 /* clear current interruts...*/
294080c646dSJean-Christophe PLAGNIOL-VILLARD 	while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
295080c646dSJean-Christophe PLAGNIOL-VILLARD 		outw (stat, I2C_STAT);
296080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
297080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
298080c646dSJean-Christophe PLAGNIOL-VILLARD 
299080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
300080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
301080c646dSJean-Christophe PLAGNIOL-VILLARD 			inw (I2C_STAT));
302080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
303080c646dSJean-Christophe PLAGNIOL-VILLARD 	outw(0xFFFF, I2C_STAT);	 /* clear delayed stuff*/
304080c646dSJean-Christophe PLAGNIOL-VILLARD }
305080c646dSJean-Christophe PLAGNIOL-VILLARD 
306080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void)
307080c646dSJean-Christophe PLAGNIOL-VILLARD {
308080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
309080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
310080c646dSJean-Christophe PLAGNIOL-VILLARD 
311080c646dSJean-Christophe PLAGNIOL-VILLARD 	do {
312080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (1000);
313080c646dSJean-Christophe PLAGNIOL-VILLARD 		status = inw (I2C_STAT);
314080c646dSJean-Christophe PLAGNIOL-VILLARD 	} while (  !(status &
315080c646dSJean-Christophe PLAGNIOL-VILLARD 		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
316080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
317080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_AL)) && timeout--);
318080c646dSJean-Christophe PLAGNIOL-VILLARD 
319080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
320080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
321080c646dSJean-Christophe PLAGNIOL-VILLARD 			inw (I2C_STAT));
322080c646dSJean-Christophe PLAGNIOL-VILLARD 			outw(0xFFFF, I2C_STAT);
323080c646dSJean-Christophe PLAGNIOL-VILLARD }
324080c646dSJean-Christophe PLAGNIOL-VILLARD 	return status;
325080c646dSJean-Christophe PLAGNIOL-VILLARD }
326