xref: /rk3399_rockchip-uboot/drivers/i2c/omap24xx_i2c.c (revision 2faa76196af4b3e93bcb9e38ed9090cbd3b06db3)
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 
28938717ceSSteve Sakoman #include "omap24xx_i2c.h"
29938717ceSSteve Sakoman 
3029565326SJohn Rigby DECLARE_GLOBAL_DATA_PTR;
3129565326SJohn Rigby 
32*2faa7619SPatil, Rachna #define I2C_STAT_TIMEO	(1 << 31)
33*2faa7619SPatil, Rachna #define I2C_TIMEOUT	10
34d708395dSSteve Sakoman 
35*2faa7619SPatil, Rachna static u32 wait_for_bb(void);
36*2faa7619SPatil, Rachna static u32 wait_for_status_mask(u16 mask);
37080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void);
38080c646dSJean-Christophe PLAGNIOL-VILLARD 
390b620ec9SAndreas Müller /*
400b620ec9SAndreas Müller  * For SPL boot some boards need i2c before SDRAM is initialised so force
410b620ec9SAndreas Müller  * variables to live in SRAM
420b620ec9SAndreas Müller  */
430b620ec9SAndreas Müller static struct i2c __attribute__((section (".data"))) *i2c_base =
440b620ec9SAndreas Müller 					(struct i2c *)I2C_DEFAULT_BASE;
450b620ec9SAndreas Müller static unsigned int __attribute__((section (".data"))) bus_initialized[I2C_BUS_MAX] =
460b620ec9SAndreas Müller 					{ [0 ... (I2C_BUS_MAX-1)] = 0 };
470b620ec9SAndreas Müller static unsigned int __attribute__((section (".data"))) current_bus = 0;
481d2e96deSDirk Behme 
49080c646dSJean-Christophe PLAGNIOL-VILLARD void i2c_init(int speed, int slaveadd)
50080c646dSJean-Christophe PLAGNIOL-VILLARD {
517f79dfb4STom Rix 	int psc, fsscll, fssclh;
527f79dfb4STom Rix 	int hsscll = 0, hssclh = 0;
537f79dfb4STom Rix 	u32 scll, sclh;
547f79dfb4STom Rix 
557f79dfb4STom Rix 	/* Only handle standard, fast and high speeds */
567f79dfb4STom Rix 	if ((speed != OMAP_I2C_STANDARD) &&
577f79dfb4STom Rix 	    (speed != OMAP_I2C_FAST_MODE) &&
587f79dfb4STom Rix 	    (speed != OMAP_I2C_HIGH_SPEED)) {
597f79dfb4STom Rix 		printf("Error : I2C unsupported speed %d\n", speed);
607f79dfb4STom Rix 		return;
617f79dfb4STom Rix 	}
627f79dfb4STom Rix 
637f79dfb4STom Rix 	psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
647f79dfb4STom Rix 	psc -= 1;
657f79dfb4STom Rix 	if (psc < I2C_PSC_MIN) {
667f79dfb4STom Rix 		printf("Error : I2C unsupported prescalar %d\n", psc);
677f79dfb4STom Rix 		return;
687f79dfb4STom Rix 	}
697f79dfb4STom Rix 
707f79dfb4STom Rix 	if (speed == OMAP_I2C_HIGH_SPEED) {
717f79dfb4STom Rix 		/* High speed */
727f79dfb4STom Rix 
737f79dfb4STom Rix 		/* For first phase of HS mode */
747f79dfb4STom Rix 		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK /
757f79dfb4STom Rix 			(2 * OMAP_I2C_FAST_MODE);
767f79dfb4STom Rix 
777f79dfb4STom Rix 		fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM;
787f79dfb4STom Rix 		fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM;
797f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
807f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
8149e9b4bdSAndreas Müller 			puts("Error : I2C initializing first phase clock\n");
827f79dfb4STom Rix 			return;
837f79dfb4STom Rix 		}
847f79dfb4STom Rix 
857f79dfb4STom Rix 		/* For second phase of HS mode */
867f79dfb4STom Rix 		hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
877f79dfb4STom Rix 
887f79dfb4STom Rix 		hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM;
897f79dfb4STom Rix 		hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM;
907f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
917f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
9249e9b4bdSAndreas Müller 			puts("Error : I2C initializing second phase clock\n");
937f79dfb4STom Rix 			return;
947f79dfb4STom Rix 		}
957f79dfb4STom Rix 
967f79dfb4STom Rix 		scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll;
977f79dfb4STom Rix 		sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh;
987f79dfb4STom Rix 
997f79dfb4STom Rix 	} else {
1007f79dfb4STom Rix 		/* Standard and fast speed */
1017f79dfb4STom Rix 		fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed);
1027f79dfb4STom Rix 
1037f79dfb4STom Rix 		fsscll -= I2C_FASTSPEED_SCLL_TRIM;
1047f79dfb4STom Rix 		fssclh -= I2C_FASTSPEED_SCLH_TRIM;
1057f79dfb4STom Rix 		if (((fsscll < 0) || (fssclh < 0)) ||
1067f79dfb4STom Rix 		    ((fsscll > 255) || (fssclh > 255))) {
10749e9b4bdSAndreas Müller 			puts("Error : I2C initializing clock\n");
1087f79dfb4STom Rix 			return;
1097f79dfb4STom Rix 		}
1107f79dfb4STom Rix 
1117f79dfb4STom Rix 		scll = (unsigned int)fsscll;
1127f79dfb4STom Rix 		sclh = (unsigned int)fssclh;
1137f79dfb4STom Rix 	}
114080c646dSJean-Christophe PLAGNIOL-VILLARD 
115*2faa7619SPatil, Rachna 	if (gd->flags & GD_FLG_RELOC)
116*2faa7619SPatil, Rachna 		bus_initialized[current_bus] = 1;
117*2faa7619SPatil, Rachna 
1181d2e96deSDirk Behme 	if (readw(&i2c_base->con) & I2C_CON_EN) {
1191d2e96deSDirk Behme 		writew(0, &i2c_base->con);
120080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay(50000);
121080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
122080c646dSJean-Christophe PLAGNIOL-VILLARD 
1231d2e96deSDirk Behme 	writew(psc, &i2c_base->psc);
1241d2e96deSDirk Behme 	writew(scll, &i2c_base->scll);
1251d2e96deSDirk Behme 	writew(sclh, &i2c_base->sclh);
1267f79dfb4STom Rix 
127080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* own address */
1281d2e96deSDirk Behme 	writew(slaveadd, &i2c_base->oa);
1291d2e96deSDirk Behme 	writew(I2C_CON_EN, &i2c_base->con);
130080c646dSJean-Christophe PLAGNIOL-VILLARD 
131080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* have to enable intrrupts or OMAP i2c module doesn't work */
132e23c7c95SDirk Behme 	writew(I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
1331d2e96deSDirk Behme 		I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
134080c646dSJean-Christophe PLAGNIOL-VILLARD 	udelay(1000);
135080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
1361d2e96deSDirk Behme 	writew(0xFFFF, &i2c_base->stat);
1371d2e96deSDirk Behme 	writew(0, &i2c_base->cnt);
138080c646dSJean-Christophe PLAGNIOL-VILLARD }
139080c646dSJean-Christophe PLAGNIOL-VILLARD 
140080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void)
141080c646dSJean-Christophe PLAGNIOL-VILLARD {	u16 stat;
142080c646dSJean-Christophe PLAGNIOL-VILLARD 
143080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* note: if you try and read data when its not there or ready
144080c646dSJean-Christophe PLAGNIOL-VILLARD 	 * you get a bus error
145080c646dSJean-Christophe PLAGNIOL-VILLARD 	 */
146080c646dSJean-Christophe PLAGNIOL-VILLARD 	while (1) {
1471d2e96deSDirk Behme 		stat = readw(&i2c_base->stat);
148080c646dSJean-Christophe PLAGNIOL-VILLARD 		if (stat == I2C_STAT_RRDY) {
149938717ceSSteve Sakoman #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) || \
150938717ceSSteve Sakoman 	defined(CONFIG_OMAP44XX)
1511d2e96deSDirk Behme 			readb(&i2c_base->data);
1527d264c1eSDirk Behme #else
1531d2e96deSDirk Behme 			readw(&i2c_base->data);
1547d264c1eSDirk Behme #endif
1551d2e96deSDirk Behme 			writew(I2C_STAT_RRDY, &i2c_base->stat);
156080c646dSJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
157080c646dSJean-Christophe PLAGNIOL-VILLARD 		} else
158080c646dSJean-Christophe PLAGNIOL-VILLARD 			break;
159080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
160080c646dSJean-Christophe PLAGNIOL-VILLARD }
161080c646dSJean-Christophe PLAGNIOL-VILLARD 
162080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe(uchar chip)
163080c646dSJean-Christophe PLAGNIOL-VILLARD {
164*2faa7619SPatil, Rachna 	u32 status;
165080c646dSJean-Christophe PLAGNIOL-VILLARD 	int res = 1; /* default = fail */
166080c646dSJean-Christophe PLAGNIOL-VILLARD 
16789677b27SMichael Jones 	if (chip == readw(&i2c_base->oa))
168080c646dSJean-Christophe PLAGNIOL-VILLARD 		return res;
169080c646dSJean-Christophe PLAGNIOL-VILLARD 
170080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* wait until bus not busy */
171*2faa7619SPatil, Rachna 	status = wait_for_bb();
172*2faa7619SPatil, Rachna 	/* exit on BUS busy */
173*2faa7619SPatil, Rachna 	if (status & I2C_STAT_TIMEO)
174*2faa7619SPatil, Rachna 		return res;
175080c646dSJean-Christophe PLAGNIOL-VILLARD 
1760e57968aSNick Thompson 	/* try to write one byte */
1771d2e96deSDirk Behme 	writew(1, &i2c_base->cnt);
178080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* set slave address */
1791d2e96deSDirk Behme 	writew(chip, &i2c_base->sa);
180080c646dSJean-Christophe PLAGNIOL-VILLARD 	/* stop bit needed here */
181*2faa7619SPatil, Rachna 	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT
182*2faa7619SPatil, Rachna 			| I2C_CON_STP, &i2c_base->con);
183*2faa7619SPatil, Rachna 	/* enough delay for the NACK bit set */
184*2faa7619SPatil, Rachna 	udelay(9000);
185080c646dSJean-Christophe PLAGNIOL-VILLARD 
186*2faa7619SPatil, Rachna 	if (!(readw(&i2c_base->stat) & I2C_STAT_NACK)) {
187*2faa7619SPatil, Rachna 		res = 0;      /* success case */
188*2faa7619SPatil, Rachna 		flush_fifo();
189*2faa7619SPatil, Rachna 		writew(0xFFFF, &i2c_base->stat);
190*2faa7619SPatil, Rachna 	} else {
191*2faa7619SPatil, Rachna 		/* failure, clear sources*/
192*2faa7619SPatil, Rachna 		writew(0xFFFF, &i2c_base->stat);
193*2faa7619SPatil, Rachna 		/* finish up xfer */
194*2faa7619SPatil, Rachna 		writew(readw(&i2c_base->con) | I2C_CON_STP, &i2c_base->con);
195*2faa7619SPatil, Rachna 		status = wait_for_bb();
196*2faa7619SPatil, Rachna 		/* exit on BUS busy */
197*2faa7619SPatil, Rachna 		if (status & I2C_STAT_TIMEO)
198*2faa7619SPatil, Rachna 			return res;
199*2faa7619SPatil, Rachna 	}
200080c646dSJean-Christophe PLAGNIOL-VILLARD 	flush_fifo();
20189677b27SMichael Jones 	/* don't allow any more data in... we don't want it. */
20289677b27SMichael Jones 	writew(0, &i2c_base->cnt);
2031d2e96deSDirk Behme 	writew(0xFFFF, &i2c_base->stat);
204080c646dSJean-Christophe PLAGNIOL-VILLARD 	return res;
205080c646dSJean-Christophe PLAGNIOL-VILLARD }
206080c646dSJean-Christophe PLAGNIOL-VILLARD 
207080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
208080c646dSJean-Christophe PLAGNIOL-VILLARD {
209*2faa7619SPatil, Rachna 	int i2c_error = 0, i;
210*2faa7619SPatil, Rachna 	u32 status;
211080c646dSJean-Christophe PLAGNIOL-VILLARD 
212*2faa7619SPatil, Rachna 	if ((alen > 2) || (alen < 0))
213*2faa7619SPatil, Rachna 		return 1;
214*2faa7619SPatil, Rachna 
215*2faa7619SPatil, Rachna 	if (alen < 2) {
216*2faa7619SPatil, Rachna 		if (addr + len > 256)
217*2faa7619SPatil, Rachna 			return 1;
218*2faa7619SPatil, Rachna 	} else if (addr + len > 0xFFFF) {
219080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
220080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
221080c646dSJean-Christophe PLAGNIOL-VILLARD 
222*2faa7619SPatil, Rachna 	/* wait until bus not busy */
223*2faa7619SPatil, Rachna 	status = wait_for_bb();
224*2faa7619SPatil, Rachna 
225*2faa7619SPatil, Rachna 	/* exit on BUS busy */
226*2faa7619SPatil, Rachna 	if (status & I2C_STAT_TIMEO)
227080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
228*2faa7619SPatil, Rachna 
229*2faa7619SPatil, Rachna 	writew((alen & 0xFF), &i2c_base->cnt);
230*2faa7619SPatil, Rachna 	/* set slave address */
231*2faa7619SPatil, Rachna 	writew(chip, &i2c_base->sa);
232*2faa7619SPatil, Rachna 	/* Clear the Tx & Rx FIFOs */
233*2faa7619SPatil, Rachna 	writew((readw(&i2c_base->buf) | I2C_RXFIFO_CLEAR |
234*2faa7619SPatil, Rachna 		I2C_TXFIFO_CLEAR), &i2c_base->buf);
235*2faa7619SPatil, Rachna 	/* no stop bit needed here */
236*2faa7619SPatil, Rachna 	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX |
237*2faa7619SPatil, Rachna 		I2C_CON_STT, &i2c_base->con);
238*2faa7619SPatil, Rachna 
239*2faa7619SPatil, Rachna 	/* wait for Transmit ready condition */
240*2faa7619SPatil, Rachna 	status = wait_for_status_mask(I2C_STAT_XRDY | I2C_STAT_NACK);
241*2faa7619SPatil, Rachna 
242*2faa7619SPatil, Rachna 	if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO))
243*2faa7619SPatil, Rachna 		i2c_error = 1;
244*2faa7619SPatil, Rachna 
245*2faa7619SPatil, Rachna 	if (!i2c_error) {
246*2faa7619SPatil, Rachna 		if (status & I2C_STAT_XRDY) {
247*2faa7619SPatil, Rachna 			switch (alen) {
248*2faa7619SPatil, Rachna 			case 2:
249*2faa7619SPatil, Rachna 				/* Send address MSByte */
250*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
251*2faa7619SPatil, Rachna 				writew(((addr >> 8) & 0xFF), &i2c_base->data);
252*2faa7619SPatil, Rachna 
253*2faa7619SPatil, Rachna 				/* Clearing XRDY event */
254*2faa7619SPatil, Rachna 				writew((status & I2C_STAT_XRDY),
255*2faa7619SPatil, Rachna 						&i2c_base->stat);
256*2faa7619SPatil, Rachna 				/* wait for Transmit ready condition */
257*2faa7619SPatil, Rachna 				status = wait_for_status_mask(I2C_STAT_XRDY |
258*2faa7619SPatil, Rachna 						I2C_STAT_NACK);
259*2faa7619SPatil, Rachna 
260*2faa7619SPatil, Rachna 				if (status & (I2C_STAT_NACK |
261*2faa7619SPatil, Rachna 						I2C_STAT_TIMEO)) {
262*2faa7619SPatil, Rachna 					i2c_error = 1;
263*2faa7619SPatil, Rachna 					break;
264080c646dSJean-Christophe PLAGNIOL-VILLARD 				}
265*2faa7619SPatil, Rachna #endif
266*2faa7619SPatil, Rachna 			case 1:
267*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
268*2faa7619SPatil, Rachna 				/* Send address LSByte */
269*2faa7619SPatil, Rachna 				writew((addr & 0xFF), &i2c_base->data);
270*2faa7619SPatil, Rachna #else
271*2faa7619SPatil, Rachna 				/* Send address Short word */
272*2faa7619SPatil, Rachna 				writew((addr & 0xFFFF), &i2c_base->data);
273*2faa7619SPatil, Rachna #endif
274*2faa7619SPatil, Rachna 				/* Clearing XRDY event */
275*2faa7619SPatil, Rachna 				writew((status & I2C_STAT_XRDY),
276*2faa7619SPatil, Rachna 					&i2c_base->stat);
277*2faa7619SPatil, Rachna 				/*wait for Transmit ready condition */
278*2faa7619SPatil, Rachna 				status = wait_for_status_mask(I2C_STAT_ARDY |
279*2faa7619SPatil, Rachna 						I2C_STAT_NACK);
280*2faa7619SPatil, Rachna 
281*2faa7619SPatil, Rachna 				if (status & (I2C_STAT_NACK |
282*2faa7619SPatil, Rachna 					I2C_STAT_TIMEO)) {
283*2faa7619SPatil, Rachna 					i2c_error = 1;
284*2faa7619SPatil, Rachna 					break;
285*2faa7619SPatil, Rachna 				}
286*2faa7619SPatil, Rachna 			}
287*2faa7619SPatil, Rachna 		} else
288*2faa7619SPatil, Rachna 			i2c_error = 1;
289*2faa7619SPatil, Rachna 	}
290*2faa7619SPatil, Rachna 
291*2faa7619SPatil, Rachna 	/* Wait for ARDY to set */
292*2faa7619SPatil, Rachna 	status = wait_for_status_mask(I2C_STAT_ARDY | I2C_STAT_NACK
293*2faa7619SPatil, Rachna 			| I2C_STAT_AL);
294*2faa7619SPatil, Rachna 
295*2faa7619SPatil, Rachna 	if (!i2c_error) {
296*2faa7619SPatil, Rachna 		/* set slave address */
297*2faa7619SPatil, Rachna 		writew(chip, &i2c_base->sa);
298*2faa7619SPatil, Rachna 		writew((len & 0xFF), &i2c_base->cnt);
299*2faa7619SPatil, Rachna 		/* Clear the Tx & Rx FIFOs */
300*2faa7619SPatil, Rachna 		writew((readw(&i2c_base->buf) | I2C_RXFIFO_CLEAR |
301*2faa7619SPatil, Rachna 			I2C_TXFIFO_CLEAR), &i2c_base->buf);
302*2faa7619SPatil, Rachna 		/* need stop bit here */
303*2faa7619SPatil, Rachna 		writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
304*2faa7619SPatil, Rachna 			&i2c_base->con);
305080c646dSJean-Christophe PLAGNIOL-VILLARD 
306080c646dSJean-Christophe PLAGNIOL-VILLARD 		for (i = 0; i < len; i++) {
307*2faa7619SPatil, Rachna 			/* wait for Receive condition */
308*2faa7619SPatil, Rachna 			status = wait_for_status_mask(I2C_STAT_RRDY |
309*2faa7619SPatil, Rachna 				I2C_STAT_NACK);
310*2faa7619SPatil, Rachna 			if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO)) {
311*2faa7619SPatil, Rachna 				i2c_error = 1;
312*2faa7619SPatil, Rachna 				break;
313*2faa7619SPatil, Rachna 			}
314*2faa7619SPatil, Rachna 
315*2faa7619SPatil, Rachna 			if (status & I2C_STAT_RRDY) {
316*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
317*2faa7619SPatil, Rachna 				buffer[i] = readb(&i2c_base->data);
318*2faa7619SPatil, Rachna #else
319*2faa7619SPatil, Rachna 				*((u16 *)&buffer[i]) =
320*2faa7619SPatil, Rachna 					readw(&i2c_base->data) & 0xFFFF;
321*2faa7619SPatil, Rachna 				i++;
322*2faa7619SPatil, Rachna #endif
323*2faa7619SPatil, Rachna 				writew((status & I2C_STAT_RRDY),
324*2faa7619SPatil, Rachna 					&i2c_base->stat);
325*2faa7619SPatil, Rachna 				udelay(1000);
326*2faa7619SPatil, Rachna 			} else {
327*2faa7619SPatil, Rachna 				i2c_error = 1;
328*2faa7619SPatil, Rachna 			}
329*2faa7619SPatil, Rachna 		}
330*2faa7619SPatil, Rachna 	}
331*2faa7619SPatil, Rachna 
332*2faa7619SPatil, Rachna 	/* Wait for ARDY to set */
333*2faa7619SPatil, Rachna 	status = wait_for_status_mask(I2C_STAT_ARDY | I2C_STAT_NACK
334*2faa7619SPatil, Rachna 			| I2C_STAT_AL);
335*2faa7619SPatil, Rachna 
336*2faa7619SPatil, Rachna 	if (i2c_error) {
337*2faa7619SPatil, Rachna 		writew(0, &i2c_base->con);
338080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
339080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
340*2faa7619SPatil, Rachna 
341*2faa7619SPatil, Rachna 	writew(I2C_CON_EN, &i2c_base->con);
342*2faa7619SPatil, Rachna 
343*2faa7619SPatil, Rachna 	while (readw(&i2c_base->stat)
344*2faa7619SPatil, Rachna 		|| (readw(&i2c_base->con) & I2C_CON_MST)) {
345*2faa7619SPatil, Rachna 		udelay(10000);
346*2faa7619SPatil, Rachna 		writew(0xFFFF, &i2c_base->stat);
347080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
348080c646dSJean-Christophe PLAGNIOL-VILLARD 
349*2faa7619SPatil, Rachna 	writew(I2C_CON_EN, &i2c_base->con);
350*2faa7619SPatil, Rachna 	flush_fifo();
351*2faa7619SPatil, Rachna 	writew(0xFFFF, &i2c_base->stat);
352*2faa7619SPatil, Rachna 	writew(0, &i2c_base->cnt);
353*2faa7619SPatil, Rachna 
354080c646dSJean-Christophe PLAGNIOL-VILLARD 	return 0;
355080c646dSJean-Christophe PLAGNIOL-VILLARD }
356080c646dSJean-Christophe PLAGNIOL-VILLARD 
357080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
358080c646dSJean-Christophe PLAGNIOL-VILLARD {
359080c646dSJean-Christophe PLAGNIOL-VILLARD 
360*2faa7619SPatil, Rachna 	int i, i2c_error = 0;
361*2faa7619SPatil, Rachna 	u32 status;
362*2faa7619SPatil, Rachna 	u16 writelen;
363*2faa7619SPatil, Rachna 
364*2faa7619SPatil, Rachna 	if (alen > 2)
365080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
366080c646dSJean-Christophe PLAGNIOL-VILLARD 
367*2faa7619SPatil, Rachna 	if (alen < 2) {
368*2faa7619SPatil, Rachna 		if (addr + len > 256)
369*2faa7619SPatil, Rachna 			return 1;
370*2faa7619SPatil, Rachna 	} else if (addr + len > 0xFFFF) {
371080c646dSJean-Christophe PLAGNIOL-VILLARD 		return 1;
372080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
373080c646dSJean-Christophe PLAGNIOL-VILLARD 
3740607e2b9SMichael Jones 	/* wait until bus not busy */
375*2faa7619SPatil, Rachna 	status = wait_for_bb();
3760607e2b9SMichael Jones 
377*2faa7619SPatil, Rachna 	/* exiting on BUS busy */
378*2faa7619SPatil, Rachna 	if (status & I2C_STAT_TIMEO)
379*2faa7619SPatil, Rachna 		return 1;
380*2faa7619SPatil, Rachna 
381*2faa7619SPatil, Rachna 	writelen = (len & 0xFFFF) + alen;
382*2faa7619SPatil, Rachna 
383*2faa7619SPatil, Rachna 	/* two bytes */
384*2faa7619SPatil, Rachna 	writew((writelen & 0xFFFF), &i2c_base->cnt);
385*2faa7619SPatil, Rachna 	/* Clear the Tx & Rx FIFOs */
386*2faa7619SPatil, Rachna 	writew((readw(&i2c_base->buf) | I2C_RXFIFO_CLEAR |
387*2faa7619SPatil, Rachna 			I2C_TXFIFO_CLEAR), &i2c_base->buf);
3880607e2b9SMichael Jones 	/* set slave address */
3890607e2b9SMichael Jones 	writew(chip, &i2c_base->sa);
3900607e2b9SMichael Jones 	/* stop bit needed here */
3910607e2b9SMichael Jones 	writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
3920607e2b9SMichael Jones 		I2C_CON_STP, &i2c_base->con);
3930607e2b9SMichael Jones 
394*2faa7619SPatil, Rachna 	/* wait for Transmit ready condition */
395*2faa7619SPatil, Rachna 	status = wait_for_status_mask(I2C_STAT_XRDY | I2C_STAT_NACK);
3960607e2b9SMichael Jones 
397*2faa7619SPatil, Rachna 	if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO))
3980607e2b9SMichael Jones 		i2c_error = 1;
3990607e2b9SMichael Jones 
400*2faa7619SPatil, Rachna 	if (!i2c_error) {
4010607e2b9SMichael Jones 		if (status & I2C_STAT_XRDY) {
402*2faa7619SPatil, Rachna 			switch (alen) {
403*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
404*2faa7619SPatil, Rachna 			case 2:
405*2faa7619SPatil, Rachna 				/* send out MSB byte */
406*2faa7619SPatil, Rachna 				writeb(((addr >> 8) & 0xFF), &i2c_base->data);
407*2faa7619SPatil, Rachna #else
408*2faa7619SPatil, Rachna 				writeb((addr  & 0xFFFF), &i2c_base->data);
409*2faa7619SPatil, Rachna 				break;
410*2faa7619SPatil, Rachna #endif
411*2faa7619SPatil, Rachna 				/* Clearing XRDY event */
412*2faa7619SPatil, Rachna 				writew((status & I2C_STAT_XRDY),
413*2faa7619SPatil, Rachna 					&i2c_base->stat);
414*2faa7619SPatil, Rachna 				/*waiting for Transmit ready * condition */
415*2faa7619SPatil, Rachna 				status = wait_for_status_mask(I2C_STAT_XRDY |
416*2faa7619SPatil, Rachna 						I2C_STAT_NACK);
417*2faa7619SPatil, Rachna 
418*2faa7619SPatil, Rachna 				if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO)) {
4190607e2b9SMichael Jones 					i2c_error = 1;
420*2faa7619SPatil, Rachna 					break;
421*2faa7619SPatil, Rachna 				}
422*2faa7619SPatil, Rachna 			case 1:
423*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
424*2faa7619SPatil, Rachna 				/* send out MSB byte */
425*2faa7619SPatil, Rachna 				writeb((addr  & 0xFF), &i2c_base->data);
426*2faa7619SPatil, Rachna #else
427*2faa7619SPatil, Rachna 				writew(((buffer[0] << 8) | (addr & 0xFF)),
428*2faa7619SPatil, Rachna 					&i2c_base->data);
429*2faa7619SPatil, Rachna #endif
4300607e2b9SMichael Jones 			}
4310607e2b9SMichael Jones 
432*2faa7619SPatil, Rachna 			/* Clearing XRDY event */
433*2faa7619SPatil, Rachna 			writew((status & I2C_STAT_XRDY), &i2c_base->stat);
4340607e2b9SMichael Jones 		}
4350607e2b9SMichael Jones 
436*2faa7619SPatil, Rachna 		/* waiting for Transmit ready condition */
437*2faa7619SPatil, Rachna 		status = wait_for_status_mask(I2C_STAT_XRDY | I2C_STAT_NACK);
438*2faa7619SPatil, Rachna 
439*2faa7619SPatil, Rachna 		if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO))
440*2faa7619SPatil, Rachna 			i2c_error = 1;
441*2faa7619SPatil, Rachna 
442*2faa7619SPatil, Rachna 		if (!i2c_error) {
443*2faa7619SPatil, Rachna 			for (i = ((alen > 1) ? 0 : 1); i < len; i++) {
4440607e2b9SMichael Jones 				if (status & I2C_STAT_XRDY) {
445*2faa7619SPatil, Rachna #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
446*2faa7619SPatil, Rachna 					writeb((buffer[i] & 0xFF),
447*2faa7619SPatil, Rachna 						&i2c_base->data);
448*2faa7619SPatil, Rachna #else
449*2faa7619SPatil, Rachna 					writew((((buffer[i] << 8) |
450*2faa7619SPatil, Rachna 					buffer[i + 1]) & 0xFFFF),
451*2faa7619SPatil, Rachna 						&i2c_base->data);
452*2faa7619SPatil, Rachna 					i++;
453*2faa7619SPatil, Rachna #endif
454*2faa7619SPatil, Rachna 				} else
4550607e2b9SMichael Jones 					i2c_error = 1;
456*2faa7619SPatil, Rachna 					/* Clearing XRDY event */
457*2faa7619SPatil, Rachna 					writew((status & I2C_STAT_XRDY),
458*2faa7619SPatil, Rachna 						&i2c_base->stat);
459*2faa7619SPatil, Rachna 					/* waiting for XRDY condition */
460*2faa7619SPatil, Rachna 					status = wait_for_status_mask(
461*2faa7619SPatil, Rachna 						I2C_STAT_XRDY |
462*2faa7619SPatil, Rachna 						I2C_STAT_ARDY |
463*2faa7619SPatil, Rachna 						I2C_STAT_NACK);
464*2faa7619SPatil, Rachna 					if (status & (I2C_STAT_NACK |
465*2faa7619SPatil, Rachna 						I2C_STAT_TIMEO)) {
466*2faa7619SPatil, Rachna 						i2c_error = 1;
467*2faa7619SPatil, Rachna 						break;
468*2faa7619SPatil, Rachna 					}
469*2faa7619SPatil, Rachna 					if (status & I2C_STAT_ARDY)
470*2faa7619SPatil, Rachna 						break;
471*2faa7619SPatil, Rachna 			}
472080c646dSJean-Christophe PLAGNIOL-VILLARD 		}
473080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
474080c646dSJean-Christophe PLAGNIOL-VILLARD 
475*2faa7619SPatil, Rachna 	status = wait_for_status_mask(I2C_STAT_ARDY | I2C_STAT_NACK |
476*2faa7619SPatil, Rachna 				I2C_STAT_AL);
477*2faa7619SPatil, Rachna 
478*2faa7619SPatil, Rachna 	if (status & (I2C_STAT_NACK | I2C_STAT_TIMEO))
479*2faa7619SPatil, Rachna 		i2c_error = 1;
480*2faa7619SPatil, Rachna 
481*2faa7619SPatil, Rachna 	if (i2c_error) {
482*2faa7619SPatil, Rachna 		writew(0, &i2c_base->con);
483*2faa7619SPatil, Rachna 		return 1;
484*2faa7619SPatil, Rachna 	}
485*2faa7619SPatil, Rachna 
486*2faa7619SPatil, Rachna 	if (!i2c_error) {
487*2faa7619SPatil, Rachna 		int eout = 200;
488*2faa7619SPatil, Rachna 
489*2faa7619SPatil, Rachna 		writew(I2C_CON_EN, &i2c_base->con);
490*2faa7619SPatil, Rachna 		while ((status = readw(&i2c_base->stat)) ||
491*2faa7619SPatil, Rachna 				(readw(&i2c_base->con) & I2C_CON_MST)) {
492*2faa7619SPatil, Rachna 			udelay(1000);
493*2faa7619SPatil, Rachna 			/* have to read to clear intrrupt */
494*2faa7619SPatil, Rachna 			writew(0xFFFF, &i2c_base->stat);
495*2faa7619SPatil, Rachna 			if (--eout == 0)
496*2faa7619SPatil, Rachna 				/* better leave with error than hang */
497*2faa7619SPatil, Rachna 				break;
498*2faa7619SPatil, Rachna 		}
499*2faa7619SPatil, Rachna 	}
500*2faa7619SPatil, Rachna 
5010607e2b9SMichael Jones 	flush_fifo();
5020607e2b9SMichael Jones 	writew(0xFFFF, &i2c_base->stat);
503*2faa7619SPatil, Rachna 	writew(0, &i2c_base->cnt);
504*2faa7619SPatil, Rachna 	return 0;
505080c646dSJean-Christophe PLAGNIOL-VILLARD }
506080c646dSJean-Christophe PLAGNIOL-VILLARD 
507*2faa7619SPatil, Rachna static u32 wait_for_bb(void)
508080c646dSJean-Christophe PLAGNIOL-VILLARD {
50973e8747fSSteve Sakoman 	int timeout = I2C_TIMEOUT;
510*2faa7619SPatil, Rachna 	u32 stat;
511080c646dSJean-Christophe PLAGNIOL-VILLARD 
5121d2e96deSDirk Behme 	while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
5131d2e96deSDirk Behme 		writew(stat, &i2c_base->stat);
51473e8747fSSteve Sakoman 		udelay(1000);
515080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
516080c646dSJean-Christophe PLAGNIOL-VILLARD 
517080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
518080c646dSJean-Christophe PLAGNIOL-VILLARD 		printf("timed out in wait_for_bb: I2C_STAT=%x\n",
5191d2e96deSDirk Behme 			readw(&i2c_base->stat));
520*2faa7619SPatil, Rachna 		stat |= I2C_STAT_TIMEO;
521080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
5221d2e96deSDirk Behme 	writew(0xFFFF, &i2c_base->stat);	 /* clear delayed stuff*/
523*2faa7619SPatil, Rachna 	return stat;
524080c646dSJean-Christophe PLAGNIOL-VILLARD }
525080c646dSJean-Christophe PLAGNIOL-VILLARD 
526*2faa7619SPatil, Rachna static u32 wait_for_status_mask(u16 mask)
527080c646dSJean-Christophe PLAGNIOL-VILLARD {
528*2faa7619SPatil, Rachna 	u32 status;
52973e8747fSSteve Sakoman 	int timeout = I2C_TIMEOUT;
530080c646dSJean-Christophe PLAGNIOL-VILLARD 
531080c646dSJean-Christophe PLAGNIOL-VILLARD 	do {
532080c646dSJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
5331d2e96deSDirk Behme 		status = readw(&i2c_base->stat);
534*2faa7619SPatil, Rachna 	} while (!(status & mask) && timeout--);
535080c646dSJean-Christophe PLAGNIOL-VILLARD 
536080c646dSJean-Christophe PLAGNIOL-VILLARD 	if (timeout <= 0) {
537*2faa7619SPatil, Rachna 		printf("timed out in wait_for_status_mask: I2C_STAT=%x\n",
5381d2e96deSDirk Behme 			readw(&i2c_base->stat));
5391d2e96deSDirk Behme 		writew(0xFFFF, &i2c_base->stat);
540*2faa7619SPatil, Rachna 		status |= I2C_STAT_TIMEO;
541080c646dSJean-Christophe PLAGNIOL-VILLARD 	}
542080c646dSJean-Christophe PLAGNIOL-VILLARD 	return status;
543080c646dSJean-Christophe PLAGNIOL-VILLARD }
5441d2e96deSDirk Behme 
5451d2e96deSDirk Behme int i2c_set_bus_num(unsigned int bus)
5461d2e96deSDirk Behme {
5471d2e96deSDirk Behme 	if ((bus < 0) || (bus >= I2C_BUS_MAX)) {
5481d2e96deSDirk Behme 		printf("Bad bus: %d\n", bus);
5491d2e96deSDirk Behme 		return -1;
5501d2e96deSDirk Behme 	}
5511d2e96deSDirk Behme 
5521d2e96deSDirk Behme #if I2C_BUS_MAX == 3
5531d2e96deSDirk Behme 	if (bus == 2)
5541d2e96deSDirk Behme 		i2c_base = (struct i2c *)I2C_BASE3;
5551d2e96deSDirk Behme 	else
5561d2e96deSDirk Behme #endif
5571d2e96deSDirk Behme 	if (bus == 1)
5581d2e96deSDirk Behme 		i2c_base = (struct i2c *)I2C_BASE2;
5591d2e96deSDirk Behme 	else
5601d2e96deSDirk Behme 		i2c_base = (struct i2c *)I2C_BASE1;
5611d2e96deSDirk Behme 
5621d2e96deSDirk Behme 	current_bus = bus;
5631d2e96deSDirk Behme 
5641d2e96deSDirk Behme 	if (!bus_initialized[current_bus])
5651d2e96deSDirk Behme 		i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
5661d2e96deSDirk Behme 
5671d2e96deSDirk Behme 	return 0;
5681d2e96deSDirk Behme }
569938717ceSSteve Sakoman 
570938717ceSSteve Sakoman int i2c_get_bus_num(void)
571938717ceSSteve Sakoman {
572938717ceSSteve Sakoman 	return (int) current_bus;
573938717ceSSteve Sakoman }
574