blob: bf6c3eeeb3f83455a14cef899f8cb818c3fde800 [file] [log] [blame]
Yann Gautierbb836ee2018-07-16 17:55:07 +02001/*
Yann Gautiera205a5c2021-08-30 15:06:54 +02002 * Copyright (c) 2016-2021, 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>
Yann Gautiera205a5c2021-08-30 15:06:54 +020016#include <drivers/clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017#include <drivers/delay_timer.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010018#include <drivers/st/stm32_gpio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000019#include <drivers/st/stm32_i2c.h>
20#include <lib/mmio.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010021#include <lib/utils.h>
Yann Gautierbb836ee2018-07-16 17:55:07 +020022
23/* STM32 I2C registers offsets */
24#define I2C_CR1 0x00U
25#define I2C_CR2 0x04U
26#define I2C_OAR1 0x08U
27#define I2C_OAR2 0x0CU
28#define I2C_TIMINGR 0x10U
29#define I2C_TIMEOUTR 0x14U
30#define I2C_ISR 0x18U
31#define I2C_ICR 0x1CU
32#define I2C_PECR 0x20U
33#define I2C_RXDR 0x24U
34#define I2C_TXDR 0x28U
35
Yann Gautierf3928f62019-02-14 11:15:03 +010036#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU
Yann Gautierbb836ee2018-07-16 17:55:07 +020037
38#define MAX_NBYTE_SIZE 255U
39
Yann Gautierf3928f62019-02-14 11:15:03 +010040#define I2C_NSEC_PER_SEC 1000000000L
Yann Gautierbb836ee2018-07-16 17:55:07 +020041
Yann Gautierf3928f62019-02-14 11:15:03 +010042/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
43#define I2C_TIMING 0x10D07DB5
Yann Gautierbb836ee2018-07-16 17:55:07 +020044
Yann Gautierf3928f62019-02-14 11:15:03 +010045static void notif_i2c_timeout(struct i2c_handle_s *hi2c)
46{
47 hi2c->i2c_err |= I2C_ERROR_TIMEOUT;
48 hi2c->i2c_mode = I2C_MODE_NONE;
49 hi2c->i2c_state = I2C_STATE_READY;
50}
Yann Gautierbb836ee2018-07-16 17:55:07 +020051
Yann Gautierf3928f62019-02-14 11:15:03 +010052/*
53 * @brief Configure I2C Analog noise filter.
54 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
55 * the configuration information for the specified I2C peripheral.
56 * @param analog_filter: New state of the Analog filter
57 * @retval 0 if OK, negative value else
58 */
59static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
60 uint32_t analog_filter)
61{
62 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
63 return -EBUSY;
64 }
65
66 hi2c->lock = 1;
67
68 hi2c->i2c_state = I2C_STATE_BUSY;
69
70 /* Disable the selected I2C peripheral */
71 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
72
73 /* Reset I2Cx ANOFF bit */
74 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF);
75
76 /* Set analog filter bit*/
77 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter);
78
79 /* Enable the selected I2C peripheral */
80 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
81
82 hi2c->i2c_state = I2C_STATE_READY;
83
84 hi2c->lock = 0;
85
86 return 0;
87}
88
89/*
90 * @brief Get I2C setup information from the device tree and set pinctrl
91 * configuration.
92 * @param fdt: Pointer to the device tree
93 * @param node: I2C node offset
94 * @param init: Ref to the initialization configuration structure
95 * @retval 0 if OK, negative value else
96 */
97int stm32_i2c_get_setup_from_fdt(void *fdt, int node,
98 struct stm32_i2c_init_s *init)
99{
100 const fdt32_t *cuint;
101
102 cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL);
103 if (cuint == NULL) {
104 init->rise_time = STM32_I2C_RISE_TIME_DEFAULT;
105 } else {
106 init->rise_time = fdt32_to_cpu(*cuint);
107 }
108
109 cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL);
110 if (cuint == NULL) {
111 init->fall_time = STM32_I2C_FALL_TIME_DEFAULT;
112 } else {
113 init->fall_time = fdt32_to_cpu(*cuint);
114 }
115
116 cuint = fdt_getprop(fdt, node, "clock-frequency", NULL);
117 if (cuint == NULL) {
118 init->speed_mode = STM32_I2C_SPEED_DEFAULT;
119 } else {
120 switch (fdt32_to_cpu(*cuint)) {
121 case STANDARD_RATE:
122 init->speed_mode = I2C_SPEED_STANDARD;
123 break;
124 case FAST_RATE:
125 init->speed_mode = I2C_SPEED_FAST;
126 break;
127 case FAST_PLUS_RATE:
128 init->speed_mode = I2C_SPEED_FAST_PLUS;
129 break;
130 default:
131 init->speed_mode = STM32_I2C_SPEED_DEFAULT;
132 break;
133 }
134 }
135
136 return dt_set_pinctrl_config(node);
137}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200138
139/*
140 * @brief Initialize the I2C device.
141 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
142 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100143 * @param init_data: Initialization configuration structure
Yann Gautierbb836ee2018-07-16 17:55:07 +0200144 * @retval 0 if OK, negative value else
145 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100146int stm32_i2c_init(struct i2c_handle_s *hi2c,
147 struct stm32_i2c_init_s *init_data)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200148{
Yann Gautierf3928f62019-02-14 11:15:03 +0100149 int rc = 0;
150 uint32_t timing = I2C_TIMING;
151
Yann Gautierbb836ee2018-07-16 17:55:07 +0200152 if (hi2c == NULL) {
153 return -ENOENT;
154 }
155
156 if (hi2c->i2c_state == I2C_STATE_RESET) {
157 hi2c->lock = 0;
158 }
159
160 hi2c->i2c_state = I2C_STATE_BUSY;
161
Yann Gautiera205a5c2021-08-30 15:06:54 +0200162 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100163
Yann Gautierbb836ee2018-07-16 17:55:07 +0200164 /* Disable the selected I2C peripheral */
165 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
166
167 /* Configure I2Cx: Frequency range */
168 mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
Yann Gautierf3928f62019-02-14 11:15:03 +0100169 timing & TIMINGR_CLEAR_MASK);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200170
171 /* Disable Own Address1 before set the Own Address1 configuration */
172 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
173
174 /* Configure I2Cx: Own Address1 and ack own address1 mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100175 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200176 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100177 I2C_OAR1_OA1EN | init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200178 } else { /* I2C_ADDRESSINGMODE_10BIT */
179 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
180 I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
Yann Gautierf3928f62019-02-14 11:15:03 +0100181 init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200182 }
183
Yann Gautierf3928f62019-02-14 11:15:03 +0100184 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0);
185
Yann Gautierbb836ee2018-07-16 17:55:07 +0200186 /* Configure I2Cx: Addressing Master mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100187 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
188 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200189 }
190
191 /*
192 * Enable the AUTOEND by default, and enable NACK
Yann Gautierf3928f62019-02-14 11:15:03 +0100193 * (should be disabled only during Slave process).
Yann Gautierbb836ee2018-07-16 17:55:07 +0200194 */
195 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
196 I2C_CR2_AUTOEND | I2C_CR2_NACK);
197
198 /* Disable Own Address2 before set the Own Address2 configuration */
199 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
200
201 /* Configure I2Cx: Dual mode and Own Address2 */
202 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
Yann Gautierf3928f62019-02-14 11:15:03 +0100203 init_data->dual_address_mode |
204 init_data->own_address2 |
205 (init_data->own_address2_masks << 8));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200206
207 /* Configure I2Cx: Generalcall and NoStretch mode */
208 mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100209 init_data->general_call_mode |
210 init_data->no_stretch_mode);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200211
212 /* Enable the selected I2C peripheral */
213 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
214
215 hi2c->i2c_err = I2C_ERROR_NONE;
216 hi2c->i2c_state = I2C_STATE_READY;
217 hi2c->i2c_mode = I2C_MODE_NONE;
218
Yann Gautierf3928f62019-02-14 11:15:03 +0100219 rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ?
220 I2C_ANALOGFILTER_ENABLE :
221 I2C_ANALOGFILTER_DISABLE);
222 if (rc != 0) {
223 ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
Yann Gautiera205a5c2021-08-30 15:06:54 +0200224 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100225 return rc;
226 }
227
Yann Gautiera205a5c2021-08-30 15:06:54 +0200228 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100229
230 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200231}
232
233/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100234 * @brief I2C Tx data register flush process.
235 * @param hi2c: I2C handle
236 * @retval None
Yann Gautierbb836ee2018-07-16 17:55:07 +0200237 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100238static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200239{
Yann Gautierf3928f62019-02-14 11:15:03 +0100240 /*
241 * If a pending TXIS flag is set,
242 * write a dummy data in TXDR to clear it.
243 */
244 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
245 0U) {
246 mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200247 }
248
Yann Gautierf3928f62019-02-14 11:15:03 +0100249 /* Flush TX register if not empty */
250 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
251 0U) {
252 mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
253 I2C_FLAG_TXE);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200254 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100255}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200256
Yann Gautierf3928f62019-02-14 11:15:03 +0100257/*
258 * @brief This function handles I2C Communication timeout.
259 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
260 * the configuration information for the specified I2C.
261 * @param flag: Specifies the I2C flag to check
262 * @param awaited_value: The awaited bit value for the flag (0 or 1)
263 * @param timeout_ref: Reference to target timeout
264 * @retval 0 if OK, negative value else
265 */
266static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
267 uint8_t awaited_value, uint64_t timeout_ref)
268{
269 for ( ; ; ) {
270 uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200271
Yann Gautierf3928f62019-02-14 11:15:03 +0100272 if (!!(isr & flag) != !!awaited_value) {
273 return 0;
274 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200275
Yann Gautierf3928f62019-02-14 11:15:03 +0100276 if (timeout_elapsed(timeout_ref)) {
277 notif_i2c_timeout(hi2c);
278 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200279
Yann Gautierf3928f62019-02-14 11:15:03 +0100280 return -EIO;
281 }
282 }
283}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200284
Yann Gautierf3928f62019-02-14 11:15:03 +0100285/*
286 * @brief This function handles Acknowledge failed detection during
287 * an I2C Communication.
288 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
289 * the configuration information for the specified I2C.
290 * @param timeout_ref: Reference to target timeout
291 * @retval 0 if OK, negative value else
292 */
293static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
294{
295 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
296 return 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200297 }
298
299 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100300 * Wait until STOP Flag is reset.
301 * AutoEnd should be initiate after AF.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200302 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100303 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
304 I2C_FLAG_STOPF) == 0U) {
305 if (timeout_elapsed(timeout_ref)) {
306 notif_i2c_timeout(hi2c);
307 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200308
Yann Gautierbb836ee2018-07-16 17:55:07 +0200309 return -EIO;
310 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200311 }
312
Yann Gautierf3928f62019-02-14 11:15:03 +0100313 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
314
Yann Gautierbb836ee2018-07-16 17:55:07 +0200315 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
316
Yann Gautierf3928f62019-02-14 11:15:03 +0100317 i2c_flush_txdr(hi2c);
318
Yann Gautierbb836ee2018-07-16 17:55:07 +0200319 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
320
Yann Gautierf3928f62019-02-14 11:15:03 +0100321 hi2c->i2c_err |= I2C_ERROR_AF;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200322 hi2c->i2c_state = I2C_STATE_READY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100323 hi2c->i2c_mode = I2C_MODE_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200324
325 hi2c->lock = 0;
326
Yann Gautierf3928f62019-02-14 11:15:03 +0100327 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200328}
329
330/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100331 * @brief This function handles I2C Communication timeout for specific usage
332 * of TXIS flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200333 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
334 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100335 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200336 * @retval 0 if OK, negative value else
337 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100338static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200339{
Yann Gautierf3928f62019-02-14 11:15:03 +0100340 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
341 I2C_FLAG_TXIS) == 0U) {
342 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200343 return -EIO;
344 }
345
Yann Gautierf3928f62019-02-14 11:15:03 +0100346 if (timeout_elapsed(timeout_ref)) {
347 notif_i2c_timeout(hi2c);
348 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200349
Yann Gautierf3928f62019-02-14 11:15:03 +0100350 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200351 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200352 }
353
Yann Gautierbb836ee2018-07-16 17:55:07 +0200354 return 0;
355}
356
357/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100358 * @brief This function handles I2C Communication timeout for specific
359 * usage of STOP flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200360 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
361 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100362 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200363 * @retval 0 if OK, negative value else
364 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100365static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200366{
Yann Gautierf3928f62019-02-14 11:15:03 +0100367 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
368 I2C_FLAG_STOPF) == 0U) {
369 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
370 return -EIO;
371 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200372
Yann Gautierf3928f62019-02-14 11:15:03 +0100373 if (timeout_elapsed(timeout_ref)) {
374 notif_i2c_timeout(hi2c);
375 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200376
Yann Gautierbb836ee2018-07-16 17:55:07 +0200377 return -EIO;
378 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100379 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200380
Yann Gautierf3928f62019-02-14 11:15:03 +0100381 return 0;
382}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200383
Yann Gautierf3928f62019-02-14 11:15:03 +0100384/*
385 * @brief Handles I2Cx communication when starting transfer or during transfer
386 * (TC or TCR flag are set).
387 * @param hi2c: I2C handle
388 * @param dev_addr: Specifies the slave address to be programmed
389 * @param size: Specifies the number of bytes to be programmed.
390 * This parameter must be a value between 0 and 255.
391 * @param i2c_mode: New state of the I2C START condition generation.
392 * This parameter can be one of the following values:
393 * @arg @ref I2C_RELOAD_MODE: Enable Reload mode.
394 * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
395 * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
396 * @param request: New state of the I2C START condition generation.
397 * This parameter can be one of the following values:
398 * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
399 * @arg @ref I2C_GENERATE_STOP: Generate stop condition
400 * (size should be set to 0).
401 * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
402 * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
403 * @retval None
404 */
405static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
406 uint16_t size, uint32_t i2c_mode,
407 uint32_t request)
408{
409 uint32_t clr_value, set_value;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200410
Yann Gautierf3928f62019-02-14 11:15:03 +0100411 clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
412 I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
413 (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200414
Yann Gautierf3928f62019-02-14 11:15:03 +0100415 set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
416 (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
417 i2c_mode | request;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200418
Yann Gautierf3928f62019-02-14 11:15:03 +0100419 mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200420}
421
422/*
423 * @brief Master sends target device address followed by internal memory
424 * address for write request.
425 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
426 * the configuration information for the specified I2C.
427 * @param dev_addr: Target device address
428 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100429 * @param mem_add_size: Size of internal memory address
430 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200431 * @retval 0 if OK, negative value else
432 */
433static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
434 uint16_t dev_addr, uint16_t mem_addr,
Yann Gautierf3928f62019-02-14 11:15:03 +0100435 uint16_t mem_add_size, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200436{
437 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
438 I2C_GENERATE_START_WRITE);
439
Yann Gautierf3928f62019-02-14 11:15:03 +0100440 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200441 return -EIO;
442 }
443
444 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
445 /* Send Memory Address */
446 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
447 (uint8_t)(mem_addr & 0x00FFU));
448 } else {
449 /* Send MSB of Memory Address */
450 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
451 (uint8_t)((mem_addr & 0xFF00U) >> 8));
452
Yann Gautierf3928f62019-02-14 11:15:03 +0100453 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200454 return -EIO;
455 }
456
457 /* Send LSB of Memory Address */
458 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
459 (uint8_t)(mem_addr & 0x00FFU));
460 }
461
Yann Gautierf3928f62019-02-14 11:15:03 +0100462 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200463 return -EIO;
464 }
465
466 return 0;
467}
468
469/*
470 * @brief Master sends target device address followed by internal memory
471 * address for read request.
472 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
473 * the configuration information for the specified I2C.
474 * @param dev_addr: Target device address
475 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100476 * @param mem_add_size: Size of internal memory address
477 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200478 * @retval 0 if OK, negative value else
479 */
480static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
481 uint16_t mem_addr, uint16_t mem_add_size,
Yann Gautierf3928f62019-02-14 11:15:03 +0100482 uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200483{
484 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
485 I2C_GENERATE_START_WRITE);
486
Yann Gautierf3928f62019-02-14 11:15:03 +0100487 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200488 return -EIO;
489 }
490
491 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
492 /* Send Memory Address */
493 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
494 (uint8_t)(mem_addr & 0x00FFU));
495 } else {
496 /* Send MSB of Memory Address */
497 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
498 (uint8_t)((mem_addr & 0xFF00U) >> 8));
499
Yann Gautierf3928f62019-02-14 11:15:03 +0100500 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200501 return -EIO;
502 }
503
504 /* Send LSB of Memory Address */
505 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
506 (uint8_t)(mem_addr & 0x00FFU));
507 }
508
Yann Gautierf3928f62019-02-14 11:15:03 +0100509 if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200510 return -EIO;
511 }
512
513 return 0;
514}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200515/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100516 * @brief Generic function to write an amount of data in blocking mode
517 * (for Memory Mode and Master Mode)
518 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
519 * the configuration information for the specified I2C.
520 * @param dev_addr: Target device address
521 * @param mem_addr: Internal memory address (if Memory Mode)
522 * @param mem_add_size: Size of internal memory address (if Memory Mode)
523 * @param p_data: Pointer to data buffer
524 * @param size: Amount of data to be sent
525 * @param timeout_ms: Timeout duration in milliseconds
526 * @param mode: Communication mode
527 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200528 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100529static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
530 uint16_t mem_addr, uint16_t mem_add_size,
531 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
532 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200533{
Yann Gautierf3928f62019-02-14 11:15:03 +0100534 uint64_t timeout_ref;
535 int rc = -EIO;
536 uint8_t *p_buff = p_data;
537 uint32_t xfer_size;
538 uint32_t xfer_count = size;
539
540 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
541 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200542 }
543
Yann Gautierf3928f62019-02-14 11:15:03 +0100544 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
545 return -EBUSY;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200546 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200547
Yann Gautierf3928f62019-02-14 11:15:03 +0100548 if ((p_data == NULL) || (size == 0U)) {
549 return -EINVAL;
550 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200551
Yann Gautiera205a5c2021-08-30 15:06:54 +0200552 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100553
554 hi2c->lock = 1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200555
Yann Gautierf3928f62019-02-14 11:15:03 +0100556 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
557 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
558 goto bail;
559 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200560
Yann Gautierf3928f62019-02-14 11:15:03 +0100561 hi2c->i2c_state = I2C_STATE_BUSY_TX;
562 hi2c->i2c_mode = mode;
563 hi2c->i2c_err = I2C_ERROR_NONE;
564
565 timeout_ref = timeout_init_us(timeout_ms * 1000);
566
567 if (mode == I2C_MODE_MEM) {
568 /* In Memory Mode, Send Slave Address and Memory Address */
569 if (i2c_request_memory_write(hi2c, dev_addr, mem_addr,
570 mem_add_size, timeout_ref) != 0) {
571 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200572 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200573
Yann Gautierf3928f62019-02-14 11:15:03 +0100574 if (xfer_count > MAX_NBYTE_SIZE) {
575 xfer_size = MAX_NBYTE_SIZE;
576 i2c_transfer_config(hi2c, dev_addr, xfer_size,
577 I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
578 } else {
579 xfer_size = xfer_count;
580 i2c_transfer_config(hi2c, dev_addr, xfer_size,
581 I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
582 }
583 } else {
584 /* In Master Mode, Send Slave Address */
585 if (xfer_count > MAX_NBYTE_SIZE) {
586 xfer_size = MAX_NBYTE_SIZE;
587 i2c_transfer_config(hi2c, dev_addr, xfer_size,
588 I2C_RELOAD_MODE,
589 I2C_GENERATE_START_WRITE);
590 } else {
591 xfer_size = xfer_count;
592 i2c_transfer_config(hi2c, dev_addr, xfer_size,
593 I2C_AUTOEND_MODE,
594 I2C_GENERATE_START_WRITE);
595 }
596 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200597
Yann Gautierf3928f62019-02-14 11:15:03 +0100598 do {
599 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
600 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200601 }
602
Yann Gautierf3928f62019-02-14 11:15:03 +0100603 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff);
604 p_buff++;
605 xfer_count--;
606 xfer_size--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200607
Yann Gautierf3928f62019-02-14 11:15:03 +0100608 if ((xfer_count != 0U) && (xfer_size == 0U)) {
609 /* Wait until TCR flag is set */
610 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
611 timeout_ref) != 0) {
612 goto bail;
613 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200614
Yann Gautierf3928f62019-02-14 11:15:03 +0100615 if (xfer_count > MAX_NBYTE_SIZE) {
616 xfer_size = MAX_NBYTE_SIZE;
617 i2c_transfer_config(hi2c, dev_addr,
618 xfer_size,
619 I2C_RELOAD_MODE,
620 I2C_NO_STARTSTOP);
621 } else {
622 xfer_size = xfer_count;
623 i2c_transfer_config(hi2c, dev_addr,
624 xfer_size,
625 I2C_AUTOEND_MODE,
626 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200627 }
628 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100629
630 } while (xfer_count > 0U);
631
632 /*
633 * No need to Check TC flag, with AUTOEND mode the stop
634 * is automatically generated.
635 * Wait until STOPF flag is reset.
636 */
637 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
638 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200639 }
640
Yann Gautierf3928f62019-02-14 11:15:03 +0100641 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
642
643 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
644
645 hi2c->i2c_state = I2C_STATE_READY;
646 hi2c->i2c_mode = I2C_MODE_NONE;
647
648 rc = 0;
649
650bail:
651 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200652 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100653
654 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200655}
656
657/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100658 * @brief Write an amount of data in blocking mode to a specific memory
659 * address.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200660 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
661 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100662 * @param dev_addr: Target device address
663 * @param mem_addr: Internal memory address
664 * @param mem_add_size: Size of internal memory address
665 * @param p_data: Pointer to data buffer
666 * @param size: Amount of data to be sent
667 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200668 * @retval 0 if OK, negative value else
669 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100670int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
671 uint16_t mem_addr, uint16_t mem_add_size,
672 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200673{
Yann Gautierf3928f62019-02-14 11:15:03 +0100674 return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size,
675 p_data, size, timeout_ms, I2C_MODE_MEM);
676}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200677
Yann Gautierf3928f62019-02-14 11:15:03 +0100678/*
679 * @brief Transmits in master mode an amount of data in blocking mode.
680 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
681 * the configuration information for the specified I2C.
682 * @param dev_addr: Target device address
683 * @param p_data: Pointer to data buffer
684 * @param size: Amount of data to be sent
685 * @param timeout_ms: Timeout duration in milliseconds
686 * @retval 0 if OK, negative value else
687 */
688int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
689 uint8_t *p_data, uint16_t size,
690 uint32_t timeout_ms)
691{
692 return i2c_write(hi2c, dev_addr, 0, 0,
693 p_data, size, timeout_ms, I2C_MODE_MASTER);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200694}
695
696/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100697 * @brief Generic function to read an amount of data in blocking mode
698 * (for Memory Mode and Master Mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200699 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
700 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100701 * @param dev_addr: Target device address
702 * @param mem_addr: Internal memory address (if Memory Mode)
703 * @param mem_add_size: Size of internal memory address (if Memory Mode)
704 * @param p_data: Pointer to data buffer
705 * @param size: Amount of data to be sent
706 * @param timeout_ms: Timeout duration in milliseconds
707 * @param mode: Communication mode
Yann Gautierbb836ee2018-07-16 17:55:07 +0200708 * @retval 0 if OK, negative value else
709 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100710static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
711 uint16_t mem_addr, uint16_t mem_add_size,
712 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
713 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200714{
Yann Gautierf3928f62019-02-14 11:15:03 +0100715 uint64_t timeout_ref;
716 int rc = -EIO;
717 uint8_t *p_buff = p_data;
718 uint32_t xfer_count = size;
719 uint32_t xfer_size;
720
721 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
722 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200723 }
724
Yann Gautierf3928f62019-02-14 11:15:03 +0100725 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
726 return -EBUSY;
727 }
728
729 if ((p_data == NULL) || (size == 0U)) {
730 return -EINVAL;
731 }
732
Yann Gautiera205a5c2021-08-30 15:06:54 +0200733 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100734
735 hi2c->lock = 1;
736
737 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
738 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
739 goto bail;
740 }
741
742 hi2c->i2c_state = I2C_STATE_BUSY_RX;
743 hi2c->i2c_mode = mode;
744 hi2c->i2c_err = I2C_ERROR_NONE;
745
746 if (mode == I2C_MODE_MEM) {
747 /* Send Memory Address */
748 if (i2c_request_memory_read(hi2c, dev_addr, mem_addr,
749 mem_add_size, timeout_ref) != 0) {
750 goto bail;
751 }
752 }
753
Yann Gautierbb836ee2018-07-16 17:55:07 +0200754 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100755 * Send Slave Address.
756 * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
757 * and generate RESTART.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200758 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100759 if (xfer_count > MAX_NBYTE_SIZE) {
760 xfer_size = MAX_NBYTE_SIZE;
761 i2c_transfer_config(hi2c, dev_addr, xfer_size,
762 I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
763 } else {
764 xfer_size = xfer_count;
765 i2c_transfer_config(hi2c, dev_addr, xfer_size,
766 I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
767 }
768
769 do {
770 if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) {
771 goto bail;
772 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200773
Yann Gautierf3928f62019-02-14 11:15:03 +0100774 *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
775 p_buff++;
776 xfer_size--;
777 xfer_count--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200778
Yann Gautierf3928f62019-02-14 11:15:03 +0100779 if ((xfer_count != 0U) && (xfer_size == 0U)) {
780 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
781 timeout_ref) != 0) {
782 goto bail;
783 }
784
785 if (xfer_count > MAX_NBYTE_SIZE) {
786 xfer_size = MAX_NBYTE_SIZE;
787 i2c_transfer_config(hi2c, dev_addr,
788 xfer_size,
789 I2C_RELOAD_MODE,
790 I2C_NO_STARTSTOP);
791 } else {
792 xfer_size = xfer_count;
793 i2c_transfer_config(hi2c, dev_addr,
794 xfer_size,
795 I2C_AUTOEND_MODE,
796 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200797 }
798 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100799 } while (xfer_count > 0U);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200800
Yann Gautierf3928f62019-02-14 11:15:03 +0100801 /*
802 * No need to Check TC flag, with AUTOEND mode the stop
803 * is automatically generated.
804 * Wait until STOPF flag is reset.
805 */
806 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
807 goto bail;
808 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200809
810 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
811
Yann Gautierbb836ee2018-07-16 17:55:07 +0200812 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
813
Yann Gautierbb836ee2018-07-16 17:55:07 +0200814 hi2c->i2c_state = I2C_STATE_READY;
815 hi2c->i2c_mode = I2C_MODE_NONE;
816
Yann Gautierf3928f62019-02-14 11:15:03 +0100817 rc = 0;
818
819bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200820 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200821 clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200822
Yann Gautierf3928f62019-02-14 11:15:03 +0100823 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200824}
825
826/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100827 * @brief Read an amount of data in blocking mode from a specific memory
828 * address.
829 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
830 * the configuration information for the specified I2C.
831 * @param dev_addr: Target device address
832 * @param mem_addr: Internal memory address
833 * @param mem_add_size: Size of internal memory address
834 * @param p_data: Pointer to data buffer
835 * @param size: Amount of data to be sent
836 * @param timeout_ms: Timeout duration in milliseconds
837 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200838 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100839int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
840 uint16_t mem_addr, uint16_t mem_add_size,
841 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200842{
Yann Gautierf3928f62019-02-14 11:15:03 +0100843 return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size,
844 p_data, size, timeout_ms, I2C_MODE_MEM);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200845}
846
847/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100848 * @brief Receives in master mode an amount of data in blocking mode.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200849 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
Yann Gautierf3928f62019-02-14 11:15:03 +0100850 * the configuration information for the specified I2C.
851 * @param dev_addr: Target device address
852 * @param p_data: Pointer to data buffer
853 * @param size: Amount of data to be sent
854 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200855 * @retval 0 if OK, negative value else
856 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100857int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
858 uint8_t *p_data, uint16_t size,
859 uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200860{
Yann Gautierf3928f62019-02-14 11:15:03 +0100861 return i2c_read(hi2c, dev_addr, 0, 0,
862 p_data, size, timeout_ms, I2C_MODE_MASTER);
863}
864
865/*
866 * @brief Checks if target device is ready for communication.
867 * @note This function is used with Memory devices
868 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
869 * the configuration information for the specified I2C.
870 * @param dev_addr: Target device address
871 * @param trials: Number of trials
872 * @param timeout_ms: Timeout duration in milliseconds
873 * @retval True if device is ready, false else
874 */
875bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
876 uint16_t dev_addr, uint32_t trials,
877 uint32_t timeout_ms)
878{
879 uint32_t i2c_trials = 0U;
880 bool rc = false;
881
Yann Gautierbb836ee2018-07-16 17:55:07 +0200882 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
Yann Gautierf3928f62019-02-14 11:15:03 +0100883 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200884 }
885
Yann Gautiera205a5c2021-08-30 15:06:54 +0200886 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100887
Yann Gautierbb836ee2018-07-16 17:55:07 +0200888 hi2c->lock = 1;
Yann Gautierf3928f62019-02-14 11:15:03 +0100889 hi2c->i2c_mode = I2C_MODE_NONE;
890
891 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
892 0U) {
893 goto bail;
894 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200895
896 hi2c->i2c_state = I2C_STATE_BUSY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100897 hi2c->i2c_err = I2C_ERROR_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200898
Yann Gautierf3928f62019-02-14 11:15:03 +0100899 do {
900 uint64_t timeout_ref;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200901
Yann Gautierf3928f62019-02-14 11:15:03 +0100902 /* Generate Start */
903 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) &
904 I2C_OAR1_OA1MODE) == 0) {
905 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
906 (((uint32_t)dev_addr & I2C_CR2_SADD) |
907 I2C_CR2_START | I2C_CR2_AUTOEND) &
908 ~I2C_CR2_RD_WRN);
909 } else {
910 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
911 (((uint32_t)dev_addr & I2C_CR2_SADD) |
912 I2C_CR2_START | I2C_CR2_ADD10) &
913 ~I2C_CR2_RD_WRN);
914 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200915
Yann Gautierf3928f62019-02-14 11:15:03 +0100916 /*
917 * No need to Check TC flag, with AUTOEND mode the stop
918 * is automatically generated.
919 * Wait until STOPF flag is set or a NACK flag is set.
920 */
921 timeout_ref = timeout_init_us(timeout_ms * 1000);
922 do {
923 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
924 (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) {
925 break;
926 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200927
Yann Gautierf3928f62019-02-14 11:15:03 +0100928 if (timeout_elapsed(timeout_ref)) {
929 notif_i2c_timeout(hi2c);
930 goto bail;
931 }
932 } while (true);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200933
Yann Gautierf3928f62019-02-14 11:15:03 +0100934 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
935 I2C_FLAG_AF) == 0U) {
936 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
937 timeout_ref) != 0) {
938 goto bail;
939 }
940
941 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
942 I2C_FLAG_STOPF);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200943
Yann Gautierf3928f62019-02-14 11:15:03 +0100944 hi2c->i2c_state = I2C_STATE_READY;
945
946 rc = true;
947 goto bail;
948 }
949
950 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) {
951 goto bail;
952 }
953
954 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
955
956 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
957
958 if (i2c_trials == trials) {
959 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
960 I2C_CR2_STOP);
961
962 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
963 timeout_ref) != 0) {
964 goto bail;
965 }
966
967 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
968 I2C_FLAG_STOPF);
969 }
970
971 i2c_trials++;
972 } while (i2c_trials < trials);
973
974 notif_i2c_timeout(hi2c);
975
976bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200977 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200978 clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200979
Yann Gautierf3928f62019-02-14 11:15:03 +0100980 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200981}
Yann Gautierf3928f62019-02-14 11:15:03 +0100982