arch/arm/stm32h7/i2c: use per-instance RCC registers for clock and reset

stm32_i2c_init() and stm32_i2c_deinit() hardcoded APB1LENR/APB1LRSTR
while taking the enable and reset bits from the per-instance config.
That is correct for I2C1-3, but I2C4 is on APB4: its clk_bit and
reset_bit are RCC_APB4ENR_I2C4EN and RCC_APB4RSTR_I2C4RST, both bit 7,
and bit 7 of APB1LENR/APB1LRSTR is TIM13.

So for I2C4 the driver enabled and pulsed the reset of TIM13 instead,
and never reset the I2C4 peripheral at all.  I2C4 still works because
rcc_enableapb4() enables I2C4EN at boot, but the peripheral reset that
stm32_i2c_reset() (CONFIG_I2C_RESET) relies on to clear a wedged I2C
state machine never happens, and deinit gates TIM13 while leaving the
I2C4 clock running.

Store the clock enable and reset register addresses in
struct stm32_i2c_config_s next to the bits, and use them in
stm32_i2c_init() and stm32_i2c_deinit().

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This commit is contained in:
Jacob Dahl 2026-08-05 20:43:40 -06:00 committed by Alan C. Assis
parent ab9007c4e9
commit 659f47a824

View file

@ -374,7 +374,9 @@ struct stm32_trace_s
struct stm32_i2c_config_s
{
uint32_t base; /* I2C base address */
uint32_t clk_reg; /* Clock enable register */
uint32_t clk_bit; /* Clock enable bit */
uint32_t rst_reg; /* Peripheral reset register */
uint32_t reset_bit; /* Reset bit */
uint32_t scl_pin; /* GPIO configuration for SCL as SCL */
uint32_t sda_pin; /* GPIO configuration for SDA as SDA */
@ -492,7 +494,9 @@ static int stm32_i2c_pm_prepare(struct pm_callback_s *cb, int domain,
static const struct stm32_i2c_config_s stm32_i2c1_config =
{
.base = STM32_I2C1_BASE,
.clk_reg = STM32_RCC_APB1LENR,
.clk_bit = RCC_APB1LENR_I2C1EN,
.rst_reg = STM32_RCC_APB1LRSTR,
.reset_bit = RCC_APB1LRSTR_I2C1RST,
.scl_pin = GPIO_I2C1_SCL,
.sda_pin = GPIO_I2C1_SDA,
@ -528,7 +532,9 @@ static struct stm32_i2c_priv_s stm32_i2c1_priv =
static const struct stm32_i2c_config_s stm32_i2c2_config =
{
.base = STM32_I2C2_BASE,
.clk_reg = STM32_RCC_APB1LENR,
.clk_bit = RCC_APB1LENR_I2C2EN,
.rst_reg = STM32_RCC_APB1LRSTR,
.reset_bit = RCC_APB1LRSTR_I2C2RST,
.scl_pin = GPIO_I2C2_SCL,
.sda_pin = GPIO_I2C2_SDA,
@ -564,7 +570,9 @@ static struct stm32_i2c_priv_s stm32_i2c2_priv =
static const struct stm32_i2c_config_s stm32_i2c3_config =
{
.base = STM32_I2C3_BASE,
.clk_reg = STM32_RCC_APB1LENR,
.clk_bit = RCC_APB1LENR_I2C3EN,
.rst_reg = STM32_RCC_APB1LRSTR,
.reset_bit = RCC_APB1LRSTR_I2C3RST,
.scl_pin = GPIO_I2C3_SCL,
.sda_pin = GPIO_I2C3_SDA,
@ -600,7 +608,9 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
static const struct stm32_i2c_config_s stm32_i2c4_config =
{
.base = STM32_I2C4_BASE,
.clk_reg = STM32_RCC_APB4ENR,
.clk_bit = RCC_APB4ENR_I2C4EN,
.rst_reg = STM32_RCC_APB4RSTR,
.reset_bit = RCC_APB4RSTR_I2C4RST,
.scl_pin = GPIO_I2C4_SCL,
.sda_pin = GPIO_I2C4_SDA,
@ -2143,9 +2153,9 @@ static int stm32_i2c_init(struct stm32_i2c_priv_s *priv)
/* Enable power and reset the peripheral */
modifyreg32(STM32_RCC_APB1LENR, 0, priv->config->clk_bit);
modifyreg32(STM32_RCC_APB1LRSTR, 0, priv->config->reset_bit);
modifyreg32(STM32_RCC_APB1LRSTR, priv->config->reset_bit, 0);
modifyreg32(priv->config->clk_reg, 0, priv->config->clk_bit);
modifyreg32(priv->config->rst_reg, 0, priv->config->reset_bit);
modifyreg32(priv->config->rst_reg, priv->config->reset_bit, 0);
/* Configure pins */
@ -2213,7 +2223,7 @@ static int stm32_i2c_deinit(struct stm32_i2c_priv_s *priv)
/* Disable clocking */
modifyreg32(STM32_RCC_APB1LENR, priv->config->clk_bit, 0);
modifyreg32(priv->config->clk_reg, priv->config->clk_bit, 0);
return OK;
}