From 8f59054ef211411d40175cda98e8c3edf5aba804 Mon Sep 17 00:00:00 2001 From: Sara Souza Date: Tue, 15 Jun 2021 18:25:24 -0300 Subject: [PATCH] risc-v/esp32c3: Adds I2C RESET support via hardware. --- arch/risc-v/src/esp32c3/esp32c3_i2c.c | 89 +++------------------------ 1 file changed, 9 insertions(+), 80 deletions(-) diff --git a/arch/risc-v/src/esp32c3/esp32c3_i2c.c b/arch/risc-v/src/esp32c3/esp32c3_i2c.c index a993b0cbb9f..8807703315c 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_i2c.c +++ b/arch/risc-v/src/esp32c3/esp32c3_i2c.c @@ -772,9 +772,9 @@ static void esp32c3_i2c_deinit(struct esp32c3_i2c_priv_s *priv) static void esp32c3_i2c_reset_fsmc(struct esp32c3_i2c_priv_s *priv) { - esp32c3_i2c_deinit(priv); + /* Reset FSM machine */ - esp32c3_i2c_init(priv); + modifyreg32(I2C_CTR_REG(priv->id), 0, I2C_FSM_RST_M); } /**************************************************************************** @@ -1140,83 +1140,12 @@ static int esp32c3_i2c_transfer(struct i2c_master_s *dev, #ifdef CONFIG_I2C_RESET static void esp32c3_i2c_clear_bus(struct esp32c3_i2c_priv_s *priv) { - uint32_t clock_count; - uint32_t stretch_count; - int ret; + uint32_t value = VALUE_TO_FIELD(I2C_SCL_CYC_NUM_DEF, I2C_SCL_RST_SLV_NUM); + modifyreg32(I2C_SCL_SP_CONF_REG(priv->id), I2C_SCL_RST_SLV_NUM_M, value); - const struct esp32c3_i2c_config_s *config = priv->config; + modifyreg32(I2C_SCL_SP_CONF_REG(priv->id), 0, I2C_SCL_RST_SLV_EN_M); - /* Use GPIO configuration to un-wedge the bus */ - - esp32c3_configgpio(config->scl_pin, INPUT_PULLUP | OUTPUT_OPEN_DRAIN); - esp32c3_gpio_matrix_out(config->scl_pin, SIG_GPIO_OUT_IDX, 0, 0); - esp32c3_configgpio(config->sda_pin, INPUT_PULLUP | OUTPUT_OPEN_DRAIN); - esp32c3_gpio_matrix_out(config->sda_pin, SIG_GPIO_OUT_IDX, 0, 0); - - /* Let SDA go high */ - - esp32c3_gpiowrite(config->sda_pin, 1); - - /* Clock the bus until any slaves currently driving it let it go. */ - - clock_count = 0; - while (!esp32c3_gpioread(config->sda_pin)) - { - /* Give up if we have tried too hard */ - - if (clock_count++ >= I2C_SCL_CYC_NUM_DEF) - { - ret = -EIO; - goto out; - } - - /* Sniff to make sure that clock stretching has finished. - * - * If the bus never relaxes, the reset has failed. - */ - - stretch_count = 0; - while (!esp32c3_gpioread(config->scl_pin)) - { - /* Give up if we have tried too hard */ - - if (stretch_count++ > 10) - { - ret = -EIO; - goto out; - } - - up_udelay(10); - } - - /* Drive SCL low */ - - esp32c3_gpiowrite(config->scl_pin, 0); - up_udelay(10); - - /* Drive SCL high again */ - - esp32c3_gpiowrite(config->scl_pin, 1); - up_udelay(10); - } - - /* Generate a start followed by a stop to reset slave - * state machines. - */ - - esp32c3_gpiowrite(config->sda_pin, 0); - up_udelay(10); - esp32c3_gpiowrite(config->scl_pin, 0); - up_udelay(10); - esp32c3_gpiowrite(config->scl_pin, 1); - up_udelay(10); - esp32c3_gpiowrite(config->sda_pin, 1); - up_udelay(10); - - ret = OK; - -out: - return ret; + modifyreg32(I2C_CTR_REG(priv->id), 0, I2C_CONF_UPGATE_M); } #endif @@ -1247,12 +1176,12 @@ static int esp32c3_i2c_reset(struct i2c_master_s *dev) flags = enter_critical_section(); - esp32c3_i2c_deinit(priv); + esp32c3_i2c_reset_fsmc(priv); + + /* Clear bus */ esp32c3_i2c_clear_bus(priv); - esp32c3_i2c_init(priv); - priv->i2cstate = I2CSTATE_IDLE; priv->msgid = 0; priv->bytes = 0;