1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <errno.h> 8*91f16700Schasinglulu #include <stdbool.h> 9*91f16700Schasinglulu #include <stdlib.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <libfdt.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <platform_def.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <drivers/clk.h> 17*91f16700Schasinglulu #include <drivers/delay_timer.h> 18*91f16700Schasinglulu #include <drivers/st/stm32_gpio.h> 19*91f16700Schasinglulu #include <drivers/st/stm32_i2c.h> 20*91f16700Schasinglulu #include <lib/mmio.h> 21*91f16700Schasinglulu #include <lib/utils.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu /* STM32 I2C registers offsets */ 24*91f16700Schasinglulu #define I2C_CR1 0x00U 25*91f16700Schasinglulu #define I2C_CR2 0x04U 26*91f16700Schasinglulu #define I2C_OAR1 0x08U 27*91f16700Schasinglulu #define I2C_OAR2 0x0CU 28*91f16700Schasinglulu #define I2C_TIMINGR 0x10U 29*91f16700Schasinglulu #define I2C_TIMEOUTR 0x14U 30*91f16700Schasinglulu #define I2C_ISR 0x18U 31*91f16700Schasinglulu #define I2C_ICR 0x1CU 32*91f16700Schasinglulu #define I2C_PECR 0x20U 33*91f16700Schasinglulu #define I2C_RXDR 0x24U 34*91f16700Schasinglulu #define I2C_TXDR 0x28U 35*91f16700Schasinglulu 36*91f16700Schasinglulu #define TIMINGR_CLEAR_MASK 0xF0FFFFFFU 37*91f16700Schasinglulu 38*91f16700Schasinglulu #define MAX_NBYTE_SIZE 255U 39*91f16700Schasinglulu 40*91f16700Schasinglulu #define I2C_NSEC_PER_SEC 1000000000L 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ 43*91f16700Schasinglulu #define I2C_TIMING 0x10D07DB5 44*91f16700Schasinglulu 45*91f16700Schasinglulu static void notif_i2c_timeout(struct i2c_handle_s *hi2c) 46*91f16700Schasinglulu { 47*91f16700Schasinglulu hi2c->i2c_err |= I2C_ERROR_TIMEOUT; 48*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 49*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 50*91f16700Schasinglulu } 51*91f16700Schasinglulu 52*91f16700Schasinglulu /* 53*91f16700Schasinglulu * @brief Configure I2C Analog noise filter. 54*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 55*91f16700Schasinglulu * the configuration information for the specified I2C peripheral. 56*91f16700Schasinglulu * @param analog_filter: New state of the Analog filter 57*91f16700Schasinglulu * @retval 0 if OK, negative value else 58*91f16700Schasinglulu */ 59*91f16700Schasinglulu static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, 60*91f16700Schasinglulu uint32_t analog_filter) 61*91f16700Schasinglulu { 62*91f16700Schasinglulu if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 63*91f16700Schasinglulu return -EBUSY; 64*91f16700Schasinglulu } 65*91f16700Schasinglulu 66*91f16700Schasinglulu hi2c->lock = 1; 67*91f16700Schasinglulu 68*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_BUSY; 69*91f16700Schasinglulu 70*91f16700Schasinglulu /* Disable the selected I2C peripheral */ 71*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 72*91f16700Schasinglulu 73*91f16700Schasinglulu /* Reset I2Cx ANOFF bit */ 74*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* Set analog filter bit*/ 77*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* Enable the selected I2C peripheral */ 80*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 81*91f16700Schasinglulu 82*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 83*91f16700Schasinglulu 84*91f16700Schasinglulu hi2c->lock = 0; 85*91f16700Schasinglulu 86*91f16700Schasinglulu return 0; 87*91f16700Schasinglulu } 88*91f16700Schasinglulu 89*91f16700Schasinglulu /* 90*91f16700Schasinglulu * @brief Get I2C setup information from the device tree and set pinctrl 91*91f16700Schasinglulu * configuration. 92*91f16700Schasinglulu * @param fdt: Pointer to the device tree 93*91f16700Schasinglulu * @param node: I2C node offset 94*91f16700Schasinglulu * @param init: Ref to the initialization configuration structure 95*91f16700Schasinglulu * @retval 0 if OK, negative value else 96*91f16700Schasinglulu */ 97*91f16700Schasinglulu int stm32_i2c_get_setup_from_fdt(void *fdt, int node, 98*91f16700Schasinglulu struct stm32_i2c_init_s *init) 99*91f16700Schasinglulu { 100*91f16700Schasinglulu const fdt32_t *cuint; 101*91f16700Schasinglulu 102*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); 103*91f16700Schasinglulu if (cuint == NULL) { 104*91f16700Schasinglulu init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; 105*91f16700Schasinglulu } else { 106*91f16700Schasinglulu init->rise_time = fdt32_to_cpu(*cuint); 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); 110*91f16700Schasinglulu if (cuint == NULL) { 111*91f16700Schasinglulu init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; 112*91f16700Schasinglulu } else { 113*91f16700Schasinglulu init->fall_time = fdt32_to_cpu(*cuint); 114*91f16700Schasinglulu } 115*91f16700Schasinglulu 116*91f16700Schasinglulu cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); 117*91f16700Schasinglulu if (cuint == NULL) { 118*91f16700Schasinglulu init->speed_mode = STM32_I2C_SPEED_DEFAULT; 119*91f16700Schasinglulu } else { 120*91f16700Schasinglulu switch (fdt32_to_cpu(*cuint)) { 121*91f16700Schasinglulu case STANDARD_RATE: 122*91f16700Schasinglulu init->speed_mode = I2C_SPEED_STANDARD; 123*91f16700Schasinglulu break; 124*91f16700Schasinglulu case FAST_RATE: 125*91f16700Schasinglulu init->speed_mode = I2C_SPEED_FAST; 126*91f16700Schasinglulu break; 127*91f16700Schasinglulu case FAST_PLUS_RATE: 128*91f16700Schasinglulu init->speed_mode = I2C_SPEED_FAST_PLUS; 129*91f16700Schasinglulu break; 130*91f16700Schasinglulu default: 131*91f16700Schasinglulu init->speed_mode = STM32_I2C_SPEED_DEFAULT; 132*91f16700Schasinglulu break; 133*91f16700Schasinglulu } 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu return dt_set_pinctrl_config(node); 137*91f16700Schasinglulu } 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* 140*91f16700Schasinglulu * @brief Initialize the I2C device. 141*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 142*91f16700Schasinglulu * the configuration information for the specified I2C. 143*91f16700Schasinglulu * @param init_data: Initialization configuration structure 144*91f16700Schasinglulu * @retval 0 if OK, negative value else 145*91f16700Schasinglulu */ 146*91f16700Schasinglulu int stm32_i2c_init(struct i2c_handle_s *hi2c, 147*91f16700Schasinglulu struct stm32_i2c_init_s *init_data) 148*91f16700Schasinglulu { 149*91f16700Schasinglulu int rc = 0; 150*91f16700Schasinglulu uint32_t timing = I2C_TIMING; 151*91f16700Schasinglulu 152*91f16700Schasinglulu if (hi2c == NULL) { 153*91f16700Schasinglulu return -ENOENT; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu if (hi2c->i2c_state == I2C_STATE_RESET) { 157*91f16700Schasinglulu hi2c->lock = 0; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_BUSY; 161*91f16700Schasinglulu 162*91f16700Schasinglulu clk_enable(hi2c->clock); 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* Disable the selected I2C peripheral */ 165*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 166*91f16700Schasinglulu 167*91f16700Schasinglulu /* Configure I2Cx: Frequency range */ 168*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, 169*91f16700Schasinglulu timing & TIMINGR_CLEAR_MASK); 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* Disable Own Address1 before set the Own Address1 configuration */ 172*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); 173*91f16700Schasinglulu 174*91f16700Schasinglulu /* Configure I2Cx: Own Address1 and ack own address1 mode */ 175*91f16700Schasinglulu if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { 176*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 177*91f16700Schasinglulu I2C_OAR1_OA1EN | init_data->own_address1); 178*91f16700Schasinglulu } else { /* I2C_ADDRESSINGMODE_10BIT */ 179*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, 180*91f16700Schasinglulu I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | 181*91f16700Schasinglulu init_data->own_address1); 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); 185*91f16700Schasinglulu 186*91f16700Schasinglulu /* Configure I2Cx: Addressing Master mode */ 187*91f16700Schasinglulu if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { 188*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); 189*91f16700Schasinglulu } 190*91f16700Schasinglulu 191*91f16700Schasinglulu /* 192*91f16700Schasinglulu * Enable the AUTOEND by default, and enable NACK 193*91f16700Schasinglulu * (should be disabled only during Slave process). 194*91f16700Schasinglulu */ 195*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 196*91f16700Schasinglulu I2C_CR2_AUTOEND | I2C_CR2_NACK); 197*91f16700Schasinglulu 198*91f16700Schasinglulu /* Disable Own Address2 before set the Own Address2 configuration */ 199*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); 200*91f16700Schasinglulu 201*91f16700Schasinglulu /* Configure I2Cx: Dual mode and Own Address2 */ 202*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, 203*91f16700Schasinglulu init_data->dual_address_mode | 204*91f16700Schasinglulu init_data->own_address2 | 205*91f16700Schasinglulu (init_data->own_address2_masks << 8)); 206*91f16700Schasinglulu 207*91f16700Schasinglulu /* Configure I2Cx: Generalcall and NoStretch mode */ 208*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, 209*91f16700Schasinglulu init_data->general_call_mode | 210*91f16700Schasinglulu init_data->no_stretch_mode); 211*91f16700Schasinglulu 212*91f16700Schasinglulu /* Enable the selected I2C peripheral */ 213*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); 214*91f16700Schasinglulu 215*91f16700Schasinglulu hi2c->i2c_err = I2C_ERROR_NONE; 216*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 217*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 218*91f16700Schasinglulu 219*91f16700Schasinglulu rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? 220*91f16700Schasinglulu I2C_ANALOGFILTER_ENABLE : 221*91f16700Schasinglulu I2C_ANALOGFILTER_DISABLE); 222*91f16700Schasinglulu if (rc != 0) { 223*91f16700Schasinglulu ERROR("Cannot initialize I2C analog filter (%d)\n", rc); 224*91f16700Schasinglulu clk_disable(hi2c->clock); 225*91f16700Schasinglulu return rc; 226*91f16700Schasinglulu } 227*91f16700Schasinglulu 228*91f16700Schasinglulu clk_disable(hi2c->clock); 229*91f16700Schasinglulu 230*91f16700Schasinglulu return rc; 231*91f16700Schasinglulu } 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* 234*91f16700Schasinglulu * @brief I2C Tx data register flush process. 235*91f16700Schasinglulu * @param hi2c: I2C handle 236*91f16700Schasinglulu * @retval None 237*91f16700Schasinglulu */ 238*91f16700Schasinglulu static void i2c_flush_txdr(struct i2c_handle_s *hi2c) 239*91f16700Schasinglulu { 240*91f16700Schasinglulu /* 241*91f16700Schasinglulu * If a pending TXIS flag is set, 242*91f16700Schasinglulu * write a dummy data in TXDR to clear it. 243*91f16700Schasinglulu */ 244*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != 245*91f16700Schasinglulu 0U) { 246*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); 247*91f16700Schasinglulu } 248*91f16700Schasinglulu 249*91f16700Schasinglulu /* Flush TX register if not empty */ 250*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == 251*91f16700Schasinglulu 0U) { 252*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, 253*91f16700Schasinglulu I2C_FLAG_TXE); 254*91f16700Schasinglulu } 255*91f16700Schasinglulu } 256*91f16700Schasinglulu 257*91f16700Schasinglulu /* 258*91f16700Schasinglulu * @brief This function handles I2C Communication timeout. 259*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 260*91f16700Schasinglulu * the configuration information for the specified I2C. 261*91f16700Schasinglulu * @param flag: Specifies the I2C flag to check 262*91f16700Schasinglulu * @param awaited_value: The awaited bit value for the flag (0 or 1) 263*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 264*91f16700Schasinglulu * @retval 0 if OK, negative value else 265*91f16700Schasinglulu */ 266*91f16700Schasinglulu static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, 267*91f16700Schasinglulu uint8_t awaited_value, uint64_t timeout_ref) 268*91f16700Schasinglulu { 269*91f16700Schasinglulu for ( ; ; ) { 270*91f16700Schasinglulu uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); 271*91f16700Schasinglulu 272*91f16700Schasinglulu if (!!(isr & flag) != !!awaited_value) { 273*91f16700Schasinglulu return 0; 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 277*91f16700Schasinglulu notif_i2c_timeout(hi2c); 278*91f16700Schasinglulu hi2c->lock = 0; 279*91f16700Schasinglulu 280*91f16700Schasinglulu return -EIO; 281*91f16700Schasinglulu } 282*91f16700Schasinglulu } 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu /* 286*91f16700Schasinglulu * @brief This function handles Acknowledge failed detection during 287*91f16700Schasinglulu * an I2C Communication. 288*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 289*91f16700Schasinglulu * the configuration information for the specified I2C. 290*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 291*91f16700Schasinglulu * @retval 0 if OK, negative value else 292*91f16700Schasinglulu */ 293*91f16700Schasinglulu static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 294*91f16700Schasinglulu { 295*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { 296*91f16700Schasinglulu return 0; 297*91f16700Schasinglulu } 298*91f16700Schasinglulu 299*91f16700Schasinglulu /* 300*91f16700Schasinglulu * Wait until STOP Flag is reset. 301*91f16700Schasinglulu * AutoEnd should be initiate after AF. 302*91f16700Schasinglulu */ 303*91f16700Schasinglulu while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 304*91f16700Schasinglulu I2C_FLAG_STOPF) == 0U) { 305*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 306*91f16700Schasinglulu notif_i2c_timeout(hi2c); 307*91f16700Schasinglulu hi2c->lock = 0; 308*91f16700Schasinglulu 309*91f16700Schasinglulu return -EIO; 310*91f16700Schasinglulu } 311*91f16700Schasinglulu } 312*91f16700Schasinglulu 313*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 314*91f16700Schasinglulu 315*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 316*91f16700Schasinglulu 317*91f16700Schasinglulu i2c_flush_txdr(hi2c); 318*91f16700Schasinglulu 319*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 320*91f16700Schasinglulu 321*91f16700Schasinglulu hi2c->i2c_err |= I2C_ERROR_AF; 322*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 323*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 324*91f16700Schasinglulu 325*91f16700Schasinglulu hi2c->lock = 0; 326*91f16700Schasinglulu 327*91f16700Schasinglulu return -EIO; 328*91f16700Schasinglulu } 329*91f16700Schasinglulu 330*91f16700Schasinglulu /* 331*91f16700Schasinglulu * @brief This function handles I2C Communication timeout for specific usage 332*91f16700Schasinglulu * of TXIS flag. 333*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 334*91f16700Schasinglulu * the configuration information for the specified I2C. 335*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 336*91f16700Schasinglulu * @retval 0 if OK, negative value else 337*91f16700Schasinglulu */ 338*91f16700Schasinglulu static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 339*91f16700Schasinglulu { 340*91f16700Schasinglulu while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 341*91f16700Schasinglulu I2C_FLAG_TXIS) == 0U) { 342*91f16700Schasinglulu if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 343*91f16700Schasinglulu return -EIO; 344*91f16700Schasinglulu } 345*91f16700Schasinglulu 346*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 347*91f16700Schasinglulu notif_i2c_timeout(hi2c); 348*91f16700Schasinglulu hi2c->lock = 0; 349*91f16700Schasinglulu 350*91f16700Schasinglulu return -EIO; 351*91f16700Schasinglulu } 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu return 0; 355*91f16700Schasinglulu } 356*91f16700Schasinglulu 357*91f16700Schasinglulu /* 358*91f16700Schasinglulu * @brief This function handles I2C Communication timeout for specific 359*91f16700Schasinglulu * usage of STOP flag. 360*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 361*91f16700Schasinglulu * the configuration information for the specified I2C. 362*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 363*91f16700Schasinglulu * @retval 0 if OK, negative value else 364*91f16700Schasinglulu */ 365*91f16700Schasinglulu static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) 366*91f16700Schasinglulu { 367*91f16700Schasinglulu while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 368*91f16700Schasinglulu I2C_FLAG_STOPF) == 0U) { 369*91f16700Schasinglulu if (i2c_ack_failed(hi2c, timeout_ref) != 0) { 370*91f16700Schasinglulu return -EIO; 371*91f16700Schasinglulu } 372*91f16700Schasinglulu 373*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 374*91f16700Schasinglulu notif_i2c_timeout(hi2c); 375*91f16700Schasinglulu hi2c->lock = 0; 376*91f16700Schasinglulu 377*91f16700Schasinglulu return -EIO; 378*91f16700Schasinglulu } 379*91f16700Schasinglulu } 380*91f16700Schasinglulu 381*91f16700Schasinglulu return 0; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu /* 385*91f16700Schasinglulu * @brief Handles I2Cx communication when starting transfer or during transfer 386*91f16700Schasinglulu * (TC or TCR flag are set). 387*91f16700Schasinglulu * @param hi2c: I2C handle 388*91f16700Schasinglulu * @param dev_addr: Specifies the slave address to be programmed 389*91f16700Schasinglulu * @param size: Specifies the number of bytes to be programmed. 390*91f16700Schasinglulu * This parameter must be a value between 0 and 255. 391*91f16700Schasinglulu * @param i2c_mode: New state of the I2C START condition generation. 392*91f16700Schasinglulu * This parameter can be one of the following values: 393*91f16700Schasinglulu * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. 394*91f16700Schasinglulu * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. 395*91f16700Schasinglulu * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. 396*91f16700Schasinglulu * @param request: New state of the I2C START condition generation. 397*91f16700Schasinglulu * This parameter can be one of the following values: 398*91f16700Schasinglulu * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. 399*91f16700Schasinglulu * @arg @ref I2C_GENERATE_STOP: Generate stop condition 400*91f16700Schasinglulu * (size should be set to 0). 401*91f16700Schasinglulu * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. 402*91f16700Schasinglulu * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. 403*91f16700Schasinglulu * @retval None 404*91f16700Schasinglulu */ 405*91f16700Schasinglulu static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, 406*91f16700Schasinglulu uint16_t size, uint32_t i2c_mode, 407*91f16700Schasinglulu uint32_t request) 408*91f16700Schasinglulu { 409*91f16700Schasinglulu uint32_t clr_value, set_value; 410*91f16700Schasinglulu 411*91f16700Schasinglulu clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | 412*91f16700Schasinglulu I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | 413*91f16700Schasinglulu (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); 414*91f16700Schasinglulu 415*91f16700Schasinglulu set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | 416*91f16700Schasinglulu (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | 417*91f16700Schasinglulu i2c_mode | request; 418*91f16700Schasinglulu 419*91f16700Schasinglulu mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); 420*91f16700Schasinglulu } 421*91f16700Schasinglulu 422*91f16700Schasinglulu /* 423*91f16700Schasinglulu * @brief Master sends target device address followed by internal memory 424*91f16700Schasinglulu * address for write request. 425*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 426*91f16700Schasinglulu * the configuration information for the specified I2C. 427*91f16700Schasinglulu * @param dev_addr: Target device address 428*91f16700Schasinglulu * @param mem_addr: Internal memory address 429*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address 430*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 431*91f16700Schasinglulu * @retval 0 if OK, negative value else 432*91f16700Schasinglulu */ 433*91f16700Schasinglulu static int i2c_request_memory_write(struct i2c_handle_s *hi2c, 434*91f16700Schasinglulu uint16_t dev_addr, uint16_t mem_addr, 435*91f16700Schasinglulu uint16_t mem_add_size, uint64_t timeout_ref) 436*91f16700Schasinglulu { 437*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, 438*91f16700Schasinglulu I2C_GENERATE_START_WRITE); 439*91f16700Schasinglulu 440*91f16700Schasinglulu if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 441*91f16700Schasinglulu return -EIO; 442*91f16700Schasinglulu } 443*91f16700Schasinglulu 444*91f16700Schasinglulu if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 445*91f16700Schasinglulu /* Send Memory Address */ 446*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 447*91f16700Schasinglulu (uint8_t)(mem_addr & 0x00FFU)); 448*91f16700Schasinglulu } else { 449*91f16700Schasinglulu /* Send MSB of Memory Address */ 450*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 451*91f16700Schasinglulu (uint8_t)((mem_addr & 0xFF00U) >> 8)); 452*91f16700Schasinglulu 453*91f16700Schasinglulu if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 454*91f16700Schasinglulu return -EIO; 455*91f16700Schasinglulu } 456*91f16700Schasinglulu 457*91f16700Schasinglulu /* Send LSB of Memory Address */ 458*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 459*91f16700Schasinglulu (uint8_t)(mem_addr & 0x00FFU)); 460*91f16700Schasinglulu } 461*91f16700Schasinglulu 462*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) { 463*91f16700Schasinglulu return -EIO; 464*91f16700Schasinglulu } 465*91f16700Schasinglulu 466*91f16700Schasinglulu return 0; 467*91f16700Schasinglulu } 468*91f16700Schasinglulu 469*91f16700Schasinglulu /* 470*91f16700Schasinglulu * @brief Master sends target device address followed by internal memory 471*91f16700Schasinglulu * address for read request. 472*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 473*91f16700Schasinglulu * the configuration information for the specified I2C. 474*91f16700Schasinglulu * @param dev_addr: Target device address 475*91f16700Schasinglulu * @param mem_addr: Internal memory address 476*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address 477*91f16700Schasinglulu * @param timeout_ref: Reference to target timeout 478*91f16700Schasinglulu * @retval 0 if OK, negative value else 479*91f16700Schasinglulu */ 480*91f16700Schasinglulu static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 481*91f16700Schasinglulu uint16_t mem_addr, uint16_t mem_add_size, 482*91f16700Schasinglulu uint64_t timeout_ref) 483*91f16700Schasinglulu { 484*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, 485*91f16700Schasinglulu I2C_GENERATE_START_WRITE); 486*91f16700Schasinglulu 487*91f16700Schasinglulu if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 488*91f16700Schasinglulu return -EIO; 489*91f16700Schasinglulu } 490*91f16700Schasinglulu 491*91f16700Schasinglulu if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { 492*91f16700Schasinglulu /* Send Memory Address */ 493*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 494*91f16700Schasinglulu (uint8_t)(mem_addr & 0x00FFU)); 495*91f16700Schasinglulu } else { 496*91f16700Schasinglulu /* Send MSB of Memory Address */ 497*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 498*91f16700Schasinglulu (uint8_t)((mem_addr & 0xFF00U) >> 8)); 499*91f16700Schasinglulu 500*91f16700Schasinglulu if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 501*91f16700Schasinglulu return -EIO; 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu /* Send LSB of Memory Address */ 505*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, 506*91f16700Schasinglulu (uint8_t)(mem_addr & 0x00FFU)); 507*91f16700Schasinglulu } 508*91f16700Schasinglulu 509*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) { 510*91f16700Schasinglulu return -EIO; 511*91f16700Schasinglulu } 512*91f16700Schasinglulu 513*91f16700Schasinglulu return 0; 514*91f16700Schasinglulu } 515*91f16700Schasinglulu /* 516*91f16700Schasinglulu * @brief Generic function to write an amount of data in blocking mode 517*91f16700Schasinglulu * (for Memory Mode and Master Mode) 518*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 519*91f16700Schasinglulu * the configuration information for the specified I2C. 520*91f16700Schasinglulu * @param dev_addr: Target device address 521*91f16700Schasinglulu * @param mem_addr: Internal memory address (if Memory Mode) 522*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address (if Memory Mode) 523*91f16700Schasinglulu * @param p_data: Pointer to data buffer 524*91f16700Schasinglulu * @param size: Amount of data to be sent 525*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 526*91f16700Schasinglulu * @param mode: Communication mode 527*91f16700Schasinglulu * @retval 0 if OK, negative value else 528*91f16700Schasinglulu */ 529*91f16700Schasinglulu static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 530*91f16700Schasinglulu uint16_t mem_addr, uint16_t mem_add_size, 531*91f16700Schasinglulu uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 532*91f16700Schasinglulu enum i2c_mode_e mode) 533*91f16700Schasinglulu { 534*91f16700Schasinglulu uint64_t timeout_ref; 535*91f16700Schasinglulu int rc = -EIO; 536*91f16700Schasinglulu uint8_t *p_buff = p_data; 537*91f16700Schasinglulu uint32_t xfer_size; 538*91f16700Schasinglulu uint32_t xfer_count = size; 539*91f16700Schasinglulu 540*91f16700Schasinglulu if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 541*91f16700Schasinglulu return -1; 542*91f16700Schasinglulu } 543*91f16700Schasinglulu 544*91f16700Schasinglulu if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 545*91f16700Schasinglulu return -EBUSY; 546*91f16700Schasinglulu } 547*91f16700Schasinglulu 548*91f16700Schasinglulu if ((p_data == NULL) || (size == 0U)) { 549*91f16700Schasinglulu return -EINVAL; 550*91f16700Schasinglulu } 551*91f16700Schasinglulu 552*91f16700Schasinglulu clk_enable(hi2c->clock); 553*91f16700Schasinglulu 554*91f16700Schasinglulu hi2c->lock = 1; 555*91f16700Schasinglulu 556*91f16700Schasinglulu timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 557*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 558*91f16700Schasinglulu goto bail; 559*91f16700Schasinglulu } 560*91f16700Schasinglulu 561*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_BUSY_TX; 562*91f16700Schasinglulu hi2c->i2c_mode = mode; 563*91f16700Schasinglulu hi2c->i2c_err = I2C_ERROR_NONE; 564*91f16700Schasinglulu 565*91f16700Schasinglulu timeout_ref = timeout_init_us(timeout_ms * 1000); 566*91f16700Schasinglulu 567*91f16700Schasinglulu if (mode == I2C_MODE_MEM) { 568*91f16700Schasinglulu /* In Memory Mode, Send Slave Address and Memory Address */ 569*91f16700Schasinglulu if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, 570*91f16700Schasinglulu mem_add_size, timeout_ref) != 0) { 571*91f16700Schasinglulu goto bail; 572*91f16700Schasinglulu } 573*91f16700Schasinglulu 574*91f16700Schasinglulu if (xfer_count > MAX_NBYTE_SIZE) { 575*91f16700Schasinglulu xfer_size = MAX_NBYTE_SIZE; 576*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 577*91f16700Schasinglulu I2C_RELOAD_MODE, I2C_NO_STARTSTOP); 578*91f16700Schasinglulu } else { 579*91f16700Schasinglulu xfer_size = xfer_count; 580*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 581*91f16700Schasinglulu I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); 582*91f16700Schasinglulu } 583*91f16700Schasinglulu } else { 584*91f16700Schasinglulu /* In Master Mode, Send Slave Address */ 585*91f16700Schasinglulu if (xfer_count > MAX_NBYTE_SIZE) { 586*91f16700Schasinglulu xfer_size = MAX_NBYTE_SIZE; 587*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 588*91f16700Schasinglulu I2C_RELOAD_MODE, 589*91f16700Schasinglulu I2C_GENERATE_START_WRITE); 590*91f16700Schasinglulu } else { 591*91f16700Schasinglulu xfer_size = xfer_count; 592*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 593*91f16700Schasinglulu I2C_AUTOEND_MODE, 594*91f16700Schasinglulu I2C_GENERATE_START_WRITE); 595*91f16700Schasinglulu } 596*91f16700Schasinglulu } 597*91f16700Schasinglulu 598*91f16700Schasinglulu do { 599*91f16700Schasinglulu if (i2c_wait_txis(hi2c, timeout_ref) != 0) { 600*91f16700Schasinglulu goto bail; 601*91f16700Schasinglulu } 602*91f16700Schasinglulu 603*91f16700Schasinglulu mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); 604*91f16700Schasinglulu p_buff++; 605*91f16700Schasinglulu xfer_count--; 606*91f16700Schasinglulu xfer_size--; 607*91f16700Schasinglulu 608*91f16700Schasinglulu if ((xfer_count != 0U) && (xfer_size == 0U)) { 609*91f16700Schasinglulu /* Wait until TCR flag is set */ 610*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 611*91f16700Schasinglulu timeout_ref) != 0) { 612*91f16700Schasinglulu goto bail; 613*91f16700Schasinglulu } 614*91f16700Schasinglulu 615*91f16700Schasinglulu if (xfer_count > MAX_NBYTE_SIZE) { 616*91f16700Schasinglulu xfer_size = MAX_NBYTE_SIZE; 617*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, 618*91f16700Schasinglulu xfer_size, 619*91f16700Schasinglulu I2C_RELOAD_MODE, 620*91f16700Schasinglulu I2C_NO_STARTSTOP); 621*91f16700Schasinglulu } else { 622*91f16700Schasinglulu xfer_size = xfer_count; 623*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, 624*91f16700Schasinglulu xfer_size, 625*91f16700Schasinglulu I2C_AUTOEND_MODE, 626*91f16700Schasinglulu I2C_NO_STARTSTOP); 627*91f16700Schasinglulu } 628*91f16700Schasinglulu } 629*91f16700Schasinglulu 630*91f16700Schasinglulu } while (xfer_count > 0U); 631*91f16700Schasinglulu 632*91f16700Schasinglulu /* 633*91f16700Schasinglulu * No need to Check TC flag, with AUTOEND mode the stop 634*91f16700Schasinglulu * is automatically generated. 635*91f16700Schasinglulu * Wait until STOPF flag is reset. 636*91f16700Schasinglulu */ 637*91f16700Schasinglulu if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 638*91f16700Schasinglulu goto bail; 639*91f16700Schasinglulu } 640*91f16700Schasinglulu 641*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 642*91f16700Schasinglulu 643*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 644*91f16700Schasinglulu 645*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 646*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 647*91f16700Schasinglulu 648*91f16700Schasinglulu rc = 0; 649*91f16700Schasinglulu 650*91f16700Schasinglulu bail: 651*91f16700Schasinglulu hi2c->lock = 0; 652*91f16700Schasinglulu clk_disable(hi2c->clock); 653*91f16700Schasinglulu 654*91f16700Schasinglulu return rc; 655*91f16700Schasinglulu } 656*91f16700Schasinglulu 657*91f16700Schasinglulu /* 658*91f16700Schasinglulu * @brief Write an amount of data in blocking mode to a specific memory 659*91f16700Schasinglulu * address. 660*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 661*91f16700Schasinglulu * the configuration information for the specified I2C. 662*91f16700Schasinglulu * @param dev_addr: Target device address 663*91f16700Schasinglulu * @param mem_addr: Internal memory address 664*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address 665*91f16700Schasinglulu * @param p_data: Pointer to data buffer 666*91f16700Schasinglulu * @param size: Amount of data to be sent 667*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 668*91f16700Schasinglulu * @retval 0 if OK, negative value else 669*91f16700Schasinglulu */ 670*91f16700Schasinglulu int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, 671*91f16700Schasinglulu uint16_t mem_addr, uint16_t mem_add_size, 672*91f16700Schasinglulu uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 673*91f16700Schasinglulu { 674*91f16700Schasinglulu return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, 675*91f16700Schasinglulu p_data, size, timeout_ms, I2C_MODE_MEM); 676*91f16700Schasinglulu } 677*91f16700Schasinglulu 678*91f16700Schasinglulu /* 679*91f16700Schasinglulu * @brief Transmits in master mode an amount of data in blocking mode. 680*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 681*91f16700Schasinglulu * the configuration information for the specified I2C. 682*91f16700Schasinglulu * @param dev_addr: Target device address 683*91f16700Schasinglulu * @param p_data: Pointer to data buffer 684*91f16700Schasinglulu * @param size: Amount of data to be sent 685*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 686*91f16700Schasinglulu * @retval 0 if OK, negative value else 687*91f16700Schasinglulu */ 688*91f16700Schasinglulu int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, 689*91f16700Schasinglulu uint8_t *p_data, uint16_t size, 690*91f16700Schasinglulu uint32_t timeout_ms) 691*91f16700Schasinglulu { 692*91f16700Schasinglulu return i2c_write(hi2c, dev_addr, 0, 0, 693*91f16700Schasinglulu p_data, size, timeout_ms, I2C_MODE_MASTER); 694*91f16700Schasinglulu } 695*91f16700Schasinglulu 696*91f16700Schasinglulu /* 697*91f16700Schasinglulu * @brief Generic function to read an amount of data in blocking mode 698*91f16700Schasinglulu * (for Memory Mode and Master Mode) 699*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 700*91f16700Schasinglulu * the configuration information for the specified I2C. 701*91f16700Schasinglulu * @param dev_addr: Target device address 702*91f16700Schasinglulu * @param mem_addr: Internal memory address (if Memory Mode) 703*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address (if Memory Mode) 704*91f16700Schasinglulu * @param p_data: Pointer to data buffer 705*91f16700Schasinglulu * @param size: Amount of data to be sent 706*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 707*91f16700Schasinglulu * @param mode: Communication mode 708*91f16700Schasinglulu * @retval 0 if OK, negative value else 709*91f16700Schasinglulu */ 710*91f16700Schasinglulu static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 711*91f16700Schasinglulu uint16_t mem_addr, uint16_t mem_add_size, 712*91f16700Schasinglulu uint8_t *p_data, uint16_t size, uint32_t timeout_ms, 713*91f16700Schasinglulu enum i2c_mode_e mode) 714*91f16700Schasinglulu { 715*91f16700Schasinglulu uint64_t timeout_ref; 716*91f16700Schasinglulu int rc = -EIO; 717*91f16700Schasinglulu uint8_t *p_buff = p_data; 718*91f16700Schasinglulu uint32_t xfer_count = size; 719*91f16700Schasinglulu uint32_t xfer_size; 720*91f16700Schasinglulu 721*91f16700Schasinglulu if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { 722*91f16700Schasinglulu return -1; 723*91f16700Schasinglulu } 724*91f16700Schasinglulu 725*91f16700Schasinglulu if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 726*91f16700Schasinglulu return -EBUSY; 727*91f16700Schasinglulu } 728*91f16700Schasinglulu 729*91f16700Schasinglulu if ((p_data == NULL) || (size == 0U)) { 730*91f16700Schasinglulu return -EINVAL; 731*91f16700Schasinglulu } 732*91f16700Schasinglulu 733*91f16700Schasinglulu clk_enable(hi2c->clock); 734*91f16700Schasinglulu 735*91f16700Schasinglulu hi2c->lock = 1; 736*91f16700Schasinglulu 737*91f16700Schasinglulu timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); 738*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { 739*91f16700Schasinglulu goto bail; 740*91f16700Schasinglulu } 741*91f16700Schasinglulu 742*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_BUSY_RX; 743*91f16700Schasinglulu hi2c->i2c_mode = mode; 744*91f16700Schasinglulu hi2c->i2c_err = I2C_ERROR_NONE; 745*91f16700Schasinglulu 746*91f16700Schasinglulu if (mode == I2C_MODE_MEM) { 747*91f16700Schasinglulu /* Send Memory Address */ 748*91f16700Schasinglulu if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, 749*91f16700Schasinglulu mem_add_size, timeout_ref) != 0) { 750*91f16700Schasinglulu goto bail; 751*91f16700Schasinglulu } 752*91f16700Schasinglulu } 753*91f16700Schasinglulu 754*91f16700Schasinglulu /* 755*91f16700Schasinglulu * Send Slave Address. 756*91f16700Schasinglulu * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE 757*91f16700Schasinglulu * and generate RESTART. 758*91f16700Schasinglulu */ 759*91f16700Schasinglulu if (xfer_count > MAX_NBYTE_SIZE) { 760*91f16700Schasinglulu xfer_size = MAX_NBYTE_SIZE; 761*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 762*91f16700Schasinglulu I2C_RELOAD_MODE, I2C_GENERATE_START_READ); 763*91f16700Schasinglulu } else { 764*91f16700Schasinglulu xfer_size = xfer_count; 765*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, xfer_size, 766*91f16700Schasinglulu I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); 767*91f16700Schasinglulu } 768*91f16700Schasinglulu 769*91f16700Schasinglulu do { 770*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { 771*91f16700Schasinglulu goto bail; 772*91f16700Schasinglulu } 773*91f16700Schasinglulu 774*91f16700Schasinglulu *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); 775*91f16700Schasinglulu p_buff++; 776*91f16700Schasinglulu xfer_size--; 777*91f16700Schasinglulu xfer_count--; 778*91f16700Schasinglulu 779*91f16700Schasinglulu if ((xfer_count != 0U) && (xfer_size == 0U)) { 780*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, 781*91f16700Schasinglulu timeout_ref) != 0) { 782*91f16700Schasinglulu goto bail; 783*91f16700Schasinglulu } 784*91f16700Schasinglulu 785*91f16700Schasinglulu if (xfer_count > MAX_NBYTE_SIZE) { 786*91f16700Schasinglulu xfer_size = MAX_NBYTE_SIZE; 787*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, 788*91f16700Schasinglulu xfer_size, 789*91f16700Schasinglulu I2C_RELOAD_MODE, 790*91f16700Schasinglulu I2C_NO_STARTSTOP); 791*91f16700Schasinglulu } else { 792*91f16700Schasinglulu xfer_size = xfer_count; 793*91f16700Schasinglulu i2c_transfer_config(hi2c, dev_addr, 794*91f16700Schasinglulu xfer_size, 795*91f16700Schasinglulu I2C_AUTOEND_MODE, 796*91f16700Schasinglulu I2C_NO_STARTSTOP); 797*91f16700Schasinglulu } 798*91f16700Schasinglulu } 799*91f16700Schasinglulu } while (xfer_count > 0U); 800*91f16700Schasinglulu 801*91f16700Schasinglulu /* 802*91f16700Schasinglulu * No need to Check TC flag, with AUTOEND mode the stop 803*91f16700Schasinglulu * is automatically generated. 804*91f16700Schasinglulu * Wait until STOPF flag is reset. 805*91f16700Schasinglulu */ 806*91f16700Schasinglulu if (i2c_wait_stop(hi2c, timeout_ref) != 0) { 807*91f16700Schasinglulu goto bail; 808*91f16700Schasinglulu } 809*91f16700Schasinglulu 810*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 811*91f16700Schasinglulu 812*91f16700Schasinglulu mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); 813*91f16700Schasinglulu 814*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 815*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 816*91f16700Schasinglulu 817*91f16700Schasinglulu rc = 0; 818*91f16700Schasinglulu 819*91f16700Schasinglulu bail: 820*91f16700Schasinglulu hi2c->lock = 0; 821*91f16700Schasinglulu clk_disable(hi2c->clock); 822*91f16700Schasinglulu 823*91f16700Schasinglulu return rc; 824*91f16700Schasinglulu } 825*91f16700Schasinglulu 826*91f16700Schasinglulu /* 827*91f16700Schasinglulu * @brief Read an amount of data in blocking mode from a specific memory 828*91f16700Schasinglulu * address. 829*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 830*91f16700Schasinglulu * the configuration information for the specified I2C. 831*91f16700Schasinglulu * @param dev_addr: Target device address 832*91f16700Schasinglulu * @param mem_addr: Internal memory address 833*91f16700Schasinglulu * @param mem_add_size: Size of internal memory address 834*91f16700Schasinglulu * @param p_data: Pointer to data buffer 835*91f16700Schasinglulu * @param size: Amount of data to be sent 836*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 837*91f16700Schasinglulu * @retval 0 if OK, negative value else 838*91f16700Schasinglulu */ 839*91f16700Schasinglulu int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, 840*91f16700Schasinglulu uint16_t mem_addr, uint16_t mem_add_size, 841*91f16700Schasinglulu uint8_t *p_data, uint16_t size, uint32_t timeout_ms) 842*91f16700Schasinglulu { 843*91f16700Schasinglulu return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, 844*91f16700Schasinglulu p_data, size, timeout_ms, I2C_MODE_MEM); 845*91f16700Schasinglulu } 846*91f16700Schasinglulu 847*91f16700Schasinglulu /* 848*91f16700Schasinglulu * @brief Receives in master mode an amount of data in blocking mode. 849*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 850*91f16700Schasinglulu * the configuration information for the specified I2C. 851*91f16700Schasinglulu * @param dev_addr: Target device address 852*91f16700Schasinglulu * @param p_data: Pointer to data buffer 853*91f16700Schasinglulu * @param size: Amount of data to be sent 854*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 855*91f16700Schasinglulu * @retval 0 if OK, negative value else 856*91f16700Schasinglulu */ 857*91f16700Schasinglulu int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, 858*91f16700Schasinglulu uint8_t *p_data, uint16_t size, 859*91f16700Schasinglulu uint32_t timeout_ms) 860*91f16700Schasinglulu { 861*91f16700Schasinglulu return i2c_read(hi2c, dev_addr, 0, 0, 862*91f16700Schasinglulu p_data, size, timeout_ms, I2C_MODE_MASTER); 863*91f16700Schasinglulu } 864*91f16700Schasinglulu 865*91f16700Schasinglulu /* 866*91f16700Schasinglulu * @brief Checks if target device is ready for communication. 867*91f16700Schasinglulu * @note This function is used with Memory devices 868*91f16700Schasinglulu * @param hi2c: Pointer to a struct i2c_handle_s structure that contains 869*91f16700Schasinglulu * the configuration information for the specified I2C. 870*91f16700Schasinglulu * @param dev_addr: Target device address 871*91f16700Schasinglulu * @param trials: Number of trials 872*91f16700Schasinglulu * @param timeout_ms: Timeout duration in milliseconds 873*91f16700Schasinglulu * @retval True if device is ready, false else 874*91f16700Schasinglulu */ 875*91f16700Schasinglulu bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, 876*91f16700Schasinglulu uint16_t dev_addr, uint32_t trials, 877*91f16700Schasinglulu uint32_t timeout_ms) 878*91f16700Schasinglulu { 879*91f16700Schasinglulu uint32_t i2c_trials = 0U; 880*91f16700Schasinglulu bool rc = false; 881*91f16700Schasinglulu 882*91f16700Schasinglulu if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { 883*91f16700Schasinglulu return rc; 884*91f16700Schasinglulu } 885*91f16700Schasinglulu 886*91f16700Schasinglulu clk_enable(hi2c->clock); 887*91f16700Schasinglulu 888*91f16700Schasinglulu hi2c->lock = 1; 889*91f16700Schasinglulu hi2c->i2c_mode = I2C_MODE_NONE; 890*91f16700Schasinglulu 891*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != 892*91f16700Schasinglulu 0U) { 893*91f16700Schasinglulu goto bail; 894*91f16700Schasinglulu } 895*91f16700Schasinglulu 896*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_BUSY; 897*91f16700Schasinglulu hi2c->i2c_err = I2C_ERROR_NONE; 898*91f16700Schasinglulu 899*91f16700Schasinglulu do { 900*91f16700Schasinglulu uint64_t timeout_ref; 901*91f16700Schasinglulu 902*91f16700Schasinglulu /* Generate Start */ 903*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & 904*91f16700Schasinglulu I2C_OAR1_OA1MODE) == 0) { 905*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 906*91f16700Schasinglulu (((uint32_t)dev_addr & I2C_CR2_SADD) | 907*91f16700Schasinglulu I2C_CR2_START | I2C_CR2_AUTOEND) & 908*91f16700Schasinglulu ~I2C_CR2_RD_WRN); 909*91f16700Schasinglulu } else { 910*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 911*91f16700Schasinglulu (((uint32_t)dev_addr & I2C_CR2_SADD) | 912*91f16700Schasinglulu I2C_CR2_START | I2C_CR2_ADD10) & 913*91f16700Schasinglulu ~I2C_CR2_RD_WRN); 914*91f16700Schasinglulu } 915*91f16700Schasinglulu 916*91f16700Schasinglulu /* 917*91f16700Schasinglulu * No need to Check TC flag, with AUTOEND mode the stop 918*91f16700Schasinglulu * is automatically generated. 919*91f16700Schasinglulu * Wait until STOPF flag is set or a NACK flag is set. 920*91f16700Schasinglulu */ 921*91f16700Schasinglulu timeout_ref = timeout_init_us(timeout_ms * 1000); 922*91f16700Schasinglulu do { 923*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 924*91f16700Schasinglulu (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { 925*91f16700Schasinglulu break; 926*91f16700Schasinglulu } 927*91f16700Schasinglulu 928*91f16700Schasinglulu if (timeout_elapsed(timeout_ref)) { 929*91f16700Schasinglulu notif_i2c_timeout(hi2c); 930*91f16700Schasinglulu goto bail; 931*91f16700Schasinglulu } 932*91f16700Schasinglulu } while (true); 933*91f16700Schasinglulu 934*91f16700Schasinglulu if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & 935*91f16700Schasinglulu I2C_FLAG_AF) == 0U) { 936*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 937*91f16700Schasinglulu timeout_ref) != 0) { 938*91f16700Schasinglulu goto bail; 939*91f16700Schasinglulu } 940*91f16700Schasinglulu 941*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 942*91f16700Schasinglulu I2C_FLAG_STOPF); 943*91f16700Schasinglulu 944*91f16700Schasinglulu hi2c->i2c_state = I2C_STATE_READY; 945*91f16700Schasinglulu 946*91f16700Schasinglulu rc = true; 947*91f16700Schasinglulu goto bail; 948*91f16700Schasinglulu } 949*91f16700Schasinglulu 950*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { 951*91f16700Schasinglulu goto bail; 952*91f16700Schasinglulu } 953*91f16700Schasinglulu 954*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); 955*91f16700Schasinglulu 956*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); 957*91f16700Schasinglulu 958*91f16700Schasinglulu if (i2c_trials == trials) { 959*91f16700Schasinglulu mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, 960*91f16700Schasinglulu I2C_CR2_STOP); 961*91f16700Schasinglulu 962*91f16700Schasinglulu if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, 963*91f16700Schasinglulu timeout_ref) != 0) { 964*91f16700Schasinglulu goto bail; 965*91f16700Schasinglulu } 966*91f16700Schasinglulu 967*91f16700Schasinglulu mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, 968*91f16700Schasinglulu I2C_FLAG_STOPF); 969*91f16700Schasinglulu } 970*91f16700Schasinglulu 971*91f16700Schasinglulu i2c_trials++; 972*91f16700Schasinglulu } while (i2c_trials < trials); 973*91f16700Schasinglulu 974*91f16700Schasinglulu notif_i2c_timeout(hi2c); 975*91f16700Schasinglulu 976*91f16700Schasinglulu bail: 977*91f16700Schasinglulu hi2c->lock = 0; 978*91f16700Schasinglulu clk_disable(hi2c->clock); 979*91f16700Schasinglulu 980*91f16700Schasinglulu return rc; 981*91f16700Schasinglulu } 982*91f16700Schasinglulu 983