blob: 32cecff6a3cd5dc6007e67fbd9a4707d7eeb0906 [file] [log] [blame]
Yann Gautierbb836ee2018-07-16 17:55:07 +02001/*
Yann Gautier42532b62019-10-02 11:46:20 +02002 * Copyright (c) 2016-2024, 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 <common/debug.h>
Yann Gautier42532b62019-10-02 11:46:20 +020012#include <common/fdt_wrappers.h>
Yann Gautiera205a5c2021-08-30 15:06:54 +020013#include <drivers/clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014#include <drivers/delay_timer.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010015#include <drivers/st/stm32_gpio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <drivers/st/stm32_i2c.h>
17#include <lib/mmio.h>
Yann Gautierf3928f62019-02-14 11:15:03 +010018#include <lib/utils.h>
Yann Gautier42532b62019-10-02 11:46:20 +020019#include <libfdt.h>
20
21#include <platform_def.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{
Yann Gautier42532b62019-10-02 11:46:20 +0200100 uint32_t read_val;
Yann Gautierf3928f62019-02-14 11:15:03 +0100101
Yann Gautier42532b62019-10-02 11:46:20 +0200102 init->rise_time = fdt_read_uint32_default(fdt, node,
103 "i2c-scl-rising-time-ns",
104 STM32_I2C_RISE_TIME_DEFAULT);
Yann Gautierf3928f62019-02-14 11:15:03 +0100105
Yann Gautier42532b62019-10-02 11:46:20 +0200106 init->fall_time = fdt_read_uint32_default(fdt, node,
107 "i2c-scl-falling-time-ns",
108 STM32_I2C_FALL_TIME_DEFAULT);
Yann Gautierf3928f62019-02-14 11:15:03 +0100109
Yann Gautier42532b62019-10-02 11:46:20 +0200110 read_val = fdt_read_uint32_default(fdt, node, "clock-frequency",
111 STANDARD_RATE);
112 switch (read_val) {
113 case FAST_PLUS_RATE:
114 init->speed_mode = I2C_SPEED_FAST_PLUS;
115 break;
116 case FAST_RATE:
117 init->speed_mode = I2C_SPEED_FAST;
118 break;
119 case STANDARD_RATE:
120 default:
121 init->speed_mode = I2C_SPEED_STANDARD;
122 break;
Yann Gautierf3928f62019-02-14 11:15:03 +0100123 }
124
125 return dt_set_pinctrl_config(node);
126}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200127
128/*
129 * @brief Initialize the I2C device.
130 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
131 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100132 * @param init_data: Initialization configuration structure
Yann Gautierbb836ee2018-07-16 17:55:07 +0200133 * @retval 0 if OK, negative value else
134 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100135int stm32_i2c_init(struct i2c_handle_s *hi2c,
136 struct stm32_i2c_init_s *init_data)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200137{
Yann Gautierf3928f62019-02-14 11:15:03 +0100138 int rc = 0;
139 uint32_t timing = I2C_TIMING;
140
Yann Gautierbb836ee2018-07-16 17:55:07 +0200141 if (hi2c == NULL) {
142 return -ENOENT;
143 }
144
145 if (hi2c->i2c_state == I2C_STATE_RESET) {
146 hi2c->lock = 0;
147 }
148
149 hi2c->i2c_state = I2C_STATE_BUSY;
150
Yann Gautiera205a5c2021-08-30 15:06:54 +0200151 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100152
Yann Gautierbb836ee2018-07-16 17:55:07 +0200153 /* Disable the selected I2C peripheral */
154 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
155
156 /* Configure I2Cx: Frequency range */
157 mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR,
Yann Gautierf3928f62019-02-14 11:15:03 +0100158 timing & TIMINGR_CLEAR_MASK);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200159
160 /* Disable Own Address1 before set the Own Address1 configuration */
161 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN);
162
163 /* Configure I2Cx: Own Address1 and ack own address1 mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100164 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200165 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100166 I2C_OAR1_OA1EN | init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200167 } else { /* I2C_ADDRESSINGMODE_10BIT */
168 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1,
169 I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE |
Yann Gautierf3928f62019-02-14 11:15:03 +0100170 init_data->own_address1);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200171 }
172
Yann Gautierf3928f62019-02-14 11:15:03 +0100173 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0);
174
Yann Gautierbb836ee2018-07-16 17:55:07 +0200175 /* Configure I2Cx: Addressing Master mode */
Yann Gautierf3928f62019-02-14 11:15:03 +0100176 if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) {
177 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200178 }
179
180 /*
181 * Enable the AUTOEND by default, and enable NACK
Yann Gautierf3928f62019-02-14 11:15:03 +0100182 * (should be disabled only during Slave process).
Yann Gautierbb836ee2018-07-16 17:55:07 +0200183 */
184 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
185 I2C_CR2_AUTOEND | I2C_CR2_NACK);
186
187 /* Disable Own Address2 before set the Own Address2 configuration */
188 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE);
189
190 /* Configure I2Cx: Dual mode and Own Address2 */
191 mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2,
Yann Gautierf3928f62019-02-14 11:15:03 +0100192 init_data->dual_address_mode |
193 init_data->own_address2 |
194 (init_data->own_address2_masks << 8));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200195
196 /* Configure I2Cx: Generalcall and NoStretch mode */
197 mmio_write_32(hi2c->i2c_base_addr + I2C_CR1,
Yann Gautierf3928f62019-02-14 11:15:03 +0100198 init_data->general_call_mode |
199 init_data->no_stretch_mode);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200200
201 /* Enable the selected I2C peripheral */
202 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE);
203
204 hi2c->i2c_err = I2C_ERROR_NONE;
205 hi2c->i2c_state = I2C_STATE_READY;
206 hi2c->i2c_mode = I2C_MODE_NONE;
207
Yann Gautierf3928f62019-02-14 11:15:03 +0100208 rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ?
209 I2C_ANALOGFILTER_ENABLE :
210 I2C_ANALOGFILTER_DISABLE);
211 if (rc != 0) {
212 ERROR("Cannot initialize I2C analog filter (%d)\n", rc);
Yann Gautiera205a5c2021-08-30 15:06:54 +0200213 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100214 return rc;
215 }
216
Yann Gautiera205a5c2021-08-30 15:06:54 +0200217 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100218
219 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200220}
221
222/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100223 * @brief I2C Tx data register flush process.
224 * @param hi2c: I2C handle
225 * @retval None
Yann Gautierbb836ee2018-07-16 17:55:07 +0200226 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100227static void i2c_flush_txdr(struct i2c_handle_s *hi2c)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200228{
Yann Gautierf3928f62019-02-14 11:15:03 +0100229 /*
230 * If a pending TXIS flag is set,
231 * write a dummy data in TXDR to clear it.
232 */
233 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) !=
234 0U) {
235 mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200236 }
237
Yann Gautierf3928f62019-02-14 11:15:03 +0100238 /* Flush TX register if not empty */
239 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) ==
240 0U) {
241 mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR,
242 I2C_FLAG_TXE);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200243 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100244}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200245
Yann Gautierf3928f62019-02-14 11:15:03 +0100246/*
247 * @brief This function handles I2C Communication timeout.
248 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
249 * the configuration information for the specified I2C.
250 * @param flag: Specifies the I2C flag to check
251 * @param awaited_value: The awaited bit value for the flag (0 or 1)
252 * @param timeout_ref: Reference to target timeout
253 * @retval 0 if OK, negative value else
254 */
255static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag,
256 uint8_t awaited_value, uint64_t timeout_ref)
257{
258 for ( ; ; ) {
259 uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200260
Yann Gautierf3928f62019-02-14 11:15:03 +0100261 if (!!(isr & flag) != !!awaited_value) {
262 return 0;
263 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200264
Yann Gautierf3928f62019-02-14 11:15:03 +0100265 if (timeout_elapsed(timeout_ref)) {
266 notif_i2c_timeout(hi2c);
267 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200268
Yann Gautierf3928f62019-02-14 11:15:03 +0100269 return -EIO;
270 }
271 }
272}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200273
Yann Gautierf3928f62019-02-14 11:15:03 +0100274/*
275 * @brief This function handles Acknowledge failed detection during
276 * an I2C Communication.
277 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
278 * the configuration information for the specified I2C.
279 * @param timeout_ref: Reference to target timeout
280 * @retval 0 if OK, negative value else
281 */
282static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
283{
284 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) {
285 return 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200286 }
287
288 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100289 * Wait until STOP Flag is reset.
290 * AutoEnd should be initiate after AF.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200291 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100292 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
293 I2C_FLAG_STOPF) == 0U) {
294 if (timeout_elapsed(timeout_ref)) {
295 notif_i2c_timeout(hi2c);
296 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200297
Yann Gautierbb836ee2018-07-16 17:55:07 +0200298 return -EIO;
299 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200300 }
301
Yann Gautierf3928f62019-02-14 11:15:03 +0100302 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
303
Yann Gautierbb836ee2018-07-16 17:55:07 +0200304 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
305
Yann Gautierf3928f62019-02-14 11:15:03 +0100306 i2c_flush_txdr(hi2c);
307
Yann Gautierbb836ee2018-07-16 17:55:07 +0200308 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
309
Yann Gautierf3928f62019-02-14 11:15:03 +0100310 hi2c->i2c_err |= I2C_ERROR_AF;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200311 hi2c->i2c_state = I2C_STATE_READY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100312 hi2c->i2c_mode = I2C_MODE_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200313
314 hi2c->lock = 0;
315
Yann Gautierf3928f62019-02-14 11:15:03 +0100316 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200317}
318
319/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100320 * @brief This function handles I2C Communication timeout for specific usage
321 * of TXIS flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200322 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
323 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100324 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200325 * @retval 0 if OK, negative value else
326 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100327static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200328{
Yann Gautierf3928f62019-02-14 11:15:03 +0100329 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
330 I2C_FLAG_TXIS) == 0U) {
331 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200332 return -EIO;
333 }
334
Yann Gautierf3928f62019-02-14 11:15:03 +0100335 if (timeout_elapsed(timeout_ref)) {
336 notif_i2c_timeout(hi2c);
337 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200338
Yann Gautierf3928f62019-02-14 11:15:03 +0100339 return -EIO;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200340 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200341 }
342
Yann Gautierbb836ee2018-07-16 17:55:07 +0200343 return 0;
344}
345
346/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100347 * @brief This function handles I2C Communication timeout for specific
348 * usage of STOP flag.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200349 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
350 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100351 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200352 * @retval 0 if OK, negative value else
353 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100354static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200355{
Yann Gautierf3928f62019-02-14 11:15:03 +0100356 while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
357 I2C_FLAG_STOPF) == 0U) {
358 if (i2c_ack_failed(hi2c, timeout_ref) != 0) {
359 return -EIO;
360 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200361
Yann Gautierf3928f62019-02-14 11:15:03 +0100362 if (timeout_elapsed(timeout_ref)) {
363 notif_i2c_timeout(hi2c);
364 hi2c->lock = 0;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200365
Yann Gautierbb836ee2018-07-16 17:55:07 +0200366 return -EIO;
367 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100368 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200369
Yann Gautierf3928f62019-02-14 11:15:03 +0100370 return 0;
371}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200372
Yann Gautierf3928f62019-02-14 11:15:03 +0100373/*
374 * @brief Handles I2Cx communication when starting transfer or during transfer
375 * (TC or TCR flag are set).
376 * @param hi2c: I2C handle
377 * @param dev_addr: Specifies the slave address to be programmed
378 * @param size: Specifies the number of bytes to be programmed.
379 * This parameter must be a value between 0 and 255.
380 * @param i2c_mode: New state of the I2C START condition generation.
381 * This parameter can be one of the following values:
382 * @arg @ref I2C_RELOAD_MODE: Enable Reload mode.
383 * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode.
384 * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode.
385 * @param request: New state of the I2C START condition generation.
386 * This parameter can be one of the following values:
387 * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition.
388 * @arg @ref I2C_GENERATE_STOP: Generate stop condition
389 * (size should be set to 0).
390 * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request.
391 * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request.
392 * @retval None
393 */
394static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr,
395 uint16_t size, uint32_t i2c_mode,
396 uint32_t request)
397{
398 uint32_t clr_value, set_value;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200399
Yann Gautierf3928f62019-02-14 11:15:03 +0100400 clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD |
401 I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) |
402 (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET)));
Yann Gautierbb836ee2018-07-16 17:55:07 +0200403
Yann Gautierf3928f62019-02-14 11:15:03 +0100404 set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) |
405 (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) |
406 i2c_mode | request;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200407
Yann Gautierf3928f62019-02-14 11:15:03 +0100408 mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200409}
410
411/*
412 * @brief Master sends target device address followed by internal memory
413 * address for write request.
414 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
415 * the configuration information for the specified I2C.
416 * @param dev_addr: Target device address
417 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100418 * @param mem_add_size: Size of internal memory address
419 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200420 * @retval 0 if OK, negative value else
421 */
422static int i2c_request_memory_write(struct i2c_handle_s *hi2c,
423 uint16_t dev_addr, uint16_t mem_addr,
Yann Gautierf3928f62019-02-14 11:15:03 +0100424 uint16_t mem_add_size, uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200425{
426 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE,
427 I2C_GENERATE_START_WRITE);
428
Yann Gautierf3928f62019-02-14 11:15:03 +0100429 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200430 return -EIO;
431 }
432
433 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
434 /* Send Memory Address */
435 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
436 (uint8_t)(mem_addr & 0x00FFU));
437 } else {
438 /* Send MSB of Memory Address */
439 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
440 (uint8_t)((mem_addr & 0xFF00U) >> 8));
441
Yann Gautierf3928f62019-02-14 11:15:03 +0100442 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200443 return -EIO;
444 }
445
446 /* Send LSB of Memory Address */
447 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
448 (uint8_t)(mem_addr & 0x00FFU));
449 }
450
Yann Gautierf3928f62019-02-14 11:15:03 +0100451 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200452 return -EIO;
453 }
454
455 return 0;
456}
457
458/*
459 * @brief Master sends target device address followed by internal memory
460 * address for read request.
461 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
462 * the configuration information for the specified I2C.
463 * @param dev_addr: Target device address
464 * @param mem_addr: Internal memory address
Yann Gautierf3928f62019-02-14 11:15:03 +0100465 * @param mem_add_size: Size of internal memory address
466 * @param timeout_ref: Reference to target timeout
Yann Gautierbb836ee2018-07-16 17:55:07 +0200467 * @retval 0 if OK, negative value else
468 */
469static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
470 uint16_t mem_addr, uint16_t mem_add_size,
Yann Gautierf3928f62019-02-14 11:15:03 +0100471 uint64_t timeout_ref)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200472{
473 i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE,
474 I2C_GENERATE_START_WRITE);
475
Yann Gautierf3928f62019-02-14 11:15:03 +0100476 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200477 return -EIO;
478 }
479
480 if (mem_add_size == I2C_MEMADD_SIZE_8BIT) {
481 /* Send Memory Address */
482 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
483 (uint8_t)(mem_addr & 0x00FFU));
484 } else {
485 /* Send MSB of Memory Address */
486 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
487 (uint8_t)((mem_addr & 0xFF00U) >> 8));
488
Yann Gautierf3928f62019-02-14 11:15:03 +0100489 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200490 return -EIO;
491 }
492
493 /* Send LSB of Memory Address */
494 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR,
495 (uint8_t)(mem_addr & 0x00FFU));
496 }
497
Yann Gautierf3928f62019-02-14 11:15:03 +0100498 if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) {
Yann Gautierbb836ee2018-07-16 17:55:07 +0200499 return -EIO;
500 }
501
502 return 0;
503}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200504/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100505 * @brief Generic function to write an amount of data in blocking mode
506 * (for Memory Mode and Master Mode)
507 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
508 * the configuration information for the specified I2C.
509 * @param dev_addr: Target device address
510 * @param mem_addr: Internal memory address (if Memory Mode)
511 * @param mem_add_size: Size of internal memory address (if Memory Mode)
512 * @param p_data: Pointer to data buffer
513 * @param size: Amount of data to be sent
514 * @param timeout_ms: Timeout duration in milliseconds
515 * @param mode: Communication mode
516 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200517 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100518static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
519 uint16_t mem_addr, uint16_t mem_add_size,
520 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
521 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200522{
Yann Gautierf3928f62019-02-14 11:15:03 +0100523 uint64_t timeout_ref;
524 int rc = -EIO;
525 uint8_t *p_buff = p_data;
526 uint32_t xfer_size;
527 uint32_t xfer_count = size;
528
529 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
530 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200531 }
532
Yann Gautierf3928f62019-02-14 11:15:03 +0100533 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
534 return -EBUSY;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200535 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200536
Yann Gautierf3928f62019-02-14 11:15:03 +0100537 if ((p_data == NULL) || (size == 0U)) {
538 return -EINVAL;
539 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200540
Yann Gautiera205a5c2021-08-30 15:06:54 +0200541 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100542
543 hi2c->lock = 1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200544
Yann Gautierf3928f62019-02-14 11:15:03 +0100545 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
546 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
547 goto bail;
548 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200549
Yann Gautierf3928f62019-02-14 11:15:03 +0100550 hi2c->i2c_state = I2C_STATE_BUSY_TX;
551 hi2c->i2c_mode = mode;
552 hi2c->i2c_err = I2C_ERROR_NONE;
553
554 timeout_ref = timeout_init_us(timeout_ms * 1000);
555
556 if (mode == I2C_MODE_MEM) {
557 /* In Memory Mode, Send Slave Address and Memory Address */
558 if (i2c_request_memory_write(hi2c, dev_addr, mem_addr,
559 mem_add_size, timeout_ref) != 0) {
560 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200561 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200562
Yann Gautierf3928f62019-02-14 11:15:03 +0100563 if (xfer_count > MAX_NBYTE_SIZE) {
564 xfer_size = MAX_NBYTE_SIZE;
565 i2c_transfer_config(hi2c, dev_addr, xfer_size,
566 I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
567 } else {
568 xfer_size = xfer_count;
569 i2c_transfer_config(hi2c, dev_addr, xfer_size,
570 I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
571 }
572 } else {
573 /* In Master Mode, Send Slave Address */
574 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,
578 I2C_GENERATE_START_WRITE);
579 } else {
580 xfer_size = xfer_count;
581 i2c_transfer_config(hi2c, dev_addr, xfer_size,
582 I2C_AUTOEND_MODE,
583 I2C_GENERATE_START_WRITE);
584 }
585 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200586
Yann Gautierf3928f62019-02-14 11:15:03 +0100587 do {
588 if (i2c_wait_txis(hi2c, timeout_ref) != 0) {
589 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200590 }
591
Yann Gautierf3928f62019-02-14 11:15:03 +0100592 mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff);
593 p_buff++;
594 xfer_count--;
595 xfer_size--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200596
Yann Gautierf3928f62019-02-14 11:15:03 +0100597 if ((xfer_count != 0U) && (xfer_size == 0U)) {
598 /* Wait until TCR flag is set */
599 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
600 timeout_ref) != 0) {
601 goto bail;
602 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200603
Yann Gautierf3928f62019-02-14 11:15:03 +0100604 if (xfer_count > MAX_NBYTE_SIZE) {
605 xfer_size = MAX_NBYTE_SIZE;
606 i2c_transfer_config(hi2c, dev_addr,
607 xfer_size,
608 I2C_RELOAD_MODE,
609 I2C_NO_STARTSTOP);
610 } else {
611 xfer_size = xfer_count;
612 i2c_transfer_config(hi2c, dev_addr,
613 xfer_size,
614 I2C_AUTOEND_MODE,
615 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200616 }
617 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100618
619 } while (xfer_count > 0U);
620
621 /*
622 * No need to Check TC flag, with AUTOEND mode the stop
623 * is automatically generated.
624 * Wait until STOPF flag is reset.
625 */
626 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
627 goto bail;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200628 }
629
Yann Gautierf3928f62019-02-14 11:15:03 +0100630 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
631
632 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
633
634 hi2c->i2c_state = I2C_STATE_READY;
635 hi2c->i2c_mode = I2C_MODE_NONE;
636
637 rc = 0;
638
639bail:
640 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200641 clk_disable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100642
643 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200644}
645
646/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100647 * @brief Write an amount of data in blocking mode to a specific memory
648 * address.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200649 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
650 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100651 * @param dev_addr: Target device address
652 * @param mem_addr: Internal memory address
653 * @param mem_add_size: Size of internal memory address
654 * @param p_data: Pointer to data buffer
655 * @param size: Amount of data to be sent
656 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200657 * @retval 0 if OK, negative value else
658 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100659int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr,
660 uint16_t mem_addr, uint16_t mem_add_size,
661 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200662{
Yann Gautierf3928f62019-02-14 11:15:03 +0100663 return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size,
664 p_data, size, timeout_ms, I2C_MODE_MEM);
665}
Yann Gautierbb836ee2018-07-16 17:55:07 +0200666
Yann Gautierf3928f62019-02-14 11:15:03 +0100667/*
668 * @brief Transmits in master mode an amount of data in blocking mode.
669 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
670 * the configuration information for the specified I2C.
671 * @param dev_addr: Target device address
672 * @param p_data: Pointer to data buffer
673 * @param size: Amount of data to be sent
674 * @param timeout_ms: Timeout duration in milliseconds
675 * @retval 0 if OK, negative value else
676 */
677int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr,
678 uint8_t *p_data, uint16_t size,
679 uint32_t timeout_ms)
680{
681 return i2c_write(hi2c, dev_addr, 0, 0,
682 p_data, size, timeout_ms, I2C_MODE_MASTER);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200683}
684
685/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100686 * @brief Generic function to read an amount of data in blocking mode
687 * (for Memory Mode and Master Mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200688 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
689 * the configuration information for the specified I2C.
Yann Gautierf3928f62019-02-14 11:15:03 +0100690 * @param dev_addr: Target device address
691 * @param mem_addr: Internal memory address (if Memory Mode)
692 * @param mem_add_size: Size of internal memory address (if Memory Mode)
693 * @param p_data: Pointer to data buffer
694 * @param size: Amount of data to be sent
695 * @param timeout_ms: Timeout duration in milliseconds
696 * @param mode: Communication mode
Yann Gautierbb836ee2018-07-16 17:55:07 +0200697 * @retval 0 if OK, negative value else
698 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100699static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
700 uint16_t mem_addr, uint16_t mem_add_size,
701 uint8_t *p_data, uint16_t size, uint32_t timeout_ms,
702 enum i2c_mode_e mode)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200703{
Yann Gautierf3928f62019-02-14 11:15:03 +0100704 uint64_t timeout_ref;
705 int rc = -EIO;
706 uint8_t *p_buff = p_data;
707 uint32_t xfer_count = size;
708 uint32_t xfer_size;
709
710 if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) {
711 return -1;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200712 }
713
Yann Gautierf3928f62019-02-14 11:15:03 +0100714 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
715 return -EBUSY;
716 }
717
718 if ((p_data == NULL) || (size == 0U)) {
719 return -EINVAL;
720 }
721
Yann Gautiera205a5c2021-08-30 15:06:54 +0200722 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100723
724 hi2c->lock = 1;
725
726 timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000);
727 if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) {
728 goto bail;
729 }
730
731 hi2c->i2c_state = I2C_STATE_BUSY_RX;
732 hi2c->i2c_mode = mode;
733 hi2c->i2c_err = I2C_ERROR_NONE;
734
735 if (mode == I2C_MODE_MEM) {
736 /* Send Memory Address */
737 if (i2c_request_memory_read(hi2c, dev_addr, mem_addr,
738 mem_add_size, timeout_ref) != 0) {
739 goto bail;
740 }
741 }
742
Yann Gautierbb836ee2018-07-16 17:55:07 +0200743 /*
Yann Gautierf3928f62019-02-14 11:15:03 +0100744 * Send Slave Address.
745 * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE
746 * and generate RESTART.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200747 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100748 if (xfer_count > MAX_NBYTE_SIZE) {
749 xfer_size = MAX_NBYTE_SIZE;
750 i2c_transfer_config(hi2c, dev_addr, xfer_size,
751 I2C_RELOAD_MODE, I2C_GENERATE_START_READ);
752 } else {
753 xfer_size = xfer_count;
754 i2c_transfer_config(hi2c, dev_addr, xfer_size,
755 I2C_AUTOEND_MODE, I2C_GENERATE_START_READ);
756 }
757
758 do {
759 if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) {
760 goto bail;
761 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200762
Yann Gautierf3928f62019-02-14 11:15:03 +0100763 *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR);
764 p_buff++;
765 xfer_size--;
766 xfer_count--;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200767
Yann Gautierf3928f62019-02-14 11:15:03 +0100768 if ((xfer_count != 0U) && (xfer_size == 0U)) {
769 if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0,
770 timeout_ref) != 0) {
771 goto bail;
772 }
773
774 if (xfer_count > MAX_NBYTE_SIZE) {
775 xfer_size = MAX_NBYTE_SIZE;
776 i2c_transfer_config(hi2c, dev_addr,
777 xfer_size,
778 I2C_RELOAD_MODE,
779 I2C_NO_STARTSTOP);
780 } else {
781 xfer_size = xfer_count;
782 i2c_transfer_config(hi2c, dev_addr,
783 xfer_size,
784 I2C_AUTOEND_MODE,
785 I2C_NO_STARTSTOP);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200786 }
787 }
Yann Gautierf3928f62019-02-14 11:15:03 +0100788 } while (xfer_count > 0U);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200789
Yann Gautierf3928f62019-02-14 11:15:03 +0100790 /*
791 * No need to Check TC flag, with AUTOEND mode the stop
792 * is automatically generated.
793 * Wait until STOPF flag is reset.
794 */
795 if (i2c_wait_stop(hi2c, timeout_ref) != 0) {
796 goto bail;
797 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200798
799 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
800
Yann Gautierbb836ee2018-07-16 17:55:07 +0200801 mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2);
802
Yann Gautierbb836ee2018-07-16 17:55:07 +0200803 hi2c->i2c_state = I2C_STATE_READY;
804 hi2c->i2c_mode = I2C_MODE_NONE;
805
Yann Gautierf3928f62019-02-14 11:15:03 +0100806 rc = 0;
807
808bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200809 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200810 clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200811
Yann Gautierf3928f62019-02-14 11:15:03 +0100812 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200813}
814
815/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100816 * @brief Read an amount of data in blocking mode from a specific memory
817 * address.
818 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
819 * the configuration information for the specified I2C.
820 * @param dev_addr: Target device address
821 * @param mem_addr: Internal memory address
822 * @param mem_add_size: Size of internal memory address
823 * @param p_data: Pointer to data buffer
824 * @param size: Amount of data to be sent
825 * @param timeout_ms: Timeout duration in milliseconds
826 * @retval 0 if OK, negative value else
Yann Gautierbb836ee2018-07-16 17:55:07 +0200827 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100828int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr,
829 uint16_t mem_addr, uint16_t mem_add_size,
830 uint8_t *p_data, uint16_t size, uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200831{
Yann Gautierf3928f62019-02-14 11:15:03 +0100832 return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size,
833 p_data, size, timeout_ms, I2C_MODE_MEM);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200834}
835
836/*
Yann Gautierf3928f62019-02-14 11:15:03 +0100837 * @brief Receives in master mode an amount of data in blocking mode.
Yann Gautierbb836ee2018-07-16 17:55:07 +0200838 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
Yann Gautierf3928f62019-02-14 11:15:03 +0100839 * the configuration information for the specified I2C.
840 * @param dev_addr: Target device address
841 * @param p_data: Pointer to data buffer
842 * @param size: Amount of data to be sent
843 * @param timeout_ms: Timeout duration in milliseconds
Yann Gautierbb836ee2018-07-16 17:55:07 +0200844 * @retval 0 if OK, negative value else
845 */
Yann Gautierf3928f62019-02-14 11:15:03 +0100846int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr,
847 uint8_t *p_data, uint16_t size,
848 uint32_t timeout_ms)
Yann Gautierbb836ee2018-07-16 17:55:07 +0200849{
Yann Gautierf3928f62019-02-14 11:15:03 +0100850 return i2c_read(hi2c, dev_addr, 0, 0,
851 p_data, size, timeout_ms, I2C_MODE_MASTER);
852}
853
854/*
855 * @brief Checks if target device is ready for communication.
856 * @note This function is used with Memory devices
857 * @param hi2c: Pointer to a struct i2c_handle_s structure that contains
858 * the configuration information for the specified I2C.
859 * @param dev_addr: Target device address
860 * @param trials: Number of trials
861 * @param timeout_ms: Timeout duration in milliseconds
862 * @retval True if device is ready, false else
863 */
864bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c,
865 uint16_t dev_addr, uint32_t trials,
866 uint32_t timeout_ms)
867{
868 uint32_t i2c_trials = 0U;
869 bool rc = false;
870
Yann Gautierbb836ee2018-07-16 17:55:07 +0200871 if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) {
Yann Gautierf3928f62019-02-14 11:15:03 +0100872 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200873 }
874
Yann Gautiera205a5c2021-08-30 15:06:54 +0200875 clk_enable(hi2c->clock);
Yann Gautierf3928f62019-02-14 11:15:03 +0100876
Yann Gautierbb836ee2018-07-16 17:55:07 +0200877 hi2c->lock = 1;
Yann Gautierf3928f62019-02-14 11:15:03 +0100878 hi2c->i2c_mode = I2C_MODE_NONE;
879
880 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) !=
881 0U) {
882 goto bail;
883 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200884
885 hi2c->i2c_state = I2C_STATE_BUSY;
Yann Gautierf3928f62019-02-14 11:15:03 +0100886 hi2c->i2c_err = I2C_ERROR_NONE;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200887
Yann Gautierf3928f62019-02-14 11:15:03 +0100888 do {
889 uint64_t timeout_ref;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200890
Yann Gautierf3928f62019-02-14 11:15:03 +0100891 /* Generate Start */
892 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) &
893 I2C_OAR1_OA1MODE) == 0) {
894 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
895 (((uint32_t)dev_addr & I2C_CR2_SADD) |
896 I2C_CR2_START | I2C_CR2_AUTOEND) &
897 ~I2C_CR2_RD_WRN);
898 } else {
899 mmio_write_32(hi2c->i2c_base_addr + I2C_CR2,
900 (((uint32_t)dev_addr & I2C_CR2_SADD) |
901 I2C_CR2_START | I2C_CR2_ADD10) &
902 ~I2C_CR2_RD_WRN);
903 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200904
Yann Gautierf3928f62019-02-14 11:15:03 +0100905 /*
906 * No need to Check TC flag, with AUTOEND mode the stop
907 * is automatically generated.
908 * Wait until STOPF flag is set or a NACK flag is set.
909 */
910 timeout_ref = timeout_init_us(timeout_ms * 1000);
911 do {
912 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
913 (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) {
914 break;
915 }
Yann Gautierbb836ee2018-07-16 17:55:07 +0200916
Yann Gautierf3928f62019-02-14 11:15:03 +0100917 if (timeout_elapsed(timeout_ref)) {
918 notif_i2c_timeout(hi2c);
919 goto bail;
920 }
921 } while (true);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200922
Yann Gautierf3928f62019-02-14 11:15:03 +0100923 if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) &
924 I2C_FLAG_AF) == 0U) {
925 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
926 timeout_ref) != 0) {
927 goto bail;
928 }
929
930 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
931 I2C_FLAG_STOPF);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200932
Yann Gautierf3928f62019-02-14 11:15:03 +0100933 hi2c->i2c_state = I2C_STATE_READY;
934
935 rc = true;
936 goto bail;
937 }
938
939 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) {
940 goto bail;
941 }
942
943 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF);
944
945 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF);
946
947 if (i2c_trials == trials) {
948 mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2,
949 I2C_CR2_STOP);
950
951 if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0,
952 timeout_ref) != 0) {
953 goto bail;
954 }
955
956 mmio_write_32(hi2c->i2c_base_addr + I2C_ICR,
957 I2C_FLAG_STOPF);
958 }
959
960 i2c_trials++;
961 } while (i2c_trials < trials);
962
963 notif_i2c_timeout(hi2c);
964
965bail:
Yann Gautierbb836ee2018-07-16 17:55:07 +0200966 hi2c->lock = 0;
Yann Gautiera205a5c2021-08-30 15:06:54 +0200967 clk_disable(hi2c->clock);
Yann Gautierbb836ee2018-07-16 17:55:07 +0200968
Yann Gautierf3928f62019-02-14 11:15:03 +0100969 return rc;
Yann Gautierbb836ee2018-07-16 17:55:07 +0200970}
Yann Gautierf3928f62019-02-14 11:15:03 +0100971