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