risc-v/esp32c3: Adds I2C RESET support via hardware.
This commit is contained in:
parent
6dc3c3d1b2
commit
8f59054ef2
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user