xref: /rk3399_ARM-atf/drivers/mentor/i2c/mi2cv.c (revision 7e4d562077463f39360df06975545c5b42910794)
1*7e4d5620SIcenowy Zheng /*
2*7e4d5620SIcenowy Zheng  * Copyright (C) 2018 Marvell International Ltd.
3*7e4d5620SIcenowy Zheng  * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
4*7e4d5620SIcenowy Zheng  *
5*7e4d5620SIcenowy Zheng  * SPDX-License-Identifier:     BSD-3-Clause
6*7e4d5620SIcenowy Zheng  * https://spdx.org/licenses
7*7e4d5620SIcenowy Zheng  */
8*7e4d5620SIcenowy Zheng 
9*7e4d5620SIcenowy Zheng /*
10*7e4d5620SIcenowy Zheng  * This driver is for Mentor Graphics Inventra MI2CV IP core, which is used
11*7e4d5620SIcenowy Zheng  * for Marvell and Allwinner SoCs in ATF.
12*7e4d5620SIcenowy Zheng  */
13*7e4d5620SIcenowy Zheng 
14*7e4d5620SIcenowy Zheng #include <debug.h>
15*7e4d5620SIcenowy Zheng #include <delay_timer.h>
16*7e4d5620SIcenowy Zheng #include <errno.h>
17*7e4d5620SIcenowy Zheng #include <mentor/mi2cv.h>
18*7e4d5620SIcenowy Zheng #include <mmio.h>
19*7e4d5620SIcenowy Zheng 
20*7e4d5620SIcenowy Zheng #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
21*7e4d5620SIcenowy Zheng #define DEBUG_I2C
22*7e4d5620SIcenowy Zheng #endif
23*7e4d5620SIcenowy Zheng 
24*7e4d5620SIcenowy Zheng #define I2C_TIMEOUT_VALUE		0x500
25*7e4d5620SIcenowy Zheng #define I2C_MAX_RETRY_CNT		1000
26*7e4d5620SIcenowy Zheng #define I2C_CMD_WRITE			0x0
27*7e4d5620SIcenowy Zheng #define I2C_CMD_READ			0x1
28*7e4d5620SIcenowy Zheng 
29*7e4d5620SIcenowy Zheng #define I2C_DATA_ADDR_7BIT_OFFS		0x1
30*7e4d5620SIcenowy Zheng #define I2C_DATA_ADDR_7BIT_MASK		(0xFF << I2C_DATA_ADDR_7BIT_OFFS)
31*7e4d5620SIcenowy Zheng 
32*7e4d5620SIcenowy Zheng #define I2C_CONTROL_ACK			0x00000004
33*7e4d5620SIcenowy Zheng #define I2C_CONTROL_IFLG		0x00000008
34*7e4d5620SIcenowy Zheng #define I2C_CONTROL_STOP		0x00000010
35*7e4d5620SIcenowy Zheng #define I2C_CONTROL_START		0x00000020
36*7e4d5620SIcenowy Zheng #define I2C_CONTROL_TWSIEN		0x00000040
37*7e4d5620SIcenowy Zheng #define I2C_CONTROL_INTEN		0x00000080
38*7e4d5620SIcenowy Zheng 
39*7e4d5620SIcenowy Zheng #define I2C_STATUS_START			0x08
40*7e4d5620SIcenowy Zheng #define I2C_STATUS_REPEATED_START		0x10
41*7e4d5620SIcenowy Zheng #define I2C_STATUS_ADDR_W_ACK			0x18
42*7e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_W_ACK			0x28
43*7e4d5620SIcenowy Zheng #define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER	0x38
44*7e4d5620SIcenowy Zheng #define I2C_STATUS_ADDR_R_ACK			0x40
45*7e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_R_ACK			0x50
46*7e4d5620SIcenowy Zheng #define I2C_STATUS_DATA_R_NAK			0x58
47*7e4d5620SIcenowy Zheng #define I2C_STATUS_LOST_ARB_GENERAL_CALL	0x78
48*7e4d5620SIcenowy Zheng #define I2C_STATUS_IDLE				0xF8
49*7e4d5620SIcenowy Zheng 
50*7e4d5620SIcenowy Zheng #define I2C_UNSTUCK_TRIGGER			0x1
51*7e4d5620SIcenowy Zheng #define I2C_UNSTUCK_ONGOING			0x2
52*7e4d5620SIcenowy Zheng #define I2C_UNSTUCK_ERROR			0x4
53*7e4d5620SIcenowy Zheng 
54*7e4d5620SIcenowy Zheng static struct mentor_i2c_regs *base;
55*7e4d5620SIcenowy Zheng 
56*7e4d5620SIcenowy Zheng static int mentor_i2c_lost_arbitration(uint32_t *status)
57*7e4d5620SIcenowy Zheng {
58*7e4d5620SIcenowy Zheng 	*status = mmio_read_32((uintptr_t)&base->status);
59*7e4d5620SIcenowy Zheng 	if ((*status == I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER) ||
60*7e4d5620SIcenowy Zheng 	    (*status == I2C_STATUS_LOST_ARB_GENERAL_CALL))
61*7e4d5620SIcenowy Zheng 		return -EAGAIN;
62*7e4d5620SIcenowy Zheng 
63*7e4d5620SIcenowy Zheng 	return 0;
64*7e4d5620SIcenowy Zheng }
65*7e4d5620SIcenowy Zheng 
66*7e4d5620SIcenowy Zheng static void mentor_i2c_interrupt_clear(void)
67*7e4d5620SIcenowy Zheng {
68*7e4d5620SIcenowy Zheng 	uint32_t reg;
69*7e4d5620SIcenowy Zheng 
70*7e4d5620SIcenowy Zheng 	reg = mmio_read_32((uintptr_t)&base->control);
71*7e4d5620SIcenowy Zheng 	reg &= ~(I2C_CONTROL_IFLG);
72*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control, reg);
73*7e4d5620SIcenowy Zheng 	/* Wait for 1 us for the clear to take effect */
74*7e4d5620SIcenowy Zheng 	udelay(1);
75*7e4d5620SIcenowy Zheng }
76*7e4d5620SIcenowy Zheng 
77*7e4d5620SIcenowy Zheng static int mentor_i2c_interrupt_get(void)
78*7e4d5620SIcenowy Zheng {
79*7e4d5620SIcenowy Zheng 	uint32_t reg;
80*7e4d5620SIcenowy Zheng 
81*7e4d5620SIcenowy Zheng 	/* get the interrupt flag bit */
82*7e4d5620SIcenowy Zheng 	reg = mmio_read_32((uintptr_t)&base->control);
83*7e4d5620SIcenowy Zheng 	reg &= I2C_CONTROL_IFLG;
84*7e4d5620SIcenowy Zheng 	return reg && I2C_CONTROL_IFLG;
85*7e4d5620SIcenowy Zheng }
86*7e4d5620SIcenowy Zheng 
87*7e4d5620SIcenowy Zheng static int mentor_i2c_wait_interrupt(void)
88*7e4d5620SIcenowy Zheng {
89*7e4d5620SIcenowy Zheng 	uint32_t timeout = 0;
90*7e4d5620SIcenowy Zheng 
91*7e4d5620SIcenowy Zheng 	while (!mentor_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE))
92*7e4d5620SIcenowy Zheng 		;
93*7e4d5620SIcenowy Zheng 	if (timeout >= I2C_TIMEOUT_VALUE)
94*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
95*7e4d5620SIcenowy Zheng 
96*7e4d5620SIcenowy Zheng 	return 0;
97*7e4d5620SIcenowy Zheng }
98*7e4d5620SIcenowy Zheng 
99*7e4d5620SIcenowy Zheng static int mentor_i2c_start_bit_set(void)
100*7e4d5620SIcenowy Zheng {
101*7e4d5620SIcenowy Zheng 	int is_int_flag = 0;
102*7e4d5620SIcenowy Zheng 	uint32_t status;
103*7e4d5620SIcenowy Zheng 
104*7e4d5620SIcenowy Zheng 	if (mentor_i2c_interrupt_get())
105*7e4d5620SIcenowy Zheng 		is_int_flag = 1;
106*7e4d5620SIcenowy Zheng 
107*7e4d5620SIcenowy Zheng 	/* set start bit */
108*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control,
109*7e4d5620SIcenowy Zheng 		      mmio_read_32((uintptr_t)&base->control) |
110*7e4d5620SIcenowy Zheng 		      I2C_CONTROL_START);
111*7e4d5620SIcenowy Zheng 
112*7e4d5620SIcenowy Zheng 	/* in case that the int flag was set before i.e. repeated start bit */
113*7e4d5620SIcenowy Zheng 	if (is_int_flag) {
114*7e4d5620SIcenowy Zheng 		VERBOSE("%s: repeated start Bit\n", __func__);
115*7e4d5620SIcenowy Zheng 		mentor_i2c_interrupt_clear();
116*7e4d5620SIcenowy Zheng 	}
117*7e4d5620SIcenowy Zheng 
118*7e4d5620SIcenowy Zheng 	if (mentor_i2c_wait_interrupt()) {
119*7e4d5620SIcenowy Zheng 		ERROR("Start clear bit timeout\n");
120*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
121*7e4d5620SIcenowy Zheng 	}
122*7e4d5620SIcenowy Zheng 
123*7e4d5620SIcenowy Zheng 	/* check that start bit went down */
124*7e4d5620SIcenowy Zheng 	if ((mmio_read_32((uintptr_t)&base->control) &
125*7e4d5620SIcenowy Zheng 	    I2C_CONTROL_START) != 0) {
126*7e4d5620SIcenowy Zheng 		ERROR("Start bit didn't went down\n");
127*7e4d5620SIcenowy Zheng 		return -EPERM;
128*7e4d5620SIcenowy Zheng 	}
129*7e4d5620SIcenowy Zheng 
130*7e4d5620SIcenowy Zheng 	/* check the status */
131*7e4d5620SIcenowy Zheng 	if (mentor_i2c_lost_arbitration(&status)) {
132*7e4d5620SIcenowy Zheng 		ERROR("%s - %d: Lost arbitration, got status %x\n",
133*7e4d5620SIcenowy Zheng 		      __func__, __LINE__, status);
134*7e4d5620SIcenowy Zheng 		return -EAGAIN;
135*7e4d5620SIcenowy Zheng 	}
136*7e4d5620SIcenowy Zheng 	if ((status != I2C_STATUS_START) &&
137*7e4d5620SIcenowy Zheng 	    (status != I2C_STATUS_REPEATED_START)) {
138*7e4d5620SIcenowy Zheng 		ERROR("Got status %x after enable start bit.\n", status);
139*7e4d5620SIcenowy Zheng 		return -EPERM;
140*7e4d5620SIcenowy Zheng 	}
141*7e4d5620SIcenowy Zheng 
142*7e4d5620SIcenowy Zheng 	return 0;
143*7e4d5620SIcenowy Zheng }
144*7e4d5620SIcenowy Zheng 
145*7e4d5620SIcenowy Zheng static int mentor_i2c_stop_bit_set(void)
146*7e4d5620SIcenowy Zheng {
147*7e4d5620SIcenowy Zheng 	int timeout;
148*7e4d5620SIcenowy Zheng 	uint32_t status;
149*7e4d5620SIcenowy Zheng 
150*7e4d5620SIcenowy Zheng 	/* Generate stop bit */
151*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control,
152*7e4d5620SIcenowy Zheng 		      mmio_read_32((uintptr_t)&base->control) |
153*7e4d5620SIcenowy Zheng 		      I2C_CONTROL_STOP);
154*7e4d5620SIcenowy Zheng 	mentor_i2c_interrupt_clear();
155*7e4d5620SIcenowy Zheng 
156*7e4d5620SIcenowy Zheng 	timeout = 0;
157*7e4d5620SIcenowy Zheng 	/* Read control register, check the control stop bit */
158*7e4d5620SIcenowy Zheng 	while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) &&
159*7e4d5620SIcenowy Zheng 	       (timeout++ < I2C_TIMEOUT_VALUE))
160*7e4d5620SIcenowy Zheng 		;
161*7e4d5620SIcenowy Zheng 	if (timeout >= I2C_TIMEOUT_VALUE) {
162*7e4d5620SIcenowy Zheng 		ERROR("Stop bit didn't went down\n");
163*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
164*7e4d5620SIcenowy Zheng 	}
165*7e4d5620SIcenowy Zheng 
166*7e4d5620SIcenowy Zheng 	/* check that stop bit went down */
167*7e4d5620SIcenowy Zheng 	if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) {
168*7e4d5620SIcenowy Zheng 		ERROR("Stop bit didn't went down\n");
169*7e4d5620SIcenowy Zheng 		return -EPERM;
170*7e4d5620SIcenowy Zheng 	}
171*7e4d5620SIcenowy Zheng 
172*7e4d5620SIcenowy Zheng 	/* check the status */
173*7e4d5620SIcenowy Zheng 	if (mentor_i2c_lost_arbitration(&status)) {
174*7e4d5620SIcenowy Zheng 		ERROR("%s - %d: Lost arbitration, got status %x\n",
175*7e4d5620SIcenowy Zheng 		      __func__, __LINE__, status);
176*7e4d5620SIcenowy Zheng 		return -EAGAIN;
177*7e4d5620SIcenowy Zheng 	}
178*7e4d5620SIcenowy Zheng 	if (status != I2C_STATUS_IDLE) {
179*7e4d5620SIcenowy Zheng 		ERROR("Got status %x after enable stop bit.\n", status);
180*7e4d5620SIcenowy Zheng 		return -EPERM;
181*7e4d5620SIcenowy Zheng 	}
182*7e4d5620SIcenowy Zheng 
183*7e4d5620SIcenowy Zheng 	return 0;
184*7e4d5620SIcenowy Zheng }
185*7e4d5620SIcenowy Zheng 
186*7e4d5620SIcenowy Zheng static int mentor_i2c_address_set(uint8_t chain, int command)
187*7e4d5620SIcenowy Zheng {
188*7e4d5620SIcenowy Zheng 	uint32_t reg, status;
189*7e4d5620SIcenowy Zheng 
190*7e4d5620SIcenowy Zheng 	reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK;
191*7e4d5620SIcenowy Zheng 	reg |= command;
192*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->data, reg);
193*7e4d5620SIcenowy Zheng 	udelay(1);
194*7e4d5620SIcenowy Zheng 
195*7e4d5620SIcenowy Zheng 	mentor_i2c_interrupt_clear();
196*7e4d5620SIcenowy Zheng 
197*7e4d5620SIcenowy Zheng 	if (mentor_i2c_wait_interrupt()) {
198*7e4d5620SIcenowy Zheng 		ERROR("Start clear bit timeout\n");
199*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
200*7e4d5620SIcenowy Zheng 	}
201*7e4d5620SIcenowy Zheng 
202*7e4d5620SIcenowy Zheng 	/* check the status */
203*7e4d5620SIcenowy Zheng 	if (mentor_i2c_lost_arbitration(&status)) {
204*7e4d5620SIcenowy Zheng 		ERROR("%s - %d: Lost arbitration, got status %x\n",
205*7e4d5620SIcenowy Zheng 		      __func__, __LINE__, status);
206*7e4d5620SIcenowy Zheng 		return -EAGAIN;
207*7e4d5620SIcenowy Zheng 	}
208*7e4d5620SIcenowy Zheng 	if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) ||
209*7e4d5620SIcenowy Zheng 	   ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) {
210*7e4d5620SIcenowy Zheng 		/* only in debug, since in boot we try to read the SPD
211*7e4d5620SIcenowy Zheng 		 * of both DRAM, and we don't want error messages in cas
212*7e4d5620SIcenowy Zheng 		 * DIMM doesn't exist.
213*7e4d5620SIcenowy Zheng 		 */
214*7e4d5620SIcenowy Zheng 		INFO("%s: ERROR - status %x addr in %s mode.\n", __func__,
215*7e4d5620SIcenowy Zheng 		     status, (command == I2C_CMD_WRITE) ? "Write" : "Read");
216*7e4d5620SIcenowy Zheng 		return -EPERM;
217*7e4d5620SIcenowy Zheng 	}
218*7e4d5620SIcenowy Zheng 
219*7e4d5620SIcenowy Zheng 	return 0;
220*7e4d5620SIcenowy Zheng }
221*7e4d5620SIcenowy Zheng 
222*7e4d5620SIcenowy Zheng /*
223*7e4d5620SIcenowy Zheng  * The I2C module contains a clock divider to generate the SCL clock.
224*7e4d5620SIcenowy Zheng  * This function calculates and sets the <N> and <M> fields in the I2C Baud
225*7e4d5620SIcenowy Zheng  * Rate Register (t=01) to obtain given 'requested_speed'.
226*7e4d5620SIcenowy Zheng  * The requested_speed will be equal to:
227*7e4d5620SIcenowy Zheng  * CONFIG_SYS_TCLK / (10 * (M + 1) * (2 << N))
228*7e4d5620SIcenowy Zheng  * Where M is the value represented by bits[6:3] and N is the value represented
229*7e4d5620SIcenowy Zheng  * by bits[2:0] of "I2C Baud Rate Register".
230*7e4d5620SIcenowy Zheng  * Therefore max M which can be set is 16 (2^4) and max N is 8 (2^3). So the
231*7e4d5620SIcenowy Zheng  * lowest possible baudrate is:
232*7e4d5620SIcenowy Zheng  * CONFIG_SYS_TCLK/(10 * (16 +1) * (2 << 8), which equals to:
233*7e4d5620SIcenowy Zheng  * CONFIG_SYS_TCLK/87040. Assuming that CONFIG_SYS_TCLK=250MHz, the lowest
234*7e4d5620SIcenowy Zheng  * possible frequency is ~2,872KHz.
235*7e4d5620SIcenowy Zheng  */
236*7e4d5620SIcenowy Zheng static unsigned int mentor_i2c_bus_speed_set(unsigned int requested_speed)
237*7e4d5620SIcenowy Zheng {
238*7e4d5620SIcenowy Zheng 	unsigned int n, m, freq, margin, min_margin = 0xffffffff;
239*7e4d5620SIcenowy Zheng 	unsigned int actual_n = 0, actual_m = 0;
240*7e4d5620SIcenowy Zheng 	int val;
241*7e4d5620SIcenowy Zheng 
242*7e4d5620SIcenowy Zheng 	/* Calculate N and M for the TWSI clock baud rate */
243*7e4d5620SIcenowy Zheng 	for (n = 0; n < 8; n++) {
244*7e4d5620SIcenowy Zheng 		for (m = 0; m < 16; m++) {
245*7e4d5620SIcenowy Zheng 			freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n));
246*7e4d5620SIcenowy Zheng 			val = requested_speed - freq;
247*7e4d5620SIcenowy Zheng 			margin = (val > 0) ? val : -val;
248*7e4d5620SIcenowy Zheng 
249*7e4d5620SIcenowy Zheng 			if ((freq <= requested_speed) &&
250*7e4d5620SIcenowy Zheng 			    (margin < min_margin)) {
251*7e4d5620SIcenowy Zheng 				min_margin = margin;
252*7e4d5620SIcenowy Zheng 				actual_n = n;
253*7e4d5620SIcenowy Zheng 				actual_m = m;
254*7e4d5620SIcenowy Zheng 			}
255*7e4d5620SIcenowy Zheng 		}
256*7e4d5620SIcenowy Zheng 	}
257*7e4d5620SIcenowy Zheng 	VERBOSE("%s: actual_n = %u, actual_m = %u\n",
258*7e4d5620SIcenowy Zheng 		__func__, actual_n, actual_m);
259*7e4d5620SIcenowy Zheng 	/* Set the baud rate */
260*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->baudrate, (actual_m << 3) | actual_n);
261*7e4d5620SIcenowy Zheng 
262*7e4d5620SIcenowy Zheng 	return 0;
263*7e4d5620SIcenowy Zheng }
264*7e4d5620SIcenowy Zheng 
265*7e4d5620SIcenowy Zheng #ifdef DEBUG_I2C
266*7e4d5620SIcenowy Zheng static int mentor_i2c_probe(uint8_t chip)
267*7e4d5620SIcenowy Zheng {
268*7e4d5620SIcenowy Zheng 	int ret = 0;
269*7e4d5620SIcenowy Zheng 
270*7e4d5620SIcenowy Zheng 	ret = mentor_i2c_start_bit_set();
271*7e4d5620SIcenowy Zheng 	if (ret != 0) {
272*7e4d5620SIcenowy Zheng 		mentor_i2c_stop_bit_set();
273*7e4d5620SIcenowy Zheng 		ERROR("%s - %d: %s", __func__, __LINE__,
274*7e4d5620SIcenowy Zheng 		      "mentor_i2c_start_bit_set failed\n");
275*7e4d5620SIcenowy Zheng 		return -EPERM;
276*7e4d5620SIcenowy Zheng 	}
277*7e4d5620SIcenowy Zheng 
278*7e4d5620SIcenowy Zheng 	ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
279*7e4d5620SIcenowy Zheng 	if (ret != 0) {
280*7e4d5620SIcenowy Zheng 		mentor_i2c_stop_bit_set();
281*7e4d5620SIcenowy Zheng 		ERROR("%s - %d: %s", __func__, __LINE__,
282*7e4d5620SIcenowy Zheng 		      "mentor_i2c_address_set failed\n");
283*7e4d5620SIcenowy Zheng 		return -EPERM;
284*7e4d5620SIcenowy Zheng 	}
285*7e4d5620SIcenowy Zheng 
286*7e4d5620SIcenowy Zheng 	mentor_i2c_stop_bit_set();
287*7e4d5620SIcenowy Zheng 
288*7e4d5620SIcenowy Zheng 	VERBOSE("%s: successful I2C probe\n", __func__);
289*7e4d5620SIcenowy Zheng 
290*7e4d5620SIcenowy Zheng 	return ret;
291*7e4d5620SIcenowy Zheng }
292*7e4d5620SIcenowy Zheng #endif
293*7e4d5620SIcenowy Zheng 
294*7e4d5620SIcenowy Zheng /* regular i2c transaction */
295*7e4d5620SIcenowy Zheng static int mentor_i2c_data_receive(uint8_t *p_block, uint32_t block_size)
296*7e4d5620SIcenowy Zheng {
297*7e4d5620SIcenowy Zheng 	uint32_t reg, status, block_size_read = block_size;
298*7e4d5620SIcenowy Zheng 
299*7e4d5620SIcenowy Zheng 	/* Wait for cause interrupt */
300*7e4d5620SIcenowy Zheng 	if (mentor_i2c_wait_interrupt()) {
301*7e4d5620SIcenowy Zheng 		ERROR("Start clear bit timeout\n");
302*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
303*7e4d5620SIcenowy Zheng 	}
304*7e4d5620SIcenowy Zheng 	while (block_size_read) {
305*7e4d5620SIcenowy Zheng 		if (block_size_read == 1) {
306*7e4d5620SIcenowy Zheng 			reg = mmio_read_32((uintptr_t)&base->control);
307*7e4d5620SIcenowy Zheng 			reg &= ~(I2C_CONTROL_ACK);
308*7e4d5620SIcenowy Zheng 			mmio_write_32((uintptr_t)&base->control, reg);
309*7e4d5620SIcenowy Zheng 		}
310*7e4d5620SIcenowy Zheng 		mentor_i2c_interrupt_clear();
311*7e4d5620SIcenowy Zheng 
312*7e4d5620SIcenowy Zheng 		if (mentor_i2c_wait_interrupt()) {
313*7e4d5620SIcenowy Zheng 			ERROR("Start clear bit timeout\n");
314*7e4d5620SIcenowy Zheng 			return -ETIMEDOUT;
315*7e4d5620SIcenowy Zheng 		}
316*7e4d5620SIcenowy Zheng 		/* check the status */
317*7e4d5620SIcenowy Zheng 		if (mentor_i2c_lost_arbitration(&status)) {
318*7e4d5620SIcenowy Zheng 			ERROR("%s - %d: Lost arbitration, got status %x\n",
319*7e4d5620SIcenowy Zheng 			      __func__, __LINE__, status);
320*7e4d5620SIcenowy Zheng 			return -EAGAIN;
321*7e4d5620SIcenowy Zheng 		}
322*7e4d5620SIcenowy Zheng 		if ((status != I2C_STATUS_DATA_R_ACK) &&
323*7e4d5620SIcenowy Zheng 		    (block_size_read != 1)) {
324*7e4d5620SIcenowy Zheng 			ERROR("Status %x in read transaction\n", status);
325*7e4d5620SIcenowy Zheng 			return -EPERM;
326*7e4d5620SIcenowy Zheng 		}
327*7e4d5620SIcenowy Zheng 		if ((status != I2C_STATUS_DATA_R_NAK) &&
328*7e4d5620SIcenowy Zheng 		    (block_size_read == 1)) {
329*7e4d5620SIcenowy Zheng 			ERROR("Status %x in Rd Terminate\n", status);
330*7e4d5620SIcenowy Zheng 			return -EPERM;
331*7e4d5620SIcenowy Zheng 		}
332*7e4d5620SIcenowy Zheng 
333*7e4d5620SIcenowy Zheng 		/* read the data */
334*7e4d5620SIcenowy Zheng 		*p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data);
335*7e4d5620SIcenowy Zheng 		VERBOSE("%s: place %d read %x\n", __func__,
336*7e4d5620SIcenowy Zheng 			block_size - block_size_read, *p_block);
337*7e4d5620SIcenowy Zheng 		p_block++;
338*7e4d5620SIcenowy Zheng 		block_size_read--;
339*7e4d5620SIcenowy Zheng 	}
340*7e4d5620SIcenowy Zheng 
341*7e4d5620SIcenowy Zheng 	return 0;
342*7e4d5620SIcenowy Zheng }
343*7e4d5620SIcenowy Zheng 
344*7e4d5620SIcenowy Zheng static int mentor_i2c_data_transmit(uint8_t *p_block, uint32_t block_size)
345*7e4d5620SIcenowy Zheng {
346*7e4d5620SIcenowy Zheng 	uint32_t status, block_size_write = block_size;
347*7e4d5620SIcenowy Zheng 
348*7e4d5620SIcenowy Zheng 	if (mentor_i2c_wait_interrupt()) {
349*7e4d5620SIcenowy Zheng 		ERROR("Start clear bit timeout\n");
350*7e4d5620SIcenowy Zheng 		return -ETIMEDOUT;
351*7e4d5620SIcenowy Zheng 	}
352*7e4d5620SIcenowy Zheng 
353*7e4d5620SIcenowy Zheng 	while (block_size_write) {
354*7e4d5620SIcenowy Zheng 		/* write the data */
355*7e4d5620SIcenowy Zheng 		mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block);
356*7e4d5620SIcenowy Zheng 		VERBOSE("%s: index = %d, data = %x\n", __func__,
357*7e4d5620SIcenowy Zheng 			block_size - block_size_write, *p_block);
358*7e4d5620SIcenowy Zheng 		p_block++;
359*7e4d5620SIcenowy Zheng 		block_size_write--;
360*7e4d5620SIcenowy Zheng 
361*7e4d5620SIcenowy Zheng 		mentor_i2c_interrupt_clear();
362*7e4d5620SIcenowy Zheng 
363*7e4d5620SIcenowy Zheng 		if (mentor_i2c_wait_interrupt()) {
364*7e4d5620SIcenowy Zheng 			ERROR("Start clear bit timeout\n");
365*7e4d5620SIcenowy Zheng 			return -ETIMEDOUT;
366*7e4d5620SIcenowy Zheng 		}
367*7e4d5620SIcenowy Zheng 
368*7e4d5620SIcenowy Zheng 		/* check the status */
369*7e4d5620SIcenowy Zheng 		if (mentor_i2c_lost_arbitration(&status)) {
370*7e4d5620SIcenowy Zheng 			ERROR("%s - %d: Lost arbitration, got status %x\n",
371*7e4d5620SIcenowy Zheng 			      __func__, __LINE__, status);
372*7e4d5620SIcenowy Zheng 			return -EAGAIN;
373*7e4d5620SIcenowy Zheng 		}
374*7e4d5620SIcenowy Zheng 		if (status != I2C_STATUS_DATA_W_ACK) {
375*7e4d5620SIcenowy Zheng 			ERROR("Status %x in write transaction\n", status);
376*7e4d5620SIcenowy Zheng 			return -EPERM;
377*7e4d5620SIcenowy Zheng 		}
378*7e4d5620SIcenowy Zheng 	}
379*7e4d5620SIcenowy Zheng 
380*7e4d5620SIcenowy Zheng 	return 0;
381*7e4d5620SIcenowy Zheng }
382*7e4d5620SIcenowy Zheng 
383*7e4d5620SIcenowy Zheng static int mentor_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen)
384*7e4d5620SIcenowy Zheng {
385*7e4d5620SIcenowy Zheng 	uint8_t off_block[2];
386*7e4d5620SIcenowy Zheng 	uint32_t off_size;
387*7e4d5620SIcenowy Zheng 
388*7e4d5620SIcenowy Zheng 	if (alen == 2) { /* 2-byte addresses support */
389*7e4d5620SIcenowy Zheng 		off_block[0] = (addr >> 8) & 0xff;
390*7e4d5620SIcenowy Zheng 		off_block[1] = addr & 0xff;
391*7e4d5620SIcenowy Zheng 		off_size = 2;
392*7e4d5620SIcenowy Zheng 	} else { /* 1-byte addresses support */
393*7e4d5620SIcenowy Zheng 		off_block[0] = addr & 0xff;
394*7e4d5620SIcenowy Zheng 		off_size = 1;
395*7e4d5620SIcenowy Zheng 	}
396*7e4d5620SIcenowy Zheng 	VERBOSE("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__,
397*7e4d5620SIcenowy Zheng 		off_size, off_block[0], off_block[1]);
398*7e4d5620SIcenowy Zheng 	return mentor_i2c_data_transmit(off_block, off_size);
399*7e4d5620SIcenowy Zheng }
400*7e4d5620SIcenowy Zheng 
401*7e4d5620SIcenowy Zheng #ifdef I2C_CAN_UNSTUCK
402*7e4d5620SIcenowy Zheng static int mentor_i2c_unstuck(int ret)
403*7e4d5620SIcenowy Zheng {
404*7e4d5620SIcenowy Zheng 	uint32_t v;
405*7e4d5620SIcenowy Zheng 
406*7e4d5620SIcenowy Zheng 	if (ret != -ETIMEDOUT)
407*7e4d5620SIcenowy Zheng 		return ret;
408*7e4d5620SIcenowy Zheng 	VERBOSE("Trying to \"unstuck i2c\"... ");
409*7e4d5620SIcenowy Zheng 	i2c_init(base);
410*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->unstuck, I2C_UNSTUCK_TRIGGER);
411*7e4d5620SIcenowy Zheng 	do {
412*7e4d5620SIcenowy Zheng 		v = mmio_read_32((uintptr_t)&base->unstuck);
413*7e4d5620SIcenowy Zheng 	} while (v & I2C_UNSTUCK_ONGOING);
414*7e4d5620SIcenowy Zheng 
415*7e4d5620SIcenowy Zheng 	if (v & I2C_UNSTUCK_ERROR) {
416*7e4d5620SIcenowy Zheng 		VERBOSE("failed - soft reset i2c\n");
417*7e4d5620SIcenowy Zheng 		ret = -EPERM;
418*7e4d5620SIcenowy Zheng 	} else {
419*7e4d5620SIcenowy Zheng 		VERBOSE("ok\n");
420*7e4d5620SIcenowy Zheng 		i2c_init(base);
421*7e4d5620SIcenowy Zheng 		ret = -EAGAIN;
422*7e4d5620SIcenowy Zheng 	}
423*7e4d5620SIcenowy Zheng 	return ret;
424*7e4d5620SIcenowy Zheng }
425*7e4d5620SIcenowy Zheng #else
426*7e4d5620SIcenowy Zheng static int mentor_i2c_unstuck(int ret)
427*7e4d5620SIcenowy Zheng {
428*7e4d5620SIcenowy Zheng 	VERBOSE("Cannot \"unstuck i2c\" - soft reset i2c\n");
429*7e4d5620SIcenowy Zheng 	return -EPERM;
430*7e4d5620SIcenowy Zheng }
431*7e4d5620SIcenowy Zheng #endif
432*7e4d5620SIcenowy Zheng 
433*7e4d5620SIcenowy Zheng /*
434*7e4d5620SIcenowy Zheng  * API Functions
435*7e4d5620SIcenowy Zheng  */
436*7e4d5620SIcenowy Zheng void i2c_init(void *i2c_base)
437*7e4d5620SIcenowy Zheng {
438*7e4d5620SIcenowy Zheng 	/* For I2C speed and slave address, now we do not set them since
439*7e4d5620SIcenowy Zheng 	 * we just provide the working speed and slave address otherwhere
440*7e4d5620SIcenowy Zheng 	 * for i2c_init
441*7e4d5620SIcenowy Zheng 	 */
442*7e4d5620SIcenowy Zheng 	base = (struct mentor_i2c_regs *)i2c_base;
443*7e4d5620SIcenowy Zheng 
444*7e4d5620SIcenowy Zheng 	/* Reset the I2C logic */
445*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->soft_reset, 0);
446*7e4d5620SIcenowy Zheng 
447*7e4d5620SIcenowy Zheng 	udelay(200);
448*7e4d5620SIcenowy Zheng 
449*7e4d5620SIcenowy Zheng 	mentor_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED);
450*7e4d5620SIcenowy Zheng 
451*7e4d5620SIcenowy Zheng 	/* Enable the I2C and slave */
452*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control,
453*7e4d5620SIcenowy Zheng 		      I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK);
454*7e4d5620SIcenowy Zheng 
455*7e4d5620SIcenowy Zheng 	/* set the I2C slave address */
456*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0);
457*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE);
458*7e4d5620SIcenowy Zheng 
459*7e4d5620SIcenowy Zheng 	/* unmask I2C interrupt */
460*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control,
461*7e4d5620SIcenowy Zheng 		      mmio_read_32((uintptr_t)&base->control) |
462*7e4d5620SIcenowy Zheng 		      I2C_CONTROL_INTEN);
463*7e4d5620SIcenowy Zheng 
464*7e4d5620SIcenowy Zheng 	udelay(10);
465*7e4d5620SIcenowy Zheng }
466*7e4d5620SIcenowy Zheng 
467*7e4d5620SIcenowy Zheng /*
468*7e4d5620SIcenowy Zheng  * i2c_read: - Read multiple bytes from an i2c device
469*7e4d5620SIcenowy Zheng  *
470*7e4d5620SIcenowy Zheng  * The higher level routines take into account that this function is only
471*7e4d5620SIcenowy Zheng  * called with len < page length of the device (see configuration file)
472*7e4d5620SIcenowy Zheng  *
473*7e4d5620SIcenowy Zheng  * @chip:	address of the chip which is to be read
474*7e4d5620SIcenowy Zheng  * @addr:	i2c data address within the chip
475*7e4d5620SIcenowy Zheng  * @alen:	length of the i2c data address (1..2 bytes)
476*7e4d5620SIcenowy Zheng  * @buffer:	where to write the data
477*7e4d5620SIcenowy Zheng  * @len:	how much byte do we want to read
478*7e4d5620SIcenowy Zheng  * @return:	0 in case of success
479*7e4d5620SIcenowy Zheng  */
480*7e4d5620SIcenowy Zheng int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
481*7e4d5620SIcenowy Zheng {
482*7e4d5620SIcenowy Zheng 	int ret = 0;
483*7e4d5620SIcenowy Zheng 	uint32_t counter = 0;
484*7e4d5620SIcenowy Zheng 
485*7e4d5620SIcenowy Zheng #ifdef DEBUG_I2C
486*7e4d5620SIcenowy Zheng 	mentor_i2c_probe(chip);
487*7e4d5620SIcenowy Zheng #endif
488*7e4d5620SIcenowy Zheng 
489*7e4d5620SIcenowy Zheng 	do {
490*7e4d5620SIcenowy Zheng 		if (ret != -EAGAIN && ret) {
491*7e4d5620SIcenowy Zheng 			ERROR("i2c transaction failed, after %d retries\n",
492*7e4d5620SIcenowy Zheng 			      counter);
493*7e4d5620SIcenowy Zheng 			mentor_i2c_stop_bit_set();
494*7e4d5620SIcenowy Zheng 			return ret;
495*7e4d5620SIcenowy Zheng 		}
496*7e4d5620SIcenowy Zheng 
497*7e4d5620SIcenowy Zheng 		/* wait for 1 us for the interrupt clear to take effect */
498*7e4d5620SIcenowy Zheng 		if (counter > 0)
499*7e4d5620SIcenowy Zheng 			udelay(1);
500*7e4d5620SIcenowy Zheng 		counter++;
501*7e4d5620SIcenowy Zheng 
502*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_start_bit_set();
503*7e4d5620SIcenowy Zheng 		if (ret) {
504*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_unstuck(ret);
505*7e4d5620SIcenowy Zheng 			continue;
506*7e4d5620SIcenowy Zheng 		}
507*7e4d5620SIcenowy Zheng 
508*7e4d5620SIcenowy Zheng 		/* if EEPROM device */
509*7e4d5620SIcenowy Zheng 		if (alen != 0) {
510*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
511*7e4d5620SIcenowy Zheng 			if (ret)
512*7e4d5620SIcenowy Zheng 				continue;
513*7e4d5620SIcenowy Zheng 
514*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_target_offset_set(chip, addr, alen);
515*7e4d5620SIcenowy Zheng 			if (ret)
516*7e4d5620SIcenowy Zheng 				continue;
517*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_start_bit_set();
518*7e4d5620SIcenowy Zheng 			if (ret)
519*7e4d5620SIcenowy Zheng 				continue;
520*7e4d5620SIcenowy Zheng 		}
521*7e4d5620SIcenowy Zheng 
522*7e4d5620SIcenowy Zheng 		ret =  mentor_i2c_address_set(chip, I2C_CMD_READ);
523*7e4d5620SIcenowy Zheng 		if (ret)
524*7e4d5620SIcenowy Zheng 			continue;
525*7e4d5620SIcenowy Zheng 
526*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_data_receive(buffer, len);
527*7e4d5620SIcenowy Zheng 		if (ret)
528*7e4d5620SIcenowy Zheng 			continue;
529*7e4d5620SIcenowy Zheng 
530*7e4d5620SIcenowy Zheng 		ret =  mentor_i2c_stop_bit_set();
531*7e4d5620SIcenowy Zheng 	} while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
532*7e4d5620SIcenowy Zheng 
533*7e4d5620SIcenowy Zheng 	if (counter == I2C_MAX_RETRY_CNT) {
534*7e4d5620SIcenowy Zheng 		ERROR("I2C transactions failed, got EAGAIN %d times\n",
535*7e4d5620SIcenowy Zheng 		      I2C_MAX_RETRY_CNT);
536*7e4d5620SIcenowy Zheng 		ret = -EPERM;
537*7e4d5620SIcenowy Zheng 	}
538*7e4d5620SIcenowy Zheng 	mmio_write_32((uintptr_t)&base->control,
539*7e4d5620SIcenowy Zheng 		      mmio_read_32((uintptr_t)&base->control) |
540*7e4d5620SIcenowy Zheng 		      I2C_CONTROL_ACK);
541*7e4d5620SIcenowy Zheng 
542*7e4d5620SIcenowy Zheng 	udelay(1);
543*7e4d5620SIcenowy Zheng 	return ret;
544*7e4d5620SIcenowy Zheng }
545*7e4d5620SIcenowy Zheng 
546*7e4d5620SIcenowy Zheng /*
547*7e4d5620SIcenowy Zheng  * i2c_write: -  Write multiple bytes to an i2c device
548*7e4d5620SIcenowy Zheng  *
549*7e4d5620SIcenowy Zheng  * The higher level routines take into account that this function is only
550*7e4d5620SIcenowy Zheng  * called with len < page length of the device (see configuration file)
551*7e4d5620SIcenowy Zheng  *
552*7e4d5620SIcenowy Zheng  * @chip:	address of the chip which is to be written
553*7e4d5620SIcenowy Zheng  * @addr:	i2c data address within the chip
554*7e4d5620SIcenowy Zheng  * @alen:	length of the i2c data address (1..2 bytes)
555*7e4d5620SIcenowy Zheng  * @buffer:	where to find the data to be written
556*7e4d5620SIcenowy Zheng  * @len:	how much byte do we want to read
557*7e4d5620SIcenowy Zheng  * @return:	0 in case of success
558*7e4d5620SIcenowy Zheng  */
559*7e4d5620SIcenowy Zheng int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
560*7e4d5620SIcenowy Zheng {
561*7e4d5620SIcenowy Zheng 	int ret = 0;
562*7e4d5620SIcenowy Zheng 	uint32_t counter = 0;
563*7e4d5620SIcenowy Zheng 
564*7e4d5620SIcenowy Zheng 	do {
565*7e4d5620SIcenowy Zheng 		if (ret != -EAGAIN && ret) {
566*7e4d5620SIcenowy Zheng 			ERROR("i2c transaction failed\n");
567*7e4d5620SIcenowy Zheng 			mentor_i2c_stop_bit_set();
568*7e4d5620SIcenowy Zheng 			return ret;
569*7e4d5620SIcenowy Zheng 		}
570*7e4d5620SIcenowy Zheng 		/* wait for 1 us for the interrupt clear to take effect */
571*7e4d5620SIcenowy Zheng 		if (counter > 0)
572*7e4d5620SIcenowy Zheng 			udelay(1);
573*7e4d5620SIcenowy Zheng 		counter++;
574*7e4d5620SIcenowy Zheng 
575*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_start_bit_set();
576*7e4d5620SIcenowy Zheng 		if (ret) {
577*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_unstuck(ret);
578*7e4d5620SIcenowy Zheng 			continue;
579*7e4d5620SIcenowy Zheng 		}
580*7e4d5620SIcenowy Zheng 
581*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
582*7e4d5620SIcenowy Zheng 		if (ret)
583*7e4d5620SIcenowy Zheng 			continue;
584*7e4d5620SIcenowy Zheng 
585*7e4d5620SIcenowy Zheng 		/* if EEPROM device */
586*7e4d5620SIcenowy Zheng 		if (alen != 0) {
587*7e4d5620SIcenowy Zheng 			ret = mentor_i2c_target_offset_set(chip, addr, alen);
588*7e4d5620SIcenowy Zheng 			if (ret)
589*7e4d5620SIcenowy Zheng 				continue;
590*7e4d5620SIcenowy Zheng 		}
591*7e4d5620SIcenowy Zheng 
592*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_data_transmit(buffer, len);
593*7e4d5620SIcenowy Zheng 		if (ret)
594*7e4d5620SIcenowy Zheng 			continue;
595*7e4d5620SIcenowy Zheng 
596*7e4d5620SIcenowy Zheng 		ret = mentor_i2c_stop_bit_set();
597*7e4d5620SIcenowy Zheng 	} while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
598*7e4d5620SIcenowy Zheng 
599*7e4d5620SIcenowy Zheng 	if (counter == I2C_MAX_RETRY_CNT) {
600*7e4d5620SIcenowy Zheng 		ERROR("I2C transactions failed, got EAGAIN %d times\n",
601*7e4d5620SIcenowy Zheng 		      I2C_MAX_RETRY_CNT);
602*7e4d5620SIcenowy Zheng 		ret = -EPERM;
603*7e4d5620SIcenowy Zheng 	}
604*7e4d5620SIcenowy Zheng 
605*7e4d5620SIcenowy Zheng 	udelay(1);
606*7e4d5620SIcenowy Zheng 	return ret;
607*7e4d5620SIcenowy Zheng }
608