1435832abSYann Gautier /* 2*586701ceSYann Gautier * Copyright (c) 2016-2024, STMicroelectronics - All Rights Reserved 3435832abSYann Gautier * 4435832abSYann Gautier * SPDX-License-Identifier: BSD-3-Clause 5435832abSYann Gautier */ 6435832abSYann Gautier 7435832abSYann Gautier #include <errno.h> 8435832abSYann Gautier #include <stdbool.h> 9435832abSYann Gautier #include <stdlib.h> 10435832abSYann Gautier 11d82d4ff0SYann Gautier #include <common/debug.h> 12*586701ceSYann Gautier #include <common/fdt_wrappers.h> 1333667d29SYann Gautier #include <drivers/clk.h> 14435832abSYann Gautier #include <drivers/delay_timer.h> 15d82d4ff0SYann Gautier #include <drivers/st/stm32_gpio.h> 16435832abSYann Gautier #include <drivers/st/stm32_i2c.h> 17435832abSYann Gautier #include <lib/mmio.h> 18d82d4ff0SYann Gautier #include <lib/utils.h> 19*586701ceSYann Gautier #include <libfdt.h> 20*586701ceSYann Gautier 21*586701ceSYann Gautier #include <platform_def.h> 22435832abSYann Gautier 23435832abSYann Gautier /* STM32 I2C registers offsets */ 24435832abSYann Gautier #define I2C_CR1 0x00U 25435832abSYann Gautier #define I2C_CR2 0x04U 26435832abSYann Gautier #define I2C_OAR1 0x08U 27435832abSYann Gautier #define I2C_OAR2 0x0CU 28435832abSYann Gautier #define I2C_TIMINGR 0x10U 29435832abSYann Gautier #define I2C_TIMEOUTR 0x14U 30435832abSYann Gautier #define I2C_ISR 0x18U 31435832abSYann Gautier #define I2C_ICR 0x1CU 32435832abSYann Gautier #define I2C_PECR 0x20U 33435832abSYann Gautier #define I2C_RXDR 0x24U 34435832abSYann Gautier #define I2C_TXDR 0x28U 35435832abSYann Gautier 36d82d4ff0SYann Gautier #define TIMINGR_CLEAR_MASK 0xF0FFFFFFU 37435832abSYann Gautier 38435832abSYann Gautier #define MAX_NBYTE_SIZE 255U 39435832abSYann Gautier 40d82d4ff0SYann Gautier #define I2C_NSEC_PER_SEC 1000000000L 41435832abSYann Gautier 42d82d4ff0SYann Gautier /* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ 43d82d4ff0SYann Gautier #define I2C_TIMING 0x10D07DB5 44435832abSYann Gautier 45d82d4ff0SYann Gautier static void notif_i2c_timeout(struct i2c_handle_s *hi2c) 46d82d4ff0SYann Gautier { 47d82d4ff0SYann Gautier hi2c->i2c_err |= I2C_ERROR_TIMEOUT; 48d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 49d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 50d82d4ff0SYann Gautier } 51435832abSYann Gautier 52d82d4ff0SYann Gautier /* 53d82d4ff0SYann Gautier * @brief Configure I2C Analog noise filter. 54d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 55d82d4ff0SYann Gautier * the configuration information for the specified I2C peripheral. 56d82d4ff0SYann Gautier * @param analog_filter: New state of the Analog filter 57d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 58d82d4ff0SYann Gautier */ 59d82d4ff0SYann Gautier static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, 60d82d4ff0SYann Gautier uint32_t analog_filter) 61d82d4ff0SYann Gautier { 62d82d4ff0SYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 63d82d4ff0SYann Gautier return -EBUSY; 64d82d4ff0SYann Gautier } 65d82d4ff0SYann Gautier 66d82d4ff0SYann Gautier hi2c->lock = 1; 67d82d4ff0SYann Gautier 68d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_BUSY; 69d82d4ff0SYann Gautier 70d82d4ff0SYann Gautier /* Disable the selected I2C peripheral */ 71d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 72d82d4ff0SYann Gautier 73d82d4ff0SYann Gautier /* Reset I2Cx ANOFF bit */ 74d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); 75d82d4ff0SYann Gautier 76d82d4ff0SYann Gautier /* Set analog filter bit*/ 77d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); 78d82d4ff0SYann Gautier 79d82d4ff0SYann Gautier /* Enable the selected I2C peripheral */ 80d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 81d82d4ff0SYann Gautier 82d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 83d82d4ff0SYann Gautier 84d82d4ff0SYann Gautier hi2c->lock = 0; 85d82d4ff0SYann Gautier 86d82d4ff0SYann Gautier return 0; 87d82d4ff0SYann Gautier } 88d82d4ff0SYann Gautier 89d82d4ff0SYann Gautier /* 90d82d4ff0SYann Gautier * @brief Get I2C setup information from the device tree and set pinctrl 91d82d4ff0SYann Gautier * configuration. 92d82d4ff0SYann Gautier * @param fdt: Pointer to the device tree 93d82d4ff0SYann Gautier * @param node: I2C node offset 94d82d4ff0SYann Gautier * @param init: Ref to the initialization configuration structure 95d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 96d82d4ff0SYann Gautier */ 97d82d4ff0SYann Gautier int stm32_i2c_get_setup_from_fdt(void *fdt, int node, 98d82d4ff0SYann Gautier struct stm32_i2c_init_s *init) 99d82d4ff0SYann Gautier { 100*586701ceSYann Gautier uint32_t read_val; 101d82d4ff0SYann Gautier 102*586701ceSYann Gautier init->rise_time = fdt_read_uint32_default(fdt, node, 103*586701ceSYann Gautier "i2c-scl-rising-time-ns", 104*586701ceSYann Gautier STM32_I2C_RISE_TIME_DEFAULT); 105d82d4ff0SYann Gautier 106*586701ceSYann Gautier init->fall_time = fdt_read_uint32_default(fdt, node, 107*586701ceSYann Gautier "i2c-scl-falling-time-ns", 108*586701ceSYann Gautier STM32_I2C_FALL_TIME_DEFAULT); 109d82d4ff0SYann Gautier 110*586701ceSYann Gautier read_val = fdt_read_uint32_default(fdt, node, "clock-frequency", 111*586701ceSYann Gautier STANDARD_RATE); 112*586701ceSYann Gautier switch (read_val) { 113*586701ceSYann Gautier case FAST_PLUS_RATE: 114*586701ceSYann Gautier init->speed_mode = I2C_SPEED_FAST_PLUS; 115d82d4ff0SYann Gautier break; 116d82d4ff0SYann Gautier case FAST_RATE: 117d82d4ff0SYann Gautier init->speed_mode = I2C_SPEED_FAST; 118d82d4ff0SYann Gautier break; 119*586701ceSYann Gautier case STANDARD_RATE: 120d82d4ff0SYann Gautier default: 121*586701ceSYann Gautier init->speed_mode = I2C_SPEED_STANDARD; 122d82d4ff0SYann Gautier break; 123d82d4ff0SYann Gautier } 124d82d4ff0SYann Gautier 125d82d4ff0SYann Gautier return dt_set_pinctrl_config(node); 126d82d4ff0SYann Gautier } 127435832abSYann Gautier 128435832abSYann Gautier /* 129435832abSYann Gautier * @brief Initialize the I2C device. 130435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 131435832abSYann Gautier * the configuration information for the specified I2C. 132d82d4ff0SYann Gautier * @param init_data: Initialization configuration structure 133435832abSYann Gautier * @retval 0 if OK, negative value else 134435832abSYann Gautier */ 135d82d4ff0SYann Gautier int stm32_i2c_init(struct i2c_handle_s *hi2c, 136d82d4ff0SYann Gautier struct stm32_i2c_init_s *init_data) 137435832abSYann Gautier { 138d82d4ff0SYann Gautier int rc = 0; 139d82d4ff0SYann Gautier uint32_t timing = I2C_TIMING; 140d82d4ff0SYann Gautier 141435832abSYann Gautier if (hi2c == NULL) { 142435832abSYann Gautier return -ENOENT; 143435832abSYann Gautier } 144435832abSYann Gautier 145435832abSYann Gautier if (hi2c->i2c_state == I2C_STATE_RESET) { 146435832abSYann Gautier hi2c->lock = 0; 147435832abSYann Gautier } 148435832abSYann Gautier 149435832abSYann Gautier hi2c->i2c_state = I2C_STATE_BUSY; 150435832abSYann Gautier 15133667d29SYann Gautier clk_enable(hi2c->clock); 152d82d4ff0SYann Gautier 153435832abSYann Gautier /* Disable the selected I2C peripheral */ 154435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 155435832abSYann Gautier 156435832abSYann Gautier /* Configure I2Cx: Frequency range */ 157435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, 158d82d4ff0SYann Gautier timing & TIMINGR_CLEAR_MASK); 159435832abSYann Gautier 160435832abSYann Gautier /* Disable Own Address1 before set the Own Address1 configuration */ 161435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); 162435832abSYann Gautier 163435832abSYann Gautier /* Configure I2Cx: Own Address1 and ack own address1 mode */ 164d82d4ff0SYann Gautier if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { 165435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 166d82d4ff0SYann Gautier I2C_OAR1_OA1EN | init_data->own_address1); 167435832abSYann Gautier } else { /* I2C_ADDRESSINGMODE_10BIT */ 168435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 169435832abSYann Gautier I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | 170d82d4ff0SYann Gautier init_data->own_address1); 171435832abSYann Gautier } 172435832abSYann Gautier 173d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); 174d82d4ff0SYann Gautier 175435832abSYann Gautier /* Configure I2Cx: Addressing Master mode */ 176d82d4ff0SYann Gautier if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { 177d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); 178435832abSYann Gautier } 179435832abSYann Gautier 180435832abSYann Gautier /* 181435832abSYann Gautier * Enable the AUTOEND by default, and enable NACK 182d82d4ff0SYann Gautier * (should be disabled only during Slave process). 183435832abSYann Gautier */ 184435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 185435832abSYann Gautier I2C_CR2_AUTOEND | I2C_CR2_NACK); 186435832abSYann Gautier 187435832abSYann Gautier /* Disable Own Address2 before set the Own Address2 configuration */ 188435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); 189435832abSYann Gautier 190435832abSYann Gautier /* Configure I2Cx: Dual mode and Own Address2 */ 191435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, 192d82d4ff0SYann Gautier init_data->dual_address_mode | 193d82d4ff0SYann Gautier init_data->own_address2 | 194d82d4ff0SYann Gautier (init_data->own_address2_masks << 8)); 195435832abSYann Gautier 196435832abSYann Gautier /* Configure I2Cx: Generalcall and NoStretch mode */ 197435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, 198d82d4ff0SYann Gautier init_data->general_call_mode | 199d82d4ff0SYann Gautier init_data->no_stretch_mode); 200435832abSYann Gautier 201435832abSYann Gautier /* Enable the selected I2C peripheral */ 202435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 203435832abSYann Gautier 204435832abSYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 205435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 206435832abSYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 207435832abSYann Gautier 208d82d4ff0SYann Gautier rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? 209d82d4ff0SYann Gautier I2C_ANALOGFILTER_ENABLE : 210d82d4ff0SYann Gautier I2C_ANALOGFILTER_DISABLE); 211d82d4ff0SYann Gautier if (rc != 0) { 212d82d4ff0SYann Gautier ERROR("Cannot initialize I2C analog filter (%d)\n", rc); 21333667d29SYann Gautier clk_disable(hi2c->clock); 214d82d4ff0SYann Gautier return rc; 215435832abSYann Gautier } 216435832abSYann Gautier 21733667d29SYann Gautier clk_disable(hi2c->clock); 218435832abSYann Gautier 219d82d4ff0SYann Gautier return rc; 220435832abSYann Gautier } 221435832abSYann Gautier 222435832abSYann Gautier /* 223435832abSYann Gautier * @brief I2C Tx data register flush process. 224d82d4ff0SYann Gautier * @param hi2c: I2C handle 225435832abSYann Gautier * @retval None 226435832abSYann Gautier */ 227435832abSYann Gautier static void i2c_flush_txdr(struct i2c_handle_s *hi2c) 228435832abSYann Gautier { 229435832abSYann Gautier /* 230435832abSYann Gautier * If a pending TXIS flag is set, 231435832abSYann Gautier * write a dummy data in TXDR to clear it. 232435832abSYann Gautier */ 233435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != 234435832abSYann Gautier 0U) { 235435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); 236435832abSYann Gautier } 237435832abSYann Gautier 238435832abSYann Gautier /* Flush TX register if not empty */ 239435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == 240435832abSYann Gautier 0U) { 241435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, 242435832abSYann Gautier I2C_FLAG_TXE); 243435832abSYann Gautier } 244435832abSYann Gautier } 245435832abSYann Gautier 246435832abSYann Gautier /* 247435832abSYann Gautier * @brief This function handles I2C Communication timeout. 248435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 249435832abSYann Gautier * the configuration information for the specified I2C. 250d82d4ff0SYann Gautier * @param flag: Specifies the I2C flag to check 251d82d4ff0SYann Gautier * @param awaited_value: The awaited bit value for the flag (0 or 1) 252d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 253435832abSYann Gautier * @retval 0 if OK, negative value else 254435832abSYann Gautier */ 255435832abSYann Gautier static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, 256d82d4ff0SYann Gautier uint8_t awaited_value, uint64_t timeout_ref) 257435832abSYann Gautier { 258d82d4ff0SYann Gautier for ( ; ; ) { 259d82d4ff0SYann Gautier uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); 260435832abSYann Gautier 261d82d4ff0SYann Gautier if (!!(isr & flag) != !!awaited_value) { 262435832abSYann Gautier return 0; 263435832abSYann Gautier } 264435832abSYann Gautier 265d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 266d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 267435832abSYann Gautier hi2c->lock = 0; 268435832abSYann Gautier 269435832abSYann Gautier return -EIO; 270435832abSYann Gautier } 271435832abSYann Gautier } 272435832abSYann Gautier } 273435832abSYann Gautier 274435832abSYann Gautier /* 275435832abSYann Gautier * @brief This function handles Acknowledge failed detection during 276435832abSYann Gautier * an I2C Communication. 277435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 278435832abSYann Gautier * the configuration information for the specified I2C. 279d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 280435832abSYann Gautier * @retval 0 if OK, negative value else 281435832abSYann Gautier */ 282d82d4ff0SYann Gautier static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 283435832abSYann Gautier { 284435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { 285435832abSYann Gautier return 0; 286435832abSYann Gautier } 287435832abSYann Gautier 288435832abSYann Gautier /* 289435832abSYann Gautier * Wait until STOP Flag is reset. 290435832abSYann Gautier * AutoEnd should be initiate after AF. 291435832abSYann Gautier */ 292435832abSYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 293435832abSYann Gautier I2C_FLAG_STOPF) == 0U) { 294d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 295d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 296435832abSYann Gautier hi2c->lock = 0; 297435832abSYann Gautier 298435832abSYann Gautier return -EIO; 299435832abSYann Gautier } 300435832abSYann Gautier } 301435832abSYann Gautier 302435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 303435832abSYann Gautier 304435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 305435832abSYann Gautier 306435832abSYann Gautier i2c_flush_txdr(hi2c); 307435832abSYann Gautier 308435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 309435832abSYann Gautier 310435832abSYann Gautier hi2c->i2c_err |= I2C_ERROR_AF; 311435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 312435832abSYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 313435832abSYann Gautier 314435832abSYann Gautier hi2c->lock = 0; 315435832abSYann Gautier 316435832abSYann Gautier return -EIO; 317435832abSYann Gautier } 318435832abSYann Gautier 319435832abSYann Gautier /* 320d82d4ff0SYann Gautier * @brief This function handles I2C Communication timeout for specific usage 321d82d4ff0SYann Gautier * of TXIS flag. 322d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 323d82d4ff0SYann Gautier * the configuration information for the specified I2C. 324d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 325d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 326d82d4ff0SYann Gautier */ 327d82d4ff0SYann Gautier static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 328d82d4ff0SYann Gautier { 329d82d4ff0SYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 330d82d4ff0SYann Gautier I2C_FLAG_TXIS) == 0U) { 331d82d4ff0SYann Gautier if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 332d82d4ff0SYann Gautier return -EIO; 333d82d4ff0SYann Gautier } 334d82d4ff0SYann Gautier 335d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 336d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 337d82d4ff0SYann Gautier hi2c->lock = 0; 338d82d4ff0SYann Gautier 339d82d4ff0SYann Gautier return -EIO; 340d82d4ff0SYann Gautier } 341d82d4ff0SYann Gautier } 342d82d4ff0SYann Gautier 343d82d4ff0SYann Gautier return 0; 344d82d4ff0SYann Gautier } 345d82d4ff0SYann Gautier 346d82d4ff0SYann Gautier /* 347d82d4ff0SYann Gautier * @brief This function handles I2C Communication timeout for specific 348d82d4ff0SYann Gautier * usage of STOP flag. 349d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 350d82d4ff0SYann Gautier * the configuration information for the specified I2C. 351d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 352d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 353d82d4ff0SYann Gautier */ 354d82d4ff0SYann Gautier static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 355d82d4ff0SYann Gautier { 356d82d4ff0SYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 357d82d4ff0SYann Gautier I2C_FLAG_STOPF) == 0U) { 358d82d4ff0SYann Gautier if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 359d82d4ff0SYann Gautier return -EIO; 360d82d4ff0SYann Gautier } 361d82d4ff0SYann Gautier 362d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 363d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 364d82d4ff0SYann Gautier hi2c->lock = 0; 365d82d4ff0SYann Gautier 366d82d4ff0SYann Gautier return -EIO; 367d82d4ff0SYann Gautier } 368d82d4ff0SYann Gautier } 369d82d4ff0SYann Gautier 370d82d4ff0SYann Gautier return 0; 371d82d4ff0SYann Gautier } 372d82d4ff0SYann Gautier 373d82d4ff0SYann Gautier /* 374435832abSYann Gautier * @brief Handles I2Cx communication when starting transfer or during transfer 375435832abSYann Gautier * (TC or TCR flag are set). 376d82d4ff0SYann Gautier * @param hi2c: I2C handle 377d82d4ff0SYann Gautier * @param dev_addr: Specifies the slave address to be programmed 378435832abSYann Gautier * @param size: Specifies the number of bytes to be programmed. 379435832abSYann Gautier * This parameter must be a value between 0 and 255. 380435832abSYann Gautier * @param i2c_mode: New state of the I2C START condition generation. 381435832abSYann Gautier * This parameter can be one of the following values: 382435832abSYann Gautier * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. 383435832abSYann Gautier * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. 384435832abSYann Gautier * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. 385435832abSYann Gautier * @param request: New state of the I2C START condition generation. 386435832abSYann Gautier * This parameter can be one of the following values: 387435832abSYann Gautier * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. 388435832abSYann Gautier * @arg @ref I2C_GENERATE_STOP: Generate stop condition 389435832abSYann Gautier * (size should be set to 0). 390435832abSYann Gautier * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. 391435832abSYann Gautier * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. 392435832abSYann Gautier * @retval None 393435832abSYann Gautier */ 394435832abSYann Gautier static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, 395435832abSYann Gautier uint16_t size, uint32_t i2c_mode, 396435832abSYann Gautier uint32_t request) 397435832abSYann Gautier { 398435832abSYann Gautier uint32_t clr_value, set_value; 399435832abSYann Gautier 400435832abSYann Gautier clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | 401435832abSYann Gautier I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | 402435832abSYann Gautier (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); 403435832abSYann Gautier 404435832abSYann Gautier set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | 405435832abSYann Gautier (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | 406435832abSYann Gautier i2c_mode | request; 407435832abSYann Gautier 408435832abSYann Gautier mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); 409435832abSYann Gautier } 410435832abSYann Gautier 411435832abSYann Gautier /* 412d82d4ff0SYann Gautier * @brief Master sends target device address followed by internal memory 413d82d4ff0SYann Gautier * address for write request. 414435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 415d82d4ff0SYann Gautier * the configuration information for the specified I2C. 416d82d4ff0SYann Gautier * @param dev_addr: Target device address 417d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 418d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 419d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 420435832abSYann Gautier * @retval 0 if OK, negative value else 421435832abSYann Gautier */ 422d82d4ff0SYann Gautier static int i2c_request_memory_write(struct i2c_handle_s *hi2c, 423d82d4ff0SYann Gautier uint16_t dev_addr, uint16_t mem_addr, 424d82d4ff0SYann Gautier uint16_t mem_add_size, uint64_t timeout_ref) 425435832abSYann Gautier { 426d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, 427d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 428d82d4ff0SYann Gautier 429d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 430d82d4ff0SYann Gautier return -EIO; 431d82d4ff0SYann Gautier } 432d82d4ff0SYann Gautier 433d82d4ff0SYann Gautier if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 434d82d4ff0SYann Gautier /* Send Memory Address */ 435d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 436d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 437d82d4ff0SYann Gautier } else { 438d82d4ff0SYann Gautier /* Send MSB of Memory Address */ 439d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 440d82d4ff0SYann Gautier (uint8_t)((mem_addr & 0xFF00U) >> 8)); 441d82d4ff0SYann Gautier 442d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 443d82d4ff0SYann Gautier return -EIO; 444d82d4ff0SYann Gautier } 445d82d4ff0SYann Gautier 446d82d4ff0SYann Gautier /* Send LSB of Memory Address */ 447d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 448d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 449d82d4ff0SYann Gautier } 450d82d4ff0SYann Gautier 451d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) { 452d82d4ff0SYann Gautier return -EIO; 453d82d4ff0SYann Gautier } 454d82d4ff0SYann Gautier 455d82d4ff0SYann Gautier return 0; 456d82d4ff0SYann Gautier } 457d82d4ff0SYann Gautier 458d82d4ff0SYann Gautier /* 459d82d4ff0SYann Gautier * @brief Master sends target device address followed by internal memory 460d82d4ff0SYann Gautier * address for read request. 461d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 462d82d4ff0SYann Gautier * the configuration information for the specified I2C. 463d82d4ff0SYann Gautier * @param dev_addr: Target device address 464d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 465d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 466d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 467d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 468d82d4ff0SYann Gautier */ 469d82d4ff0SYann Gautier static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 470d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 471d82d4ff0SYann Gautier uint64_t timeout_ref) 472d82d4ff0SYann Gautier { 473d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, 474d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 475d82d4ff0SYann Gautier 476d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 477d82d4ff0SYann Gautier return -EIO; 478d82d4ff0SYann Gautier } 479d82d4ff0SYann Gautier 480d82d4ff0SYann Gautier if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 481d82d4ff0SYann Gautier /* Send Memory Address */ 482d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 483d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 484d82d4ff0SYann Gautier } else { 485d82d4ff0SYann Gautier /* Send MSB of Memory Address */ 486d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 487d82d4ff0SYann Gautier (uint8_t)((mem_addr & 0xFF00U) >> 8)); 488d82d4ff0SYann Gautier 489d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 490d82d4ff0SYann Gautier return -EIO; 491d82d4ff0SYann Gautier } 492d82d4ff0SYann Gautier 493d82d4ff0SYann Gautier /* Send LSB of Memory Address */ 494d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 495d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 496d82d4ff0SYann Gautier } 497d82d4ff0SYann Gautier 498d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) { 499d82d4ff0SYann Gautier return -EIO; 500d82d4ff0SYann Gautier } 501d82d4ff0SYann Gautier 502d82d4ff0SYann Gautier return 0; 503d82d4ff0SYann Gautier } 504d82d4ff0SYann Gautier /* 505d82d4ff0SYann Gautier * @brief Generic function to write an amount of data in blocking mode 506d82d4ff0SYann Gautier * (for Memory Mode and Master Mode) 507d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 508d82d4ff0SYann Gautier * the configuration information for the specified I2C. 509d82d4ff0SYann Gautier * @param dev_addr: Target device address 510d82d4ff0SYann Gautier * @param mem_addr: Internal memory address (if Memory Mode) 511d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address (if Memory Mode) 512d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 513d82d4ff0SYann Gautier * @param size: Amount of data to be sent 514d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 515d82d4ff0SYann Gautier * @param mode: Communication mode 516d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 517d82d4ff0SYann Gautier */ 518d82d4ff0SYann Gautier static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 519d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 520d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 521d82d4ff0SYann Gautier enum i2c_mode_e mode) 522d82d4ff0SYann Gautier { 523d82d4ff0SYann Gautier uint64_t timeout_ref; 524d82d4ff0SYann Gautier int rc = -EIO; 525d82d4ff0SYann Gautier uint8_t *p_buff = p_data; 526d82d4ff0SYann Gautier uint32_t xfer_size; 527d82d4ff0SYann Gautier uint32_t xfer_count = size; 528d82d4ff0SYann Gautier 529d82d4ff0SYann Gautier if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 530d82d4ff0SYann Gautier return -1; 531d82d4ff0SYann Gautier } 532d82d4ff0SYann Gautier 533435832abSYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 534435832abSYann Gautier return -EBUSY; 535435832abSYann Gautier } 536435832abSYann Gautier 537d82d4ff0SYann Gautier if ((p_data == NULL) || (size == 0U)) { 538d82d4ff0SYann Gautier return -EINVAL; 539d82d4ff0SYann Gautier } 540d82d4ff0SYann Gautier 54133667d29SYann Gautier clk_enable(hi2c->clock); 542d82d4ff0SYann Gautier 543435832abSYann Gautier hi2c->lock = 1; 544435832abSYann Gautier 545d82d4ff0SYann Gautier timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 546d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 547d82d4ff0SYann Gautier goto bail; 548d82d4ff0SYann Gautier } 549d82d4ff0SYann Gautier 550d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_BUSY_TX; 551d82d4ff0SYann Gautier hi2c->i2c_mode = mode; 552d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 553d82d4ff0SYann Gautier 554d82d4ff0SYann Gautier timeout_ref = timeout_init_us(timeout_ms * 1000); 555d82d4ff0SYann Gautier 556d82d4ff0SYann Gautier if (mode == I2C_MODE_MEM) { 557d82d4ff0SYann Gautier /* In Memory Mode, Send Slave Address and Memory Address */ 558d82d4ff0SYann Gautier if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, 559d82d4ff0SYann Gautier mem_add_size, timeout_ref) != 0) { 560d82d4ff0SYann Gautier goto bail; 561d82d4ff0SYann Gautier } 562d82d4ff0SYann Gautier 563d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 564d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 565d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 566d82d4ff0SYann Gautier I2C_RELOAD_MODE, I2C_NO_STARTSTOP); 567d82d4ff0SYann Gautier } else { 568d82d4ff0SYann Gautier xfer_size = xfer_count; 569d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 570d82d4ff0SYann Gautier I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); 571d82d4ff0SYann Gautier } 572d82d4ff0SYann Gautier } else { 573d82d4ff0SYann Gautier /* In Master Mode, Send Slave Address */ 574d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 575d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 576d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 577d82d4ff0SYann Gautier I2C_RELOAD_MODE, 578d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 579d82d4ff0SYann Gautier } else { 580d82d4ff0SYann Gautier xfer_size = xfer_count; 581d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 582d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 583d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 584d82d4ff0SYann Gautier } 585d82d4ff0SYann Gautier } 586d82d4ff0SYann Gautier 587d82d4ff0SYann Gautier do { 588d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 589d82d4ff0SYann Gautier goto bail; 590d82d4ff0SYann Gautier } 591d82d4ff0SYann Gautier 592d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); 593d82d4ff0SYann Gautier p_buff++; 594d82d4ff0SYann Gautier xfer_count--; 595d82d4ff0SYann Gautier xfer_size--; 596d82d4ff0SYann Gautier 597d82d4ff0SYann Gautier if ((xfer_count != 0U) && (xfer_size == 0U)) { 598d82d4ff0SYann Gautier /* Wait until TCR flag is set */ 599d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 600d82d4ff0SYann Gautier timeout_ref) != 0) { 601d82d4ff0SYann Gautier goto bail; 602d82d4ff0SYann Gautier } 603d82d4ff0SYann Gautier 604d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 605d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 606d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 607d82d4ff0SYann Gautier xfer_size, 608d82d4ff0SYann Gautier I2C_RELOAD_MODE, 609d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 610d82d4ff0SYann Gautier } else { 611d82d4ff0SYann Gautier xfer_size = xfer_count; 612d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 613d82d4ff0SYann Gautier xfer_size, 614d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 615d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 616d82d4ff0SYann Gautier } 617d82d4ff0SYann Gautier } 618d82d4ff0SYann Gautier 619d82d4ff0SYann Gautier } while (xfer_count > 0U); 620d82d4ff0SYann Gautier 621d82d4ff0SYann Gautier /* 622d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 623d82d4ff0SYann Gautier * is automatically generated. 624d82d4ff0SYann Gautier * Wait until STOPF flag is reset. 625d82d4ff0SYann Gautier */ 626d82d4ff0SYann Gautier if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 627d82d4ff0SYann Gautier goto bail; 628d82d4ff0SYann Gautier } 629d82d4ff0SYann Gautier 630d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 631d82d4ff0SYann Gautier 632d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 633d82d4ff0SYann Gautier 634d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 635d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 636d82d4ff0SYann Gautier 637d82d4ff0SYann Gautier rc = 0; 638d82d4ff0SYann Gautier 639d82d4ff0SYann Gautier bail: 640d82d4ff0SYann Gautier hi2c->lock = 0; 64133667d29SYann Gautier clk_disable(hi2c->clock); 642d82d4ff0SYann Gautier 643d82d4ff0SYann Gautier return rc; 644d82d4ff0SYann Gautier } 645d82d4ff0SYann Gautier 646d82d4ff0SYann Gautier /* 647d82d4ff0SYann Gautier * @brief Write an amount of data in blocking mode to a specific memory 648d82d4ff0SYann Gautier * address. 649d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 650d82d4ff0SYann Gautier * the configuration information for the specified I2C. 651d82d4ff0SYann Gautier * @param dev_addr: Target device address 652d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 653d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 654d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 655d82d4ff0SYann Gautier * @param size: Amount of data to be sent 656d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 657d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 658d82d4ff0SYann Gautier */ 659d82d4ff0SYann Gautier int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 660d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 661d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 662d82d4ff0SYann Gautier { 663d82d4ff0SYann Gautier return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, 664d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MEM); 665d82d4ff0SYann Gautier } 666d82d4ff0SYann Gautier 667d82d4ff0SYann Gautier /* 668d82d4ff0SYann Gautier * @brief Transmits in master mode an amount of data in blocking mode. 669d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 670d82d4ff0SYann Gautier * the configuration information for the specified I2C. 671d82d4ff0SYann Gautier * @param dev_addr: Target device address 672d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 673d82d4ff0SYann Gautier * @param size: Amount of data to be sent 674d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 675d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 676d82d4ff0SYann Gautier */ 677d82d4ff0SYann Gautier int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, 678d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, 679d82d4ff0SYann Gautier uint32_t timeout_ms) 680d82d4ff0SYann Gautier { 681d82d4ff0SYann Gautier return i2c_write(hi2c, dev_addr, 0, 0, 682d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MASTER); 683d82d4ff0SYann Gautier } 684d82d4ff0SYann Gautier 685d82d4ff0SYann Gautier /* 686d82d4ff0SYann Gautier * @brief Generic function to read an amount of data in blocking mode 687d82d4ff0SYann Gautier * (for Memory Mode and Master Mode) 688d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 689d82d4ff0SYann Gautier * the configuration information for the specified I2C. 690d82d4ff0SYann Gautier * @param dev_addr: Target device address 691d82d4ff0SYann Gautier * @param mem_addr: Internal memory address (if Memory Mode) 692d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address (if Memory Mode) 693d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 694d82d4ff0SYann Gautier * @param size: Amount of data to be sent 695d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 696d82d4ff0SYann Gautier * @param mode: Communication mode 697d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 698d82d4ff0SYann Gautier */ 699d82d4ff0SYann Gautier static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 700d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 701d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 702d82d4ff0SYann Gautier enum i2c_mode_e mode) 703d82d4ff0SYann Gautier { 704d82d4ff0SYann Gautier uint64_t timeout_ref; 705d82d4ff0SYann Gautier int rc = -EIO; 706d82d4ff0SYann Gautier uint8_t *p_buff = p_data; 707d82d4ff0SYann Gautier uint32_t xfer_count = size; 708d82d4ff0SYann Gautier uint32_t xfer_size; 709d82d4ff0SYann Gautier 710d82d4ff0SYann Gautier if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 711d82d4ff0SYann Gautier return -1; 712d82d4ff0SYann Gautier } 713d82d4ff0SYann Gautier 714d82d4ff0SYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 715d82d4ff0SYann Gautier return -EBUSY; 716d82d4ff0SYann Gautier } 717d82d4ff0SYann Gautier 718d82d4ff0SYann Gautier if ((p_data == NULL) || (size == 0U)) { 719d82d4ff0SYann Gautier return -EINVAL; 720d82d4ff0SYann Gautier } 721d82d4ff0SYann Gautier 72233667d29SYann Gautier clk_enable(hi2c->clock); 723d82d4ff0SYann Gautier 724d82d4ff0SYann Gautier hi2c->lock = 1; 725d82d4ff0SYann Gautier 726d82d4ff0SYann Gautier timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 727d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 728d82d4ff0SYann Gautier goto bail; 729d82d4ff0SYann Gautier } 730d82d4ff0SYann Gautier 731d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_BUSY_RX; 732d82d4ff0SYann Gautier hi2c->i2c_mode = mode; 733d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 734d82d4ff0SYann Gautier 735d82d4ff0SYann Gautier if (mode == I2C_MODE_MEM) { 736d82d4ff0SYann Gautier /* Send Memory Address */ 737d82d4ff0SYann Gautier if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, 738d82d4ff0SYann Gautier mem_add_size, timeout_ref) != 0) { 739d82d4ff0SYann Gautier goto bail; 740d82d4ff0SYann Gautier } 741d82d4ff0SYann Gautier } 742d82d4ff0SYann Gautier 743d82d4ff0SYann Gautier /* 744d82d4ff0SYann Gautier * Send Slave Address. 745d82d4ff0SYann Gautier * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE 746d82d4ff0SYann Gautier * and generate RESTART. 747d82d4ff0SYann Gautier */ 748d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 749d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 750d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 751d82d4ff0SYann Gautier I2C_RELOAD_MODE, I2C_GENERATE_START_READ); 752d82d4ff0SYann Gautier } else { 753d82d4ff0SYann Gautier xfer_size = xfer_count; 754d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 755d82d4ff0SYann Gautier I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); 756d82d4ff0SYann Gautier } 757d82d4ff0SYann Gautier 758d82d4ff0SYann Gautier do { 759d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { 760d82d4ff0SYann Gautier goto bail; 761d82d4ff0SYann Gautier } 762d82d4ff0SYann Gautier 763d82d4ff0SYann Gautier *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); 764d82d4ff0SYann Gautier p_buff++; 765d82d4ff0SYann Gautier xfer_size--; 766d82d4ff0SYann Gautier xfer_count--; 767d82d4ff0SYann Gautier 768d82d4ff0SYann Gautier if ((xfer_count != 0U) && (xfer_size == 0U)) { 769d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 770d82d4ff0SYann Gautier timeout_ref) != 0) { 771d82d4ff0SYann Gautier goto bail; 772d82d4ff0SYann Gautier } 773d82d4ff0SYann Gautier 774d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 775d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 776d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 777d82d4ff0SYann Gautier xfer_size, 778d82d4ff0SYann Gautier I2C_RELOAD_MODE, 779d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 780d82d4ff0SYann Gautier } else { 781d82d4ff0SYann Gautier xfer_size = xfer_count; 782d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 783d82d4ff0SYann Gautier xfer_size, 784d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 785d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 786d82d4ff0SYann Gautier } 787d82d4ff0SYann Gautier } 788d82d4ff0SYann Gautier } while (xfer_count > 0U); 789d82d4ff0SYann Gautier 790d82d4ff0SYann Gautier /* 791d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 792d82d4ff0SYann Gautier * is automatically generated. 793d82d4ff0SYann Gautier * Wait until STOPF flag is reset. 794d82d4ff0SYann Gautier */ 795d82d4ff0SYann Gautier if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 796d82d4ff0SYann Gautier goto bail; 797d82d4ff0SYann Gautier } 798d82d4ff0SYann Gautier 799d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 800d82d4ff0SYann Gautier 801d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 802d82d4ff0SYann Gautier 803d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 804d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 805d82d4ff0SYann Gautier 806d82d4ff0SYann Gautier rc = 0; 807d82d4ff0SYann Gautier 808d82d4ff0SYann Gautier bail: 809d82d4ff0SYann Gautier hi2c->lock = 0; 81033667d29SYann Gautier clk_disable(hi2c->clock); 811d82d4ff0SYann Gautier 812d82d4ff0SYann Gautier return rc; 813d82d4ff0SYann Gautier } 814d82d4ff0SYann Gautier 815d82d4ff0SYann Gautier /* 816d82d4ff0SYann Gautier * @brief Read an amount of data in blocking mode from a specific memory 817d82d4ff0SYann Gautier * address. 818d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 819d82d4ff0SYann Gautier * the configuration information for the specified I2C. 820d82d4ff0SYann Gautier * @param dev_addr: Target device address 821d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 822d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 823d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 824d82d4ff0SYann Gautier * @param size: Amount of data to be sent 825d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 826d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 827d82d4ff0SYann Gautier */ 828d82d4ff0SYann Gautier int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 829d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 830d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 831d82d4ff0SYann Gautier { 832d82d4ff0SYann Gautier return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, 833d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MEM); 834d82d4ff0SYann Gautier } 835d82d4ff0SYann Gautier 836d82d4ff0SYann Gautier /* 837d82d4ff0SYann Gautier * @brief Receives in master mode an amount of data in blocking mode. 838d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 839d82d4ff0SYann Gautier * the configuration information for the specified I2C. 840d82d4ff0SYann Gautier * @param dev_addr: Target device address 841d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 842d82d4ff0SYann Gautier * @param size: Amount of data to be sent 843d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 844d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 845d82d4ff0SYann Gautier */ 846d82d4ff0SYann Gautier int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, 847d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, 848d82d4ff0SYann Gautier uint32_t timeout_ms) 849d82d4ff0SYann Gautier { 850d82d4ff0SYann Gautier return i2c_read(hi2c, dev_addr, 0, 0, 851d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MASTER); 852d82d4ff0SYann Gautier } 853d82d4ff0SYann Gautier 854d82d4ff0SYann Gautier /* 855d82d4ff0SYann Gautier * @brief Checks if target device is ready for communication. 856d82d4ff0SYann Gautier * @note This function is used with Memory devices 857d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 858d82d4ff0SYann Gautier * the configuration information for the specified I2C. 859d82d4ff0SYann Gautier * @param dev_addr: Target device address 860d82d4ff0SYann Gautier * @param trials: Number of trials 861d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 862d82d4ff0SYann Gautier * @retval True if device is ready, false else 863d82d4ff0SYann Gautier */ 864d82d4ff0SYann Gautier bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, 865d82d4ff0SYann Gautier uint16_t dev_addr, uint32_t trials, 866d82d4ff0SYann Gautier uint32_t timeout_ms) 867d82d4ff0SYann Gautier { 868d82d4ff0SYann Gautier uint32_t i2c_trials = 0U; 869d82d4ff0SYann Gautier bool rc = false; 870d82d4ff0SYann Gautier 871d82d4ff0SYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 872d82d4ff0SYann Gautier return rc; 873d82d4ff0SYann Gautier } 874d82d4ff0SYann Gautier 87533667d29SYann Gautier clk_enable(hi2c->clock); 876d82d4ff0SYann Gautier 877d82d4ff0SYann Gautier hi2c->lock = 1; 878d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 879d82d4ff0SYann Gautier 880d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != 881d82d4ff0SYann Gautier 0U) { 882d82d4ff0SYann Gautier goto bail; 883d82d4ff0SYann Gautier } 884d82d4ff0SYann Gautier 885435832abSYann Gautier hi2c->i2c_state = I2C_STATE_BUSY; 886d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 887435832abSYann Gautier 888d82d4ff0SYann Gautier do { 889d82d4ff0SYann Gautier uint64_t timeout_ref; 890435832abSYann Gautier 891d82d4ff0SYann Gautier /* Generate Start */ 892d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & 893d82d4ff0SYann Gautier I2C_OAR1_OA1MODE) == 0) { 894d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 895d82d4ff0SYann Gautier (((uint32_t)dev_addr & I2C_CR2_SADD) | 896d82d4ff0SYann Gautier I2C_CR2_START | I2C_CR2_AUTOEND) & 897d82d4ff0SYann Gautier ~I2C_CR2_RD_WRN); 898d82d4ff0SYann Gautier } else { 899d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 900d82d4ff0SYann Gautier (((uint32_t)dev_addr & I2C_CR2_SADD) | 901d82d4ff0SYann Gautier I2C_CR2_START | I2C_CR2_ADD10) & 902d82d4ff0SYann Gautier ~I2C_CR2_RD_WRN); 903d82d4ff0SYann Gautier } 904435832abSYann Gautier 905d82d4ff0SYann Gautier /* 906d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 907d82d4ff0SYann Gautier * is automatically generated. 908d82d4ff0SYann Gautier * Wait until STOPF flag is set or a NACK flag is set. 909d82d4ff0SYann Gautier */ 910d82d4ff0SYann Gautier timeout_ref = timeout_init_us(timeout_ms * 1000); 911d82d4ff0SYann Gautier do { 912d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 913d82d4ff0SYann Gautier (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { 914d82d4ff0SYann Gautier break; 915d82d4ff0SYann Gautier } 916435832abSYann Gautier 917d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 918d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 919d82d4ff0SYann Gautier goto bail; 920d82d4ff0SYann Gautier } 921d82d4ff0SYann Gautier } while (true); 922d82d4ff0SYann Gautier 923d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 924d82d4ff0SYann Gautier I2C_FLAG_AF) == 0U) { 925d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 926d82d4ff0SYann Gautier timeout_ref) != 0) { 927d82d4ff0SYann Gautier goto bail; 928d82d4ff0SYann Gautier } 929d82d4ff0SYann Gautier 930d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 931d82d4ff0SYann Gautier I2C_FLAG_STOPF); 932435832abSYann Gautier 933435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 934435832abSYann Gautier 935d82d4ff0SYann Gautier rc = true; 936d82d4ff0SYann Gautier goto bail; 937435832abSYann Gautier } 938d82d4ff0SYann Gautier 939d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { 940d82d4ff0SYann Gautier goto bail; 941d82d4ff0SYann Gautier } 942d82d4ff0SYann Gautier 943d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 944d82d4ff0SYann Gautier 945d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 946d82d4ff0SYann Gautier 947d82d4ff0SYann Gautier if (i2c_trials == trials) { 948d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 949d82d4ff0SYann Gautier I2C_CR2_STOP); 950d82d4ff0SYann Gautier 951d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 952d82d4ff0SYann Gautier timeout_ref) != 0) { 953d82d4ff0SYann Gautier goto bail; 954d82d4ff0SYann Gautier } 955d82d4ff0SYann Gautier 956d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 957d82d4ff0SYann Gautier I2C_FLAG_STOPF); 958d82d4ff0SYann Gautier } 959d82d4ff0SYann Gautier 960d82d4ff0SYann Gautier i2c_trials++; 961d82d4ff0SYann Gautier } while (i2c_trials < trials); 962d82d4ff0SYann Gautier 963d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 964d82d4ff0SYann Gautier 965d82d4ff0SYann Gautier bail: 966d82d4ff0SYann Gautier hi2c->lock = 0; 96733667d29SYann Gautier clk_disable(hi2c->clock); 968d82d4ff0SYann Gautier 969d82d4ff0SYann Gautier return rc; 970d82d4ff0SYann Gautier } 971d82d4ff0SYann Gautier 972