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