1435832abSYann Gautier /* 2*33667d29SYann Gautier * Copyright (c) 2016-2021, 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 <libfdt.h> 12d82d4ff0SYann Gautier 13d82d4ff0SYann Gautier #include <platform_def.h> 14d82d4ff0SYann Gautier 15d82d4ff0SYann Gautier #include <common/debug.h> 16*33667d29SYann Gautier #include <drivers/clk.h> 17435832abSYann Gautier #include <drivers/delay_timer.h> 18d82d4ff0SYann Gautier #include <drivers/st/stm32_gpio.h> 19435832abSYann Gautier #include <drivers/st/stm32_i2c.h> 20435832abSYann Gautier #include <lib/mmio.h> 21d82d4ff0SYann Gautier #include <lib/utils.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 { 100d82d4ff0SYann Gautier const fdt32_t *cuint; 101d82d4ff0SYann Gautier 102d82d4ff0SYann Gautier cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); 103d82d4ff0SYann Gautier if (cuint == NULL) { 104d82d4ff0SYann Gautier init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; 105d82d4ff0SYann Gautier } else { 106d82d4ff0SYann Gautier init->rise_time = fdt32_to_cpu(*cuint); 107d82d4ff0SYann Gautier } 108d82d4ff0SYann Gautier 109d82d4ff0SYann Gautier cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); 110d82d4ff0SYann Gautier if (cuint == NULL) { 111d82d4ff0SYann Gautier init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; 112d82d4ff0SYann Gautier } else { 113d82d4ff0SYann Gautier init->fall_time = fdt32_to_cpu(*cuint); 114d82d4ff0SYann Gautier } 115d82d4ff0SYann Gautier 116d82d4ff0SYann Gautier cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); 117d82d4ff0SYann Gautier if (cuint == NULL) { 118d82d4ff0SYann Gautier init->speed_mode = STM32_I2C_SPEED_DEFAULT; 119d82d4ff0SYann Gautier } else { 120d82d4ff0SYann Gautier switch (fdt32_to_cpu(*cuint)) { 121d82d4ff0SYann Gautier case STANDARD_RATE: 122d82d4ff0SYann Gautier init->speed_mode = I2C_SPEED_STANDARD; 123d82d4ff0SYann Gautier break; 124d82d4ff0SYann Gautier case FAST_RATE: 125d82d4ff0SYann Gautier init->speed_mode = I2C_SPEED_FAST; 126d82d4ff0SYann Gautier break; 127d82d4ff0SYann Gautier case FAST_PLUS_RATE: 128d82d4ff0SYann Gautier init->speed_mode = I2C_SPEED_FAST_PLUS; 129d82d4ff0SYann Gautier break; 130d82d4ff0SYann Gautier default: 131d82d4ff0SYann Gautier init->speed_mode = STM32_I2C_SPEED_DEFAULT; 132d82d4ff0SYann Gautier break; 133d82d4ff0SYann Gautier } 134d82d4ff0SYann Gautier } 135d82d4ff0SYann Gautier 136d82d4ff0SYann Gautier return dt_set_pinctrl_config(node); 137d82d4ff0SYann Gautier } 138435832abSYann Gautier 139435832abSYann Gautier /* 140435832abSYann Gautier * @brief Initialize the I2C device. 141435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 142435832abSYann Gautier * the configuration information for the specified I2C. 143d82d4ff0SYann Gautier * @param init_data: Initialization configuration structure 144435832abSYann Gautier * @retval 0 if OK, negative value else 145435832abSYann Gautier */ 146d82d4ff0SYann Gautier int stm32_i2c_init(struct i2c_handle_s *hi2c, 147d82d4ff0SYann Gautier struct stm32_i2c_init_s *init_data) 148435832abSYann Gautier { 149d82d4ff0SYann Gautier int rc = 0; 150d82d4ff0SYann Gautier uint32_t timing = I2C_TIMING; 151d82d4ff0SYann Gautier 152435832abSYann Gautier if (hi2c == NULL) { 153435832abSYann Gautier return -ENOENT; 154435832abSYann Gautier } 155435832abSYann Gautier 156435832abSYann Gautier if (hi2c->i2c_state == I2C_STATE_RESET) { 157435832abSYann Gautier hi2c->lock = 0; 158435832abSYann Gautier } 159435832abSYann Gautier 160435832abSYann Gautier hi2c->i2c_state = I2C_STATE_BUSY; 161435832abSYann Gautier 162*33667d29SYann Gautier clk_enable(hi2c->clock); 163d82d4ff0SYann Gautier 164435832abSYann Gautier /* Disable the selected I2C peripheral */ 165435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 166435832abSYann Gautier 167435832abSYann Gautier /* Configure I2Cx: Frequency range */ 168435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, 169d82d4ff0SYann Gautier timing & TIMINGR_CLEAR_MASK); 170435832abSYann Gautier 171435832abSYann Gautier /* Disable Own Address1 before set the Own Address1 configuration */ 172435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); 173435832abSYann Gautier 174435832abSYann Gautier /* Configure I2Cx: Own Address1 and ack own address1 mode */ 175d82d4ff0SYann Gautier if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { 176435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 177d82d4ff0SYann Gautier I2C_OAR1_OA1EN | init_data->own_address1); 178435832abSYann Gautier } else { /* I2C_ADDRESSINGMODE_10BIT */ 179435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 180435832abSYann Gautier I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | 181d82d4ff0SYann Gautier init_data->own_address1); 182435832abSYann Gautier } 183435832abSYann Gautier 184d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); 185d82d4ff0SYann Gautier 186435832abSYann Gautier /* Configure I2Cx: Addressing Master mode */ 187d82d4ff0SYann Gautier if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { 188d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); 189435832abSYann Gautier } 190435832abSYann Gautier 191435832abSYann Gautier /* 192435832abSYann Gautier * Enable the AUTOEND by default, and enable NACK 193d82d4ff0SYann Gautier * (should be disabled only during Slave process). 194435832abSYann Gautier */ 195435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 196435832abSYann Gautier I2C_CR2_AUTOEND | I2C_CR2_NACK); 197435832abSYann Gautier 198435832abSYann Gautier /* Disable Own Address2 before set the Own Address2 configuration */ 199435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); 200435832abSYann Gautier 201435832abSYann Gautier /* Configure I2Cx: Dual mode and Own Address2 */ 202435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, 203d82d4ff0SYann Gautier init_data->dual_address_mode | 204d82d4ff0SYann Gautier init_data->own_address2 | 205d82d4ff0SYann Gautier (init_data->own_address2_masks << 8)); 206435832abSYann Gautier 207435832abSYann Gautier /* Configure I2Cx: Generalcall and NoStretch mode */ 208435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, 209d82d4ff0SYann Gautier init_data->general_call_mode | 210d82d4ff0SYann Gautier init_data->no_stretch_mode); 211435832abSYann Gautier 212435832abSYann Gautier /* Enable the selected I2C peripheral */ 213435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 214435832abSYann Gautier 215435832abSYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 216435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 217435832abSYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 218435832abSYann Gautier 219d82d4ff0SYann Gautier rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? 220d82d4ff0SYann Gautier I2C_ANALOGFILTER_ENABLE : 221d82d4ff0SYann Gautier I2C_ANALOGFILTER_DISABLE); 222d82d4ff0SYann Gautier if (rc != 0) { 223d82d4ff0SYann Gautier ERROR("Cannot initialize I2C analog filter (%d)\n", rc); 224*33667d29SYann Gautier clk_disable(hi2c->clock); 225d82d4ff0SYann Gautier return rc; 226435832abSYann Gautier } 227435832abSYann Gautier 228*33667d29SYann Gautier clk_disable(hi2c->clock); 229435832abSYann Gautier 230d82d4ff0SYann Gautier return rc; 231435832abSYann Gautier } 232435832abSYann Gautier 233435832abSYann Gautier /* 234435832abSYann Gautier * @brief I2C Tx data register flush process. 235d82d4ff0SYann Gautier * @param hi2c: I2C handle 236435832abSYann Gautier * @retval None 237435832abSYann Gautier */ 238435832abSYann Gautier static void i2c_flush_txdr(struct i2c_handle_s *hi2c) 239435832abSYann Gautier { 240435832abSYann Gautier /* 241435832abSYann Gautier * If a pending TXIS flag is set, 242435832abSYann Gautier * write a dummy data in TXDR to clear it. 243435832abSYann Gautier */ 244435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != 245435832abSYann Gautier 0U) { 246435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); 247435832abSYann Gautier } 248435832abSYann Gautier 249435832abSYann Gautier /* Flush TX register if not empty */ 250435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == 251435832abSYann Gautier 0U) { 252435832abSYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, 253435832abSYann Gautier I2C_FLAG_TXE); 254435832abSYann Gautier } 255435832abSYann Gautier } 256435832abSYann Gautier 257435832abSYann Gautier /* 258435832abSYann Gautier * @brief This function handles I2C Communication timeout. 259435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 260435832abSYann Gautier * the configuration information for the specified I2C. 261d82d4ff0SYann Gautier * @param flag: Specifies the I2C flag to check 262d82d4ff0SYann Gautier * @param awaited_value: The awaited bit value for the flag (0 or 1) 263d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 264435832abSYann Gautier * @retval 0 if OK, negative value else 265435832abSYann Gautier */ 266435832abSYann Gautier static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, 267d82d4ff0SYann Gautier uint8_t awaited_value, uint64_t timeout_ref) 268435832abSYann Gautier { 269d82d4ff0SYann Gautier for ( ; ; ) { 270d82d4ff0SYann Gautier uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); 271435832abSYann Gautier 272d82d4ff0SYann Gautier if (!!(isr & flag) != !!awaited_value) { 273435832abSYann Gautier return 0; 274435832abSYann Gautier } 275435832abSYann Gautier 276d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 277d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 278435832abSYann Gautier hi2c->lock = 0; 279435832abSYann Gautier 280435832abSYann Gautier return -EIO; 281435832abSYann Gautier } 282435832abSYann Gautier } 283435832abSYann Gautier } 284435832abSYann Gautier 285435832abSYann Gautier /* 286435832abSYann Gautier * @brief This function handles Acknowledge failed detection during 287435832abSYann Gautier * an I2C Communication. 288435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 289435832abSYann Gautier * the configuration information for the specified I2C. 290d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 291435832abSYann Gautier * @retval 0 if OK, negative value else 292435832abSYann Gautier */ 293d82d4ff0SYann Gautier static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 294435832abSYann Gautier { 295435832abSYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { 296435832abSYann Gautier return 0; 297435832abSYann Gautier } 298435832abSYann Gautier 299435832abSYann Gautier /* 300435832abSYann Gautier * Wait until STOP Flag is reset. 301435832abSYann Gautier * AutoEnd should be initiate after AF. 302435832abSYann Gautier */ 303435832abSYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 304435832abSYann Gautier I2C_FLAG_STOPF) == 0U) { 305d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 306d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 307435832abSYann Gautier hi2c->lock = 0; 308435832abSYann Gautier 309435832abSYann Gautier return -EIO; 310435832abSYann Gautier } 311435832abSYann Gautier } 312435832abSYann Gautier 313435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 314435832abSYann Gautier 315435832abSYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 316435832abSYann Gautier 317435832abSYann Gautier i2c_flush_txdr(hi2c); 318435832abSYann Gautier 319435832abSYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 320435832abSYann Gautier 321435832abSYann Gautier hi2c->i2c_err |= I2C_ERROR_AF; 322435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 323435832abSYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 324435832abSYann Gautier 325435832abSYann Gautier hi2c->lock = 0; 326435832abSYann Gautier 327435832abSYann Gautier return -EIO; 328435832abSYann Gautier } 329435832abSYann Gautier 330435832abSYann Gautier /* 331d82d4ff0SYann Gautier * @brief This function handles I2C Communication timeout for specific usage 332d82d4ff0SYann Gautier * of TXIS flag. 333d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 334d82d4ff0SYann Gautier * the configuration information for the specified I2C. 335d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 336d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 337d82d4ff0SYann Gautier */ 338d82d4ff0SYann Gautier static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 339d82d4ff0SYann Gautier { 340d82d4ff0SYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 341d82d4ff0SYann Gautier I2C_FLAG_TXIS) == 0U) { 342d82d4ff0SYann Gautier if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 343d82d4ff0SYann Gautier return -EIO; 344d82d4ff0SYann Gautier } 345d82d4ff0SYann Gautier 346d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 347d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 348d82d4ff0SYann Gautier hi2c->lock = 0; 349d82d4ff0SYann Gautier 350d82d4ff0SYann Gautier return -EIO; 351d82d4ff0SYann Gautier } 352d82d4ff0SYann Gautier } 353d82d4ff0SYann Gautier 354d82d4ff0SYann Gautier return 0; 355d82d4ff0SYann Gautier } 356d82d4ff0SYann Gautier 357d82d4ff0SYann Gautier /* 358d82d4ff0SYann Gautier * @brief This function handles I2C Communication timeout for specific 359d82d4ff0SYann Gautier * usage of STOP flag. 360d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 361d82d4ff0SYann Gautier * the configuration information for the specified I2C. 362d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 363d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 364d82d4ff0SYann Gautier */ 365d82d4ff0SYann Gautier static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 366d82d4ff0SYann Gautier { 367d82d4ff0SYann Gautier while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 368d82d4ff0SYann Gautier I2C_FLAG_STOPF) == 0U) { 369d82d4ff0SYann Gautier if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 370d82d4ff0SYann Gautier return -EIO; 371d82d4ff0SYann Gautier } 372d82d4ff0SYann Gautier 373d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 374d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 375d82d4ff0SYann Gautier hi2c->lock = 0; 376d82d4ff0SYann Gautier 377d82d4ff0SYann Gautier return -EIO; 378d82d4ff0SYann Gautier } 379d82d4ff0SYann Gautier } 380d82d4ff0SYann Gautier 381d82d4ff0SYann Gautier return 0; 382d82d4ff0SYann Gautier } 383d82d4ff0SYann Gautier 384d82d4ff0SYann Gautier /* 385435832abSYann Gautier * @brief Handles I2Cx communication when starting transfer or during transfer 386435832abSYann Gautier * (TC or TCR flag are set). 387d82d4ff0SYann Gautier * @param hi2c: I2C handle 388d82d4ff0SYann Gautier * @param dev_addr: Specifies the slave address to be programmed 389435832abSYann Gautier * @param size: Specifies the number of bytes to be programmed. 390435832abSYann Gautier * This parameter must be a value between 0 and 255. 391435832abSYann Gautier * @param i2c_mode: New state of the I2C START condition generation. 392435832abSYann Gautier * This parameter can be one of the following values: 393435832abSYann Gautier * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. 394435832abSYann Gautier * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. 395435832abSYann Gautier * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. 396435832abSYann Gautier * @param request: New state of the I2C START condition generation. 397435832abSYann Gautier * This parameter can be one of the following values: 398435832abSYann Gautier * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. 399435832abSYann Gautier * @arg @ref I2C_GENERATE_STOP: Generate stop condition 400435832abSYann Gautier * (size should be set to 0). 401435832abSYann Gautier * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. 402435832abSYann Gautier * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. 403435832abSYann Gautier * @retval None 404435832abSYann Gautier */ 405435832abSYann Gautier static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, 406435832abSYann Gautier uint16_t size, uint32_t i2c_mode, 407435832abSYann Gautier uint32_t request) 408435832abSYann Gautier { 409435832abSYann Gautier uint32_t clr_value, set_value; 410435832abSYann Gautier 411435832abSYann Gautier clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | 412435832abSYann Gautier I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | 413435832abSYann Gautier (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); 414435832abSYann Gautier 415435832abSYann Gautier set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | 416435832abSYann Gautier (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | 417435832abSYann Gautier i2c_mode | request; 418435832abSYann Gautier 419435832abSYann Gautier mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); 420435832abSYann Gautier } 421435832abSYann Gautier 422435832abSYann Gautier /* 423d82d4ff0SYann Gautier * @brief Master sends target device address followed by internal memory 424d82d4ff0SYann Gautier * address for write request. 425435832abSYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 426d82d4ff0SYann Gautier * the configuration information for the specified I2C. 427d82d4ff0SYann Gautier * @param dev_addr: Target device address 428d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 429d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 430d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 431435832abSYann Gautier * @retval 0 if OK, negative value else 432435832abSYann Gautier */ 433d82d4ff0SYann Gautier static int i2c_request_memory_write(struct i2c_handle_s *hi2c, 434d82d4ff0SYann Gautier uint16_t dev_addr, uint16_t mem_addr, 435d82d4ff0SYann Gautier uint16_t mem_add_size, uint64_t timeout_ref) 436435832abSYann Gautier { 437d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, 438d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 439d82d4ff0SYann Gautier 440d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 441d82d4ff0SYann Gautier return -EIO; 442d82d4ff0SYann Gautier } 443d82d4ff0SYann Gautier 444d82d4ff0SYann Gautier if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 445d82d4ff0SYann Gautier /* Send Memory Address */ 446d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 447d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 448d82d4ff0SYann Gautier } else { 449d82d4ff0SYann Gautier /* Send MSB of Memory Address */ 450d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 451d82d4ff0SYann Gautier (uint8_t)((mem_addr & 0xFF00U) >> 8)); 452d82d4ff0SYann Gautier 453d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 454d82d4ff0SYann Gautier return -EIO; 455d82d4ff0SYann Gautier } 456d82d4ff0SYann Gautier 457d82d4ff0SYann Gautier /* Send LSB of Memory Address */ 458d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 459d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 460d82d4ff0SYann Gautier } 461d82d4ff0SYann Gautier 462d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) { 463d82d4ff0SYann Gautier return -EIO; 464d82d4ff0SYann Gautier } 465d82d4ff0SYann Gautier 466d82d4ff0SYann Gautier return 0; 467d82d4ff0SYann Gautier } 468d82d4ff0SYann Gautier 469d82d4ff0SYann Gautier /* 470d82d4ff0SYann Gautier * @brief Master sends target device address followed by internal memory 471d82d4ff0SYann Gautier * address for read request. 472d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 473d82d4ff0SYann Gautier * the configuration information for the specified I2C. 474d82d4ff0SYann Gautier * @param dev_addr: Target device address 475d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 476d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 477d82d4ff0SYann Gautier * @param timeout_ref: Reference to target timeout 478d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 479d82d4ff0SYann Gautier */ 480d82d4ff0SYann Gautier static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 481d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 482d82d4ff0SYann Gautier uint64_t timeout_ref) 483d82d4ff0SYann Gautier { 484d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, 485d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 486d82d4ff0SYann Gautier 487d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 488d82d4ff0SYann Gautier return -EIO; 489d82d4ff0SYann Gautier } 490d82d4ff0SYann Gautier 491d82d4ff0SYann Gautier if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 492d82d4ff0SYann Gautier /* Send Memory Address */ 493d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 494d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 495d82d4ff0SYann Gautier } else { 496d82d4ff0SYann Gautier /* Send MSB of Memory Address */ 497d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 498d82d4ff0SYann Gautier (uint8_t)((mem_addr & 0xFF00U) >> 8)); 499d82d4ff0SYann Gautier 500d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 501d82d4ff0SYann Gautier return -EIO; 502d82d4ff0SYann Gautier } 503d82d4ff0SYann Gautier 504d82d4ff0SYann Gautier /* Send LSB of Memory Address */ 505d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 506d82d4ff0SYann Gautier (uint8_t)(mem_addr & 0x00FFU)); 507d82d4ff0SYann Gautier } 508d82d4ff0SYann Gautier 509d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) { 510d82d4ff0SYann Gautier return -EIO; 511d82d4ff0SYann Gautier } 512d82d4ff0SYann Gautier 513d82d4ff0SYann Gautier return 0; 514d82d4ff0SYann Gautier } 515d82d4ff0SYann Gautier /* 516d82d4ff0SYann Gautier * @brief Generic function to write an amount of data in blocking mode 517d82d4ff0SYann Gautier * (for Memory Mode and Master Mode) 518d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 519d82d4ff0SYann Gautier * the configuration information for the specified I2C. 520d82d4ff0SYann Gautier * @param dev_addr: Target device address 521d82d4ff0SYann Gautier * @param mem_addr: Internal memory address (if Memory Mode) 522d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address (if Memory Mode) 523d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 524d82d4ff0SYann Gautier * @param size: Amount of data to be sent 525d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 526d82d4ff0SYann Gautier * @param mode: Communication mode 527d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 528d82d4ff0SYann Gautier */ 529d82d4ff0SYann Gautier static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 530d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 531d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 532d82d4ff0SYann Gautier enum i2c_mode_e mode) 533d82d4ff0SYann Gautier { 534d82d4ff0SYann Gautier uint64_t timeout_ref; 535d82d4ff0SYann Gautier int rc = -EIO; 536d82d4ff0SYann Gautier uint8_t *p_buff = p_data; 537d82d4ff0SYann Gautier uint32_t xfer_size; 538d82d4ff0SYann Gautier uint32_t xfer_count = size; 539d82d4ff0SYann Gautier 540d82d4ff0SYann Gautier if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 541d82d4ff0SYann Gautier return -1; 542d82d4ff0SYann Gautier } 543d82d4ff0SYann Gautier 544435832abSYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 545435832abSYann Gautier return -EBUSY; 546435832abSYann Gautier } 547435832abSYann Gautier 548d82d4ff0SYann Gautier if ((p_data == NULL) || (size == 0U)) { 549d82d4ff0SYann Gautier return -EINVAL; 550d82d4ff0SYann Gautier } 551d82d4ff0SYann Gautier 552*33667d29SYann Gautier clk_enable(hi2c->clock); 553d82d4ff0SYann Gautier 554435832abSYann Gautier hi2c->lock = 1; 555435832abSYann Gautier 556d82d4ff0SYann Gautier timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 557d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 558d82d4ff0SYann Gautier goto bail; 559d82d4ff0SYann Gautier } 560d82d4ff0SYann Gautier 561d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_BUSY_TX; 562d82d4ff0SYann Gautier hi2c->i2c_mode = mode; 563d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 564d82d4ff0SYann Gautier 565d82d4ff0SYann Gautier timeout_ref = timeout_init_us(timeout_ms * 1000); 566d82d4ff0SYann Gautier 567d82d4ff0SYann Gautier if (mode == I2C_MODE_MEM) { 568d82d4ff0SYann Gautier /* In Memory Mode, Send Slave Address and Memory Address */ 569d82d4ff0SYann Gautier if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, 570d82d4ff0SYann Gautier mem_add_size, timeout_ref) != 0) { 571d82d4ff0SYann Gautier goto bail; 572d82d4ff0SYann Gautier } 573d82d4ff0SYann Gautier 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, I2C_NO_STARTSTOP); 578d82d4ff0SYann Gautier } else { 579d82d4ff0SYann Gautier xfer_size = xfer_count; 580d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 581d82d4ff0SYann Gautier I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); 582d82d4ff0SYann Gautier } 583d82d4ff0SYann Gautier } else { 584d82d4ff0SYann Gautier /* In Master Mode, Send Slave Address */ 585d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 586d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 587d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 588d82d4ff0SYann Gautier I2C_RELOAD_MODE, 589d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 590d82d4ff0SYann Gautier } else { 591d82d4ff0SYann Gautier xfer_size = xfer_count; 592d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 593d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 594d82d4ff0SYann Gautier I2C_GENERATE_START_WRITE); 595d82d4ff0SYann Gautier } 596d82d4ff0SYann Gautier } 597d82d4ff0SYann Gautier 598d82d4ff0SYann Gautier do { 599d82d4ff0SYann Gautier if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 600d82d4ff0SYann Gautier goto bail; 601d82d4ff0SYann Gautier } 602d82d4ff0SYann Gautier 603d82d4ff0SYann Gautier mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); 604d82d4ff0SYann Gautier p_buff++; 605d82d4ff0SYann Gautier xfer_count--; 606d82d4ff0SYann Gautier xfer_size--; 607d82d4ff0SYann Gautier 608d82d4ff0SYann Gautier if ((xfer_count != 0U) && (xfer_size == 0U)) { 609d82d4ff0SYann Gautier /* Wait until TCR flag is set */ 610d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 611d82d4ff0SYann Gautier timeout_ref) != 0) { 612d82d4ff0SYann Gautier goto bail; 613d82d4ff0SYann Gautier } 614d82d4ff0SYann Gautier 615d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 616d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 617d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 618d82d4ff0SYann Gautier xfer_size, 619d82d4ff0SYann Gautier I2C_RELOAD_MODE, 620d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 621d82d4ff0SYann Gautier } else { 622d82d4ff0SYann Gautier xfer_size = xfer_count; 623d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 624d82d4ff0SYann Gautier xfer_size, 625d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 626d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 627d82d4ff0SYann Gautier } 628d82d4ff0SYann Gautier } 629d82d4ff0SYann Gautier 630d82d4ff0SYann Gautier } while (xfer_count > 0U); 631d82d4ff0SYann Gautier 632d82d4ff0SYann Gautier /* 633d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 634d82d4ff0SYann Gautier * is automatically generated. 635d82d4ff0SYann Gautier * Wait until STOPF flag is reset. 636d82d4ff0SYann Gautier */ 637d82d4ff0SYann Gautier if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 638d82d4ff0SYann Gautier goto bail; 639d82d4ff0SYann Gautier } 640d82d4ff0SYann Gautier 641d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 642d82d4ff0SYann Gautier 643d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 644d82d4ff0SYann Gautier 645d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 646d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 647d82d4ff0SYann Gautier 648d82d4ff0SYann Gautier rc = 0; 649d82d4ff0SYann Gautier 650d82d4ff0SYann Gautier bail: 651d82d4ff0SYann Gautier hi2c->lock = 0; 652*33667d29SYann Gautier clk_disable(hi2c->clock); 653d82d4ff0SYann Gautier 654d82d4ff0SYann Gautier return rc; 655d82d4ff0SYann Gautier } 656d82d4ff0SYann Gautier 657d82d4ff0SYann Gautier /* 658d82d4ff0SYann Gautier * @brief Write an amount of data in blocking mode to a specific memory 659d82d4ff0SYann Gautier * address. 660d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 661d82d4ff0SYann Gautier * the configuration information for the specified I2C. 662d82d4ff0SYann Gautier * @param dev_addr: Target device address 663d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 664d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 665d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 666d82d4ff0SYann Gautier * @param size: Amount of data to be sent 667d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 668d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 669d82d4ff0SYann Gautier */ 670d82d4ff0SYann Gautier int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 671d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 672d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 673d82d4ff0SYann Gautier { 674d82d4ff0SYann Gautier return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, 675d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MEM); 676d82d4ff0SYann Gautier } 677d82d4ff0SYann Gautier 678d82d4ff0SYann Gautier /* 679d82d4ff0SYann Gautier * @brief Transmits in master mode an amount of data in blocking mode. 680d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 681d82d4ff0SYann Gautier * the configuration information for the specified I2C. 682d82d4ff0SYann Gautier * @param dev_addr: Target device address 683d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 684d82d4ff0SYann Gautier * @param size: Amount of data to be sent 685d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 686d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 687d82d4ff0SYann Gautier */ 688d82d4ff0SYann Gautier int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, 689d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, 690d82d4ff0SYann Gautier uint32_t timeout_ms) 691d82d4ff0SYann Gautier { 692d82d4ff0SYann Gautier return i2c_write(hi2c, dev_addr, 0, 0, 693d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MASTER); 694d82d4ff0SYann Gautier } 695d82d4ff0SYann Gautier 696d82d4ff0SYann Gautier /* 697d82d4ff0SYann Gautier * @brief Generic function to read an amount of data in blocking mode 698d82d4ff0SYann Gautier * (for Memory Mode and Master Mode) 699d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 700d82d4ff0SYann Gautier * the configuration information for the specified I2C. 701d82d4ff0SYann Gautier * @param dev_addr: Target device address 702d82d4ff0SYann Gautier * @param mem_addr: Internal memory address (if Memory Mode) 703d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address (if Memory Mode) 704d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 705d82d4ff0SYann Gautier * @param size: Amount of data to be sent 706d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 707d82d4ff0SYann Gautier * @param mode: Communication mode 708d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 709d82d4ff0SYann Gautier */ 710d82d4ff0SYann Gautier static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 711d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 712d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 713d82d4ff0SYann Gautier enum i2c_mode_e mode) 714d82d4ff0SYann Gautier { 715d82d4ff0SYann Gautier uint64_t timeout_ref; 716d82d4ff0SYann Gautier int rc = -EIO; 717d82d4ff0SYann Gautier uint8_t *p_buff = p_data; 718d82d4ff0SYann Gautier uint32_t xfer_count = size; 719d82d4ff0SYann Gautier uint32_t xfer_size; 720d82d4ff0SYann Gautier 721d82d4ff0SYann Gautier if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 722d82d4ff0SYann Gautier return -1; 723d82d4ff0SYann Gautier } 724d82d4ff0SYann Gautier 725d82d4ff0SYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 726d82d4ff0SYann Gautier return -EBUSY; 727d82d4ff0SYann Gautier } 728d82d4ff0SYann Gautier 729d82d4ff0SYann Gautier if ((p_data == NULL) || (size == 0U)) { 730d82d4ff0SYann Gautier return -EINVAL; 731d82d4ff0SYann Gautier } 732d82d4ff0SYann Gautier 733*33667d29SYann Gautier clk_enable(hi2c->clock); 734d82d4ff0SYann Gautier 735d82d4ff0SYann Gautier hi2c->lock = 1; 736d82d4ff0SYann Gautier 737d82d4ff0SYann Gautier timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 738d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 739d82d4ff0SYann Gautier goto bail; 740d82d4ff0SYann Gautier } 741d82d4ff0SYann Gautier 742d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_BUSY_RX; 743d82d4ff0SYann Gautier hi2c->i2c_mode = mode; 744d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 745d82d4ff0SYann Gautier 746d82d4ff0SYann Gautier if (mode == I2C_MODE_MEM) { 747d82d4ff0SYann Gautier /* Send Memory Address */ 748d82d4ff0SYann Gautier if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, 749d82d4ff0SYann Gautier mem_add_size, timeout_ref) != 0) { 750d82d4ff0SYann Gautier goto bail; 751d82d4ff0SYann Gautier } 752d82d4ff0SYann Gautier } 753d82d4ff0SYann Gautier 754d82d4ff0SYann Gautier /* 755d82d4ff0SYann Gautier * Send Slave Address. 756d82d4ff0SYann Gautier * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE 757d82d4ff0SYann Gautier * and generate RESTART. 758d82d4ff0SYann Gautier */ 759d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 760d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 761d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 762d82d4ff0SYann Gautier I2C_RELOAD_MODE, I2C_GENERATE_START_READ); 763d82d4ff0SYann Gautier } else { 764d82d4ff0SYann Gautier xfer_size = xfer_count; 765d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, xfer_size, 766d82d4ff0SYann Gautier I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); 767d82d4ff0SYann Gautier } 768d82d4ff0SYann Gautier 769d82d4ff0SYann Gautier do { 770d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { 771d82d4ff0SYann Gautier goto bail; 772d82d4ff0SYann Gautier } 773d82d4ff0SYann Gautier 774d82d4ff0SYann Gautier *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); 775d82d4ff0SYann Gautier p_buff++; 776d82d4ff0SYann Gautier xfer_size--; 777d82d4ff0SYann Gautier xfer_count--; 778d82d4ff0SYann Gautier 779d82d4ff0SYann Gautier if ((xfer_count != 0U) && (xfer_size == 0U)) { 780d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 781d82d4ff0SYann Gautier timeout_ref) != 0) { 782d82d4ff0SYann Gautier goto bail; 783d82d4ff0SYann Gautier } 784d82d4ff0SYann Gautier 785d82d4ff0SYann Gautier if (xfer_count > MAX_NBYTE_SIZE) { 786d82d4ff0SYann Gautier xfer_size = MAX_NBYTE_SIZE; 787d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 788d82d4ff0SYann Gautier xfer_size, 789d82d4ff0SYann Gautier I2C_RELOAD_MODE, 790d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 791d82d4ff0SYann Gautier } else { 792d82d4ff0SYann Gautier xfer_size = xfer_count; 793d82d4ff0SYann Gautier i2c_transfer_config(hi2c, dev_addr, 794d82d4ff0SYann Gautier xfer_size, 795d82d4ff0SYann Gautier I2C_AUTOEND_MODE, 796d82d4ff0SYann Gautier I2C_NO_STARTSTOP); 797d82d4ff0SYann Gautier } 798d82d4ff0SYann Gautier } 799d82d4ff0SYann Gautier } while (xfer_count > 0U); 800d82d4ff0SYann Gautier 801d82d4ff0SYann Gautier /* 802d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 803d82d4ff0SYann Gautier * is automatically generated. 804d82d4ff0SYann Gautier * Wait until STOPF flag is reset. 805d82d4ff0SYann Gautier */ 806d82d4ff0SYann Gautier if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 807d82d4ff0SYann Gautier goto bail; 808d82d4ff0SYann Gautier } 809d82d4ff0SYann Gautier 810d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 811d82d4ff0SYann Gautier 812d82d4ff0SYann Gautier mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 813d82d4ff0SYann Gautier 814d82d4ff0SYann Gautier hi2c->i2c_state = I2C_STATE_READY; 815d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 816d82d4ff0SYann Gautier 817d82d4ff0SYann Gautier rc = 0; 818d82d4ff0SYann Gautier 819d82d4ff0SYann Gautier bail: 820d82d4ff0SYann Gautier hi2c->lock = 0; 821*33667d29SYann Gautier clk_disable(hi2c->clock); 822d82d4ff0SYann Gautier 823d82d4ff0SYann Gautier return rc; 824d82d4ff0SYann Gautier } 825d82d4ff0SYann Gautier 826d82d4ff0SYann Gautier /* 827d82d4ff0SYann Gautier * @brief Read an amount of data in blocking mode from a specific memory 828d82d4ff0SYann Gautier * address. 829d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 830d82d4ff0SYann Gautier * the configuration information for the specified I2C. 831d82d4ff0SYann Gautier * @param dev_addr: Target device address 832d82d4ff0SYann Gautier * @param mem_addr: Internal memory address 833d82d4ff0SYann Gautier * @param mem_add_size: Size of internal memory address 834d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 835d82d4ff0SYann Gautier * @param size: Amount of data to be sent 836d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 837d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 838d82d4ff0SYann Gautier */ 839d82d4ff0SYann Gautier int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 840d82d4ff0SYann Gautier uint16_t mem_addr, uint16_t mem_add_size, 841d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 842d82d4ff0SYann Gautier { 843d82d4ff0SYann Gautier return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, 844d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MEM); 845d82d4ff0SYann Gautier } 846d82d4ff0SYann Gautier 847d82d4ff0SYann Gautier /* 848d82d4ff0SYann Gautier * @brief Receives in master mode an amount of data in blocking mode. 849d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 850d82d4ff0SYann Gautier * the configuration information for the specified I2C. 851d82d4ff0SYann Gautier * @param dev_addr: Target device address 852d82d4ff0SYann Gautier * @param p_data: Pointer to data buffer 853d82d4ff0SYann Gautier * @param size: Amount of data to be sent 854d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 855d82d4ff0SYann Gautier * @retval 0 if OK, negative value else 856d82d4ff0SYann Gautier */ 857d82d4ff0SYann Gautier int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, 858d82d4ff0SYann Gautier uint8_t *p_data, uint16_t size, 859d82d4ff0SYann Gautier uint32_t timeout_ms) 860d82d4ff0SYann Gautier { 861d82d4ff0SYann Gautier return i2c_read(hi2c, dev_addr, 0, 0, 862d82d4ff0SYann Gautier p_data, size, timeout_ms, I2C_MODE_MASTER); 863d82d4ff0SYann Gautier } 864d82d4ff0SYann Gautier 865d82d4ff0SYann Gautier /* 866d82d4ff0SYann Gautier * @brief Checks if target device is ready for communication. 867d82d4ff0SYann Gautier * @note This function is used with Memory devices 868d82d4ff0SYann Gautier * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 869d82d4ff0SYann Gautier * the configuration information for the specified I2C. 870d82d4ff0SYann Gautier * @param dev_addr: Target device address 871d82d4ff0SYann Gautier * @param trials: Number of trials 872d82d4ff0SYann Gautier * @param timeout_ms: Timeout duration in milliseconds 873d82d4ff0SYann Gautier * @retval True if device is ready, false else 874d82d4ff0SYann Gautier */ 875d82d4ff0SYann Gautier bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, 876d82d4ff0SYann Gautier uint16_t dev_addr, uint32_t trials, 877d82d4ff0SYann Gautier uint32_t timeout_ms) 878d82d4ff0SYann Gautier { 879d82d4ff0SYann Gautier uint32_t i2c_trials = 0U; 880d82d4ff0SYann Gautier bool rc = false; 881d82d4ff0SYann Gautier 882d82d4ff0SYann Gautier if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 883d82d4ff0SYann Gautier return rc; 884d82d4ff0SYann Gautier } 885d82d4ff0SYann Gautier 886*33667d29SYann Gautier clk_enable(hi2c->clock); 887d82d4ff0SYann Gautier 888d82d4ff0SYann Gautier hi2c->lock = 1; 889d82d4ff0SYann Gautier hi2c->i2c_mode = I2C_MODE_NONE; 890d82d4ff0SYann Gautier 891d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != 892d82d4ff0SYann Gautier 0U) { 893d82d4ff0SYann Gautier goto bail; 894d82d4ff0SYann Gautier } 895d82d4ff0SYann Gautier 896435832abSYann Gautier hi2c->i2c_state = I2C_STATE_BUSY; 897d82d4ff0SYann Gautier hi2c->i2c_err = I2C_ERROR_NONE; 898435832abSYann Gautier 899d82d4ff0SYann Gautier do { 900d82d4ff0SYann Gautier uint64_t timeout_ref; 901435832abSYann Gautier 902d82d4ff0SYann Gautier /* Generate Start */ 903d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & 904d82d4ff0SYann Gautier I2C_OAR1_OA1MODE) == 0) { 905d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 906d82d4ff0SYann Gautier (((uint32_t)dev_addr & I2C_CR2_SADD) | 907d82d4ff0SYann Gautier I2C_CR2_START | I2C_CR2_AUTOEND) & 908d82d4ff0SYann Gautier ~I2C_CR2_RD_WRN); 909d82d4ff0SYann Gautier } else { 910d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 911d82d4ff0SYann Gautier (((uint32_t)dev_addr & I2C_CR2_SADD) | 912d82d4ff0SYann Gautier I2C_CR2_START | I2C_CR2_ADD10) & 913d82d4ff0SYann Gautier ~I2C_CR2_RD_WRN); 914d82d4ff0SYann Gautier } 915435832abSYann Gautier 916d82d4ff0SYann Gautier /* 917d82d4ff0SYann Gautier * No need to Check TC flag, with AUTOEND mode the stop 918d82d4ff0SYann Gautier * is automatically generated. 919d82d4ff0SYann Gautier * Wait until STOPF flag is set or a NACK flag is set. 920d82d4ff0SYann Gautier */ 921d82d4ff0SYann Gautier timeout_ref = timeout_init_us(timeout_ms * 1000); 922d82d4ff0SYann Gautier do { 923d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 924d82d4ff0SYann Gautier (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { 925d82d4ff0SYann Gautier break; 926d82d4ff0SYann Gautier } 927435832abSYann Gautier 928d82d4ff0SYann Gautier if (timeout_elapsed(timeout_ref)) { 929d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 930d82d4ff0SYann Gautier goto bail; 931d82d4ff0SYann Gautier } 932d82d4ff0SYann Gautier } while (true); 933d82d4ff0SYann Gautier 934d82d4ff0SYann Gautier if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 935d82d4ff0SYann Gautier I2C_FLAG_AF) == 0U) { 936d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 937d82d4ff0SYann Gautier timeout_ref) != 0) { 938d82d4ff0SYann Gautier goto bail; 939d82d4ff0SYann Gautier } 940d82d4ff0SYann Gautier 941d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 942d82d4ff0SYann Gautier I2C_FLAG_STOPF); 943435832abSYann Gautier 944435832abSYann Gautier hi2c->i2c_state = I2C_STATE_READY; 945435832abSYann Gautier 946d82d4ff0SYann Gautier rc = true; 947d82d4ff0SYann Gautier goto bail; 948435832abSYann Gautier } 949d82d4ff0SYann Gautier 950d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { 951d82d4ff0SYann Gautier goto bail; 952d82d4ff0SYann Gautier } 953d82d4ff0SYann Gautier 954d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 955d82d4ff0SYann Gautier 956d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 957d82d4ff0SYann Gautier 958d82d4ff0SYann Gautier if (i2c_trials == trials) { 959d82d4ff0SYann Gautier mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 960d82d4ff0SYann Gautier I2C_CR2_STOP); 961d82d4ff0SYann Gautier 962d82d4ff0SYann Gautier if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 963d82d4ff0SYann Gautier timeout_ref) != 0) { 964d82d4ff0SYann Gautier goto bail; 965d82d4ff0SYann Gautier } 966d82d4ff0SYann Gautier 967d82d4ff0SYann Gautier mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 968d82d4ff0SYann Gautier I2C_FLAG_STOPF); 969d82d4ff0SYann Gautier } 970d82d4ff0SYann Gautier 971d82d4ff0SYann Gautier i2c_trials++; 972d82d4ff0SYann Gautier } while (i2c_trials < trials); 973d82d4ff0SYann Gautier 974d82d4ff0SYann Gautier notif_i2c_timeout(hi2c); 975d82d4ff0SYann Gautier 976d82d4ff0SYann Gautier bail: 977d82d4ff0SYann Gautier hi2c->lock = 0; 978*33667d29SYann Gautier clk_disable(hi2c->clock); 979d82d4ff0SYann Gautier 980d82d4ff0SYann Gautier return rc; 981d82d4ff0SYann Gautier } 982d82d4ff0SYann Gautier 983