On 5/23/25 11:46, Antonio Borneo wrote:
> From: Clément Le Goffic <clement.legof...@foss.st.com>
> 
> Add a mean to check the IWDG status based on the peripheral version.
> This is done by either checking the status bit ONF either by updating
> the reload register with the same value and check if the reload succeed.
> 
> Signed-off-by: Clément Le Goffic <clement.legof...@foss.st.com>
> Signed-off-by: Antonio Borneo <antonio.bor...@foss.st.com>
> ---
>  drivers/watchdog/stm32mp_wdt.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/drivers/watchdog/stm32mp_wdt.c b/drivers/watchdog/stm32mp_wdt.c
> index 97ab8cfe7ab..0712524b4a8 100644
> --- a/drivers/watchdog/stm32mp_wdt.c
> +++ b/drivers/watchdog/stm32mp_wdt.c
> @@ -21,11 +21,13 @@
>  #define IWDG_PR              0x04    /* Prescaler Register */
>  #define IWDG_RLR     0x08    /* ReLoad Register */
>  #define IWDG_SR              0x0C    /* Status Register */
> +#define IWDG_VERR    0x3F4   /* Version Register */
>  
>  /* IWDG_KR register bit mask */
>  #define KR_KEY_RELOAD        0xAAAA  /* Reload counter enable */
>  #define KR_KEY_ENABLE        0xCCCC  /* Peripheral enable */
>  #define KR_KEY_EWA   0x5555  /* Write access enable */
> +#define KR_KEY_DWA   0x0000  /* Write access disable*/
>  
>  /* IWDG_PR register bit values */
>  #define PR_256               0x06    /* Prescaler set to 256 */
> @@ -36,10 +38,17 @@
>  /* IWDG_SR register bit values */
>  #define SR_PVU               BIT(0)  /* Watchdog prescaler value update */
>  #define SR_RVU               BIT(1)  /* Watchdog counter reload value update 
> */
> +#define SR_ONF               BIT(8)  /* Watchdog enable status bit */
> +
> +/* IWDG Compatibility */
> +#define ONF_MIN_VER  0x31
> +
> +#define TIMEOUT_US   10000
>  
>  struct stm32mp_wdt_priv {
>       fdt_addr_t base;                /* registers addr in physical memory */
>       unsigned long wdt_clk_rate;     /* Watchdog dedicated clock rate */
> +     unsigned int hw_version;        /* Peripheral version */
>  };
>  
>  static int stm32mp_wdt_reset(struct udevice *dev)
> @@ -90,6 +99,7 @@ static int stm32mp_wdt_start(struct udevice *dev, u64 
> timeout_ms, ulong flags)
>  static int stm32mp_wdt_probe(struct udevice *dev)
>  {
>       struct stm32mp_wdt_priv *priv = dev_get_priv(dev);
> +     u32 rlr, sr;
>       struct clk clk;
>       int ret;
>  
> @@ -115,6 +125,29 @@ static int stm32mp_wdt_probe(struct udevice *dev)
>  
>       priv->wdt_clk_rate = clk_get_rate(&clk);
>  
> +     priv->hw_version = readl(priv->base + IWDG_VERR);
> +
> +     if (priv->hw_version >= ONF_MIN_VER) {
> +             if (readl(priv->base + IWDG_SR) & SR_ONF)
> +                     wdt_set_force_autostart(dev);
> +     } else {
> +             /*
> +              * Workaround for old versions without IWDG_SR_ONF bit:
> +              * - write in IWDG_RLR_OFFSET
> +              * - wait for sync
> +              * - if sync succeeds, then iwdg is running
> +              */
> +             writel(KR_KEY_EWA, priv->base + IWDG_KR);
> +             rlr = readl(priv->base + IWDG_RLR);
> +             writel(rlr, priv->base + IWDG_RLR);
> +             ret = readl_poll_timeout(priv->base + IWDG_SR, sr, sr & SR_RVU,
> +                                      TIMEOUT_US);
> +             if (!ret)
> +                     wdt_set_force_autostart(dev);
> +
> +             writel(KR_KEY_DWA, priv->base + IWDG_KR);
> +     }
> +
>       dev_dbg(dev, "IWDG init done\n");
>  
>       return 0;
Reviewed-by: Patrice Chotard <patrice.chot...@foss.st.com>

Thanks
Patrice

Reply via email to