xref: /rk3399_rockchip-uboot/drivers/i2c/davinci_i2c.c (revision 356d15ebb2b0bb2adde2ca4fe4cccb87f75531a0)
1942ba996SJean-Christophe PLAGNIOL-VILLARD /*
2942ba996SJean-Christophe PLAGNIOL-VILLARD  * TI DaVinci (TMS320DM644x) I2C driver.
3942ba996SJean-Christophe PLAGNIOL-VILLARD  *
4942ba996SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
5942ba996SJean-Christophe PLAGNIOL-VILLARD  *
6942ba996SJean-Christophe PLAGNIOL-VILLARD  * --------------------------------------------------------
7942ba996SJean-Christophe PLAGNIOL-VILLARD  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
9942ba996SJean-Christophe PLAGNIOL-VILLARD  */
10942ba996SJean-Christophe PLAGNIOL-VILLARD 
11942ba996SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
12942ba996SJean-Christophe PLAGNIOL-VILLARD #include <i2c.h>
13942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h>
14942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/i2c_defs.h>
15*356d15ebSKaricheri, Muralidharan #include "davinci_i2c.h"
16942ba996SJean-Christophe PLAGNIOL-VILLARD 
17942ba996SJean-Christophe PLAGNIOL-VILLARD #define CHECK_NACK() \
18942ba996SJean-Christophe PLAGNIOL-VILLARD 	do {\
19942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\
20942ba996SJean-Christophe PLAGNIOL-VILLARD 			REG(I2C_CON) = 0;\
21942ba996SJean-Christophe PLAGNIOL-VILLARD 			return(1);\
22942ba996SJean-Christophe PLAGNIOL-VILLARD 		}\
23942ba996SJean-Christophe PLAGNIOL-VILLARD 	} while (0)
24942ba996SJean-Christophe PLAGNIOL-VILLARD 
25942ba996SJean-Christophe PLAGNIOL-VILLARD 
26942ba996SJean-Christophe PLAGNIOL-VILLARD static int wait_for_bus(void)
27942ba996SJean-Christophe PLAGNIOL-VILLARD {
28942ba996SJean-Christophe PLAGNIOL-VILLARD 	int	stat, timeout;
29942ba996SJean-Christophe PLAGNIOL-VILLARD 
30942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
31942ba996SJean-Christophe PLAGNIOL-VILLARD 
32942ba996SJean-Christophe PLAGNIOL-VILLARD 	for (timeout = 0; timeout < 10; timeout++) {
33942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) {
34942ba996SJean-Christophe PLAGNIOL-VILLARD 			REG(I2C_STAT) = 0xffff;
35942ba996SJean-Christophe PLAGNIOL-VILLARD 			return(0);
36942ba996SJean-Christophe PLAGNIOL-VILLARD 		}
37942ba996SJean-Christophe PLAGNIOL-VILLARD 
38942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_STAT) = stat;
39942ba996SJean-Christophe PLAGNIOL-VILLARD 		udelay(50000);
40942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
41942ba996SJean-Christophe PLAGNIOL-VILLARD 
42942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
43942ba996SJean-Christophe PLAGNIOL-VILLARD 	return(1);
44942ba996SJean-Christophe PLAGNIOL-VILLARD }
45942ba996SJean-Christophe PLAGNIOL-VILLARD 
46942ba996SJean-Christophe PLAGNIOL-VILLARD 
47942ba996SJean-Christophe PLAGNIOL-VILLARD static int poll_i2c_irq(int mask)
48942ba996SJean-Christophe PLAGNIOL-VILLARD {
49942ba996SJean-Christophe PLAGNIOL-VILLARD 	int	stat, timeout;
50942ba996SJean-Christophe PLAGNIOL-VILLARD 
51942ba996SJean-Christophe PLAGNIOL-VILLARD 	for (timeout = 0; timeout < 10; timeout++) {
52942ba996SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
53942ba996SJean-Christophe PLAGNIOL-VILLARD 		stat = REG(I2C_STAT);
54942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (stat & mask) {
55942ba996SJean-Christophe PLAGNIOL-VILLARD 			return(stat);
56942ba996SJean-Christophe PLAGNIOL-VILLARD 		}
57942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
58942ba996SJean-Christophe PLAGNIOL-VILLARD 
59942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
60942ba996SJean-Christophe PLAGNIOL-VILLARD 	return(stat | I2C_TIMEOUT);
61942ba996SJean-Christophe PLAGNIOL-VILLARD }
62942ba996SJean-Christophe PLAGNIOL-VILLARD 
63942ba996SJean-Christophe PLAGNIOL-VILLARD 
64942ba996SJean-Christophe PLAGNIOL-VILLARD void flush_rx(void)
65942ba996SJean-Christophe PLAGNIOL-VILLARD {
66942ba996SJean-Christophe PLAGNIOL-VILLARD 	while (1) {
67942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (!(REG(I2C_STAT) & I2C_STAT_RRDY))
68942ba996SJean-Christophe PLAGNIOL-VILLARD 			break;
69942ba996SJean-Christophe PLAGNIOL-VILLARD 
70bd0f5ca8SAnatolij Gustschin 		REG(I2C_DRR);
71942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_STAT) = I2C_STAT_RRDY;
72942ba996SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
73942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
74942ba996SJean-Christophe PLAGNIOL-VILLARD }
75942ba996SJean-Christophe PLAGNIOL-VILLARD 
76942ba996SJean-Christophe PLAGNIOL-VILLARD 
77942ba996SJean-Christophe PLAGNIOL-VILLARD void i2c_init(int speed, int slaveadd)
78942ba996SJean-Christophe PLAGNIOL-VILLARD {
79942ba996SJean-Christophe PLAGNIOL-VILLARD 	u_int32_t	div, psc;
80942ba996SJean-Christophe PLAGNIOL-VILLARD 
81942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (REG(I2C_CON) & I2C_CON_EN) {
82942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CON) = 0;
83942ba996SJean-Christophe PLAGNIOL-VILLARD 		udelay (50000);
84942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
85942ba996SJean-Christophe PLAGNIOL-VILLARD 
86942ba996SJean-Christophe PLAGNIOL-VILLARD 	psc = 2;
87942ba996SJean-Christophe PLAGNIOL-VILLARD 	div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10;	/* SCLL + SCLH */
88942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_PSC) = psc;			/* 27MHz / (2 + 1) = 9MHz */
89942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_SCLL) = (div * 50) / 100;	/* 50% Duty */
90942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_SCLH) = div - REG(I2C_SCLL);
91942ba996SJean-Christophe PLAGNIOL-VILLARD 
92942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_OA) = slaveadd;
93942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = 0;
94942ba996SJean-Christophe PLAGNIOL-VILLARD 
95942ba996SJean-Christophe PLAGNIOL-VILLARD 	/* Interrupts must be enabled or I2C module won't work */
96942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE |
97942ba996SJean-Christophe PLAGNIOL-VILLARD 		I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE;
98942ba996SJean-Christophe PLAGNIOL-VILLARD 
99942ba996SJean-Christophe PLAGNIOL-VILLARD 	/* Now enable I2C controller (get it out of reset) */
100942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = I2C_CON_EN;
101942ba996SJean-Christophe PLAGNIOL-VILLARD 
102942ba996SJean-Christophe PLAGNIOL-VILLARD 	udelay(1000);
103942ba996SJean-Christophe PLAGNIOL-VILLARD }
104942ba996SJean-Christophe PLAGNIOL-VILLARD 
10549d6da60SHeiko Schocher int i2c_set_bus_speed(unsigned int speed)
10649d6da60SHeiko Schocher {
10749d6da60SHeiko Schocher 	i2c_init(speed, CONFIG_SYS_I2C_SLAVE);
10849d6da60SHeiko Schocher 	return 0;
10949d6da60SHeiko Schocher }
110942ba996SJean-Christophe PLAGNIOL-VILLARD 
111942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_probe(u_int8_t chip)
112942ba996SJean-Christophe PLAGNIOL-VILLARD {
113942ba996SJean-Christophe PLAGNIOL-VILLARD 	int	rc = 1;
114942ba996SJean-Christophe PLAGNIOL-VILLARD 
115942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (chip == REG(I2C_OA)) {
116942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(rc);
117942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
118942ba996SJean-Christophe PLAGNIOL-VILLARD 
119942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = 0;
120942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (wait_for_bus()) {return(1);}
121942ba996SJean-Christophe PLAGNIOL-VILLARD 
122942ba996SJean-Christophe PLAGNIOL-VILLARD 	/* try to read one byte from current (or only) address */
123942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = 1;
124942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_SA) = chip;
125942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP);
126942ba996SJean-Christophe PLAGNIOL-VILLARD 	udelay (50000);
127942ba996SJean-Christophe PLAGNIOL-VILLARD 
128942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (!(REG(I2C_STAT) & I2C_STAT_NACK)) {
129942ba996SJean-Christophe PLAGNIOL-VILLARD 		rc = 0;
130942ba996SJean-Christophe PLAGNIOL-VILLARD 		flush_rx();
131942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_STAT) = 0xffff;
132942ba996SJean-Christophe PLAGNIOL-VILLARD 	} else {
133942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_STAT) = 0xffff;
134942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CON) |= I2C_CON_STP;
135942ba996SJean-Christophe PLAGNIOL-VILLARD 		udelay(20000);
136942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (wait_for_bus()) {return(1);}
137942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
138942ba996SJean-Christophe PLAGNIOL-VILLARD 
139942ba996SJean-Christophe PLAGNIOL-VILLARD 	flush_rx();
140942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
141942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = 0;
142942ba996SJean-Christophe PLAGNIOL-VILLARD 	return(rc);
143942ba996SJean-Christophe PLAGNIOL-VILLARD }
144942ba996SJean-Christophe PLAGNIOL-VILLARD 
145942ba996SJean-Christophe PLAGNIOL-VILLARD 
146942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
147942ba996SJean-Christophe PLAGNIOL-VILLARD {
148942ba996SJean-Christophe PLAGNIOL-VILLARD 	u_int32_t	tmp;
149942ba996SJean-Christophe PLAGNIOL-VILLARD 	int		i;
150942ba996SJean-Christophe PLAGNIOL-VILLARD 
151942ba996SJean-Christophe PLAGNIOL-VILLARD 	if ((alen < 0) || (alen > 2)) {
152942ba996SJean-Christophe PLAGNIOL-VILLARD 		printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
153942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(1);
154942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
155942ba996SJean-Christophe PLAGNIOL-VILLARD 
156942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (wait_for_bus()) {return(1);}
157942ba996SJean-Christophe PLAGNIOL-VILLARD 
158942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (alen != 0) {
159942ba996SJean-Christophe PLAGNIOL-VILLARD 		/* Start address phase */
160942ba996SJean-Christophe PLAGNIOL-VILLARD 		tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX;
161942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CNT) = alen;
162942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_SA) = chip;
163942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CON) = tmp;
164942ba996SJean-Christophe PLAGNIOL-VILLARD 
165942ba996SJean-Christophe PLAGNIOL-VILLARD 		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
166942ba996SJean-Christophe PLAGNIOL-VILLARD 
167942ba996SJean-Christophe PLAGNIOL-VILLARD 		CHECK_NACK();
168942ba996SJean-Christophe PLAGNIOL-VILLARD 
169942ba996SJean-Christophe PLAGNIOL-VILLARD 		switch (alen) {
170942ba996SJean-Christophe PLAGNIOL-VILLARD 			case 2:
171942ba996SJean-Christophe PLAGNIOL-VILLARD 				/* Send address MSByte */
172942ba996SJean-Christophe PLAGNIOL-VILLARD 				if (tmp & I2C_STAT_XRDY) {
173942ba996SJean-Christophe PLAGNIOL-VILLARD 					REG(I2C_DXR) = (addr >> 8) & 0xff;
174942ba996SJean-Christophe PLAGNIOL-VILLARD 				} else {
175942ba996SJean-Christophe PLAGNIOL-VILLARD 					REG(I2C_CON) = 0;
176942ba996SJean-Christophe PLAGNIOL-VILLARD 					return(1);
177942ba996SJean-Christophe PLAGNIOL-VILLARD 				}
178942ba996SJean-Christophe PLAGNIOL-VILLARD 
179942ba996SJean-Christophe PLAGNIOL-VILLARD 				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
180942ba996SJean-Christophe PLAGNIOL-VILLARD 
181942ba996SJean-Christophe PLAGNIOL-VILLARD 				CHECK_NACK();
182942ba996SJean-Christophe PLAGNIOL-VILLARD 				/* No break, fall through */
183942ba996SJean-Christophe PLAGNIOL-VILLARD 			case 1:
184942ba996SJean-Christophe PLAGNIOL-VILLARD 				/* Send address LSByte */
185942ba996SJean-Christophe PLAGNIOL-VILLARD 				if (tmp & I2C_STAT_XRDY) {
186942ba996SJean-Christophe PLAGNIOL-VILLARD 					REG(I2C_DXR) = addr & 0xff;
187942ba996SJean-Christophe PLAGNIOL-VILLARD 				} else {
188942ba996SJean-Christophe PLAGNIOL-VILLARD 					REG(I2C_CON) = 0;
189942ba996SJean-Christophe PLAGNIOL-VILLARD 					return(1);
190942ba996SJean-Christophe PLAGNIOL-VILLARD 				}
191942ba996SJean-Christophe PLAGNIOL-VILLARD 
192942ba996SJean-Christophe PLAGNIOL-VILLARD 				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY);
193942ba996SJean-Christophe PLAGNIOL-VILLARD 
194942ba996SJean-Christophe PLAGNIOL-VILLARD 				CHECK_NACK();
195942ba996SJean-Christophe PLAGNIOL-VILLARD 
196942ba996SJean-Christophe PLAGNIOL-VILLARD 				if (!(tmp & I2C_STAT_ARDY)) {
197942ba996SJean-Christophe PLAGNIOL-VILLARD 					REG(I2C_CON) = 0;
198942ba996SJean-Christophe PLAGNIOL-VILLARD 					return(1);
199942ba996SJean-Christophe PLAGNIOL-VILLARD 				}
200942ba996SJean-Christophe PLAGNIOL-VILLARD 		}
201942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
202942ba996SJean-Christophe PLAGNIOL-VILLARD 
203942ba996SJean-Christophe PLAGNIOL-VILLARD 	/* Address phase is over, now read 'len' bytes and stop */
204942ba996SJean-Christophe PLAGNIOL-VILLARD 	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP;
205942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = len & 0xffff;
206942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_SA) = chip;
207942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = tmp;
208942ba996SJean-Christophe PLAGNIOL-VILLARD 
209942ba996SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
210942ba996SJean-Christophe PLAGNIOL-VILLARD 		tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR);
211942ba996SJean-Christophe PLAGNIOL-VILLARD 
212942ba996SJean-Christophe PLAGNIOL-VILLARD 		CHECK_NACK();
213942ba996SJean-Christophe PLAGNIOL-VILLARD 
214942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (tmp & I2C_STAT_RRDY) {
215942ba996SJean-Christophe PLAGNIOL-VILLARD 			buf[i] = REG(I2C_DRR);
216942ba996SJean-Christophe PLAGNIOL-VILLARD 		} else {
217942ba996SJean-Christophe PLAGNIOL-VILLARD 			REG(I2C_CON) = 0;
218942ba996SJean-Christophe PLAGNIOL-VILLARD 			return(1);
219942ba996SJean-Christophe PLAGNIOL-VILLARD 		}
220942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
221942ba996SJean-Christophe PLAGNIOL-VILLARD 
222942ba996SJean-Christophe PLAGNIOL-VILLARD 	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
223942ba996SJean-Christophe PLAGNIOL-VILLARD 
224942ba996SJean-Christophe PLAGNIOL-VILLARD 	CHECK_NACK();
225942ba996SJean-Christophe PLAGNIOL-VILLARD 
226942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (!(tmp & I2C_STAT_SCD)) {
227942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CON) = 0;
228942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(1);
229942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
230942ba996SJean-Christophe PLAGNIOL-VILLARD 
231942ba996SJean-Christophe PLAGNIOL-VILLARD 	flush_rx();
232942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
233942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = 0;
234942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = 0;
235942ba996SJean-Christophe PLAGNIOL-VILLARD 
236942ba996SJean-Christophe PLAGNIOL-VILLARD 	return(0);
237942ba996SJean-Christophe PLAGNIOL-VILLARD }
238942ba996SJean-Christophe PLAGNIOL-VILLARD 
239942ba996SJean-Christophe PLAGNIOL-VILLARD 
240942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len)
241942ba996SJean-Christophe PLAGNIOL-VILLARD {
242942ba996SJean-Christophe PLAGNIOL-VILLARD 	u_int32_t	tmp;
243942ba996SJean-Christophe PLAGNIOL-VILLARD 	int		i;
244942ba996SJean-Christophe PLAGNIOL-VILLARD 
245942ba996SJean-Christophe PLAGNIOL-VILLARD 	if ((alen < 0) || (alen > 2)) {
246942ba996SJean-Christophe PLAGNIOL-VILLARD 		printf("%s(): bogus address length %x\n", __FUNCTION__, alen);
247942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(1);
248942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
249942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (len < 0) {
250942ba996SJean-Christophe PLAGNIOL-VILLARD 		printf("%s(): bogus length %x\n", __FUNCTION__, len);
251942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(1);
252942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
253942ba996SJean-Christophe PLAGNIOL-VILLARD 
254942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (wait_for_bus()) {return(1);}
255942ba996SJean-Christophe PLAGNIOL-VILLARD 
256942ba996SJean-Christophe PLAGNIOL-VILLARD 	/* Start address phase */
257942ba996SJean-Christophe PLAGNIOL-VILLARD 	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP;
258942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen;
259942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_SA) = chip;
260942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = tmp;
261942ba996SJean-Christophe PLAGNIOL-VILLARD 
262942ba996SJean-Christophe PLAGNIOL-VILLARD 	switch (alen) {
263942ba996SJean-Christophe PLAGNIOL-VILLARD 		case 2:
264942ba996SJean-Christophe PLAGNIOL-VILLARD 			/* Send address MSByte */
265942ba996SJean-Christophe PLAGNIOL-VILLARD 			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
266942ba996SJean-Christophe PLAGNIOL-VILLARD 
267942ba996SJean-Christophe PLAGNIOL-VILLARD 			CHECK_NACK();
268942ba996SJean-Christophe PLAGNIOL-VILLARD 
269942ba996SJean-Christophe PLAGNIOL-VILLARD 			if (tmp & I2C_STAT_XRDY) {
270942ba996SJean-Christophe PLAGNIOL-VILLARD 				REG(I2C_DXR) = (addr >> 8) & 0xff;
271942ba996SJean-Christophe PLAGNIOL-VILLARD 			} else {
272942ba996SJean-Christophe PLAGNIOL-VILLARD 				REG(I2C_CON) = 0;
273942ba996SJean-Christophe PLAGNIOL-VILLARD 				return(1);
274942ba996SJean-Christophe PLAGNIOL-VILLARD 			}
275942ba996SJean-Christophe PLAGNIOL-VILLARD 			/* No break, fall through */
276942ba996SJean-Christophe PLAGNIOL-VILLARD 		case 1:
277942ba996SJean-Christophe PLAGNIOL-VILLARD 			/* Send address LSByte */
278942ba996SJean-Christophe PLAGNIOL-VILLARD 			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
279942ba996SJean-Christophe PLAGNIOL-VILLARD 
280942ba996SJean-Christophe PLAGNIOL-VILLARD 			CHECK_NACK();
281942ba996SJean-Christophe PLAGNIOL-VILLARD 
282942ba996SJean-Christophe PLAGNIOL-VILLARD 			if (tmp & I2C_STAT_XRDY) {
283942ba996SJean-Christophe PLAGNIOL-VILLARD 				REG(I2C_DXR) = addr & 0xff;
284942ba996SJean-Christophe PLAGNIOL-VILLARD 			} else {
285942ba996SJean-Christophe PLAGNIOL-VILLARD 				REG(I2C_CON) = 0;
286942ba996SJean-Christophe PLAGNIOL-VILLARD 				return(1);
287942ba996SJean-Christophe PLAGNIOL-VILLARD 			}
288942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
289942ba996SJean-Christophe PLAGNIOL-VILLARD 
290942ba996SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < len; i++) {
291942ba996SJean-Christophe PLAGNIOL-VILLARD 		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK);
292942ba996SJean-Christophe PLAGNIOL-VILLARD 
293942ba996SJean-Christophe PLAGNIOL-VILLARD 		CHECK_NACK();
294942ba996SJean-Christophe PLAGNIOL-VILLARD 
295942ba996SJean-Christophe PLAGNIOL-VILLARD 		if (tmp & I2C_STAT_XRDY) {
296942ba996SJean-Christophe PLAGNIOL-VILLARD 			REG(I2C_DXR) = buf[i];
297942ba996SJean-Christophe PLAGNIOL-VILLARD 		} else {
298942ba996SJean-Christophe PLAGNIOL-VILLARD 			return(1);
299942ba996SJean-Christophe PLAGNIOL-VILLARD 		}
300942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
301942ba996SJean-Christophe PLAGNIOL-VILLARD 
302942ba996SJean-Christophe PLAGNIOL-VILLARD 	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK);
303942ba996SJean-Christophe PLAGNIOL-VILLARD 
304942ba996SJean-Christophe PLAGNIOL-VILLARD 	CHECK_NACK();
305942ba996SJean-Christophe PLAGNIOL-VILLARD 
306942ba996SJean-Christophe PLAGNIOL-VILLARD 	if (!(tmp & I2C_STAT_SCD)) {
307942ba996SJean-Christophe PLAGNIOL-VILLARD 		REG(I2C_CON) = 0;
308942ba996SJean-Christophe PLAGNIOL-VILLARD 		return(1);
309942ba996SJean-Christophe PLAGNIOL-VILLARD 	}
310942ba996SJean-Christophe PLAGNIOL-VILLARD 
311942ba996SJean-Christophe PLAGNIOL-VILLARD 	flush_rx();
312942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_STAT) = 0xffff;
313942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CNT) = 0;
314942ba996SJean-Christophe PLAGNIOL-VILLARD 	REG(I2C_CON) = 0;
315942ba996SJean-Christophe PLAGNIOL-VILLARD 
316942ba996SJean-Christophe PLAGNIOL-VILLARD 	return(0);
317942ba996SJean-Christophe PLAGNIOL-VILLARD }
318