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