On stm32mp25, DIER (former IER) must only be modified when the lptimer is enabled. On earlier SoCs, it must be only be modified when it is disabled. Read the LPTIM_VERR register to properly manage the enable state, before accessing IER. Signed-off-by: Patrick Delaunay <patrick.delaunay@xxxxxxxxxxx> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@xxxxxxxxxxx> --- Changes in V2: - rely on fallback compatible as no specific .data is associated to the driver. Use version data from MFD core. - Added interrupt enable register access update in (missed in V1) --- drivers/clocksource/timer-stm32-lp.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index a4c95161cb22..96d975adf7a4 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -25,6 +25,7 @@ struct stm32_lp_private { struct clock_event_device clkevt; unsigned long period; struct device *dev; + bool ier_wr_enabled; /* Enables LPTIMER before writing into IER register */ }; static struct stm32_lp_private* @@ -37,8 +38,15 @@ static int stm32_clkevent_lp_shutdown(struct clock_event_device *clkevt) { struct stm32_lp_private *priv = to_priv(clkevt); - regmap_write(priv->reg, STM32_LPTIM_CR, 0); + /* Disable LPTIMER either before or after writing IER register (else, keep it enabled) */ + if (!priv->ier_wr_enabled) + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + regmap_write(priv->reg, STM32_LPTIM_IER, 0); + + if (priv->ier_wr_enabled) + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + /* clear pending flags */ regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_ARRMCF); @@ -51,12 +59,21 @@ static int stm32_clkevent_lp_set_timer(unsigned long evt, { struct stm32_lp_private *priv = to_priv(clkevt); - /* disable LPTIMER to be able to write into IER register*/ - regmap_write(priv->reg, STM32_LPTIM_CR, 0); + if (!priv->ier_wr_enabled) { + /* Disable LPTIMER to be able to write into IER register */ + regmap_write(priv->reg, STM32_LPTIM_CR, 0); + } else { + /* Enable LPTIMER to be able to write into IER register */ + regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + } + /* enable ARR interrupt */ regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE); + /* enable LPTIMER to be able to write into ARR register */ - regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + if (!priv->ier_wr_enabled) + regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE); + /* set next event counter */ regmap_write(priv->reg, STM32_LPTIM_ARR, evt); @@ -151,6 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) return -ENOMEM; priv->reg = ddata->regmap; + priv->ier_wr_enabled = ddata->version == STM32_LPTIM_VERR_23; ret = clk_prepare_enable(ddata->clk); if (ret) return -EINVAL; -- 2.25.1