xref: /optee_os/core/drivers/ls_i2c.c (revision 819d014119042d2aa547508c8a565425d5c0dc47)
1*819d0141SSahil Malhotra // SPDX-License-Identifier: BSD-2-Clause
2*819d0141SSahil Malhotra /*
3*819d0141SSahil Malhotra  * Copyright 2021 NXP
4*819d0141SSahil Malhotra  *
5*819d0141SSahil Malhotra  * I2C driver for I2C Controller
6*819d0141SSahil Malhotra  *
7*819d0141SSahil Malhotra  */
8*819d0141SSahil Malhotra #include <assert.h>
9*819d0141SSahil Malhotra #include <drivers/ls_i2c.h>
10*819d0141SSahil Malhotra #include <io.h>
11*819d0141SSahil Malhotra #include <kernel/boot.h>
12*819d0141SSahil Malhotra #include <kernel/dt.h>
13*819d0141SSahil Malhotra #include <kernel/delay.h>
14*819d0141SSahil Malhotra #include <libfdt.h>
15*819d0141SSahil Malhotra #include <mm/core_memprot.h>
16*819d0141SSahil Malhotra #include <string.h>
17*819d0141SSahil Malhotra 
18*819d0141SSahil Malhotra static const char * const i2c_controller_map[] = {
19*819d0141SSahil Malhotra 	"/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000",
20*819d0141SSahil Malhotra 	"/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000",
21*819d0141SSahil Malhotra 	"/soc/i2c@2060000", "/soc/i2c@2070000"
22*819d0141SSahil Malhotra };
23*819d0141SSahil Malhotra 
24*819d0141SSahil Malhotra /*
25*819d0141SSahil Malhotra  * I2C divisor and ibfd register values when glitch filter is enabled
26*819d0141SSahil Malhotra  * In case of duplicate SCL divisor value, the ibfd value with high MUL value
27*819d0141SSahil Malhotra  * has been selected. A higher MUL value results in a lower sampling rate of
28*819d0141SSahil Malhotra  * the I2C signals. This gives the I2C module greater immunity against glitches
29*819d0141SSahil Malhotra  * in the I2C signals.
30*819d0141SSahil Malhotra  */
31*819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = {
32*819d0141SSahil Malhotra 	{ 34, 0x0 },	 { 36, 0x1 },	  { 38, 0x2 },	  { 40, 0x3 },
33*819d0141SSahil Malhotra 	{ 42, 0x4 },	 { 44, 0x8 },	  { 48, 0x9 },	  { 52, 0xA },
34*819d0141SSahil Malhotra 	{ 54, 0x7 },	 { 56, 0xB },	  { 60, 0xC },	  { 64, 0x10 },
35*819d0141SSahil Malhotra 	{ 68, 0x40 },	 { 72, 0x41 },	  { 76, 0x42 },	  { 80, 0x43 },
36*819d0141SSahil Malhotra 	{ 84, 0x44 },	 { 88, 0x48 },	  { 96, 0x49 },	  { 104, 0x4A },
37*819d0141SSahil Malhotra 	{ 108, 0x47 },	 { 112, 0x4B },	  { 120, 0x4C },  { 128, 0x50 },
38*819d0141SSahil Malhotra 	{ 136, 0x80 },	 { 144, 0x81 },	  { 152, 0x82 },  { 160, 0x83 },
39*819d0141SSahil Malhotra 	{ 168, 0x84 },	 { 176, 0x88 },	  { 192, 0x89 },  { 208, 0x8A },
40*819d0141SSahil Malhotra 	{ 216, 0x87 },	 { 224, 0x8B },	  { 240, 0x8C },  { 256, 0x90 },
41*819d0141SSahil Malhotra 	{ 288, 0x91 },	 { 320, 0x92 },	  { 336, 0x8F },  { 352, 0x93 },
42*819d0141SSahil Malhotra 	{ 384, 0x98 },	 { 416, 0x95 },	  { 448, 0x99 },  { 480, 0x96 },
43*819d0141SSahil Malhotra 	{ 512, 0x9A },	 { 576, 0x9B },	  { 640, 0xA0 },  { 704, 0x9D },
44*819d0141SSahil Malhotra 	{ 768, 0xA1 },	 { 832, 0x9E },	  { 896, 0xA2 },  { 960, 0x67 },
45*819d0141SSahil Malhotra 	{ 1024, 0xA3 },	 { 1152, 0xA4 },  { 1280, 0xA8 }, { 1536, 0xA9 },
46*819d0141SSahil Malhotra 	{ 1792, 0xAA },	 { 1920, 0xA7 },  { 2048, 0xAB }, { 2304, 0xAC },
47*819d0141SSahil Malhotra 	{ 2560, 0xB0 },	 { 3072, 0xB1 },  { 3584, 0xB2 }, { 3840, 0xAF },
48*819d0141SSahil Malhotra 	{ 4096, 0xB3 },	 { 4608, 0xB4 },  { 5120, 0xB8 }, { 6144, 0xB9 },
49*819d0141SSahil Malhotra 	{ 7168, 0xBA },	 { 7680, 0xB7 },  { 8192, 0xBB }, { 9216, 0xBC },
50*819d0141SSahil Malhotra 	{ 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF }
51*819d0141SSahil Malhotra };
52*819d0141SSahil Malhotra 
53*819d0141SSahil Malhotra /*
54*819d0141SSahil Malhotra  * I2C divisor and ibfd register values when glitch filter is disabled.
55*819d0141SSahil Malhotra  * In case of duplicate SCL divisor value, the ibfd value with high MUL value
56*819d0141SSahil Malhotra  * has been selected. A higher MUL value results in a lower sampling rate of
57*819d0141SSahil Malhotra  * the I2C signals. This gives the I2C module greater immunity against glitches
58*819d0141SSahil Malhotra  * in the I2C signals.
59*819d0141SSahil Malhotra  */
60*819d0141SSahil Malhotra static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = {
61*819d0141SSahil Malhotra 	{ 20, 0x0 },	 { 22, 0x1 },	  { 24, 0x2 },	  { 26, 0x3 },
62*819d0141SSahil Malhotra 	{ 28, 0x8 },	 { 30, 0x5 },	  { 32, 0x9 },	  { 34, 0x6 },
63*819d0141SSahil Malhotra 	{ 36, 0x0A },	 { 40, 0x40 },	  { 44, 0x41 },	  { 48, 0x42 },
64*819d0141SSahil Malhotra 	{ 52, 0x43 },	 { 56, 0x48 },	  { 60, 0x45 },	  { 64, 0x49 },
65*819d0141SSahil Malhotra 	{ 68, 0x46 },	 { 72, 0x4A },	  { 80, 0x80 },	  { 88, 0x81 },
66*819d0141SSahil Malhotra 	{ 96, 0x82 },	 { 104, 0x83 },	  { 112, 0x88 },  { 120, 0x85 },
67*819d0141SSahil Malhotra 	{ 128, 0x89 },	 { 136, 0x86 },	  { 144, 0x8A },  { 160, 0x8B },
68*819d0141SSahil Malhotra 	{ 176, 0x8C },	 { 192, 0x90 },	  { 208, 0x56 },  { 224, 0x91 },
69*819d0141SSahil Malhotra 	{ 240, 0x1F },	 { 256, 0x92 },	  { 272, 0x8F },  { 288, 0x93 },
70*819d0141SSahil Malhotra 	{ 320, 0x98 },	 { 352, 0x95 },	  { 384, 0x99 },  { 416, 0x96 },
71*819d0141SSahil Malhotra 	{ 448, 0x9A },	 { 480, 0x5F },	  { 512, 0x9B },  { 576, 0x9C },
72*819d0141SSahil Malhotra 	{ 640, 0xA0 },	 { 768, 0xA1 },	  { 896, 0xA2 },  { 960, 0x9F },
73*819d0141SSahil Malhotra 	{ 1024, 0xA3 },	 { 1152, 0xA4 },  { 1280, 0xA8 }, { 1536, 0xA9 },
74*819d0141SSahil Malhotra 	{ 1792, 0xAA },	 { 1920, 0xA7 },  { 2048, 0xAB }, { 2304, 0xAC },
75*819d0141SSahil Malhotra 	{ 2560, 0xAD },	 { 3072, 0xB1 },  { 3584, 0xB2 }, { 3840, 0xAF },
76*819d0141SSahil Malhotra 	{ 4096, 0xB3 },	 { 4608, 0xB4 },  { 5120, 0xB8 }, { 6144, 0xB9 },
77*819d0141SSahil Malhotra 	{ 7168, 0xBA },	 { 7680, 0xB7 },  { 8192, 0xBB }, { 9216, 0xBC },
78*819d0141SSahil Malhotra 	{ 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF }
79*819d0141SSahil Malhotra };
80*819d0141SSahil Malhotra 
81*819d0141SSahil Malhotra void i2c_reset(vaddr_t base)
82*819d0141SSahil Malhotra {
83*819d0141SSahil Malhotra 	struct i2c_regs *regs = (struct i2c_regs *)base;
84*819d0141SSahil Malhotra 
85*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
86*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF);
87*819d0141SSahil Malhotra 	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN);
88*819d0141SSahil Malhotra 	io_clrbits8((vaddr_t)&regs->ibic, I2C_IBIC_BIIE);
89*819d0141SSahil Malhotra }
90*819d0141SSahil Malhotra 
91*819d0141SSahil Malhotra /*
92*819d0141SSahil Malhotra  * Get I2c Bus Frequency Divider Register value based on clock_divisor
93*819d0141SSahil Malhotra  * and if the glitch is enabled or not in I2c controller.
94*819d0141SSahil Malhotra  * base			Base address of I2C controller
95*819d0141SSahil Malhotra  * clock_divisor	Clock Divisor
96*819d0141SSahil Malhotra  */
97*819d0141SSahil Malhotra static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor)
98*819d0141SSahil Malhotra {
99*819d0141SSahil Malhotra 	struct i2c_regs *regs = (struct i2c_regs *)base;
100*819d0141SSahil Malhotra 	const struct i2c_clock_divisor_pair *dpair = NULL;
101*819d0141SSahil Malhotra 	size_t dpair_sz = 0;
102*819d0141SSahil Malhotra 	unsigned int n = 0;
103*819d0141SSahil Malhotra 
104*819d0141SSahil Malhotra 	if (io_read8((vaddr_t)&regs->ibdbg) & I2C_IBDBG_GLFLT_EN) {
105*819d0141SSahil Malhotra 		dpair = clk_div_glitch_enabled;
106*819d0141SSahil Malhotra 		dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled);
107*819d0141SSahil Malhotra 	} else {
108*819d0141SSahil Malhotra 		dpair = clk_div_glitch_disabled;
109*819d0141SSahil Malhotra 		dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled);
110*819d0141SSahil Malhotra 	}
111*819d0141SSahil Malhotra 
112*819d0141SSahil Malhotra 	for (n = 0; n < dpair_sz - 1; n++)
113*819d0141SSahil Malhotra 		if (clock_divisor < dpair[n].divisor)
114*819d0141SSahil Malhotra 			break;
115*819d0141SSahil Malhotra 
116*819d0141SSahil Malhotra 	return dpair[n].ibfd;
117*819d0141SSahil Malhotra }
118*819d0141SSahil Malhotra 
119*819d0141SSahil Malhotra TEE_Result i2c_init(struct ls_i2c_data *i2c_data)
120*819d0141SSahil Malhotra {
121*819d0141SSahil Malhotra 	struct i2c_regs *regs = NULL;
122*819d0141SSahil Malhotra 	uint16_t clock_divisor = 0;
123*819d0141SSahil Malhotra 	uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */
124*819d0141SSahil Malhotra 	size_t size = 0;
125*819d0141SSahil Malhotra 	int node = 0;
126*819d0141SSahil Malhotra 	vaddr_t ctrl_base = 0;
127*819d0141SSahil Malhotra 	void *fdt = NULL;
128*819d0141SSahil Malhotra 
129*819d0141SSahil Malhotra 	/*
130*819d0141SSahil Malhotra 	 * First get the I2C Controller base address from the DTB
131*819d0141SSahil Malhotra 	 * if DTB present and if the I2C Controller defined in it.
132*819d0141SSahil Malhotra 	 */
133*819d0141SSahil Malhotra 	fdt = get_embedded_dt();
134*819d0141SSahil Malhotra 	if (!fdt) {
135*819d0141SSahil Malhotra 		EMSG("Unable to get the Embedded DTB, I2C init failed\n");
136*819d0141SSahil Malhotra 		return TEE_ERROR_GENERIC;
137*819d0141SSahil Malhotra 	}
138*819d0141SSahil Malhotra 
139*819d0141SSahil Malhotra 	node = fdt_path_offset(fdt,
140*819d0141SSahil Malhotra 			       i2c_controller_map[i2c_data->i2c_controller]);
141*819d0141SSahil Malhotra 	if (node > 0) {
142*819d0141SSahil Malhotra 		if (dt_map_dev(fdt, node, &ctrl_base, &size) < 0) {
143*819d0141SSahil Malhotra 			EMSG("Unable to get virtual address");
144*819d0141SSahil Malhotra 			return TEE_ERROR_GENERIC;
145*819d0141SSahil Malhotra 		}
146*819d0141SSahil Malhotra 	} else {
147*819d0141SSahil Malhotra 		EMSG("Unable to get I2C offset node");
148*819d0141SSahil Malhotra 		return TEE_ERROR_ITEM_NOT_FOUND;
149*819d0141SSahil Malhotra 	}
150*819d0141SSahil Malhotra 
151*819d0141SSahil Malhotra 	i2c_data->base = ctrl_base;
152*819d0141SSahil Malhotra 
153*819d0141SSahil Malhotra 	regs = (struct i2c_regs *)ctrl_base;
154*819d0141SSahil Malhotra 
155*819d0141SSahil Malhotra 	clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) /
156*819d0141SSahil Malhotra 			i2c_data->speed;
157*819d0141SSahil Malhotra 	ibfd = i2c_get_ibfd(ctrl_base, clock_divisor);
158*819d0141SSahil Malhotra 
159*819d0141SSahil Malhotra 	io_write8((vaddr_t)&regs->ibfd, ibfd);
160*819d0141SSahil Malhotra 
161*819d0141SSahil Malhotra 	i2c_reset(ctrl_base);
162*819d0141SSahil Malhotra 
163*819d0141SSahil Malhotra 	return TEE_SUCCESS;
164*819d0141SSahil Malhotra }
165*819d0141SSahil Malhotra 
166*819d0141SSahil Malhotra /*
167*819d0141SSahil Malhotra  * Check if I2C bus is busy with previous transaction or not.
168*819d0141SSahil Malhotra  * regs         pointer to I2c controller registers
169*819d0141SSahil Malhotra  * test_busy	this flag tells if we need to check the busy bit in IBSR reg
170*819d0141SSahil Malhotra  */
171*819d0141SSahil Malhotra static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy)
172*819d0141SSahil Malhotra {
173*819d0141SSahil Malhotra 	unsigned int n = 0;
174*819d0141SSahil Malhotra 	uint8_t reg = 0;
175*819d0141SSahil Malhotra 
176*819d0141SSahil Malhotra 	for (n = 0; n < I2C_NUM_RETRIES; n++) {
177*819d0141SSahil Malhotra 		reg = io_read8((vaddr_t)&regs->ibsr);
178*819d0141SSahil Malhotra 
179*819d0141SSahil Malhotra 		if (reg & I2C_IBSR_IBAL) {
180*819d0141SSahil Malhotra 			io_write8((vaddr_t)&regs->ibsr, reg);
181*819d0141SSahil Malhotra 			return TEE_ERROR_BUSY;
182*819d0141SSahil Malhotra 		}
183*819d0141SSahil Malhotra 
184*819d0141SSahil Malhotra 		if (test_busy && (reg & I2C_IBSR_IBB))
185*819d0141SSahil Malhotra 			break;
186*819d0141SSahil Malhotra 
187*819d0141SSahil Malhotra 		if (!test_busy && !(reg & I2C_IBSR_IBB))
188*819d0141SSahil Malhotra 			break;
189*819d0141SSahil Malhotra 
190*819d0141SSahil Malhotra 		mdelay(1);
191*819d0141SSahil Malhotra 	}
192*819d0141SSahil Malhotra 
193*819d0141SSahil Malhotra 	if (n == I2C_NUM_RETRIES)
194*819d0141SSahil Malhotra 		return TEE_ERROR_BUSY;
195*819d0141SSahil Malhotra 
196*819d0141SSahil Malhotra 	return TEE_SUCCESS;
197*819d0141SSahil Malhotra }
198*819d0141SSahil Malhotra 
199*819d0141SSahil Malhotra /*
200*819d0141SSahil Malhotra  * Check if data transfer to/from i2c controller is complete.
201*819d0141SSahil Malhotra  * regs		pointer to I2c controller registers
202*819d0141SSahil Malhotra  * test_rx_ack	this flag tells if we need to check RXAK bit in IBSR reg
203*819d0141SSahil Malhotra  */
204*819d0141SSahil Malhotra static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack)
205*819d0141SSahil Malhotra {
206*819d0141SSahil Malhotra 	unsigned int n = 0;
207*819d0141SSahil Malhotra 	uint8_t reg = 0;
208*819d0141SSahil Malhotra 
209*819d0141SSahil Malhotra 	for (n = 0; n < I2C_NUM_RETRIES; n++) {
210*819d0141SSahil Malhotra 		reg = io_read8((vaddr_t)&regs->ibsr);
211*819d0141SSahil Malhotra 
212*819d0141SSahil Malhotra 		if (reg & I2C_IBSR_IBIF) {
213*819d0141SSahil Malhotra 			/* Write 1 to clear the IBIF field */
214*819d0141SSahil Malhotra 			io_write8((vaddr_t)&regs->ibsr, reg);
215*819d0141SSahil Malhotra 			break;
216*819d0141SSahil Malhotra 		}
217*819d0141SSahil Malhotra 		mdelay(1);
218*819d0141SSahil Malhotra 	}
219*819d0141SSahil Malhotra 
220*819d0141SSahil Malhotra 	if (n == I2C_NUM_RETRIES)
221*819d0141SSahil Malhotra 		return TEE_ERROR_BUSY;
222*819d0141SSahil Malhotra 
223*819d0141SSahil Malhotra 	if (test_rx_ack && (reg & I2C_IBSR_RXAK))
224*819d0141SSahil Malhotra 		return TEE_ERROR_NO_DATA;
225*819d0141SSahil Malhotra 
226*819d0141SSahil Malhotra 	if (reg & I2C_IBSR_TCF)
227*819d0141SSahil Malhotra 		return TEE_SUCCESS;
228*819d0141SSahil Malhotra 
229*819d0141SSahil Malhotra 	return TEE_ERROR_GENERIC;
230*819d0141SSahil Malhotra }
231*819d0141SSahil Malhotra 
232*819d0141SSahil Malhotra /*
233*819d0141SSahil Malhotra  * Read data from I2c controller.
234*819d0141SSahil Malhotra  * regs			pointer to I2c controller registers
235*819d0141SSahil Malhotra  * slave_address	slave address from which to read
236*819d0141SSahil Malhotra  * operation		pointer to i2c_operation struct
237*819d0141SSahil Malhotra  * is_last_operation	if current operation is last operation
238*819d0141SSahil Malhotra  */
239*819d0141SSahil Malhotra static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address,
240*819d0141SSahil Malhotra 			   struct i2c_operation *operation,
241*819d0141SSahil Malhotra 			   bool is_last_operation)
242*819d0141SSahil Malhotra {
243*819d0141SSahil Malhotra 	TEE_Result res = TEE_ERROR_GENERIC;
244*819d0141SSahil Malhotra 	unsigned int n = 0;
245*819d0141SSahil Malhotra 
246*819d0141SSahil Malhotra 	/* Write Slave Address */
247*819d0141SSahil Malhotra 	io_write8((vaddr_t)&regs->ibdr, (slave_address << 0x1) | BIT(0));
248*819d0141SSahil Malhotra 	res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
249*819d0141SSahil Malhotra 	if (res)
250*819d0141SSahil Malhotra 		return res;
251*819d0141SSahil Malhotra 
252*819d0141SSahil Malhotra 	/* select Receive mode. */
253*819d0141SSahil Malhotra 	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_TXRX);
254*819d0141SSahil Malhotra 	if (operation->length_in_bytes > 1) {
255*819d0141SSahil Malhotra 		/* Set No ACK = 0 */
256*819d0141SSahil Malhotra 		io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_NOACK);
257*819d0141SSahil Malhotra 	}
258*819d0141SSahil Malhotra 
259*819d0141SSahil Malhotra 	/* Perform a dummy read to initiate the receive operation. */
260*819d0141SSahil Malhotra 	io_read8((vaddr_t)&regs->ibdr);
261*819d0141SSahil Malhotra 
262*819d0141SSahil Malhotra 	for (n = 0; n < operation->length_in_bytes; n++) {
263*819d0141SSahil Malhotra 		res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK);
264*819d0141SSahil Malhotra 		if (res)
265*819d0141SSahil Malhotra 			return res;
266*819d0141SSahil Malhotra 		if (n == (operation->length_in_bytes - 2)) {
267*819d0141SSahil Malhotra 			/* Set No ACK = 1 */
268*819d0141SSahil Malhotra 			io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_NOACK);
269*819d0141SSahil Malhotra 		} else if (n == (operation->length_in_bytes - 1)) {
270*819d0141SSahil Malhotra 			if (!is_last_operation) {
271*819d0141SSahil Malhotra 				/* select Transmit mode (for repeat start) */
272*819d0141SSahil Malhotra 				io_setbits8((vaddr_t)&regs->ibcr,
273*819d0141SSahil Malhotra 					    I2C_IBCR_TXRX);
274*819d0141SSahil Malhotra 			} else {
275*819d0141SSahil Malhotra 				/* Generate Stop Signal */
276*819d0141SSahil Malhotra 				io_clrbits8((vaddr_t)&regs->ibcr,
277*819d0141SSahil Malhotra 					    (I2C_IBCR_MSSL | I2C_IBCR_TXRX));
278*819d0141SSahil Malhotra 				res = i2c_bus_test_bus_busy(regs,
279*819d0141SSahil Malhotra 							    I2C_BUS_TEST_IDLE);
280*819d0141SSahil Malhotra 				if (res)
281*819d0141SSahil Malhotra 					return res;
282*819d0141SSahil Malhotra 			}
283*819d0141SSahil Malhotra 		}
284*819d0141SSahil Malhotra 		operation->buffer[n] = io_read8((vaddr_t)&regs->ibdr);
285*819d0141SSahil Malhotra 	}
286*819d0141SSahil Malhotra 
287*819d0141SSahil Malhotra 	return TEE_SUCCESS;
288*819d0141SSahil Malhotra }
289*819d0141SSahil Malhotra 
290*819d0141SSahil Malhotra /*
291*819d0141SSahil Malhotra  * Write data to I2c controller
292*819d0141SSahil Malhotra  * regs			pointer to I2c controller registers
293*819d0141SSahil Malhotra  * slave_address	slave address from which to read
294*819d0141SSahil Malhotra  * operation		pointer to i2c_operation struct
295*819d0141SSahil Malhotra  */
296*819d0141SSahil Malhotra static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address,
297*819d0141SSahil Malhotra 			    struct i2c_operation *operation)
298*819d0141SSahil Malhotra {
299*819d0141SSahil Malhotra 	TEE_Result res = TEE_ERROR_GENERIC;
300*819d0141SSahil Malhotra 	unsigned int n = 0;
301*819d0141SSahil Malhotra 
302*819d0141SSahil Malhotra 	/* Write Slave Address */
303*819d0141SSahil Malhotra 	io_write8((vaddr_t)&regs->ibdr,
304*819d0141SSahil Malhotra 		  (slave_address << 0x1) & ~(BIT(0)));
305*819d0141SSahil Malhotra 	res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
306*819d0141SSahil Malhotra 	if (res)
307*819d0141SSahil Malhotra 		return res;
308*819d0141SSahil Malhotra 
309*819d0141SSahil Malhotra 	/* Write Data */
310*819d0141SSahil Malhotra 	for (n = 0; n < operation->length_in_bytes; n++) {
311*819d0141SSahil Malhotra 		io_write8((vaddr_t)&regs->ibdr, operation->buffer[n]);
312*819d0141SSahil Malhotra 		res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK);
313*819d0141SSahil Malhotra 		if (res)
314*819d0141SSahil Malhotra 			return res;
315*819d0141SSahil Malhotra 	}
316*819d0141SSahil Malhotra 
317*819d0141SSahil Malhotra 	return TEE_SUCCESS;
318*819d0141SSahil Malhotra }
319*819d0141SSahil Malhotra 
320*819d0141SSahil Malhotra /*
321*819d0141SSahil Malhotra  * Generate Stop Signal and disable I2C controller.
322*819d0141SSahil Malhotra  * regs		pointer to I2c controller registers
323*819d0141SSahil Malhotra  */
324*819d0141SSahil Malhotra static TEE_Result i2c_stop(struct i2c_regs *regs)
325*819d0141SSahil Malhotra {
326*819d0141SSahil Malhotra 	TEE_Result res = TEE_SUCCESS;
327*819d0141SSahil Malhotra 	uint8_t reg = 0;
328*819d0141SSahil Malhotra 
329*819d0141SSahil Malhotra 	reg = io_read8((vaddr_t)&regs->ibsr);
330*819d0141SSahil Malhotra 	if (reg & I2C_IBSR_IBB) {
331*819d0141SSahil Malhotra 		/* Generate Stop Signal */
332*819d0141SSahil Malhotra 		io_clrbits8((vaddr_t)&regs->ibcr,
333*819d0141SSahil Malhotra 			    I2C_IBCR_MSSL | I2C_IBCR_TXRX);
334*819d0141SSahil Malhotra 		res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE);
335*819d0141SSahil Malhotra 		if (res)
336*819d0141SSahil Malhotra 			return res;
337*819d0141SSahil Malhotra 	}
338*819d0141SSahil Malhotra 
339*819d0141SSahil Malhotra 	/* Disable I2c Controller */
340*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
341*819d0141SSahil Malhotra 
342*819d0141SSahil Malhotra 	return TEE_SUCCESS;
343*819d0141SSahil Malhotra }
344*819d0141SSahil Malhotra 
345*819d0141SSahil Malhotra /*
346*819d0141SSahil Malhotra  * Generate Start Signal and set I2C controller in transmit mode.
347*819d0141SSahil Malhotra  * regs		pointer to I2c controller registers
348*819d0141SSahil Malhotra  */
349*819d0141SSahil Malhotra static TEE_Result i2c_start(struct i2c_regs *regs)
350*819d0141SSahil Malhotra {
351*819d0141SSahil Malhotra 	TEE_Result res = TEE_ERROR_GENERIC;
352*819d0141SSahil Malhotra 
353*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF);
354*819d0141SSahil Malhotra 	io_clrbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MDIS);
355*819d0141SSahil Malhotra 
356*819d0141SSahil Malhotra 	/* Wait controller to be stable */
357*819d0141SSahil Malhotra 	mdelay(1);
358*819d0141SSahil Malhotra 
359*819d0141SSahil Malhotra 	/* Generate Start Signal */
360*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_MSSL);
361*819d0141SSahil Malhotra 	res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY);
362*819d0141SSahil Malhotra 	if (res)
363*819d0141SSahil Malhotra 		return res;
364*819d0141SSahil Malhotra 
365*819d0141SSahil Malhotra 	/* Select Transmit Mode. set No ACK = 1 */
366*819d0141SSahil Malhotra 	io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK);
367*819d0141SSahil Malhotra 
368*819d0141SSahil Malhotra 	return TEE_SUCCESS;
369*819d0141SSahil Malhotra }
370*819d0141SSahil Malhotra 
371*819d0141SSahil Malhotra TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address,
372*819d0141SSahil Malhotra 			struct i2c_operation *i2c_operation,
373*819d0141SSahil Malhotra 			unsigned int operation_count)
374*819d0141SSahil Malhotra {
375*819d0141SSahil Malhotra 	unsigned int n = 0;
376*819d0141SSahil Malhotra 	struct i2c_regs *regs = (struct i2c_regs *)base;
377*819d0141SSahil Malhotra 	struct i2c_operation *operation = NULL;
378*819d0141SSahil Malhotra 	TEE_Result res = TEE_ERROR_GENERIC;
379*819d0141SSahil Malhotra 	bool is_last_operation = false;
380*819d0141SSahil Malhotra 
381*819d0141SSahil Malhotra 	res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE);
382*819d0141SSahil Malhotra 	if (res)
383*819d0141SSahil Malhotra 		goto out;
384*819d0141SSahil Malhotra 
385*819d0141SSahil Malhotra 	res = i2c_start(regs);
386*819d0141SSahil Malhotra 	if (res)
387*819d0141SSahil Malhotra 		goto out;
388*819d0141SSahil Malhotra 
389*819d0141SSahil Malhotra 	for (n = 0, operation = i2c_operation;
390*819d0141SSahil Malhotra 	     n < operation_count; n++, operation++) {
391*819d0141SSahil Malhotra 		if (n == (operation_count - 1))
392*819d0141SSahil Malhotra 			is_last_operation = true;
393*819d0141SSahil Malhotra 
394*819d0141SSahil Malhotra 		/* Send repeat start after first transmit/receive */
395*819d0141SSahil Malhotra 		if (n) {
396*819d0141SSahil Malhotra 			io_setbits8((vaddr_t)&regs->ibcr, I2C_IBCR_RSTA);
397*819d0141SSahil Malhotra 			res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY);
398*819d0141SSahil Malhotra 			if (res)
399*819d0141SSahil Malhotra 				goto out;
400*819d0141SSahil Malhotra 		}
401*819d0141SSahil Malhotra 
402*819d0141SSahil Malhotra 		/* Read/write data */
403*819d0141SSahil Malhotra 		if (operation->flags & I2C_FLAG_READ)
404*819d0141SSahil Malhotra 			res = i2c_read(regs, slave_address, operation,
405*819d0141SSahil Malhotra 				       is_last_operation);
406*819d0141SSahil Malhotra 		else
407*819d0141SSahil Malhotra 			res = i2c_write(regs, slave_address, operation);
408*819d0141SSahil Malhotra 		if (res)
409*819d0141SSahil Malhotra 			goto out;
410*819d0141SSahil Malhotra 	}
411*819d0141SSahil Malhotra 
412*819d0141SSahil Malhotra out:
413*819d0141SSahil Malhotra 	i2c_stop(regs);
414*819d0141SSahil Malhotra 
415*819d0141SSahil Malhotra 	return res;
416*819d0141SSahil Malhotra }
417