From 1473f6ac882fde8078826ca828aa3494ff98bf08 Mon Sep 17 00:00:00 2001 From: Prasanthi Chellakumar Date: Tue, 9 Oct 2018 11:46:40 -0700 Subject: arm: at91: wdt: Convert watchdog driver to dm/dt Convert the Watchdog driver for AT91SAM9x processors to support the driver model and device tree. Changes "CONFIG_AT91SAM9_WATCHDOG" to new "CONFIG_WDT_AT91" Kconfig option. Signed-off-by: Prasanthi Chellakumar --- drivers/watchdog/Kconfig | 10 ++++ drivers/watchdog/Makefile | 2 +- drivers/watchdog/at91sam9_wdt.c | 104 ++++++++++++++++++++++++++++++---------- 3 files changed, 91 insertions(+), 25 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 02f4e1e32fc..a911dba73a4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -118,4 +118,14 @@ config IMX_WATCHDOG Select this to enable the IMX and LSCH2 of Layerscape watchdog driver. +config WDT_AT91 + bool "AT91 watchdog timer support" + depends on WDT + help + Select this to enable Microchip watchdog timer, which can be found on + some AT91 devices. + +config AT91_HW_WDT_TIMEOUT + bool "AT91 watchdog timeout specified" + depends on WDT_AT91 endmenu diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 08406caa0f9..a5c27b0f4cf 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -3,7 +3,7 @@ # (C) Copyright 2008 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_AT91SAM9_WATCHDOG) += at91sam9_wdt.o +obj-$(CONFIG_WDT_AT91) += at91sam9_wdt.o obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o ifneq (,$(filter $(SOC), mx25 mx31 mx35 mx5 mx6 mx7 vf610)) obj-y += imx_watchdog.o diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index fca2849918f..13f8772e413 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -2,7 +2,7 @@ /* * [origin: Linux kernel drivers/watchdog/at91sam9_wdt.c] * - * Watchdog driver for Atmel AT91SAM9x processors. + * Watchdog driver for AT91SAM9x processors. * * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr @@ -14,38 +14,47 @@ * write to this register. Inform Linux to it too */ -#include -#include -#include #include #include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; /* * AT91SAM9 watchdog runs a 12bit counter @ 256Hz, * use this to convert a watchdog - * value from/to milliseconds. + * value from seconds. */ -#define ms_to_ticks(t) (((t << 8) / 1000) - 1) -#define ticks_to_ms(t) (((t + 1) * 1000) >> 8) +#define WDT_SEC2TICKS(s) (((s) << 8) - 1) /* Hardware timeout in seconds */ -#if !defined(CONFIG_AT91_HW_WDT_TIMEOUT) -#define WDT_HW_TIMEOUT 2 -#else -#define WDT_HW_TIMEOUT CONFIG_AT91_HW_WDT_TIMEOUT -#endif +#define WDT_MAX_TIMEOUT 16 +#define WDT_MIN_TIMEOUT 0 +#define WDT_DEFAULT_TIMEOUT 2 + +struct at91_wdt_priv { + void __iomem *regs; + u32 regval; + u32 timeout; +}; /* * Set the watchdog time interval in 1/256Hz (write-once) * Counter is 12 bit. */ -static int at91_wdt_settimeout(unsigned int timeout) +static int at91_wdt_start(struct udevice *dev, u64 timeout_s, ulong flags) { - unsigned int reg; - at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; + struct at91_wdt_priv *priv = dev_get_priv(dev); + u32 timeout = WDT_SEC2TICKS(timeout_s); + + if (timeout_s > WDT_MAX_TIMEOUT || timeout_s < WDT_MIN_TIMEOUT) + timeout = priv->timeout; /* Check if disabled */ - if (readl(&wd->mr) & AT91_WDT_MR_WDDIS) { + if (readl(priv->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) { printf("sorry, watchdog is disabled\n"); return -1; } @@ -57,24 +66,71 @@ static int at91_wdt_settimeout(unsigned int timeout) * 4096 / 256 = 16 seconds. */ - reg = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */ + priv->regval = 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(timeout); /* timer value */ - writel(reg, &wd->mr); + writel(priv->regval, priv->regs + AT91_WDT_MR); + + return 0; +} + +static int at91_wdt_stop(struct udevice *dev) +{ + struct at91_wdt_priv *priv = dev_get_priv(dev); + + /* Disable Watchdog Timer */ + priv->regval |= AT91_WDT_MR_WDDIS; + writel(priv->regval, priv->regs + AT91_WDT_MR); return 0; } -void hw_watchdog_reset(void) +static int at91_wdt_reset(struct udevice *dev) { - at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; - writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, &wd->cr); + struct at91_wdt_priv *priv = dev_get_priv(dev); + + writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, priv->regs + AT91_WDT_CR); + + return 0; } -void hw_watchdog_init(void) +static const struct wdt_ops at91_wdt_ops = { + .start = at91_wdt_start, + .stop = at91_wdt_stop, + .reset = at91_wdt_reset, +}; + +static const struct udevice_id at91_wdt_ids[] = { + { .compatible = "atmel,at91sam9260-wdt" }, + {} +}; + +static int at91_wdt_probe(struct udevice *dev) { - /* 16 seconds timer, resets enabled */ - at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); + struct at91_wdt_priv *priv = dev_get_priv(dev); + + priv->regs = dev_remap_addr(dev); + if (!priv->regs) + return -EINVAL; + +#ifdef CONFIG_AT91_HW_WDT_TIMEOUT + priv->timeout = dev_read_u32_default(dev, "timeout-sec", + WDT_DEFAULT_TIMEOUT); + debug("%s: timeout %d", __func__, priv->timeout); +#endif + + debug("%s: Probing wdt%u\n", __func__, dev->seq); + + return 0; } + +U_BOOT_DRIVER(at91_wdt) = { + .name = "at91_wdt", + .id = UCLASS_WDT, + .of_match = at91_wdt_ids, + .priv_auto_alloc_size = sizeof(struct at91_wdt_priv), + .ops = &at91_wdt_ops, + .probe = at91_wdt_probe, +}; -- cgit v1.2.3