blob: ed880522b0da23d74f62032b45165de0cbe3bf40 [file] [log] [blame]
Yann Gautierbb836ee2018-07-16 17:55:07 +02001/*
Yann Gautier113f31e2019-01-17 09:34:18 +01002 * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
Yann Gautierbb836ee2018-07-16 17:55:07 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautierbb836ee2018-07-16 17:55:07 +02007#include <errno.h>
Yann Gautierbb836ee2018-07-16 17:55:07 +02008#include <stdbool.h>
9#include <stdlib.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
Yann Gautierf3928f62019-02-14 11:15:03 +010011#include <libfdt.h>
12
13#include <platform_def.h>
14
15#include <common/debug.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <drivers/delay_timer.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010017#include <drivers/st/stm32_gpio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000018#include <drivers/st/stm32_i2c.h>
19#include <lib/mmio.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010020#include <lib/utils.h>
Yann Gautierbb836ee2018-07-16 17:55:07 +020021
22/* STM32 I2C registers offsets */
23#define I2C_CR1 0x00U
24#define I2C_CR2 0x04U
25#define I2C_OAR1 0x08U
26#define I2C_OAR2 0x0CU
27#define I2C_TIMINGR 0x10U
28#define I2C_TIMEOUTR 0x14U
29#define I2C_ISR 0x18U
30#define I2C_ICR 0x1CU
31#define I2C_PECR 0x20U
32#define I2C_RXDR 0x24U
33#define I2C_TXDR 0x28U
34
Yann Gautierf3928f62019-02-14 11:15:03 +010035#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU
Yann Gautierbb836ee2018-07-16 17:55:07 +020036
37#define MAX_NBYTE_SIZE 255U
38
Yann Gautierf3928f62019-02-14 11:15:03 +010039#define I2C_NSEC_PER_SEC 1000000000L
Yann Gautierbb836ee2018-07-16 17:55:07 +020040
Yann Gautierf3928f62019-02-14 11:15:03 +010041/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
42#define I2C_TIMING 0x10D07DB5
Yann Gautierbb836ee2018-07-16 17:55:07 +020043
Yann Gautierf3928f62019-02-14 11:15:03 +010044static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
45{
46 hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
47 hi2c->i2c_mode = I2C_MODE_NONE;
48 hi2c->i2c_state = I2C_STATE_READY;
49}
Yann Gautierbb836ee2018-07-16 17:55:07 +020050
Yann Gautierf3928f62019-02-14 11:15:03 +010051/*
52 * @brief Configure I2C Analog noise filter.
53 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
54 * the configuration information for the specified I2C peripheral.
55 * @param analog_filter: New state of the Analog filter
56 * @retval 0 if OK, negative value else
57 */
58static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
59 uint32_t analog_filter)
60{
61 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
62 return -EBUSY;
63 }
64
65 hi2c->lock = 1;
66
67 hi2c->i2c_state = I2C_STATE_BUSY;
68
69 /* Disable the selected I2C peripheral */
70 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
71
72 /* Reset I2Cx ANOFF bit */
73 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
74
75 /* Set analog filter bit*/
76 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
77
78 /* Enable the selected I2C peripheral */
79 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
80
81 hi2c->i2c_state = I2C_STATE_READY;
82
83 hi2c->lock = 0;
84
85 return 0;
86}
87
88/*
89 * @brief Get I2C setup information from the device tree and set pinctrl
90 * configuration.
91 * @param fdt: Pointer to the device tree
92 * @param node: I2C node offset
93 * @param init: Ref to the initialization configuration structure
94 * @retval 0 if OK, negative value else
95 */
96int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
97 struct stm32_i2c_init_s *init)
98{
99 const fdt32_t *cuint;
100
101 cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
102 if (cuint == NULL) {
103 init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
104 } else {
105 init->rise_time = fdt32_to_cpu(*cuint);
106 }
107
108 cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
109 if (cuint == NULL) {
110 init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
111 } else {
112 init->fall_time = fdt32_to_cpu(*cuint);
113 }
114
115 cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
116 if (cuint == NULL) {
117 init->speed_mode = STM32_I2C_SPEED_DEFAULT;
118 } else {
119 switch (fdt32_to_cpu(*cuint)) {
120 case STANDARD_RATE:
121 init->speed_mode = I2C_SPEED_STANDARD;
122 break;
123 case FAST_RATE:
124 init->speed_mode = I2C_SPEED_FAST;
125 break;
126 case FAST_PLUS_RATE:
127 init->speed_mode = I2C_SPEED_FAST_PLUS;
128 break;
129 default:
130 init->speed_mode = STM32_I2C_SPEED_DEFAULT;
131 break;
132 }
133 }
134
135 return dt_set_pinctrl_config(node);
136}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200137
138/*
139 * @brief Initialize the I2C device.
140 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
141 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100142 * @param init_data: Initialization configuration structure
Yann Gautierbb836ee2018-07-16 17:55:07 +0200143 * @retval 0 if OK, negative value else
144 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100145int stm32_i2c_init(struct i2c_handle_s *hi2c,
146 struct stm32_i2c_init_s *init_data)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200147{
Yann Gautierf3928f62019-02-14 11:15:03 +0100148 int rc = 0;
149 uint32_t timing = I2C_TIMING;
150
Yann Gautierbb836ee2018-07-16 17:55:07 +0200151 if (hi2c == NULL) {
152 return -ENOENT;
153 }
154
155 if (hi2c->i2c_state == I2C_STATE_RESET) {
156 hi2c->lock = 0;
157 }
158
159 hi2c->i2c_state = I2C_STATE_BUSY;
160
Yann Gautierf3928f62019-02-14 11:15:03 +0100161 stm32mp_clk_enable(hi2c->clock);
162
Yann Gautierbb836ee2018-07-16 17:55:07 +0200163 /* Disable the selected I2C peripheral */
164 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
165
166 /* Configure I2Cx: Frequency range */
167 mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
Yann Gautierf3928f62019-02-14 11:15:03 +0100168 timing & TIMINGR_CLEAR_MASK);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200169
170 /* Disable Own Address1 before set the Own Address1 configuration */
171 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
172
173 /* Configure I2Cx: Own Address1 and ack own address1 mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100174 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200175 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100176 I2C_OAR1_OA1EN | init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200177 } else { /* I2C_ADDRESSINGMODE_10BIT */
178 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
179 I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
Yann Gautierf3928f62019-02-14 11:15:03 +0100180 init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200181 }
182
Yann Gautierf3928f62019-02-14 11:15:03 +0100183 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0);
184
Yann Gautierbb836ee2018-07-16 17:55:07 +0200185 /* Configure I2Cx: Addressing Master mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100186 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
187 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200188 }
189
190 /*
191 * Enable the AUTOEND by default, and enable NACK
Yann Gautierf3928f62019-02-14 11:15:03 +0100192 * (should be disabled only during Slave process).
Yann Gautierbb836ee2018-07-16 17:55:07 +0200193 */
194 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
195 I2C_CR2_AUTOEND | I2C_CR2_NACK);
196
197 /* Disable Own Address2 before set the Own Address2 configuration */
198 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
199
200 /* Configure I2Cx: Dual mode and Own Address2 */
201 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
Yann Gautierf3928f62019-02-14 11:15:03 +0100202 init_data->dual_address_mode |
203 init_data->own_address2 |
204 (init_data->own_address2_masks << 8));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200205
206 /* Configure I2Cx: Generalcall and NoStretch mode */
207 mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100208 init_data->general_call_mode |
209 init_data->no_stretch_mode);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200210
211 /* Enable the selected I2C peripheral */
212 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
213
214 hi2c->i2c_err = I2C_ERROR_NONE;
215 hi2c->i2c_state = I2C_STATE_READY;
216 hi2c->i2c_mode = I2C_MODE_NONE;
217
Yann Gautierf3928f62019-02-14 11:15:03 +0100218 rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ?
219 I2C_ANALOGFILTER_ENABLE :
220 I2C_ANALOGFILTER_DISABLE);
221 if (rc != 0) {
222 ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
223 stm32mp_clk_disable(hi2c->clock);
224 return rc;
225 }
226
227 stm32mp_clk_disable(hi2c->clock);
228
229 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200230}
231
232/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100233 * @brief I2C Tx data register flush process.
234 * @param hi2c: I2C handle
235 * @retval None
Yann Gautierbb836ee2018-07-16 17:55:07 +0200236 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100237static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200238{
Yann Gautierf3928f62019-02-14 11:15:03 +0100239 /*
240 * If a pending TXIS flag is set,
241 * write a dummy data in TXDR to clear it.
242 */
243 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
244 0U) {
245 mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200246 }
247
Yann Gautierf3928f62019-02-14 11:15:03 +0100248 /* Flush TX register if not empty */
249 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
250 0U) {
251 mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
252 I2C_FLAG_TXE);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200253 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100254}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200255
Yann Gautierf3928f62019-02-14 11:15:03 +0100256/*
257 * @brief This function handles I2C Communication timeout.
258 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
259 * the configuration information for the specified I2C.
260 * @param flag: Specifies the I2C flag to check
261 * @param awaited_value: The awaited bit value for the flag (0 or 1)
262 * @param timeout_ref: Reference to target timeout
263 * @retval 0 if OK, negative value else
264 */
265static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
266 uint8_t awaited_value, uint64_t timeout_ref)
267{
268 for ( ; ; ) {
269 uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200270
Yann Gautierf3928f62019-02-14 11:15:03 +0100271 if (!!(isr & flag) != !!awaited_value) {
272 return 0;
273 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200274
Yann Gautierf3928f62019-02-14 11:15:03 +0100275 if (timeout_elapsed(timeout_ref)) {
276 notif_i2c_timeout(hi2c);
277 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200278
Yann Gautierf3928f62019-02-14 11:15:03 +0100279 return -EIO;
280 }
281 }
282}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200283
Yann Gautierf3928f62019-02-14 11:15:03 +0100284/*
285 * @brief This function handles Acknowledge failed detection during
286 * an I2C Communication.
287 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
288 * the configuration information for the specified I2C.
289 * @param timeout_ref: Reference to target timeout
290 * @retval 0 if OK, negative value else
291 */
292static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
293{
294 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
295 return 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200296 }
297
298 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100299 * Wait until STOP Flag is reset.
300 * AutoEnd should be initiate after AF.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200301 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100302 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
303 I2C_FLAG_STOPF) == 0U) {
304 if (timeout_elapsed(timeout_ref)) {
305 notif_i2c_timeout(hi2c);
306 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200307
Yann Gautierbb836ee2018-07-16 17:55:07 +0200308 return -EIO;
309 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200310 }
311
Yann Gautierf3928f62019-02-14 11:15:03 +0100312 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
313
Yann Gautierbb836ee2018-07-16 17:55:07 +0200314 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
315
Yann Gautierf3928f62019-02-14 11:15:03 +0100316 i2c_flush_txdr(hi2c);
317
Yann Gautierbb836ee2018-07-16 17:55:07 +0200318 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
319
Yann Gautierf3928f62019-02-14 11:15:03 +0100320 hi2c->i2c_err |= I2C_ERROR_AF;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200321 hi2c->i2c_state = I2C_STATE_READY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100322 hi2c->i2c_mode = I2C_MODE_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200323
324 hi2c->lock = 0;
325
Yann Gautierf3928f62019-02-14 11:15:03 +0100326 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200327}
328
329/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100330 * @brief This function handles I2C Communication timeout for specific usage
331 * of TXIS flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200332 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
333 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100334 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200335 * @retval 0 if OK, negative value else
336 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100337static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200338{
Yann Gautierf3928f62019-02-14 11:15:03 +0100339 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
340 I2C_FLAG_TXIS) == 0U) {
341 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200342 return -EIO;
343 }
344
Yann Gautierf3928f62019-02-14 11:15:03 +0100345 if (timeout_elapsed(timeout_ref)) {
346 notif_i2c_timeout(hi2c);
347 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200348
Yann Gautierf3928f62019-02-14 11:15:03 +0100349 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200350 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200351 }
352
Yann Gautierbb836ee2018-07-16 17:55:07 +0200353 return 0;
354}
355
356/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100357 * @brief This function handles I2C Communication timeout for specific
358 * usage of STOP flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200359 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
360 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100361 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200362 * @retval 0 if OK, negative value else
363 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100364static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200365{
Yann Gautierf3928f62019-02-14 11:15:03 +0100366 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
367 I2C_FLAG_STOPF) == 0U) {
368 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
369 return -EIO;
370 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200371
Yann Gautierf3928f62019-02-14 11:15:03 +0100372 if (timeout_elapsed(timeout_ref)) {
373 notif_i2c_timeout(hi2c);
374 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200375
Yann Gautierbb836ee2018-07-16 17:55:07 +0200376 return -EIO;
377 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100378 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200379
Yann Gautierf3928f62019-02-14 11:15:03 +0100380 return 0;
381}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200382
Yann Gautierf3928f62019-02-14 11:15:03 +0100383/*
384 * @brief Handles I2Cx communication when starting transfer or during transfer
385 * (TC or TCR flag are set).
386 * @param hi2c: I2C handle
387 * @param dev_addr: Specifies the slave address to be programmed
388 * @param size: Specifies the number of bytes to be programmed.
389 * This parameter must be a value between 0 and 255.
390 * @param i2c_mode: New state of the I2C START condition generation.
391 * This parameter can be one of the following values:
392 * @arg @ref I2C_RELOAD_MODE: Enable Reload mode.
393 * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
394 * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
395 * @param request: New state of the I2C START condition generation.
396 * This parameter can be one of the following values:
397 * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
398 * @arg @ref I2C_GENERATE_STOP: Generate stop condition
399 * (size should be set to 0).
400 * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
401 * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
402 * @retval None
403 */
404static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
405 uint16_t size, uint32_t i2c_mode,
406 uint32_t request)
407{
408 uint32_t clr_value, set_value;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200409
Yann Gautierf3928f62019-02-14 11:15:03 +0100410 clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
411 I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
412 (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200413
Yann Gautierf3928f62019-02-14 11:15:03 +0100414 set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
415 (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
416 i2c_mode | request;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200417
Yann Gautierf3928f62019-02-14 11:15:03 +0100418 mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200419}
420
421/*
422 * @brief Master sends target device address followed by internal memory
423 * address for write request.
424 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
425 * the configuration information for the specified I2C.
426 * @param dev_addr: Target device address
427 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100428 * @param mem_add_size: Size of internal memory address
429 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200430 * @retval 0 if OK, negative value else
431 */
432static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
433 uint16_t dev_addr, uint16_t mem_addr,
Yann Gautierf3928f62019-02-14 11:15:03 +0100434 uint16_t mem_add_size, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200435{
436 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
437 I2C_GENERATE_START_WRITE);
438
Yann Gautierf3928f62019-02-14 11:15:03 +0100439 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200440 return -EIO;
441 }
442
443 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
444 /* Send Memory Address */
445 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
446 (uint8_t)(mem_addr & 0x00FFU));
447 } else {
448 /* Send MSB of Memory Address */
449 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
450 (uint8_t)((mem_addr & 0xFF00U) >> 8));
451
Yann Gautierf3928f62019-02-14 11:15:03 +0100452 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200453 return -EIO;
454 }
455
456 /* Send LSB of Memory Address */
457 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
458 (uint8_t)(mem_addr & 0x00FFU));
459 }
460
Yann Gautierf3928f62019-02-14 11:15:03 +0100461 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200462 return -EIO;
463 }
464
465 return 0;
466}
467
468/*
469 * @brief Master sends target device address followed by internal memory
470 * address for read request.
471 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
472 * the configuration information for the specified I2C.
473 * @param dev_addr: Target device address
474 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100475 * @param mem_add_size: Size of internal memory address
476 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200477 * @retval 0 if OK, negative value else
478 */
479static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
480 uint16_t mem_addr, uint16_t mem_add_size,
Yann Gautierf3928f62019-02-14 11:15:03 +0100481 uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200482{
483 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
484 I2C_GENERATE_START_WRITE);
485
Yann Gautierf3928f62019-02-14 11:15:03 +0100486 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200487 return -EIO;
488 }
489
490 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
491 /* Send Memory Address */
492 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
493 (uint8_t)(mem_addr & 0x00FFU));
494 } else {
495 /* Send MSB of Memory Address */
496 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
497 (uint8_t)((mem_addr & 0xFF00U) >> 8));
498
Yann Gautierf3928f62019-02-14 11:15:03 +0100499 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200500 return -EIO;
501 }
502
503 /* Send LSB of Memory Address */
504 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
505 (uint8_t)(mem_addr & 0x00FFU));
506 }
507
Yann Gautierf3928f62019-02-14 11:15:03 +0100508 if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200509 return -EIO;
510 }
511
512 return 0;
513}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200514/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100515 * @brief Generic function to write an amount of data in blocking mode
516 * (for Memory Mode and Master Mode)
517 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
518 * the configuration information for the specified I2C.
519 * @param dev_addr: Target device address
520 * @param mem_addr: Internal memory address (if Memory Mode)
521 * @param mem_add_size: Size of internal memory address (if Memory Mode)
522 * @param p_data: Pointer to data buffer
523 * @param size: Amount of data to be sent
524 * @param timeout_ms: Timeout duration in milliseconds
525 * @param mode: Communication mode
526 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200527 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100528static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
529 uint16_t mem_addr, uint16_t mem_add_size,
530 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
531 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200532{
Yann Gautierf3928f62019-02-14 11:15:03 +0100533 uint64_t timeout_ref;
534 int rc = -EIO;
535 uint8_t *p_buff = p_data;
536 uint32_t xfer_size;
537 uint32_t xfer_count = size;
538
539 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
540 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200541 }
542
Yann Gautierf3928f62019-02-14 11:15:03 +0100543 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
544 return -EBUSY;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200545 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200546
Yann Gautierf3928f62019-02-14 11:15:03 +0100547 if ((p_data == NULL) || (size == 0U)) {
548 return -EINVAL;
549 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200550
Yann Gautierf3928f62019-02-14 11:15:03 +0100551 stm32mp_clk_enable(hi2c->clock);
552
553 hi2c->lock = 1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200554
Yann Gautierf3928f62019-02-14 11:15:03 +0100555 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
556 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
557 goto bail;
558 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200559
Yann Gautierf3928f62019-02-14 11:15:03 +0100560 hi2c->i2c_state = I2C_STATE_BUSY_TX;
561 hi2c->i2c_mode = mode;
562 hi2c->i2c_err = I2C_ERROR_NONE;
563
564 timeout_ref = timeout_init_us(timeout_ms * 1000);
565
566 if (mode == I2C_MODE_MEM) {
567 /* In Memory Mode, Send Slave Address and Memory Address */
568 if (i2c_request_memory_write(hi2c, dev_addr, mem_addr,
569 mem_add_size, timeout_ref) != 0) {
570 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200571 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200572
Yann Gautierf3928f62019-02-14 11:15:03 +0100573 if (xfer_count > MAX_NBYTE_SIZE) {
574 xfer_size = MAX_NBYTE_SIZE;
575 i2c_transfer_config(hi2c, dev_addr, xfer_size,
576 I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
577 } else {
578 xfer_size = xfer_count;
579 i2c_transfer_config(hi2c, dev_addr, xfer_size,
580 I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
581 }
582 } else {
583 /* In Master Mode, Send Slave Address */
584 if (xfer_count > MAX_NBYTE_SIZE) {
585 xfer_size = MAX_NBYTE_SIZE;
586 i2c_transfer_config(hi2c, dev_addr, xfer_size,
587 I2C_RELOAD_MODE,
588 I2C_GENERATE_START_WRITE);
589 } else {
590 xfer_size = xfer_count;
591 i2c_transfer_config(hi2c, dev_addr, xfer_size,
592 I2C_AUTOEND_MODE,
593 I2C_GENERATE_START_WRITE);
594 }
595 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200596
Yann Gautierf3928f62019-02-14 11:15:03 +0100597 do {
598 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
599 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200600 }
601
Yann Gautierf3928f62019-02-14 11:15:03 +0100602 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff);
603 p_buff++;
604 xfer_count--;
605 xfer_size--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200606
Yann Gautierf3928f62019-02-14 11:15:03 +0100607 if ((xfer_count != 0U) && (xfer_size == 0U)) {
608 /* Wait until TCR flag is set */
609 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
610 timeout_ref) != 0) {
611 goto bail;
612 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200613
Yann Gautierf3928f62019-02-14 11:15:03 +0100614 if (xfer_count > MAX_NBYTE_SIZE) {
615 xfer_size = MAX_NBYTE_SIZE;
616 i2c_transfer_config(hi2c, dev_addr,
617 xfer_size,
618 I2C_RELOAD_MODE,
619 I2C_NO_STARTSTOP);
620 } else {
621 xfer_size = xfer_count;
622 i2c_transfer_config(hi2c, dev_addr,
623 xfer_size,
624 I2C_AUTOEND_MODE,
625 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200626 }
627 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100628
629 } while (xfer_count > 0U);
630
631 /*
632 * No need to Check TC flag, with AUTOEND mode the stop
633 * is automatically generated.
634 * Wait until STOPF flag is reset.
635 */
636 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
637 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200638 }
639
Yann Gautierf3928f62019-02-14 11:15:03 +0100640 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
641
642 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
643
644 hi2c->i2c_state = I2C_STATE_READY;
645 hi2c->i2c_mode = I2C_MODE_NONE;
646
647 rc = 0;
648
649bail:
650 hi2c->lock = 0;
651 stm32mp_clk_disable(hi2c->clock);
652
653 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200654}
655
656/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100657 * @brief Write an amount of data in blocking mode to a specific memory
658 * address.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200659 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
660 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100661 * @param dev_addr: Target device address
662 * @param mem_addr: Internal memory address
663 * @param mem_add_size: Size of internal memory address
664 * @param p_data: Pointer to data buffer
665 * @param size: Amount of data to be sent
666 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200667 * @retval 0 if OK, negative value else
668 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100669int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
670 uint16_t mem_addr, uint16_t mem_add_size,
671 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200672{
Yann Gautierf3928f62019-02-14 11:15:03 +0100673 return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size,
674 p_data, size, timeout_ms, I2C_MODE_MEM);
675}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200676
Yann Gautierf3928f62019-02-14 11:15:03 +0100677/*
678 * @brief Transmits in master mode an amount of data in blocking mode.
679 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
680 * the configuration information for the specified I2C.
681 * @param dev_addr: Target device address
682 * @param p_data: Pointer to data buffer
683 * @param size: Amount of data to be sent
684 * @param timeout_ms: Timeout duration in milliseconds
685 * @retval 0 if OK, negative value else
686 */
687int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
688 uint8_t *p_data, uint16_t size,
689 uint32_t timeout_ms)
690{
691 return i2c_write(hi2c, dev_addr, 0, 0,
692 p_data, size, timeout_ms, I2C_MODE_MASTER);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200693}
694
695/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100696 * @brief Generic function to read an amount of data in blocking mode
697 * (for Memory Mode and Master Mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200698 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
699 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100700 * @param dev_addr: Target device address
701 * @param mem_addr: Internal memory address (if Memory Mode)
702 * @param mem_add_size: Size of internal memory address (if Memory Mode)
703 * @param p_data: Pointer to data buffer
704 * @param size: Amount of data to be sent
705 * @param timeout_ms: Timeout duration in milliseconds
706 * @param mode: Communication mode
Yann Gautierbb836ee2018-07-16 17:55:07 +0200707 * @retval 0 if OK, negative value else
708 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100709static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
710 uint16_t mem_addr, uint16_t mem_add_size,
711 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
712 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200713{
Yann Gautierf3928f62019-02-14 11:15:03 +0100714 uint64_t timeout_ref;
715 int rc = -EIO;
716 uint8_t *p_buff = p_data;
717 uint32_t xfer_count = size;
718 uint32_t xfer_size;
719
720 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
721 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200722 }
723
Yann Gautierf3928f62019-02-14 11:15:03 +0100724 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
725 return -EBUSY;
726 }
727
728 if ((p_data == NULL) || (size == 0U)) {
729 return -EINVAL;
730 }
731
732 stm32mp_clk_enable(hi2c->clock);
733
734 hi2c->lock = 1;
735
736 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
737 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
738 goto bail;
739 }
740
741 hi2c->i2c_state = I2C_STATE_BUSY_RX;
742 hi2c->i2c_mode = mode;
743 hi2c->i2c_err = I2C_ERROR_NONE;
744
745 if (mode == I2C_MODE_MEM) {
746 /* Send Memory Address */
747 if (i2c_request_memory_read(hi2c, dev_addr, mem_addr,
748 mem_add_size, timeout_ref) != 0) {
749 goto bail;
750 }
751 }
752
Yann Gautierbb836ee2018-07-16 17:55:07 +0200753 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100754 * Send Slave Address.
755 * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
756 * and generate RESTART.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200757 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100758 if (xfer_count > MAX_NBYTE_SIZE) {
759 xfer_size = MAX_NBYTE_SIZE;
760 i2c_transfer_config(hi2c, dev_addr, xfer_size,
761 I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
762 } else {
763 xfer_size = xfer_count;
764 i2c_transfer_config(hi2c, dev_addr, xfer_size,
765 I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
766 }
767
768 do {
769 if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) {
770 goto bail;
771 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200772
Yann Gautierf3928f62019-02-14 11:15:03 +0100773 *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
774 p_buff++;
775 xfer_size--;
776 xfer_count--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200777
Yann Gautierf3928f62019-02-14 11:15:03 +0100778 if ((xfer_count != 0U) && (xfer_size == 0U)) {
779 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
780 timeout_ref) != 0) {
781 goto bail;
782 }
783
784 if (xfer_count > MAX_NBYTE_SIZE) {
785 xfer_size = MAX_NBYTE_SIZE;
786 i2c_transfer_config(hi2c, dev_addr,
787 xfer_size,
788 I2C_RELOAD_MODE,
789 I2C_NO_STARTSTOP);
790 } else {
791 xfer_size = xfer_count;
792 i2c_transfer_config(hi2c, dev_addr,
793 xfer_size,
794 I2C_AUTOEND_MODE,
795 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200796 }
797 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100798 } while (xfer_count > 0U);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200799
Yann Gautierf3928f62019-02-14 11:15:03 +0100800 /*
801 * No need to Check TC flag, with AUTOEND mode the stop
802 * is automatically generated.
803 * Wait until STOPF flag is reset.
804 */
805 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
806 goto bail;
807 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200808
809 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
810
Yann Gautierbb836ee2018-07-16 17:55:07 +0200811 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
812
Yann Gautierbb836ee2018-07-16 17:55:07 +0200813 hi2c->i2c_state = I2C_STATE_READY;
814 hi2c->i2c_mode = I2C_MODE_NONE;
815
Yann Gautierf3928f62019-02-14 11:15:03 +0100816 rc = 0;
817
818bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200819 hi2c->lock = 0;
Yann Gautierf3928f62019-02-14 11:15:03 +0100820 stm32mp_clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200821
Yann Gautierf3928f62019-02-14 11:15:03 +0100822 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200823}
824
825/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100826 * @brief Read an amount of data in blocking mode from a specific memory
827 * address.
828 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
829 * the configuration information for the specified I2C.
830 * @param dev_addr: Target device address
831 * @param mem_addr: Internal memory address
832 * @param mem_add_size: Size of internal memory address
833 * @param p_data: Pointer to data buffer
834 * @param size: Amount of data to be sent
835 * @param timeout_ms: Timeout duration in milliseconds
836 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200837 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100838int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
839 uint16_t mem_addr, uint16_t mem_add_size,
840 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200841{
Yann Gautierf3928f62019-02-14 11:15:03 +0100842 return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size,
843 p_data, size, timeout_ms, I2C_MODE_MEM);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200844}
845
846/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100847 * @brief Receives in master mode an amount of data in blocking mode.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200848 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
Yann Gautierf3928f62019-02-14 11:15:03 +0100849 * the configuration information for the specified I2C.
850 * @param dev_addr: Target device address
851 * @param p_data: Pointer to data buffer
852 * @param size: Amount of data to be sent
853 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200854 * @retval 0 if OK, negative value else
855 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100856int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
857 uint8_t *p_data, uint16_t size,
858 uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200859{
Yann Gautierf3928f62019-02-14 11:15:03 +0100860 return i2c_read(hi2c, dev_addr, 0, 0,
861 p_data, size, timeout_ms, I2C_MODE_MASTER);
862}
863
864/*
865 * @brief Checks if target device is ready for communication.
866 * @note This function is used with Memory devices
867 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
868 * the configuration information for the specified I2C.
869 * @param dev_addr: Target device address
870 * @param trials: Number of trials
871 * @param timeout_ms: Timeout duration in milliseconds
872 * @retval True if device is ready, false else
873 */
874bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
875 uint16_t dev_addr, uint32_t trials,
876 uint32_t timeout_ms)
877{
878 uint32_t i2c_trials = 0U;
879 bool rc = false;
880
Yann Gautierbb836ee2018-07-16 17:55:07 +0200881 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
Yann Gautierf3928f62019-02-14 11:15:03 +0100882 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200883 }
884
Yann Gautierf3928f62019-02-14 11:15:03 +0100885 stm32mp_clk_enable(hi2c->clock);
886
Yann Gautierbb836ee2018-07-16 17:55:07 +0200887 hi2c->lock = 1;
Yann Gautierf3928f62019-02-14 11:15:03 +0100888 hi2c->i2c_mode = I2C_MODE_NONE;
889
890 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
891 0U) {
892 goto bail;
893 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200894
895 hi2c->i2c_state = I2C_STATE_BUSY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100896 hi2c->i2c_err = I2C_ERROR_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200897
Yann Gautierf3928f62019-02-14 11:15:03 +0100898 do {
899 uint64_t timeout_ref;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200900
Yann Gautierf3928f62019-02-14 11:15:03 +0100901 /* Generate Start */
902 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) &
903 I2C_OAR1_OA1MODE) == 0) {
904 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
905 (((uint32_t)dev_addr & I2C_CR2_SADD) |
906 I2C_CR2_START | I2C_CR2_AUTOEND) &
907 ~I2C_CR2_RD_WRN);
908 } else {
909 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
910 (((uint32_t)dev_addr & I2C_CR2_SADD) |
911 I2C_CR2_START | I2C_CR2_ADD10) &
912 ~I2C_CR2_RD_WRN);
913 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200914
Yann Gautierf3928f62019-02-14 11:15:03 +0100915 /*
916 * No need to Check TC flag, with AUTOEND mode the stop
917 * is automatically generated.
918 * Wait until STOPF flag is set or a NACK flag is set.
919 */
920 timeout_ref = timeout_init_us(timeout_ms * 1000);
921 do {
922 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
923 (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) {
924 break;
925 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200926
Yann Gautierf3928f62019-02-14 11:15:03 +0100927 if (timeout_elapsed(timeout_ref)) {
928 notif_i2c_timeout(hi2c);
929 goto bail;
930 }
931 } while (true);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200932
Yann Gautierf3928f62019-02-14 11:15:03 +0100933 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
934 I2C_FLAG_AF) == 0U) {
935 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
936 timeout_ref) != 0) {
937 goto bail;
938 }
939
940 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
941 I2C_FLAG_STOPF);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200942
Yann Gautierf3928f62019-02-14 11:15:03 +0100943 hi2c->i2c_state = I2C_STATE_READY;
944
945 rc = true;
946 goto bail;
947 }
948
949 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) {
950 goto bail;
951 }
952
953 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
954
955 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
956
957 if (i2c_trials == trials) {
958 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
959 I2C_CR2_STOP);
960
961 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
962 timeout_ref) != 0) {
963 goto bail;
964 }
965
966 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
967 I2C_FLAG_STOPF);
968 }
969
970 i2c_trials++;
971 } while (i2c_trials < trials);
972
973 notif_i2c_timeout(hi2c);
974
975bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200976 hi2c->lock = 0;
Yann Gautierf3928f62019-02-14 11:15:03 +0100977 stm32mp_clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200978
Yann Gautierf3928f62019-02-14 11:15:03 +0100979 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200980}
Yann Gautierf3928f62019-02-14 11:15:03 +0100981