xref: /rk3399_ARM-atf/drivers/st/i2c/stm32_i2c.c (revision d82d4ff0666711067328d2d34e2bdc009e84969f)
1435832abSYann Gautier /*
2435832abSYann Gautier  * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
3435832abSYann Gautier  *
4435832abSYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
5435832abSYann Gautier  */
6435832abSYann Gautier 
7435832abSYann Gautier #include <errno.h>
8435832abSYann Gautier #include <stdbool.h>
9435832abSYann Gautier #include <stdlib.h>
10435832abSYann Gautier 
11*d82d4ff0SYann Gautier #include <libfdt.h>
12*d82d4ff0SYann Gautier 
13*d82d4ff0SYann Gautier #include <platform_def.h>
14*d82d4ff0SYann Gautier 
15*d82d4ff0SYann Gautier #include <common/debug.h>
16435832abSYann Gautier #include <drivers/delay_timer.h>
17*d82d4ff0SYann Gautier #include <drivers/st/stm32_gpio.h>
18435832abSYann Gautier #include <drivers/st/stm32_i2c.h>
19435832abSYann Gautier #include <lib/mmio.h>
20*d82d4ff0SYann Gautier #include <lib/utils.h>
21435832abSYann Gautier 
22435832abSYann Gautier /* STM32 I2C registers offsets */
23435832abSYann Gautier #define I2C_CR1			0x00U
24435832abSYann Gautier #define I2C_CR2			0x04U
25435832abSYann Gautier #define I2C_OAR1		0x08U
26435832abSYann Gautier #define I2C_OAR2		0x0CU
27435832abSYann Gautier #define I2C_TIMINGR		0x10U
28435832abSYann Gautier #define I2C_TIMEOUTR		0x14U
29435832abSYann Gautier #define I2C_ISR			0x18U
30435832abSYann Gautier #define I2C_ICR			0x1CU
31435832abSYann Gautier #define I2C_PECR		0x20U
32435832abSYann Gautier #define I2C_RXDR		0x24U
33435832abSYann Gautier #define I2C_TXDR		0x28U
34435832abSYann Gautier 
35*d82d4ff0SYann Gautier #define TIMINGR_CLEAR_MASK	0xF0FFFFFFU
36435832abSYann Gautier 
37435832abSYann Gautier #define MAX_NBYTE_SIZE		255U
38435832abSYann Gautier 
39*d82d4ff0SYann Gautier #define I2C_NSEC_PER_SEC	1000000000L
40435832abSYann Gautier 
41*d82d4ff0SYann Gautier /* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
42*d82d4ff0SYann Gautier #define I2C_TIMING			0x10D07DB5
43435832abSYann Gautier 
44*d82d4ff0SYann Gautier static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
45*d82d4ff0SYann Gautier {
46*d82d4ff0SYann Gautier 	hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
47*d82d4ff0SYann Gautier 	hi2c->i2c_mode = I2C_MODE_NONE;
48*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
49*d82d4ff0SYann Gautier }
50435832abSYann Gautier 
51*d82d4ff0SYann Gautier /*
52*d82d4ff0SYann Gautier  * @brief  Configure I2C Analog noise filter.
53*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
54*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C peripheral.
55*d82d4ff0SYann Gautier  * @param  analog_filter: New state of the Analog filter
56*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
57*d82d4ff0SYann Gautier  */
58*d82d4ff0SYann Gautier static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
59*d82d4ff0SYann Gautier 				    uint32_t analog_filter)
60*d82d4ff0SYann Gautier {
61*d82d4ff0SYann Gautier 	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
62*d82d4ff0SYann Gautier 		return -EBUSY;
63*d82d4ff0SYann Gautier 	}
64*d82d4ff0SYann Gautier 
65*d82d4ff0SYann Gautier 	hi2c->lock = 1;
66*d82d4ff0SYann Gautier 
67*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_BUSY;
68*d82d4ff0SYann Gautier 
69*d82d4ff0SYann Gautier 	/* Disable the selected I2C peripheral */
70*d82d4ff0SYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
71*d82d4ff0SYann Gautier 
72*d82d4ff0SYann Gautier 	/* Reset I2Cx ANOFF bit */
73*d82d4ff0SYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
74*d82d4ff0SYann Gautier 
75*d82d4ff0SYann Gautier 	/* Set analog filter bit*/
76*d82d4ff0SYann Gautier 	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
77*d82d4ff0SYann Gautier 
78*d82d4ff0SYann Gautier 	/* Enable the selected I2C peripheral */
79*d82d4ff0SYann Gautier 	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
80*d82d4ff0SYann Gautier 
81*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
82*d82d4ff0SYann Gautier 
83*d82d4ff0SYann Gautier 	hi2c->lock = 0;
84*d82d4ff0SYann Gautier 
85*d82d4ff0SYann Gautier 	return 0;
86*d82d4ff0SYann Gautier }
87*d82d4ff0SYann Gautier 
88*d82d4ff0SYann Gautier /*
89*d82d4ff0SYann Gautier  * @brief  Get I2C setup information from the device tree and set pinctrl
90*d82d4ff0SYann Gautier  *         configuration.
91*d82d4ff0SYann Gautier  * @param  fdt: Pointer to the device tree
92*d82d4ff0SYann Gautier  * @param  node: I2C node offset
93*d82d4ff0SYann Gautier  * @param  init: Ref to the initialization configuration structure
94*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
95*d82d4ff0SYann Gautier  */
96*d82d4ff0SYann Gautier int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
97*d82d4ff0SYann Gautier 				 struct stm32_i2c_init_s *init)
98*d82d4ff0SYann Gautier {
99*d82d4ff0SYann Gautier 	const fdt32_t *cuint;
100*d82d4ff0SYann Gautier 
101*d82d4ff0SYann Gautier 	cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
102*d82d4ff0SYann Gautier 	if (cuint == NULL) {
103*d82d4ff0SYann Gautier 		init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
104*d82d4ff0SYann Gautier 	} else {
105*d82d4ff0SYann Gautier 		init->rise_time = fdt32_to_cpu(*cuint);
106*d82d4ff0SYann Gautier 	}
107*d82d4ff0SYann Gautier 
108*d82d4ff0SYann Gautier 	cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
109*d82d4ff0SYann Gautier 	if (cuint == NULL) {
110*d82d4ff0SYann Gautier 		init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
111*d82d4ff0SYann Gautier 	} else {
112*d82d4ff0SYann Gautier 		init->fall_time = fdt32_to_cpu(*cuint);
113*d82d4ff0SYann Gautier 	}
114*d82d4ff0SYann Gautier 
115*d82d4ff0SYann Gautier 	cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
116*d82d4ff0SYann Gautier 	if (cuint == NULL) {
117*d82d4ff0SYann Gautier 		init->speed_mode = STM32_I2C_SPEED_DEFAULT;
118*d82d4ff0SYann Gautier 	} else {
119*d82d4ff0SYann Gautier 		switch (fdt32_to_cpu(*cuint)) {
120*d82d4ff0SYann Gautier 		case STANDARD_RATE:
121*d82d4ff0SYann Gautier 			init->speed_mode = I2C_SPEED_STANDARD;
122*d82d4ff0SYann Gautier 			break;
123*d82d4ff0SYann Gautier 		case FAST_RATE:
124*d82d4ff0SYann Gautier 			init->speed_mode = I2C_SPEED_FAST;
125*d82d4ff0SYann Gautier 			break;
126*d82d4ff0SYann Gautier 		case FAST_PLUS_RATE:
127*d82d4ff0SYann Gautier 			init->speed_mode = I2C_SPEED_FAST_PLUS;
128*d82d4ff0SYann Gautier 			break;
129*d82d4ff0SYann Gautier 		default:
130*d82d4ff0SYann Gautier 			init->speed_mode = STM32_I2C_SPEED_DEFAULT;
131*d82d4ff0SYann Gautier 			break;
132*d82d4ff0SYann Gautier 		}
133*d82d4ff0SYann Gautier 	}
134*d82d4ff0SYann Gautier 
135*d82d4ff0SYann Gautier 	return dt_set_pinctrl_config(node);
136*d82d4ff0SYann Gautier }
137435832abSYann Gautier 
138435832abSYann Gautier /*
139435832abSYann Gautier  * @brief  Initialize the I2C device.
140435832abSYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
141435832abSYann Gautier  *               the configuration information for the specified I2C.
142*d82d4ff0SYann Gautier  * @param  init_data: Initialization configuration structure
143435832abSYann Gautier  * @retval 0 if OK, negative value else
144435832abSYann Gautier  */
145*d82d4ff0SYann Gautier int stm32_i2c_init(struct i2c_handle_s *hi2c,
146*d82d4ff0SYann Gautier 		   struct stm32_i2c_init_s *init_data)
147435832abSYann Gautier {
148*d82d4ff0SYann Gautier 	int rc = 0;
149*d82d4ff0SYann Gautier 	uint32_t timing = I2C_TIMING;
150*d82d4ff0SYann Gautier 
151435832abSYann Gautier 	if (hi2c == NULL) {
152435832abSYann Gautier 		return -ENOENT;
153435832abSYann Gautier 	}
154435832abSYann Gautier 
155435832abSYann Gautier 	if (hi2c->i2c_state == I2C_STATE_RESET) {
156435832abSYann Gautier 		hi2c->lock = 0;
157435832abSYann Gautier 	}
158435832abSYann Gautier 
159435832abSYann Gautier 	hi2c->i2c_state = I2C_STATE_BUSY;
160435832abSYann Gautier 
161*d82d4ff0SYann Gautier 	stm32mp_clk_enable(hi2c->clock);
162*d82d4ff0SYann Gautier 
163435832abSYann Gautier 	/* Disable the selected I2C peripheral */
164435832abSYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
165435832abSYann Gautier 
166435832abSYann Gautier 	/* Configure I2Cx: Frequency range */
167435832abSYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
168*d82d4ff0SYann Gautier 		      timing & TIMINGR_CLEAR_MASK);
169435832abSYann Gautier 
170435832abSYann Gautier 	/* Disable Own Address1 before set the Own Address1 configuration */
171435832abSYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
172435832abSYann Gautier 
173435832abSYann Gautier 	/* Configure I2Cx: Own Address1 and ack own address1 mode */
174*d82d4ff0SYann Gautier 	if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
175435832abSYann Gautier 		mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
176*d82d4ff0SYann Gautier 			      I2C_OAR1_OA1EN | init_data->own_address1);
177435832abSYann Gautier 	} else { /* I2C_ADDRESSINGMODE_10BIT */
178435832abSYann Gautier 		mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
179435832abSYann Gautier 			      I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
180*d82d4ff0SYann Gautier 			      init_data->own_address1);
181435832abSYann Gautier 	}
182435832abSYann Gautier 
183*d82d4ff0SYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0);
184*d82d4ff0SYann Gautier 
185435832abSYann Gautier 	/* Configure I2Cx: Addressing Master mode */
186*d82d4ff0SYann Gautier 	if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
187*d82d4ff0SYann Gautier 		mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
188435832abSYann Gautier 	}
189435832abSYann Gautier 
190435832abSYann Gautier 	/*
191435832abSYann Gautier 	 * Enable the AUTOEND by default, and enable NACK
192*d82d4ff0SYann Gautier 	 * (should be disabled only during Slave process).
193435832abSYann Gautier 	 */
194435832abSYann Gautier 	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
195435832abSYann Gautier 			I2C_CR2_AUTOEND | I2C_CR2_NACK);
196435832abSYann Gautier 
197435832abSYann Gautier 	/* Disable Own Address2 before set the Own Address2 configuration */
198435832abSYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
199435832abSYann Gautier 
200435832abSYann Gautier 	/* Configure I2Cx: Dual mode and Own Address2 */
201435832abSYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
202*d82d4ff0SYann Gautier 		      init_data->dual_address_mode |
203*d82d4ff0SYann Gautier 		      init_data->own_address2 |
204*d82d4ff0SYann Gautier 		      (init_data->own_address2_masks << 8));
205435832abSYann Gautier 
206435832abSYann Gautier 	/* Configure I2Cx: Generalcall and NoStretch mode */
207435832abSYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
208*d82d4ff0SYann Gautier 		      init_data->general_call_mode |
209*d82d4ff0SYann Gautier 		      init_data->no_stretch_mode);
210435832abSYann Gautier 
211435832abSYann Gautier 	/* Enable the selected I2C peripheral */
212435832abSYann Gautier 	mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
213435832abSYann Gautier 
214435832abSYann Gautier 	hi2c->i2c_err = I2C_ERROR_NONE;
215435832abSYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
216435832abSYann Gautier 	hi2c->i2c_mode = I2C_MODE_NONE;
217435832abSYann Gautier 
218*d82d4ff0SYann Gautier 	rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ?
219*d82d4ff0SYann Gautier 						I2C_ANALOGFILTER_ENABLE :
220*d82d4ff0SYann Gautier 						I2C_ANALOGFILTER_DISABLE);
221*d82d4ff0SYann Gautier 	if (rc != 0) {
222*d82d4ff0SYann Gautier 		ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
223*d82d4ff0SYann Gautier 		stm32mp_clk_disable(hi2c->clock);
224*d82d4ff0SYann Gautier 		return rc;
225435832abSYann Gautier 	}
226435832abSYann Gautier 
227*d82d4ff0SYann Gautier 	stm32mp_clk_disable(hi2c->clock);
228435832abSYann Gautier 
229*d82d4ff0SYann Gautier 	return rc;
230435832abSYann Gautier }
231435832abSYann Gautier 
232435832abSYann Gautier /*
233435832abSYann Gautier  * @brief  I2C Tx data register flush process.
234*d82d4ff0SYann Gautier  * @param  hi2c: I2C handle
235435832abSYann Gautier  * @retval None
236435832abSYann Gautier  */
237435832abSYann Gautier static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
238435832abSYann Gautier {
239435832abSYann Gautier 	/*
240435832abSYann Gautier 	 * If a pending TXIS flag is set,
241435832abSYann Gautier 	 * write a dummy data in TXDR to clear it.
242435832abSYann Gautier 	 */
243435832abSYann Gautier 	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
244435832abSYann Gautier 	    0U) {
245435832abSYann Gautier 		mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
246435832abSYann Gautier 	}
247435832abSYann Gautier 
248435832abSYann Gautier 	/* Flush TX register if not empty */
249435832abSYann Gautier 	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
250435832abSYann Gautier 	    0U) {
251435832abSYann Gautier 		mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
252435832abSYann Gautier 				I2C_FLAG_TXE);
253435832abSYann Gautier 	}
254435832abSYann Gautier }
255435832abSYann Gautier 
256435832abSYann Gautier /*
257435832abSYann Gautier  * @brief  This function handles I2C Communication timeout.
258435832abSYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
259435832abSYann Gautier  *               the configuration information for the specified I2C.
260*d82d4ff0SYann Gautier  * @param  flag: Specifies the I2C flag to check
261*d82d4ff0SYann Gautier  * @param  awaited_value: The awaited bit value for the flag (0 or 1)
262*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
263435832abSYann Gautier  * @retval 0 if OK, negative value else
264435832abSYann Gautier  */
265435832abSYann Gautier static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
266*d82d4ff0SYann Gautier 			 uint8_t awaited_value, uint64_t timeout_ref)
267435832abSYann Gautier {
268*d82d4ff0SYann Gautier 	for ( ; ; ) {
269*d82d4ff0SYann Gautier 		uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR);
270435832abSYann Gautier 
271*d82d4ff0SYann Gautier 		if (!!(isr & flag) != !!awaited_value) {
272435832abSYann Gautier 			return 0;
273435832abSYann Gautier 		}
274435832abSYann Gautier 
275*d82d4ff0SYann Gautier 		if (timeout_elapsed(timeout_ref)) {
276*d82d4ff0SYann Gautier 			notif_i2c_timeout(hi2c);
277435832abSYann Gautier 			hi2c->lock = 0;
278435832abSYann Gautier 
279435832abSYann Gautier 			return -EIO;
280435832abSYann Gautier 		}
281435832abSYann Gautier 	}
282435832abSYann Gautier }
283435832abSYann Gautier 
284435832abSYann Gautier /*
285435832abSYann Gautier  * @brief  This function handles Acknowledge failed detection during
286435832abSYann Gautier  *	   an I2C Communication.
287435832abSYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
288435832abSYann Gautier  *               the configuration information for the specified I2C.
289*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
290435832abSYann Gautier  * @retval 0 if OK, negative value else
291435832abSYann Gautier  */
292*d82d4ff0SYann Gautier static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
293435832abSYann Gautier {
294435832abSYann Gautier 	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
295435832abSYann Gautier 		return 0;
296435832abSYann Gautier 	}
297435832abSYann Gautier 
298435832abSYann Gautier 	/*
299435832abSYann Gautier 	 * Wait until STOP Flag is reset.
300435832abSYann Gautier 	 * AutoEnd should be initiate after AF.
301435832abSYann Gautier 	 */
302435832abSYann Gautier 	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
303435832abSYann Gautier 		I2C_FLAG_STOPF) == 0U) {
304*d82d4ff0SYann Gautier 		if (timeout_elapsed(timeout_ref)) {
305*d82d4ff0SYann Gautier 			notif_i2c_timeout(hi2c);
306435832abSYann Gautier 			hi2c->lock = 0;
307435832abSYann Gautier 
308435832abSYann Gautier 			return -EIO;
309435832abSYann Gautier 		}
310435832abSYann Gautier 	}
311435832abSYann Gautier 
312435832abSYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
313435832abSYann Gautier 
314435832abSYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
315435832abSYann Gautier 
316435832abSYann Gautier 	i2c_flush_txdr(hi2c);
317435832abSYann Gautier 
318435832abSYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
319435832abSYann Gautier 
320435832abSYann Gautier 	hi2c->i2c_err |= I2C_ERROR_AF;
321435832abSYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
322435832abSYann Gautier 	hi2c->i2c_mode = I2C_MODE_NONE;
323435832abSYann Gautier 
324435832abSYann Gautier 	hi2c->lock = 0;
325435832abSYann Gautier 
326435832abSYann Gautier 	return -EIO;
327435832abSYann Gautier }
328435832abSYann Gautier 
329435832abSYann Gautier /*
330*d82d4ff0SYann Gautier  * @brief  This function handles I2C Communication timeout for specific usage
331*d82d4ff0SYann Gautier  *	   of TXIS flag.
332*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
333*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
334*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
335*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
336*d82d4ff0SYann Gautier  */
337*d82d4ff0SYann Gautier static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
338*d82d4ff0SYann Gautier {
339*d82d4ff0SYann Gautier 	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
340*d82d4ff0SYann Gautier 		I2C_FLAG_TXIS) == 0U) {
341*d82d4ff0SYann Gautier 		if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
342*d82d4ff0SYann Gautier 			return -EIO;
343*d82d4ff0SYann Gautier 		}
344*d82d4ff0SYann Gautier 
345*d82d4ff0SYann Gautier 		if (timeout_elapsed(timeout_ref)) {
346*d82d4ff0SYann Gautier 			notif_i2c_timeout(hi2c);
347*d82d4ff0SYann Gautier 			hi2c->lock = 0;
348*d82d4ff0SYann Gautier 
349*d82d4ff0SYann Gautier 			return -EIO;
350*d82d4ff0SYann Gautier 		}
351*d82d4ff0SYann Gautier 	}
352*d82d4ff0SYann Gautier 
353*d82d4ff0SYann Gautier 	return 0;
354*d82d4ff0SYann Gautier }
355*d82d4ff0SYann Gautier 
356*d82d4ff0SYann Gautier /*
357*d82d4ff0SYann Gautier  * @brief  This function handles I2C Communication timeout for specific
358*d82d4ff0SYann Gautier  *	   usage of STOP flag.
359*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
360*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
361*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
362*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
363*d82d4ff0SYann Gautier  */
364*d82d4ff0SYann Gautier static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
365*d82d4ff0SYann Gautier {
366*d82d4ff0SYann Gautier 	while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
367*d82d4ff0SYann Gautier 		 I2C_FLAG_STOPF) == 0U) {
368*d82d4ff0SYann Gautier 		if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
369*d82d4ff0SYann Gautier 			return -EIO;
370*d82d4ff0SYann Gautier 		}
371*d82d4ff0SYann Gautier 
372*d82d4ff0SYann Gautier 		if (timeout_elapsed(timeout_ref)) {
373*d82d4ff0SYann Gautier 			notif_i2c_timeout(hi2c);
374*d82d4ff0SYann Gautier 			hi2c->lock = 0;
375*d82d4ff0SYann Gautier 
376*d82d4ff0SYann Gautier 			return -EIO;
377*d82d4ff0SYann Gautier 		}
378*d82d4ff0SYann Gautier 	}
379*d82d4ff0SYann Gautier 
380*d82d4ff0SYann Gautier 	return 0;
381*d82d4ff0SYann Gautier }
382*d82d4ff0SYann Gautier 
383*d82d4ff0SYann Gautier /*
384435832abSYann Gautier  * @brief  Handles I2Cx communication when starting transfer or during transfer
385435832abSYann Gautier  *	   (TC or TCR flag are set).
386*d82d4ff0SYann Gautier  * @param  hi2c: I2C handle
387*d82d4ff0SYann Gautier  * @param  dev_addr: Specifies the slave address to be programmed
388435832abSYann Gautier  * @param  size: Specifies the number of bytes to be programmed.
389435832abSYann Gautier  *   This parameter must be a value between 0 and 255.
390435832abSYann Gautier  * @param  i2c_mode: New state of the I2C START condition generation.
391435832abSYann Gautier  *   This parameter can be one of the following values:
392435832abSYann Gautier  *     @arg @ref I2C_RELOAD_MODE: Enable Reload mode.
393435832abSYann Gautier  *     @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
394435832abSYann Gautier  *     @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
395435832abSYann Gautier  * @param  request: New state of the I2C START condition generation.
396435832abSYann Gautier  *   This parameter can be one of the following values:
397435832abSYann Gautier  *     @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
398435832abSYann Gautier  *     @arg @ref I2C_GENERATE_STOP: Generate stop condition
399435832abSYann Gautier  *                                  (size should be set to 0).
400435832abSYann Gautier  *     @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
401435832abSYann Gautier  *     @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
402435832abSYann Gautier  * @retval None
403435832abSYann Gautier  */
404435832abSYann Gautier static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
405435832abSYann Gautier 				uint16_t size, uint32_t i2c_mode,
406435832abSYann Gautier 				uint32_t request)
407435832abSYann Gautier {
408435832abSYann Gautier 	uint32_t clr_value, set_value;
409435832abSYann Gautier 
410435832abSYann Gautier 	clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
411435832abSYann Gautier 		     I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
412435832abSYann Gautier 		(I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
413435832abSYann Gautier 
414435832abSYann Gautier 	set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
415435832abSYann Gautier 		(((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
416435832abSYann Gautier 		i2c_mode | request;
417435832abSYann Gautier 
418435832abSYann Gautier 	mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
419435832abSYann Gautier }
420435832abSYann Gautier 
421435832abSYann Gautier /*
422*d82d4ff0SYann Gautier  * @brief  Master sends target device address followed by internal memory
423*d82d4ff0SYann Gautier  *	   address for write request.
424435832abSYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
425*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
426*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
427*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address
428*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address
429*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
430435832abSYann Gautier  * @retval 0 if OK, negative value else
431435832abSYann Gautier  */
432*d82d4ff0SYann Gautier static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
433*d82d4ff0SYann Gautier 				    uint16_t dev_addr, uint16_t mem_addr,
434*d82d4ff0SYann Gautier 				    uint16_t mem_add_size, uint64_t timeout_ref)
435435832abSYann Gautier {
436*d82d4ff0SYann Gautier 	i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
437*d82d4ff0SYann Gautier 			    I2C_GENERATE_START_WRITE);
438*d82d4ff0SYann Gautier 
439*d82d4ff0SYann Gautier 	if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
440*d82d4ff0SYann Gautier 		return -EIO;
441*d82d4ff0SYann Gautier 	}
442*d82d4ff0SYann Gautier 
443*d82d4ff0SYann Gautier 	if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
444*d82d4ff0SYann Gautier 		/* Send Memory Address */
445*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
446*d82d4ff0SYann Gautier 			     (uint8_t)(mem_addr & 0x00FFU));
447*d82d4ff0SYann Gautier 	} else {
448*d82d4ff0SYann Gautier 		/* Send MSB of Memory Address */
449*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
450*d82d4ff0SYann Gautier 			     (uint8_t)((mem_addr & 0xFF00U) >> 8));
451*d82d4ff0SYann Gautier 
452*d82d4ff0SYann Gautier 		if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
453*d82d4ff0SYann Gautier 			return -EIO;
454*d82d4ff0SYann Gautier 		}
455*d82d4ff0SYann Gautier 
456*d82d4ff0SYann Gautier 		/* Send LSB of Memory Address */
457*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
458*d82d4ff0SYann Gautier 			     (uint8_t)(mem_addr & 0x00FFU));
459*d82d4ff0SYann Gautier 	}
460*d82d4ff0SYann Gautier 
461*d82d4ff0SYann Gautier 	if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) {
462*d82d4ff0SYann Gautier 		return -EIO;
463*d82d4ff0SYann Gautier 	}
464*d82d4ff0SYann Gautier 
465*d82d4ff0SYann Gautier 	return 0;
466*d82d4ff0SYann Gautier }
467*d82d4ff0SYann Gautier 
468*d82d4ff0SYann Gautier /*
469*d82d4ff0SYann Gautier  * @brief  Master sends target device address followed by internal memory
470*d82d4ff0SYann Gautier  *	   address for read request.
471*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
472*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
473*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
474*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address
475*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address
476*d82d4ff0SYann Gautier  * @param  timeout_ref: Reference to target timeout
477*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
478*d82d4ff0SYann Gautier  */
479*d82d4ff0SYann Gautier static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
480*d82d4ff0SYann Gautier 				   uint16_t mem_addr, uint16_t mem_add_size,
481*d82d4ff0SYann Gautier 				   uint64_t timeout_ref)
482*d82d4ff0SYann Gautier {
483*d82d4ff0SYann Gautier 	i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
484*d82d4ff0SYann Gautier 			    I2C_GENERATE_START_WRITE);
485*d82d4ff0SYann Gautier 
486*d82d4ff0SYann Gautier 	if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
487*d82d4ff0SYann Gautier 		return -EIO;
488*d82d4ff0SYann Gautier 	}
489*d82d4ff0SYann Gautier 
490*d82d4ff0SYann Gautier 	if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
491*d82d4ff0SYann Gautier 		/* Send Memory Address */
492*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
493*d82d4ff0SYann Gautier 			     (uint8_t)(mem_addr & 0x00FFU));
494*d82d4ff0SYann Gautier 	} else {
495*d82d4ff0SYann Gautier 		/* Send MSB of Memory Address */
496*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
497*d82d4ff0SYann Gautier 			     (uint8_t)((mem_addr & 0xFF00U) >> 8));
498*d82d4ff0SYann Gautier 
499*d82d4ff0SYann Gautier 		if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
500*d82d4ff0SYann Gautier 			return -EIO;
501*d82d4ff0SYann Gautier 		}
502*d82d4ff0SYann Gautier 
503*d82d4ff0SYann Gautier 		/* Send LSB of Memory Address */
504*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
505*d82d4ff0SYann Gautier 			     (uint8_t)(mem_addr & 0x00FFU));
506*d82d4ff0SYann Gautier 	}
507*d82d4ff0SYann Gautier 
508*d82d4ff0SYann Gautier 	if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) {
509*d82d4ff0SYann Gautier 		return -EIO;
510*d82d4ff0SYann Gautier 	}
511*d82d4ff0SYann Gautier 
512*d82d4ff0SYann Gautier 	return 0;
513*d82d4ff0SYann Gautier }
514*d82d4ff0SYann Gautier /*
515*d82d4ff0SYann Gautier  * @brief  Generic function to write an amount of data in blocking mode
516*d82d4ff0SYann Gautier  *         (for Memory Mode and Master Mode)
517*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
518*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
519*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
520*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address (if Memory Mode)
521*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address (if Memory Mode)
522*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
523*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
524*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
525*d82d4ff0SYann Gautier  * @param  mode: Communication mode
526*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
527*d82d4ff0SYann Gautier  */
528*d82d4ff0SYann Gautier static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
529*d82d4ff0SYann Gautier 		     uint16_t mem_addr, uint16_t mem_add_size,
530*d82d4ff0SYann Gautier 		     uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
531*d82d4ff0SYann Gautier 		     enum i2c_mode_e mode)
532*d82d4ff0SYann Gautier {
533*d82d4ff0SYann Gautier 	uint64_t timeout_ref;
534*d82d4ff0SYann Gautier 	int rc = -EIO;
535*d82d4ff0SYann Gautier 	uint8_t *p_buff = p_data;
536*d82d4ff0SYann Gautier 	uint32_t xfer_size;
537*d82d4ff0SYann Gautier 	uint32_t xfer_count = size;
538*d82d4ff0SYann Gautier 
539*d82d4ff0SYann Gautier 	if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
540*d82d4ff0SYann Gautier 		return -1;
541*d82d4ff0SYann Gautier 	}
542*d82d4ff0SYann Gautier 
543435832abSYann Gautier 	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
544435832abSYann Gautier 		return -EBUSY;
545435832abSYann Gautier 	}
546435832abSYann Gautier 
547*d82d4ff0SYann Gautier 	if ((p_data == NULL) || (size == 0U)) {
548*d82d4ff0SYann Gautier 		return -EINVAL;
549*d82d4ff0SYann Gautier 	}
550*d82d4ff0SYann Gautier 
551*d82d4ff0SYann Gautier 	stm32mp_clk_enable(hi2c->clock);
552*d82d4ff0SYann Gautier 
553435832abSYann Gautier 	hi2c->lock = 1;
554435832abSYann Gautier 
555*d82d4ff0SYann Gautier 	timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
556*d82d4ff0SYann Gautier 	if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
557*d82d4ff0SYann Gautier 		goto bail;
558*d82d4ff0SYann Gautier 	}
559*d82d4ff0SYann Gautier 
560*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_BUSY_TX;
561*d82d4ff0SYann Gautier 	hi2c->i2c_mode = mode;
562*d82d4ff0SYann Gautier 	hi2c->i2c_err = I2C_ERROR_NONE;
563*d82d4ff0SYann Gautier 
564*d82d4ff0SYann Gautier 	timeout_ref = timeout_init_us(timeout_ms * 1000);
565*d82d4ff0SYann Gautier 
566*d82d4ff0SYann Gautier 	if (mode == I2C_MODE_MEM) {
567*d82d4ff0SYann Gautier 		/* In Memory Mode, Send Slave Address and Memory Address */
568*d82d4ff0SYann Gautier 		if (i2c_request_memory_write(hi2c, dev_addr, mem_addr,
569*d82d4ff0SYann Gautier 					     mem_add_size, timeout_ref) != 0) {
570*d82d4ff0SYann Gautier 			goto bail;
571*d82d4ff0SYann Gautier 		}
572*d82d4ff0SYann Gautier 
573*d82d4ff0SYann Gautier 		if (xfer_count > MAX_NBYTE_SIZE) {
574*d82d4ff0SYann Gautier 			xfer_size = MAX_NBYTE_SIZE;
575*d82d4ff0SYann Gautier 			i2c_transfer_config(hi2c, dev_addr, xfer_size,
576*d82d4ff0SYann Gautier 					    I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
577*d82d4ff0SYann Gautier 		} else {
578*d82d4ff0SYann Gautier 			xfer_size = xfer_count;
579*d82d4ff0SYann Gautier 			i2c_transfer_config(hi2c, dev_addr, xfer_size,
580*d82d4ff0SYann Gautier 					    I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
581*d82d4ff0SYann Gautier 		}
582*d82d4ff0SYann Gautier 	} else {
583*d82d4ff0SYann Gautier 		/* In Master Mode, Send Slave Address */
584*d82d4ff0SYann Gautier 		if (xfer_count > MAX_NBYTE_SIZE) {
585*d82d4ff0SYann Gautier 			xfer_size = MAX_NBYTE_SIZE;
586*d82d4ff0SYann Gautier 			i2c_transfer_config(hi2c, dev_addr, xfer_size,
587*d82d4ff0SYann Gautier 					    I2C_RELOAD_MODE,
588*d82d4ff0SYann Gautier 					    I2C_GENERATE_START_WRITE);
589*d82d4ff0SYann Gautier 		} else {
590*d82d4ff0SYann Gautier 			xfer_size = xfer_count;
591*d82d4ff0SYann Gautier 			i2c_transfer_config(hi2c, dev_addr, xfer_size,
592*d82d4ff0SYann Gautier 					    I2C_AUTOEND_MODE,
593*d82d4ff0SYann Gautier 					    I2C_GENERATE_START_WRITE);
594*d82d4ff0SYann Gautier 		}
595*d82d4ff0SYann Gautier 	}
596*d82d4ff0SYann Gautier 
597*d82d4ff0SYann Gautier 	do {
598*d82d4ff0SYann Gautier 		if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
599*d82d4ff0SYann Gautier 			goto bail;
600*d82d4ff0SYann Gautier 		}
601*d82d4ff0SYann Gautier 
602*d82d4ff0SYann Gautier 		mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff);
603*d82d4ff0SYann Gautier 		p_buff++;
604*d82d4ff0SYann Gautier 		xfer_count--;
605*d82d4ff0SYann Gautier 		xfer_size--;
606*d82d4ff0SYann Gautier 
607*d82d4ff0SYann Gautier 		if ((xfer_count != 0U) && (xfer_size == 0U)) {
608*d82d4ff0SYann Gautier 			/* Wait until TCR flag is set */
609*d82d4ff0SYann Gautier 			if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
610*d82d4ff0SYann Gautier 					  timeout_ref) != 0) {
611*d82d4ff0SYann Gautier 				goto bail;
612*d82d4ff0SYann Gautier 			}
613*d82d4ff0SYann Gautier 
614*d82d4ff0SYann Gautier 			if (xfer_count > MAX_NBYTE_SIZE) {
615*d82d4ff0SYann Gautier 				xfer_size = MAX_NBYTE_SIZE;
616*d82d4ff0SYann Gautier 				i2c_transfer_config(hi2c, dev_addr,
617*d82d4ff0SYann Gautier 						    xfer_size,
618*d82d4ff0SYann Gautier 						    I2C_RELOAD_MODE,
619*d82d4ff0SYann Gautier 						    I2C_NO_STARTSTOP);
620*d82d4ff0SYann Gautier 			} else {
621*d82d4ff0SYann Gautier 				xfer_size = xfer_count;
622*d82d4ff0SYann Gautier 				i2c_transfer_config(hi2c, dev_addr,
623*d82d4ff0SYann Gautier 						    xfer_size,
624*d82d4ff0SYann Gautier 						    I2C_AUTOEND_MODE,
625*d82d4ff0SYann Gautier 						    I2C_NO_STARTSTOP);
626*d82d4ff0SYann Gautier 			}
627*d82d4ff0SYann Gautier 		}
628*d82d4ff0SYann Gautier 
629*d82d4ff0SYann Gautier 	} while (xfer_count > 0U);
630*d82d4ff0SYann Gautier 
631*d82d4ff0SYann Gautier 	/*
632*d82d4ff0SYann Gautier 	 * No need to Check TC flag, with AUTOEND mode the stop
633*d82d4ff0SYann Gautier 	 * is automatically generated.
634*d82d4ff0SYann Gautier 	 * Wait until STOPF flag is reset.
635*d82d4ff0SYann Gautier 	 */
636*d82d4ff0SYann Gautier 	if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
637*d82d4ff0SYann Gautier 		goto bail;
638*d82d4ff0SYann Gautier 	}
639*d82d4ff0SYann Gautier 
640*d82d4ff0SYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
641*d82d4ff0SYann Gautier 
642*d82d4ff0SYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
643*d82d4ff0SYann Gautier 
644*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
645*d82d4ff0SYann Gautier 	hi2c->i2c_mode  = I2C_MODE_NONE;
646*d82d4ff0SYann Gautier 
647*d82d4ff0SYann Gautier 	rc = 0;
648*d82d4ff0SYann Gautier 
649*d82d4ff0SYann Gautier bail:
650*d82d4ff0SYann Gautier 	hi2c->lock = 0;
651*d82d4ff0SYann Gautier 	stm32mp_clk_disable(hi2c->clock);
652*d82d4ff0SYann Gautier 
653*d82d4ff0SYann Gautier 	return rc;
654*d82d4ff0SYann Gautier }
655*d82d4ff0SYann Gautier 
656*d82d4ff0SYann Gautier /*
657*d82d4ff0SYann Gautier  * @brief  Write an amount of data in blocking mode to a specific memory
658*d82d4ff0SYann Gautier  *         address.
659*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
660*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
661*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
662*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address
663*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address
664*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
665*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
666*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
667*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
668*d82d4ff0SYann Gautier  */
669*d82d4ff0SYann Gautier int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
670*d82d4ff0SYann Gautier 			uint16_t mem_addr, uint16_t mem_add_size,
671*d82d4ff0SYann Gautier 			uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
672*d82d4ff0SYann Gautier {
673*d82d4ff0SYann Gautier 	return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size,
674*d82d4ff0SYann Gautier 			 p_data, size, timeout_ms, I2C_MODE_MEM);
675*d82d4ff0SYann Gautier }
676*d82d4ff0SYann Gautier 
677*d82d4ff0SYann Gautier /*
678*d82d4ff0SYann Gautier  * @brief  Transmits in master mode an amount of data in blocking mode.
679*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
680*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
681*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
682*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
683*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
684*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
685*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
686*d82d4ff0SYann Gautier  */
687*d82d4ff0SYann Gautier int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
688*d82d4ff0SYann Gautier 			      uint8_t *p_data, uint16_t size,
689*d82d4ff0SYann Gautier 			      uint32_t timeout_ms)
690*d82d4ff0SYann Gautier {
691*d82d4ff0SYann Gautier 	return i2c_write(hi2c, dev_addr, 0, 0,
692*d82d4ff0SYann Gautier 			 p_data, size, timeout_ms, I2C_MODE_MASTER);
693*d82d4ff0SYann Gautier }
694*d82d4ff0SYann Gautier 
695*d82d4ff0SYann Gautier /*
696*d82d4ff0SYann Gautier  * @brief  Generic function to read an amount of data in blocking mode
697*d82d4ff0SYann Gautier  *         (for Memory Mode and Master Mode)
698*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
699*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
700*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
701*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address (if Memory Mode)
702*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address (if Memory Mode)
703*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
704*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
705*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
706*d82d4ff0SYann Gautier  * @param  mode: Communication mode
707*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
708*d82d4ff0SYann Gautier  */
709*d82d4ff0SYann Gautier static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
710*d82d4ff0SYann Gautier 		    uint16_t mem_addr, uint16_t mem_add_size,
711*d82d4ff0SYann Gautier 		    uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
712*d82d4ff0SYann Gautier 		    enum i2c_mode_e mode)
713*d82d4ff0SYann Gautier {
714*d82d4ff0SYann Gautier 	uint64_t timeout_ref;
715*d82d4ff0SYann Gautier 	int rc = -EIO;
716*d82d4ff0SYann Gautier 	uint8_t *p_buff = p_data;
717*d82d4ff0SYann Gautier 	uint32_t xfer_count = size;
718*d82d4ff0SYann Gautier 	uint32_t xfer_size;
719*d82d4ff0SYann Gautier 
720*d82d4ff0SYann Gautier 	if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
721*d82d4ff0SYann Gautier 		return -1;
722*d82d4ff0SYann Gautier 	}
723*d82d4ff0SYann Gautier 
724*d82d4ff0SYann Gautier 	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
725*d82d4ff0SYann Gautier 		return -EBUSY;
726*d82d4ff0SYann Gautier 	}
727*d82d4ff0SYann Gautier 
728*d82d4ff0SYann Gautier 	if ((p_data == NULL) || (size == 0U)) {
729*d82d4ff0SYann Gautier 		return  -EINVAL;
730*d82d4ff0SYann Gautier 	}
731*d82d4ff0SYann Gautier 
732*d82d4ff0SYann Gautier 	stm32mp_clk_enable(hi2c->clock);
733*d82d4ff0SYann Gautier 
734*d82d4ff0SYann Gautier 	hi2c->lock = 1;
735*d82d4ff0SYann Gautier 
736*d82d4ff0SYann Gautier 	timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
737*d82d4ff0SYann Gautier 	if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
738*d82d4ff0SYann Gautier 		goto bail;
739*d82d4ff0SYann Gautier 	}
740*d82d4ff0SYann Gautier 
741*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_BUSY_RX;
742*d82d4ff0SYann Gautier 	hi2c->i2c_mode = mode;
743*d82d4ff0SYann Gautier 	hi2c->i2c_err = I2C_ERROR_NONE;
744*d82d4ff0SYann Gautier 
745*d82d4ff0SYann Gautier 	if (mode == I2C_MODE_MEM) {
746*d82d4ff0SYann Gautier 		/* Send Memory Address */
747*d82d4ff0SYann Gautier 		if (i2c_request_memory_read(hi2c, dev_addr, mem_addr,
748*d82d4ff0SYann Gautier 					    mem_add_size, timeout_ref) != 0) {
749*d82d4ff0SYann Gautier 			goto bail;
750*d82d4ff0SYann Gautier 		}
751*d82d4ff0SYann Gautier 	}
752*d82d4ff0SYann Gautier 
753*d82d4ff0SYann Gautier 	/*
754*d82d4ff0SYann Gautier 	 * Send Slave Address.
755*d82d4ff0SYann Gautier 	 * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
756*d82d4ff0SYann Gautier 	 * and generate RESTART.
757*d82d4ff0SYann Gautier 	 */
758*d82d4ff0SYann Gautier 	if (xfer_count > MAX_NBYTE_SIZE) {
759*d82d4ff0SYann Gautier 		xfer_size = MAX_NBYTE_SIZE;
760*d82d4ff0SYann Gautier 		i2c_transfer_config(hi2c, dev_addr, xfer_size,
761*d82d4ff0SYann Gautier 				    I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
762*d82d4ff0SYann Gautier 	} else {
763*d82d4ff0SYann Gautier 		xfer_size = xfer_count;
764*d82d4ff0SYann Gautier 		i2c_transfer_config(hi2c, dev_addr, xfer_size,
765*d82d4ff0SYann Gautier 				    I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
766*d82d4ff0SYann Gautier 	}
767*d82d4ff0SYann Gautier 
768*d82d4ff0SYann Gautier 	do {
769*d82d4ff0SYann Gautier 		if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) {
770*d82d4ff0SYann Gautier 			goto bail;
771*d82d4ff0SYann Gautier 		}
772*d82d4ff0SYann Gautier 
773*d82d4ff0SYann Gautier 		*p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
774*d82d4ff0SYann Gautier 		p_buff++;
775*d82d4ff0SYann Gautier 		xfer_size--;
776*d82d4ff0SYann Gautier 		xfer_count--;
777*d82d4ff0SYann Gautier 
778*d82d4ff0SYann Gautier 		if ((xfer_count != 0U) && (xfer_size == 0U)) {
779*d82d4ff0SYann Gautier 			if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
780*d82d4ff0SYann Gautier 					  timeout_ref) != 0) {
781*d82d4ff0SYann Gautier 				goto bail;
782*d82d4ff0SYann Gautier 			}
783*d82d4ff0SYann Gautier 
784*d82d4ff0SYann Gautier 			if (xfer_count > MAX_NBYTE_SIZE) {
785*d82d4ff0SYann Gautier 				xfer_size = MAX_NBYTE_SIZE;
786*d82d4ff0SYann Gautier 				i2c_transfer_config(hi2c, dev_addr,
787*d82d4ff0SYann Gautier 						    xfer_size,
788*d82d4ff0SYann Gautier 						    I2C_RELOAD_MODE,
789*d82d4ff0SYann Gautier 						    I2C_NO_STARTSTOP);
790*d82d4ff0SYann Gautier 			} else {
791*d82d4ff0SYann Gautier 				xfer_size = xfer_count;
792*d82d4ff0SYann Gautier 				i2c_transfer_config(hi2c, dev_addr,
793*d82d4ff0SYann Gautier 						    xfer_size,
794*d82d4ff0SYann Gautier 						    I2C_AUTOEND_MODE,
795*d82d4ff0SYann Gautier 						    I2C_NO_STARTSTOP);
796*d82d4ff0SYann Gautier 			}
797*d82d4ff0SYann Gautier 		}
798*d82d4ff0SYann Gautier 	} while (xfer_count > 0U);
799*d82d4ff0SYann Gautier 
800*d82d4ff0SYann Gautier 	/*
801*d82d4ff0SYann Gautier 	 * No need to Check TC flag, with AUTOEND mode the stop
802*d82d4ff0SYann Gautier 	 * is automatically generated.
803*d82d4ff0SYann Gautier 	 * Wait until STOPF flag is reset.
804*d82d4ff0SYann Gautier 	 */
805*d82d4ff0SYann Gautier 	if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
806*d82d4ff0SYann Gautier 		goto bail;
807*d82d4ff0SYann Gautier 	}
808*d82d4ff0SYann Gautier 
809*d82d4ff0SYann Gautier 	mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
810*d82d4ff0SYann Gautier 
811*d82d4ff0SYann Gautier 	mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
812*d82d4ff0SYann Gautier 
813*d82d4ff0SYann Gautier 	hi2c->i2c_state = I2C_STATE_READY;
814*d82d4ff0SYann Gautier 	hi2c->i2c_mode = I2C_MODE_NONE;
815*d82d4ff0SYann Gautier 
816*d82d4ff0SYann Gautier 	rc = 0;
817*d82d4ff0SYann Gautier 
818*d82d4ff0SYann Gautier bail:
819*d82d4ff0SYann Gautier 	hi2c->lock = 0;
820*d82d4ff0SYann Gautier 	stm32mp_clk_disable(hi2c->clock);
821*d82d4ff0SYann Gautier 
822*d82d4ff0SYann Gautier 	return rc;
823*d82d4ff0SYann Gautier }
824*d82d4ff0SYann Gautier 
825*d82d4ff0SYann Gautier /*
826*d82d4ff0SYann Gautier  * @brief  Read an amount of data in blocking mode from a specific memory
827*d82d4ff0SYann Gautier  *	   address.
828*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
829*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
830*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
831*d82d4ff0SYann Gautier  * @param  mem_addr: Internal memory address
832*d82d4ff0SYann Gautier  * @param  mem_add_size: Size of internal memory address
833*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
834*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
835*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
836*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
837*d82d4ff0SYann Gautier  */
838*d82d4ff0SYann Gautier int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
839*d82d4ff0SYann Gautier 		       uint16_t mem_addr, uint16_t mem_add_size,
840*d82d4ff0SYann Gautier 		       uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
841*d82d4ff0SYann Gautier {
842*d82d4ff0SYann Gautier 	return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size,
843*d82d4ff0SYann Gautier 			p_data, size, timeout_ms, I2C_MODE_MEM);
844*d82d4ff0SYann Gautier }
845*d82d4ff0SYann Gautier 
846*d82d4ff0SYann Gautier /*
847*d82d4ff0SYann Gautier  * @brief  Receives in master mode an amount of data in blocking mode.
848*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
849*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
850*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
851*d82d4ff0SYann Gautier  * @param  p_data: Pointer to data buffer
852*d82d4ff0SYann Gautier  * @param  size: Amount of data to be sent
853*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
854*d82d4ff0SYann Gautier  * @retval 0 if OK, negative value else
855*d82d4ff0SYann Gautier  */
856*d82d4ff0SYann Gautier int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
857*d82d4ff0SYann Gautier 			     uint8_t *p_data, uint16_t size,
858*d82d4ff0SYann Gautier 			     uint32_t timeout_ms)
859*d82d4ff0SYann Gautier {
860*d82d4ff0SYann Gautier 	return i2c_read(hi2c, dev_addr, 0, 0,
861*d82d4ff0SYann Gautier 			p_data, size, timeout_ms, I2C_MODE_MASTER);
862*d82d4ff0SYann Gautier }
863*d82d4ff0SYann Gautier 
864*d82d4ff0SYann Gautier /*
865*d82d4ff0SYann Gautier  * @brief  Checks if target device is ready for communication.
866*d82d4ff0SYann Gautier  * @note   This function is used with Memory devices
867*d82d4ff0SYann Gautier  * @param  hi2c: Pointer to a struct i2c_handle_s structure that contains
868*d82d4ff0SYann Gautier  *               the configuration information for the specified I2C.
869*d82d4ff0SYann Gautier  * @param  dev_addr: Target device address
870*d82d4ff0SYann Gautier  * @param  trials: Number of trials
871*d82d4ff0SYann Gautier  * @param  timeout_ms: Timeout duration in milliseconds
872*d82d4ff0SYann Gautier  * @retval True if device is ready, false else
873*d82d4ff0SYann Gautier  */
874*d82d4ff0SYann Gautier bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
875*d82d4ff0SYann Gautier 			       uint16_t dev_addr, uint32_t trials,
876*d82d4ff0SYann Gautier 			       uint32_t timeout_ms)
877*d82d4ff0SYann Gautier {
878*d82d4ff0SYann Gautier 	uint32_t i2c_trials = 0U;
879*d82d4ff0SYann Gautier 	bool rc = false;
880*d82d4ff0SYann Gautier 
881*d82d4ff0SYann Gautier 	if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
882*d82d4ff0SYann Gautier 		return rc;
883*d82d4ff0SYann Gautier 	}
884*d82d4ff0SYann Gautier 
885*d82d4ff0SYann Gautier 	stm32mp_clk_enable(hi2c->clock);
886*d82d4ff0SYann Gautier 
887*d82d4ff0SYann Gautier 	hi2c->lock = 1;
888*d82d4ff0SYann Gautier 	hi2c->i2c_mode = I2C_MODE_NONE;
889*d82d4ff0SYann Gautier 
890*d82d4ff0SYann Gautier 	if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
891*d82d4ff0SYann Gautier 	    0U) {
892*d82d4ff0SYann Gautier 		goto bail;
893*d82d4ff0SYann Gautier 	}
894*d82d4ff0SYann Gautier 
895435832abSYann Gautier 	hi2c->i2c_state = I2C_STATE_BUSY;
896*d82d4ff0SYann Gautier 	hi2c->i2c_err = I2C_ERROR_NONE;
897435832abSYann Gautier 
898*d82d4ff0SYann Gautier 	do {
899*d82d4ff0SYann Gautier 		uint64_t timeout_ref;
900435832abSYann Gautier 
901*d82d4ff0SYann Gautier 		/* Generate Start */
902*d82d4ff0SYann Gautier 		if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) &
903*d82d4ff0SYann Gautier 		     I2C_OAR1_OA1MODE) == 0) {
904*d82d4ff0SYann Gautier 			mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
905*d82d4ff0SYann Gautier 				      (((uint32_t)dev_addr & I2C_CR2_SADD) |
906*d82d4ff0SYann Gautier 				       I2C_CR2_START | I2C_CR2_AUTOEND) &
907*d82d4ff0SYann Gautier 				      ~I2C_CR2_RD_WRN);
908*d82d4ff0SYann Gautier 		} else {
909*d82d4ff0SYann Gautier 			mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
910*d82d4ff0SYann Gautier 				      (((uint32_t)dev_addr & I2C_CR2_SADD) |
911*d82d4ff0SYann Gautier 				       I2C_CR2_START | I2C_CR2_ADD10) &
912*d82d4ff0SYann Gautier 				      ~I2C_CR2_RD_WRN);
913*d82d4ff0SYann Gautier 		}
914435832abSYann Gautier 
915*d82d4ff0SYann Gautier 		/*
916*d82d4ff0SYann Gautier 		 * No need to Check TC flag, with AUTOEND mode the stop
917*d82d4ff0SYann Gautier 		 * is automatically generated.
918*d82d4ff0SYann Gautier 		 * Wait until STOPF flag is set or a NACK flag is set.
919*d82d4ff0SYann Gautier 		 */
920*d82d4ff0SYann Gautier 		timeout_ref = timeout_init_us(timeout_ms * 1000);
921*d82d4ff0SYann Gautier 		do {
922*d82d4ff0SYann Gautier 			if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
923*d82d4ff0SYann Gautier 			     (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) {
924*d82d4ff0SYann Gautier 				break;
925*d82d4ff0SYann Gautier 			}
926435832abSYann Gautier 
927*d82d4ff0SYann Gautier 			if (timeout_elapsed(timeout_ref)) {
928*d82d4ff0SYann Gautier 				notif_i2c_timeout(hi2c);
929*d82d4ff0SYann Gautier 				goto bail;
930*d82d4ff0SYann Gautier 			}
931*d82d4ff0SYann Gautier 		} while (true);
932*d82d4ff0SYann Gautier 
933*d82d4ff0SYann Gautier 		if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
934*d82d4ff0SYann Gautier 		     I2C_FLAG_AF) == 0U) {
935*d82d4ff0SYann Gautier 			if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
936*d82d4ff0SYann Gautier 					  timeout_ref) != 0) {
937*d82d4ff0SYann Gautier 				goto bail;
938*d82d4ff0SYann Gautier 			}
939*d82d4ff0SYann Gautier 
940*d82d4ff0SYann Gautier 			mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
941*d82d4ff0SYann Gautier 				      I2C_FLAG_STOPF);
942435832abSYann Gautier 
943435832abSYann Gautier 			hi2c->i2c_state = I2C_STATE_READY;
944435832abSYann Gautier 
945*d82d4ff0SYann Gautier 			rc = true;
946*d82d4ff0SYann Gautier 			goto bail;
947435832abSYann Gautier 		}
948*d82d4ff0SYann Gautier 
949*d82d4ff0SYann Gautier 		if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) {
950*d82d4ff0SYann Gautier 			goto bail;
951*d82d4ff0SYann Gautier 		}
952*d82d4ff0SYann Gautier 
953*d82d4ff0SYann Gautier 		mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
954*d82d4ff0SYann Gautier 
955*d82d4ff0SYann Gautier 		mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
956*d82d4ff0SYann Gautier 
957*d82d4ff0SYann Gautier 		if (i2c_trials == trials) {
958*d82d4ff0SYann Gautier 			mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
959*d82d4ff0SYann Gautier 					I2C_CR2_STOP);
960*d82d4ff0SYann Gautier 
961*d82d4ff0SYann Gautier 			if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
962*d82d4ff0SYann Gautier 					  timeout_ref) != 0) {
963*d82d4ff0SYann Gautier 				goto bail;
964*d82d4ff0SYann Gautier 			}
965*d82d4ff0SYann Gautier 
966*d82d4ff0SYann Gautier 			mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
967*d82d4ff0SYann Gautier 				      I2C_FLAG_STOPF);
968*d82d4ff0SYann Gautier 		}
969*d82d4ff0SYann Gautier 
970*d82d4ff0SYann Gautier 		i2c_trials++;
971*d82d4ff0SYann Gautier 	} while (i2c_trials < trials);
972*d82d4ff0SYann Gautier 
973*d82d4ff0SYann Gautier 	notif_i2c_timeout(hi2c);
974*d82d4ff0SYann Gautier 
975*d82d4ff0SYann Gautier bail:
976*d82d4ff0SYann Gautier 	hi2c->lock = 0;
977*d82d4ff0SYann Gautier 	stm32mp_clk_disable(hi2c->clock);
978*d82d4ff0SYann Gautier 
979*d82d4ff0SYann Gautier 	return rc;
980*d82d4ff0SYann Gautier }
981*d82d4ff0SYann Gautier 
982