[PATCH v2 4/8] clocksource: stm32-lptimer: add support for stm32mp25

From: Fabrice Gasnier
Date: Tue Mar 04 2025 - 13:06:21 EST


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