Report the hardware-limited maximum timeout value to the wdt
uclass by setting max_timeout_ms in the per-device uclass-plat
data during octeontx_wdt_probe().

The timeout is programmed via the 16-bit WDOG_LEN field in
configured steps, so the largest representable timeout is
(0xffff << 8) steps. This is then converted to milliseconds
via the timershift and clock rate, and set only when the rate
is valid and non-zero.

Signed-off-by: Juuso Rinta <[email protected]>
---
 drivers/watchdog/octeontx_wdt.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/watchdog/octeontx_wdt.c b/drivers/watchdog/octeontx_wdt.c
index 7299a9f9739..5f8a7dba547 100644
--- a/drivers/watchdog/octeontx_wdt.c
+++ b/drivers/watchdog/octeontx_wdt.c
@@ -6,6 +6,7 @@
  */
 
 #include <clk.h>
+#include <div64.h>
 #include <dm.h>
 #include <errno.h>
 #include <wdt.h>
@@ -107,6 +108,8 @@ static int octeontx_wdt_remove(struct udevice *dev)
 static int octeontx_wdt_probe(struct udevice *dev)
 {
        struct octeontx_wdt *priv = dev_get_priv(dev);
+       struct wdt_uc_plat *plat = dev_get_uclass_plat(dev);
+       u64 clk_rate;
        int ret;
 
        priv->reg = dev_remap_addr(dev);
@@ -132,6 +135,20 @@ static int octeontx_wdt_probe(struct udevice *dev)
                ret = clk_enable(&priv->clk);
                if (ret)
                        return ret;
+
+               clk_rate = clk_get_rate(&priv->clk);
+       } else {
+               clk_rate = gd->bus_clk;
+       }
+
+       /*
+        * WDOG_LEN is a 16-bit field counting in configured steps, so the
+        * largest timeout the hardware can represent is (0xffff << 8) steps.
+        */
+       if (!IS_ERR_VALUE(clk_rate) && clk_rate) {
+               u64 max_cycles = ((u64)0xffff << 8) << priv->data->timer_shift;
+
+               plat->max_timeout_ms = lldiv(max_cycles * 1000, clk_rate);
        }
 
        return 0;

-- 
2.39.2

Reply via email to