xref: /rk3399_rockchip-uboot/drivers/i2c/omap24xx_i2c.c (revision 7d264c1ef267cfc8d928bc8577a7cc907f2f5e47)
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 static void wait_for_bb (void);
29080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void);
30080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void);
31080c646dSJean-Christophe PLAGNIOL-VILLARD 
32080c646dSJean-Christophe PLAGNIOL-VILLARD void i2c_init (int speed, int slaveadd)
33080c646dSJean-Christophe PLAGNIOL-VILLARD {
34080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 scl;
35080c646dSJean-Christophe PLAGNIOL-VILLARD 
36e23c7c95SDirk Behme 	writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
37080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay(1000);
38e23c7c95SDirk Behme 	writew(0x0, I2C_SYSC); /* will probably self clear but */
39080c646dSJean-Christophe PLAGNIOL-VILLARD 
40e23c7c95SDirk Behme 	if (readw (I2C_CON) & I2C_CON_EN) {
41e23c7c95SDirk Behme 		writew (0, I2C_CON);
42080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
43080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
44080c646dSJean-Christophe PLAGNIOL-VILLARD 
458ed44d91SWolfgang Denk 	/* 12MHz I2C module clock */
46e23c7c95SDirk Behme 	writew (0, I2C_PSC);
47080c646dSJean-Christophe PLAGNIOL-VILLARD 	speed = speed/1000;		    /* 100 or 400 */
48080c646dSJean-Christophe PLAGNIOL-VILLARD 	scl = ((12000/(speed*2)) - 7);	/* use 7 when PSC = 0 */
49e23c7c95SDirk Behme 	writew (scl, I2C_SCLL);
50e23c7c95SDirk Behme 	writew (scl, I2C_SCLH);
51080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* own address */
52e23c7c95SDirk Behme 	writew (slaveadd, I2C_OA);
53e23c7c95SDirk Behme 	writew (I2C_CON_EN, I2C_CON);
54080c646dSJean-Christophe PLAGNIOL-VILLARD 
55080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* have to enable intrrupts or OMAP i2c module doesn't work */
56e23c7c95SDirk Behme 	writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
57080c646dSJean-Christophe PLAGNIOL-VILLARD 		I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
58080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (1000);
59080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
60e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
61e23c7c95SDirk Behme 	writew (0, I2C_CNT);
62080c646dSJean-Christophe PLAGNIOL-VILLARD }
63080c646dSJean-Christophe PLAGNIOL-VILLARD 
64080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
65080c646dSJean-Christophe PLAGNIOL-VILLARD {
66080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
67080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
68080c646dSJean-Christophe PLAGNIOL-VILLARD 
69080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
70080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
71080c646dSJean-Christophe PLAGNIOL-VILLARD 
72080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* one byte only */
73e23c7c95SDirk Behme 	writew (1, I2C_CNT);
74080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
75e23c7c95SDirk Behme 	writew (devaddr, I2C_SA);
76080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* no stop bit needed here */
77e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
78080c646dSJean-Christophe PLAGNIOL-VILLARD 
79080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
80080c646dSJean-Christophe PLAGNIOL-VILLARD 
81080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
82080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* Important: have to use byte access */
83e23c7c95SDirk Behme 		writeb (regoffset, I2C_DATA);
84080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (20000);
85e23c7c95SDirk Behme 		if (readw (I2C_STAT) & I2C_STAT_NACK) {
86080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
87080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
88080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
89080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
90080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
91080c646dSJean-Christophe PLAGNIOL-VILLARD 
92080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
93080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* free bus, otherwise we can't use a combined transction */
94e23c7c95SDirk Behme 		writew (0, I2C_CON);
95e23c7c95SDirk Behme 		while (readw (I2C_STAT) || (readw (I2C_CON) & I2C_CON_MST)) {
96080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (10000);
97080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* Have to clear pending interrupt to clear I2C_STAT */
98e23c7c95SDirk Behme 			writew (0xFFFF, I2C_STAT);
99080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
100080c646dSJean-Christophe PLAGNIOL-VILLARD 
101080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
102080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* set slave address */
103e23c7c95SDirk Behme 		writew (devaddr, I2C_SA);
104080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* read one byte from slave */
105e23c7c95SDirk Behme 		writew (1, I2C_CNT);
106080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* need stop bit here */
107e23c7c95SDirk Behme 		writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
108080c646dSJean-Christophe PLAGNIOL-VILLARD 			I2C_CON);
109080c646dSJean-Christophe PLAGNIOL-VILLARD 
110080c646dSJean-Christophe PLAGNIOL-VILLARD 		status = wait_for_pin ();
111080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (status & I2C_STAT_RRDY) {
112*7d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
113*7d264c1eSDirk Behme 			*value = readb (I2C_DATA);
114*7d264c1eSDirk Behme #else
115e23c7c95SDirk Behme 			*value = readw (I2C_DATA);
116*7d264c1eSDirk Behme #endif
117080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (20000);
118080c646dSJean-Christophe PLAGNIOL-VILLARD 		} else {
119080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
120080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
121080c646dSJean-Christophe PLAGNIOL-VILLARD 
122080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (!i2c_error) {
123e23c7c95SDirk Behme 			writew (I2C_CON_EN, I2C_CON);
124e23c7c95SDirk Behme 			while (readw (I2C_STAT)
125e23c7c95SDirk Behme 			       || (readw (I2C_CON) & I2C_CON_MST)) {
126080c646dSJean-Christophe PLAGNIOL-VILLARD 				udelay (10000);
127e23c7c95SDirk Behme 				writew (0xFFFF, I2C_STAT);
128080c646dSJean-Christophe PLAGNIOL-VILLARD 			}
129080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
130080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
131080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
132e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
133e23c7c95SDirk Behme 	writew (0, I2C_CNT);
134080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
135080c646dSJean-Christophe PLAGNIOL-VILLARD }
136080c646dSJean-Christophe PLAGNIOL-VILLARD 
137080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
138080c646dSJean-Christophe PLAGNIOL-VILLARD {
139080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
140080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status, stat;
141080c646dSJean-Christophe PLAGNIOL-VILLARD 
142080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
143080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
144080c646dSJean-Christophe PLAGNIOL-VILLARD 
145080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* two bytes */
146e23c7c95SDirk Behme 	writew (2, I2C_CNT);
147080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
148e23c7c95SDirk Behme 	writew (devaddr, I2C_SA);
149080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
150e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
151080c646dSJean-Christophe PLAGNIOL-VILLARD 		I2C_CON_STP, I2C_CON);
152080c646dSJean-Christophe PLAGNIOL-VILLARD 
153080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until state change */
154080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
155080c646dSJean-Christophe PLAGNIOL-VILLARD 
156080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
157*7d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
158*7d264c1eSDirk Behme 		/* send out 1 byte */
159*7d264c1eSDirk Behme 		writeb (regoffset, I2C_DATA);
160*7d264c1eSDirk Behme 		writew (I2C_STAT_XRDY, I2C_STAT);
161*7d264c1eSDirk Behme 
162*7d264c1eSDirk Behme 		status = wait_for_pin ();
163*7d264c1eSDirk Behme 		if ((status & I2C_STAT_XRDY)) {
164*7d264c1eSDirk Behme 			/* send out next 1 byte */
165*7d264c1eSDirk Behme 			writeb (value, I2C_DATA);
166*7d264c1eSDirk Behme 			writew (I2C_STAT_XRDY, I2C_STAT);
167*7d264c1eSDirk Behme 		} else {
168*7d264c1eSDirk Behme 			i2c_error = 1;
169*7d264c1eSDirk Behme 		}
170*7d264c1eSDirk Behme #else
171080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* send out two bytes */
172e23c7c95SDirk Behme 		writew ((value << 8) + regoffset, I2C_DATA);
173*7d264c1eSDirk Behme #endif
174080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* must have enough delay to allow BB bit to go low */
175080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
176e23c7c95SDirk Behme 		if (readw (I2C_STAT) & I2C_STAT_NACK) {
177080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
178080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
179080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
180080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
181080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
182080c646dSJean-Christophe PLAGNIOL-VILLARD 
183080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
184080c646dSJean-Christophe PLAGNIOL-VILLARD 		int eout = 200;
185080c646dSJean-Christophe PLAGNIOL-VILLARD 
186e23c7c95SDirk Behme 		writew (I2C_CON_EN, I2C_CON);
187e23c7c95SDirk Behme 		while ((stat = readw (I2C_STAT)) || (readw (I2C_CON) & I2C_CON_MST)) {
188080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (1000);
189080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* have to read to clear intrrupt */
190e23c7c95SDirk Behme 			writew (0xFFFF, I2C_STAT);
191080c646dSJean-Christophe PLAGNIOL-VILLARD 			if(--eout == 0) /* better leave with error than hang */
192080c646dSJean-Christophe PLAGNIOL-VILLARD 				break;
193080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
194080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
195080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
196e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
197e23c7c95SDirk Behme 	writew (0, I2C_CNT);
198080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
199080c646dSJean-Christophe PLAGNIOL-VILLARD }
200080c646dSJean-Christophe PLAGNIOL-VILLARD 
201080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void)
202080c646dSJean-Christophe PLAGNIOL-VILLARD {	u16 stat;
203080c646dSJean-Christophe PLAGNIOL-VILLARD 
204080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* note: if you try and read data when its not there or ready
205080c646dSJean-Christophe PLAGNIOL-VILLARD 	 * you get a bus error
206080c646dSJean-Christophe PLAGNIOL-VILLARD 	 */
207080c646dSJean-Christophe PLAGNIOL-VILLARD 	while(1){
208e23c7c95SDirk Behme 		stat = readw(I2C_STAT);
209080c646dSJean-Christophe PLAGNIOL-VILLARD 		if(stat == I2C_STAT_RRDY){
210*7d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
211*7d264c1eSDirk Behme 			readb(I2C_DATA);
212*7d264c1eSDirk Behme #else
213e23c7c95SDirk Behme 			readw(I2C_DATA);
214*7d264c1eSDirk Behme #endif
215e23c7c95SDirk Behme 			writew(I2C_STAT_RRDY,I2C_STAT);
216080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
217080c646dSJean-Christophe PLAGNIOL-VILLARD 		}else
218080c646dSJean-Christophe PLAGNIOL-VILLARD 			break;
219080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
220080c646dSJean-Christophe PLAGNIOL-VILLARD }
221080c646dSJean-Christophe PLAGNIOL-VILLARD 
222080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip)
223080c646dSJean-Christophe PLAGNIOL-VILLARD {
224080c646dSJean-Christophe PLAGNIOL-VILLARD 	int res = 1; /* default = fail */
225080c646dSJean-Christophe PLAGNIOL-VILLARD 
226e23c7c95SDirk Behme 	if (chip == readw (I2C_OA)) {
227080c646dSJean-Christophe PLAGNIOL-VILLARD 		return res;
228080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
229080c646dSJean-Christophe PLAGNIOL-VILLARD 
230080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
231080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
232080c646dSJean-Christophe PLAGNIOL-VILLARD 
233080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* try to read one byte */
234e23c7c95SDirk Behme 	writew (1, I2C_CNT);
235080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
236e23c7c95SDirk Behme 	writew (chip, I2C_SA);
237080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
238e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
239080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* enough delay for the NACK bit set */
240080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (50000);
241080c646dSJean-Christophe PLAGNIOL-VILLARD 
242e23c7c95SDirk Behme 	if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
243080c646dSJean-Christophe PLAGNIOL-VILLARD 		res = 0;      /* success case */
244080c646dSJean-Christophe PLAGNIOL-VILLARD 		flush_fifo();
245e23c7c95SDirk Behme 		writew(0xFFFF, I2C_STAT);
246080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
247e23c7c95SDirk Behme 		writew(0xFFFF, I2C_STAT);	 /* failue, clear sources*/
248e23c7c95SDirk Behme 		writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
249080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay(20000);
250080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
251080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
252080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
253e23c7c95SDirk Behme 	writew (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
254e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);
255080c646dSJean-Christophe PLAGNIOL-VILLARD 	return res;
256080c646dSJean-Christophe PLAGNIOL-VILLARD }
257080c646dSJean-Christophe PLAGNIOL-VILLARD 
258080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
259080c646dSJean-Christophe PLAGNIOL-VILLARD {
260080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
261080c646dSJean-Christophe PLAGNIOL-VILLARD 
262080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
263080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
264080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
265080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
266080c646dSJean-Christophe PLAGNIOL-VILLARD 
267080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
268080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
269080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
270080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
271080c646dSJean-Christophe PLAGNIOL-VILLARD 
272080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
273080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_read_byte (chip, addr + i, &buffer[i])) {
274080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
2756d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
276080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
277080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
278080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
279080c646dSJean-Christophe PLAGNIOL-VILLARD 
280080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
281080c646dSJean-Christophe PLAGNIOL-VILLARD }
282080c646dSJean-Christophe PLAGNIOL-VILLARD 
283080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
284080c646dSJean-Christophe PLAGNIOL-VILLARD {
285080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
286080c646dSJean-Christophe PLAGNIOL-VILLARD 
287080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
288080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
289080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
290080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
291080c646dSJean-Christophe PLAGNIOL-VILLARD 
292080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
293080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
294080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
295080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
296080c646dSJean-Christophe PLAGNIOL-VILLARD 
297080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
298080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_write_byte (chip, addr + i, buffer[i])) {
299080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
3006d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
301080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
302080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
303080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
304080c646dSJean-Christophe PLAGNIOL-VILLARD 
305080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
306080c646dSJean-Christophe PLAGNIOL-VILLARD }
307080c646dSJean-Christophe PLAGNIOL-VILLARD 
308080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void)
309080c646dSJean-Christophe PLAGNIOL-VILLARD {
310080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
311080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 stat;
312080c646dSJean-Christophe PLAGNIOL-VILLARD 
313e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);	 /* clear current interruts...*/
314e23c7c95SDirk Behme 	while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
315e23c7c95SDirk Behme 		writew (stat, I2C_STAT);
316080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
317080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
318080c646dSJean-Christophe PLAGNIOL-VILLARD 
319080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
320080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
321e23c7c95SDirk Behme 			readw (I2C_STAT));
322080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
323e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);	 /* clear delayed stuff*/
324080c646dSJean-Christophe PLAGNIOL-VILLARD }
325080c646dSJean-Christophe PLAGNIOL-VILLARD 
326080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void)
327080c646dSJean-Christophe PLAGNIOL-VILLARD {
328080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
329080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
330080c646dSJean-Christophe PLAGNIOL-VILLARD 
331080c646dSJean-Christophe PLAGNIOL-VILLARD 	do {
332080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (1000);
333e23c7c95SDirk Behme 		status = readw (I2C_STAT);
334080c646dSJean-Christophe PLAGNIOL-VILLARD 	} while (  !(status &
335080c646dSJean-Christophe PLAGNIOL-VILLARD 		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
336080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
337080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_AL)) && timeout--);
338080c646dSJean-Christophe PLAGNIOL-VILLARD 
339080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
340080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
341e23c7c95SDirk Behme 			readw (I2C_STAT));
342e23c7c95SDirk Behme 			writew(0xFFFF, I2C_STAT);
343080c646dSJean-Christophe PLAGNIOL-VILLARD }
344080c646dSJean-Christophe PLAGNIOL-VILLARD 	return status;
345080c646dSJean-Christophe PLAGNIOL-VILLARD }
346