SAM9X60 has a slightly different watchdog implementation:
- Timer value moved into a new register WLR
- Some MR register fields have their position changed

This patch add SAM9X60 support, also adds a compatible
for SAMA5D4 who is the same as existing SAM9260.

Signed-off-by: Zixun LI <ad...@hifiphile.com>
---
 arch/arm/mach-at91/include/mach/at91_wdt.h |  7 ++++
 drivers/watchdog/at91sam9_wdt.c            | 39 +++++++++++++++++-----
 2 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-at91/include/mach/at91_wdt.h 
b/arch/arm/mach-at91/include/mach/at91_wdt.h
index 9ba5283123b..9a3976d9e97 100644
--- a/arch/arm/mach-at91/include/mach/at91_wdt.h
+++ b/arch/arm/mach-at91/include/mach/at91_wdt.h
@@ -19,9 +19,16 @@
 
 #else
 
+enum {
+       AT91_WDT_MODE_SAM9260 = 0,
+       AT91_WDT_MODE_SAM9X60 = 1
+};
+
 struct at91_wdt_priv {
        void __iomem *regs;
        u32 mr;
+       u32 wddis;
+       u8 mode;
 };
 
 #endif
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 5ca3e5a5fde..72e13787448 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -49,7 +49,7 @@ static int at91_wdt_start(struct udevice *dev, u64 
timeout_ms, ulong flags)
        ticks = WDT_SEC2TICKS(timeout);
 
        /* Check if disabled */
-       if (readl(wdt->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) {
+       if (readl(wdt->regs + AT91_WDT_MR) & wdt->wddis) {
                printf("sorry, watchdog is disabled\n");
                return -1;
        }
@@ -60,11 +60,21 @@ static int at91_wdt_start(struct udevice *dev, u64 
timeout_ms, ulong flags)
         * Since WDV is a 12-bit counter, the maximum period is
         * 4096 / 256 = 16 seconds.
         */
-       wdt->mr = AT91_WDT_MR_WDRSTEN   /* causes watchdog reset */
-               | AT91_WDT_MR_WDDBGHLT          /* disabled in debug mode */
-               | AT91_WDT_MR_WDD(0xfff)        /* restart at any time */
-               | AT91_WDT_MR_WDV(ticks);       /* timer value */
-       writel(wdt->mr, wdt->regs + AT91_WDT_MR);
+
+       if (wdt->mode == AT91_WDT_MODE_SAM9260) {
+               wdt->mr = AT91_WDT_MR_WDRSTEN   /* causes watchdog reset */
+                   | AT91_WDT_MR_WDDBGHLT      /* disabled in debug mode */
+                   | AT91_WDT_MR_WDD(0xfff)    /* restart at any time */
+                   | AT91_WDT_MR_WDV(ticks);   /* timer value */
+               writel(wdt->mr, wdt->regs + AT91_WDT_MR);
+       } else if (wdt->mode == AT91_WDT_MODE_SAM9X60) {
+               writel(AT91_SAM9X60_WLR_COUNTER(ticks), /* timer value */
+                      wdt->regs + AT91_SAM9X60_WLR);
+
+               wdt->mr = AT91_SAM9X60_MR_PERIODRST /* causes watchdog reset */
+                       | AT91_SAM9X60_MR_WDDBGHLT; /* disabled in debug mode */
+               writel(wdt->mr, wdt->regs + AT91_WDT_MR);
+       }
 
        return 0;
 }
@@ -74,7 +84,7 @@ static int at91_wdt_stop(struct udevice *dev)
        struct at91_wdt_priv *wdt = dev_get_priv(dev);
 
        /* Disable Watchdog Timer */
-       wdt->mr |= AT91_WDT_MR_WDDIS;
+       wdt->mr |= wdt->wddis;
        writel(wdt->mr, wdt->regs + AT91_WDT_MR);
 
        return 0;
@@ -96,7 +106,14 @@ static const struct wdt_ops at91_wdt_ops = {
 };
 
 static const struct udevice_id at91_wdt_ids[] = {
-       { .compatible = "atmel,at91sam9260-wdt" },
+       { .compatible = "atmel,at91sam9260-wdt",
+         .data = AT91_WDT_MODE_SAM9260 },
+       { .compatible = "atmel,sama5d4-wdt",
+         .data = AT91_WDT_MODE_SAM9260 },
+       { .compatible = "microchip,sam9x60-wdt",
+         .data = AT91_WDT_MODE_SAM9X60 },
+       { .compatible = "microchip,sama7g5-wdt",
+         .data = AT91_WDT_MODE_SAM9X60 },
        {}
 };
 
@@ -108,6 +125,12 @@ static int at91_wdt_probe(struct udevice *dev)
        if (!wdt->regs)
                return -EINVAL;
 
+       wdt->mode = dev_get_driver_data(dev);
+       if (wdt->mode == AT91_WDT_MODE_SAM9260)
+               wdt->wddis = AT91_WDT_MR_WDDIS;
+       else if (wdt->mode == AT91_WDT_MODE_SAM9X60)
+               wdt->wddis = AT91_SAM9X60_MR_WDDIS;
+
        debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
 
        return 0;
-- 
2.49.0

Reply via email to