xref: /rk3399_rockchip-uboot/drivers/i2c/omap24xx_i2c.c (revision 7f79dfb48b7419d5caa1cf932fcff4e2fb7040af)
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 {
34*7f79dfb4STom Rix 	int psc, fsscll, fssclh;
35*7f79dfb4STom Rix 	int hsscll = 0, hssclh = 0;
36*7f79dfb4STom Rix 	u32 scll, sclh;
37*7f79dfb4STom Rix 
38*7f79dfb4STom Rix 	/* Only handle standard, fast and high speeds */
39*7f79dfb4STom Rix 	if ((speed != OMAP_I2C_STANDARD) &&
40*7f79dfb4STom Rix 	    (speed != OMAP_I2C_FAST_MODE) &&
41*7f79dfb4STom Rix 	    (speed != OMAP_I2C_HIGH_SPEED)) {
42*7f79dfb4STom Rix 		printf("Error : I2C unsupported speed %d\n", speed);
43*7f79dfb4STom Rix 		return;
44*7f79dfb4STom Rix 	}
45*7f79dfb4STom Rix 
46*7f79dfb4STom Rix 	psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
47*7f79dfb4STom Rix 	psc -= 1;
48*7f79dfb4STom Rix 	if (psc < I2C_PSC_MIN) {
49*7f79dfb4STom Rix 		printf("Error : I2C unsupported prescalar %d\n", psc);
50*7f79dfb4STom Rix 		return;
51*7f79dfb4STom Rix 	}
52*7f79dfb4STom Rix 
53*7f79dfb4STom Rix 	if (speed == OMAP_I2C_HIGH_SPEED) {
54*7f79dfb4STom Rix 		/* High speed */
55*7f79dfb4STom Rix 
56*7f79dfb4STom Rix 		/* For first phase of HS mode */
57*7f79dfb4STom Rix 		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
58*7f79dfb4STom Rix 			(2 * OMAP_I2C_FAST_MODE);
59*7f79dfb4STom Rix 
60*7f79dfb4STom Rix 		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
61*7f79dfb4STom Rix 		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
62*7f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
63*7f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
64*7f79dfb4STom Rix 			printf("Error : I2C initializing first phase clock\n");
65*7f79dfb4STom Rix 			return;
66*7f79dfb4STom Rix 		}
67*7f79dfb4STom Rix 
68*7f79dfb4STom Rix 		/* For second phase of HS mode */
69*7f79dfb4STom Rix 		hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
70*7f79dfb4STom Rix 
71*7f79dfb4STom Rix 		hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
72*7f79dfb4STom Rix 		hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
73*7f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
74*7f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
75*7f79dfb4STom Rix 			printf("Error : I2C initializing second phase clock\n");
76*7f79dfb4STom Rix 			return;
77*7f79dfb4STom Rix 		}
78*7f79dfb4STom Rix 
79*7f79dfb4STom Rix 		scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
80*7f79dfb4STom Rix 		sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh;
81*7f79dfb4STom Rix 
82*7f79dfb4STom Rix 	} else {
83*7f79dfb4STom Rix 		/* Standard and fast speed */
84*7f79dfb4STom Rix 		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
85*7f79dfb4STom Rix 
86*7f79dfb4STom Rix 		fsscll -= I2C_FASTSPEED_SCLL_TRIM;
87*7f79dfb4STom Rix 		fssclh -= I2C_FASTSPEED_SCLH_TRIM;
88*7f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
89*7f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
90*7f79dfb4STom Rix 			printf("Error : I2C initializing clock\n");
91*7f79dfb4STom Rix 			return;
92*7f79dfb4STom Rix 		}
93*7f79dfb4STom Rix 
94*7f79dfb4STom Rix 		scll = (unsigned int)fsscll;
95*7f79dfb4STom Rix 		sclh = (unsigned int)fssclh;
96*7f79dfb4STom Rix 	}
97080c646dSJean-Christophe PLAGNIOL-VILLARD 
98e23c7c95SDirk Behme 	writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
99080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay(1000);
100e23c7c95SDirk Behme 	writew(0x0, I2C_SYSC); /* will probably self clear but */
101080c646dSJean-Christophe PLAGNIOL-VILLARD 
102e23c7c95SDirk Behme 	if (readw (I2C_CON) & I2C_CON_EN) {
103e23c7c95SDirk Behme 		writew (0, I2C_CON);
104080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
105080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
106080c646dSJean-Christophe PLAGNIOL-VILLARD 
107*7f79dfb4STom Rix 	writew(psc, I2C_PSC);
108*7f79dfb4STom Rix 	writew(scll, I2C_SCLL);
109*7f79dfb4STom Rix 	writew(sclh, I2C_SCLH);
110*7f79dfb4STom Rix 
111080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* own address */
112e23c7c95SDirk Behme 	writew (slaveadd, I2C_OA);
113e23c7c95SDirk Behme 	writew (I2C_CON_EN, I2C_CON);
114080c646dSJean-Christophe PLAGNIOL-VILLARD 
115080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* have to enable intrrupts or OMAP i2c module doesn't work */
116e23c7c95SDirk Behme 	writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
117080c646dSJean-Christophe PLAGNIOL-VILLARD 		I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
118080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (1000);
119080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
120e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
121e23c7c95SDirk Behme 	writew (0, I2C_CNT);
122080c646dSJean-Christophe PLAGNIOL-VILLARD }
123080c646dSJean-Christophe PLAGNIOL-VILLARD 
124080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
125080c646dSJean-Christophe PLAGNIOL-VILLARD {
126080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
127080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
128080c646dSJean-Christophe PLAGNIOL-VILLARD 
129080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
130080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
131080c646dSJean-Christophe PLAGNIOL-VILLARD 
132080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* one byte only */
133e23c7c95SDirk Behme 	writew (1, I2C_CNT);
134080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
135e23c7c95SDirk Behme 	writew (devaddr, I2C_SA);
136080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* no stop bit needed here */
137e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
138080c646dSJean-Christophe PLAGNIOL-VILLARD 
139080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
140080c646dSJean-Christophe PLAGNIOL-VILLARD 
141080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
142080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* Important: have to use byte access */
143e23c7c95SDirk Behme 		writeb (regoffset, I2C_DATA);
144080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (20000);
145e23c7c95SDirk Behme 		if (readw (I2C_STAT) & I2C_STAT_NACK) {
146080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
147080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
148080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
149080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
150080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
151080c646dSJean-Christophe PLAGNIOL-VILLARD 
152080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
153080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* free bus, otherwise we can't use a combined transction */
154e23c7c95SDirk Behme 		writew (0, I2C_CON);
155e23c7c95SDirk Behme 		while (readw (I2C_STAT) || (readw (I2C_CON) & I2C_CON_MST)) {
156080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (10000);
157080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* Have to clear pending interrupt to clear I2C_STAT */
158e23c7c95SDirk Behme 			writew (0xFFFF, I2C_STAT);
159080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
160080c646dSJean-Christophe PLAGNIOL-VILLARD 
161080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
162080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* set slave address */
163e23c7c95SDirk Behme 		writew (devaddr, I2C_SA);
164080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* read one byte from slave */
165e23c7c95SDirk Behme 		writew (1, I2C_CNT);
166080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* need stop bit here */
167e23c7c95SDirk Behme 		writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
168080c646dSJean-Christophe PLAGNIOL-VILLARD 			I2C_CON);
169080c646dSJean-Christophe PLAGNIOL-VILLARD 
170080c646dSJean-Christophe PLAGNIOL-VILLARD 		status = wait_for_pin ();
171080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (status & I2C_STAT_RRDY) {
1727d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
1737d264c1eSDirk Behme 			*value = readb (I2C_DATA);
1747d264c1eSDirk Behme #else
175e23c7c95SDirk Behme 			*value = readw (I2C_DATA);
1767d264c1eSDirk Behme #endif
177080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (20000);
178080c646dSJean-Christophe PLAGNIOL-VILLARD 		} else {
179080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
180080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
181080c646dSJean-Christophe PLAGNIOL-VILLARD 
182080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (!i2c_error) {
183e23c7c95SDirk Behme 			writew (I2C_CON_EN, I2C_CON);
184e23c7c95SDirk Behme 			while (readw (I2C_STAT)
185e23c7c95SDirk Behme 			       || (readw (I2C_CON) & I2C_CON_MST)) {
186080c646dSJean-Christophe PLAGNIOL-VILLARD 				udelay (10000);
187e23c7c95SDirk Behme 				writew (0xFFFF, I2C_STAT);
188080c646dSJean-Christophe PLAGNIOL-VILLARD 			}
189080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
190080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
191080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
192e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
193e23c7c95SDirk Behme 	writew (0, I2C_CNT);
194080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
195080c646dSJean-Christophe PLAGNIOL-VILLARD }
196080c646dSJean-Christophe PLAGNIOL-VILLARD 
197080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
198080c646dSJean-Christophe PLAGNIOL-VILLARD {
199080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i2c_error = 0;
200080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status, stat;
201080c646dSJean-Christophe PLAGNIOL-VILLARD 
202080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
203080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
204080c646dSJean-Christophe PLAGNIOL-VILLARD 
205080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* two bytes */
206e23c7c95SDirk Behme 	writew (2, I2C_CNT);
207080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
208e23c7c95SDirk Behme 	writew (devaddr, I2C_SA);
209080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
210e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
211080c646dSJean-Christophe PLAGNIOL-VILLARD 		I2C_CON_STP, I2C_CON);
212080c646dSJean-Christophe PLAGNIOL-VILLARD 
213080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until state change */
214080c646dSJean-Christophe PLAGNIOL-VILLARD 	status = wait_for_pin ();
215080c646dSJean-Christophe PLAGNIOL-VILLARD 
216080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (status & I2C_STAT_XRDY) {
2177d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
2187d264c1eSDirk Behme 		/* send out 1 byte */
2197d264c1eSDirk Behme 		writeb (regoffset, I2C_DATA);
2207d264c1eSDirk Behme 		writew (I2C_STAT_XRDY, I2C_STAT);
2217d264c1eSDirk Behme 
2227d264c1eSDirk Behme 		status = wait_for_pin ();
2237d264c1eSDirk Behme 		if ((status & I2C_STAT_XRDY)) {
2247d264c1eSDirk Behme 			/* send out next 1 byte */
2257d264c1eSDirk Behme 			writeb (value, I2C_DATA);
2267d264c1eSDirk Behme 			writew (I2C_STAT_XRDY, I2C_STAT);
2277d264c1eSDirk Behme 		} else {
2287d264c1eSDirk Behme 			i2c_error = 1;
2297d264c1eSDirk Behme 		}
2307d264c1eSDirk Behme #else
231080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* send out two bytes */
232e23c7c95SDirk Behme 		writew ((value << 8) + regoffset, I2C_DATA);
2337d264c1eSDirk Behme #endif
234080c646dSJean-Christophe PLAGNIOL-VILLARD 		/* must have enough delay to allow BB bit to go low */
235080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
236e23c7c95SDirk Behme 		if (readw (I2C_STAT) & I2C_STAT_NACK) {
237080c646dSJean-Christophe PLAGNIOL-VILLARD 			i2c_error = 1;
238080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
239080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
240080c646dSJean-Christophe PLAGNIOL-VILLARD 		i2c_error = 1;
241080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
242080c646dSJean-Christophe PLAGNIOL-VILLARD 
243080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (!i2c_error) {
244080c646dSJean-Christophe PLAGNIOL-VILLARD 		int eout = 200;
245080c646dSJean-Christophe PLAGNIOL-VILLARD 
246e23c7c95SDirk Behme 		writew (I2C_CON_EN, I2C_CON);
247e23c7c95SDirk Behme 		while ((stat = readw (I2C_STAT)) || (readw (I2C_CON) & I2C_CON_MST)) {
248080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay (1000);
249080c646dSJean-Christophe PLAGNIOL-VILLARD 			/* have to read to clear intrrupt */
250e23c7c95SDirk Behme 			writew (0xFFFF, I2C_STAT);
251080c646dSJean-Christophe PLAGNIOL-VILLARD 			if(--eout == 0) /* better leave with error than hang */
252080c646dSJean-Christophe PLAGNIOL-VILLARD 				break;
253080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
254080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
255080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
256e23c7c95SDirk Behme 	writew (0xFFFF, I2C_STAT);
257e23c7c95SDirk Behme 	writew (0, I2C_CNT);
258080c646dSJean-Christophe PLAGNIOL-VILLARD 	return i2c_error;
259080c646dSJean-Christophe PLAGNIOL-VILLARD }
260080c646dSJean-Christophe PLAGNIOL-VILLARD 
261080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void)
262080c646dSJean-Christophe PLAGNIOL-VILLARD {	u16 stat;
263080c646dSJean-Christophe PLAGNIOL-VILLARD 
264080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* note: if you try and read data when its not there or ready
265080c646dSJean-Christophe PLAGNIOL-VILLARD 	 * you get a bus error
266080c646dSJean-Christophe PLAGNIOL-VILLARD 	 */
267080c646dSJean-Christophe PLAGNIOL-VILLARD 	while(1){
268e23c7c95SDirk Behme 		stat = readw(I2C_STAT);
269080c646dSJean-Christophe PLAGNIOL-VILLARD 		if(stat == I2C_STAT_RRDY){
2707d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
2717d264c1eSDirk Behme 			readb(I2C_DATA);
2727d264c1eSDirk Behme #else
273e23c7c95SDirk Behme 			readw(I2C_DATA);
2747d264c1eSDirk Behme #endif
275e23c7c95SDirk Behme 			writew(I2C_STAT_RRDY,I2C_STAT);
276080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
277080c646dSJean-Christophe PLAGNIOL-VILLARD 		}else
278080c646dSJean-Christophe PLAGNIOL-VILLARD 			break;
279080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
280080c646dSJean-Christophe PLAGNIOL-VILLARD }
281080c646dSJean-Christophe PLAGNIOL-VILLARD 
282080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip)
283080c646dSJean-Christophe PLAGNIOL-VILLARD {
284080c646dSJean-Christophe PLAGNIOL-VILLARD 	int res = 1; /* default = fail */
285080c646dSJean-Christophe PLAGNIOL-VILLARD 
286e23c7c95SDirk Behme 	if (chip == readw (I2C_OA)) {
287080c646dSJean-Christophe PLAGNIOL-VILLARD 		return res;
288080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
289080c646dSJean-Christophe PLAGNIOL-VILLARD 
290080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
291080c646dSJean-Christophe PLAGNIOL-VILLARD 	wait_for_bb ();
292080c646dSJean-Christophe PLAGNIOL-VILLARD 
293080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* try to read one byte */
294e23c7c95SDirk Behme 	writew (1, I2C_CNT);
295080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
296e23c7c95SDirk Behme 	writew (chip, I2C_SA);
297080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
298e23c7c95SDirk Behme 	writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
299080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* enough delay for the NACK bit set */
300080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay (50000);
301080c646dSJean-Christophe PLAGNIOL-VILLARD 
302e23c7c95SDirk Behme 	if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
303080c646dSJean-Christophe PLAGNIOL-VILLARD 		res = 0;      /* success case */
304080c646dSJean-Christophe PLAGNIOL-VILLARD 		flush_fifo();
305e23c7c95SDirk Behme 		writew(0xFFFF, I2C_STAT);
306080c646dSJean-Christophe PLAGNIOL-VILLARD 	} else {
307e23c7c95SDirk Behme 		writew(0xFFFF, I2C_STAT);	 /* failue, clear sources*/
308e23c7c95SDirk Behme 		writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
309080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay(20000);
310080c646dSJean-Christophe PLAGNIOL-VILLARD 		wait_for_bb ();
311080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
312080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
313e23c7c95SDirk Behme 	writew (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
314e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);
315080c646dSJean-Christophe PLAGNIOL-VILLARD 	return res;
316080c646dSJean-Christophe PLAGNIOL-VILLARD }
317080c646dSJean-Christophe PLAGNIOL-VILLARD 
318080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
319080c646dSJean-Christophe PLAGNIOL-VILLARD {
320080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
321080c646dSJean-Christophe PLAGNIOL-VILLARD 
322080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
323080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
324080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
325080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
326080c646dSJean-Christophe PLAGNIOL-VILLARD 
327080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
328080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
329080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
330080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
331080c646dSJean-Christophe PLAGNIOL-VILLARD 
332080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
333080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_read_byte (chip, addr + i, &buffer[i])) {
334080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
3356d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
336080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
337080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
338080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
339080c646dSJean-Christophe PLAGNIOL-VILLARD 
340080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
341080c646dSJean-Christophe PLAGNIOL-VILLARD }
342080c646dSJean-Christophe PLAGNIOL-VILLARD 
343080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
344080c646dSJean-Christophe PLAGNIOL-VILLARD {
345080c646dSJean-Christophe PLAGNIOL-VILLARD 	int i;
346080c646dSJean-Christophe PLAGNIOL-VILLARD 
347080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (alen > 1) {
348080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: addr len %d not supported\n", alen);
349080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
350080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
351080c646dSJean-Christophe PLAGNIOL-VILLARD 
352080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (addr + len > 256) {
353080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("I2C read: address out of range\n");
354080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
355080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
356080c646dSJean-Christophe PLAGNIOL-VILLARD 
357080c646dSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
358080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (i2c_write_byte (chip, addr + i, buffer[i])) {
359080c646dSJean-Christophe PLAGNIOL-VILLARD 			printf ("I2C read: I/O error\n");
3606d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 			i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
361080c646dSJean-Christophe PLAGNIOL-VILLARD 			return 1;
362080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
363080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
364080c646dSJean-Christophe PLAGNIOL-VILLARD 
365080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
366080c646dSJean-Christophe PLAGNIOL-VILLARD }
367080c646dSJean-Christophe PLAGNIOL-VILLARD 
368080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void)
369080c646dSJean-Christophe PLAGNIOL-VILLARD {
370080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
371080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 stat;
372080c646dSJean-Christophe PLAGNIOL-VILLARD 
373e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);	 /* clear current interruts...*/
374e23c7c95SDirk Behme 	while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
375e23c7c95SDirk Behme 		writew (stat, I2C_STAT);
376080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
377080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
378080c646dSJean-Christophe PLAGNIOL-VILLARD 
379080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
380080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
381e23c7c95SDirk Behme 			readw (I2C_STAT));
382080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
383e23c7c95SDirk Behme 	writew(0xFFFF, I2C_STAT);	 /* clear delayed stuff*/
384080c646dSJean-Christophe PLAGNIOL-VILLARD }
385080c646dSJean-Christophe PLAGNIOL-VILLARD 
386080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void)
387080c646dSJean-Christophe PLAGNIOL-VILLARD {
388080c646dSJean-Christophe PLAGNIOL-VILLARD 	u16 status;
389080c646dSJean-Christophe PLAGNIOL-VILLARD 	int timeout = 10;
390080c646dSJean-Christophe PLAGNIOL-VILLARD 
391080c646dSJean-Christophe PLAGNIOL-VILLARD 	do {
392080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay (1000);
393e23c7c95SDirk Behme 		status = readw (I2C_STAT);
394080c646dSJean-Christophe PLAGNIOL-VILLARD 	} while (  !(status &
395080c646dSJean-Christophe PLAGNIOL-VILLARD 		   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
396080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
397080c646dSJean-Christophe PLAGNIOL-VILLARD 		    I2C_STAT_AL)) && timeout--);
398080c646dSJean-Christophe PLAGNIOL-VILLARD 
399080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
400080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
401e23c7c95SDirk Behme 			readw (I2C_STAT));
402e23c7c95SDirk Behme 			writew(0xFFFF, I2C_STAT);
403080c646dSJean-Christophe PLAGNIOL-VILLARD }
404080c646dSJean-Christophe PLAGNIOL-VILLARD 	return status;
405080c646dSJean-Christophe PLAGNIOL-VILLARD }
406