From 45a6d231b2f9b891a7df517fc40b8466e12f2b57 Mon Sep 17 00:00:00 2001 From: Paolo Pisati Date: Fri, 10 Feb 2017 17:28:05 +0100 Subject: [PATCH] bcm2835_wdt: support for the BCM2835/2836 watchdog Signed-off-by: Paolo Pisati --- arch/arm/mach-bcm283x/reset.c | 21 ++++++++++++++++++--- board/raspberrypi/rpi/rpi.c | 4 ++++ drivers/watchdog/Kconfig | 12 ++++++++++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/bcm2835_wdt.c | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 drivers/watchdog/bcm2835_wdt.c diff --git a/arch/arm/mach-bcm283x/reset.c b/arch/arm/mach-bcm283x/reset.c index 685815c..b62cb8a 100644 --- a/arch/arm/mach-bcm283x/reset.c +++ b/arch/arm/mach-bcm283x/reset.c @@ -21,18 +21,33 @@ */ #define BCM2835_WDOG_RSTS_RASPBERRYPI_HALT 0x555 +/* max ticks timeout */ +#define BCM2835_WDOG_MAX_TIMEOUT 0x000fffff + +#ifdef CONFIG_BCM2835_WDT +extern void hw_watchdog_disable(void); +#else +void hw_watchdog_disable(void) {} +#endif + __efi_runtime_data struct bcm2835_wdog_regs *wdog_regs = (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; -void __efi_runtime reset_cpu(ulong addr) +void __efi_runtime reset_cpu(ulong ticks) { - uint32_t rstc; + uint32_t rstc, timeout; + + if (ticks == 0) { + hw_watchdog_disable(); + timeout = RESET_TIMEOUT; + } else + timeout = ticks & BCM2835_WDOG_MAX_TIMEOUT; rstc = readl(&wdog_regs->rstc); rstc &= ~BCM2835_WDOG_RSTC_WRCFG_MASK; rstc |= BCM2835_WDOG_RSTC_WRCFG_FULL_RESET; - writel(BCM2835_WDOG_PASSWORD | RESET_TIMEOUT, &wdog_regs->wdog); + writel(BCM2835_WDOG_PASSWORD | timeout, &wdog_regs->wdog); writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc); } diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index c99beed..82da9e5 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -23,6 +23,7 @@ #ifdef CONFIG_ARM64 #include #endif +#include DECLARE_GLOBAL_DATA_PTR; @@ -455,6 +456,9 @@ static void rpi_disable_inactive_uart(void) int board_init(void) { +#ifdef CONFIG_HW_WATCHDOG + hw_watchdog_init(); +#endif #ifndef CONFIG_PL01X_SERIAL rpi_disable_inactive_uart(); #endif diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2034e3c..bdaf5d4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1,5 +1,17 @@ menu "Watchdog Timer Support" +config HW_WATCHDOG + bool + +config BCM2835_WDT + bool "Enable BCM2835/2836 watchdog driver" + select HW_WATCHDOG + help + Say Y here to enable the BCM2835/2836 watchdog + + This provides basic infrastructure to support BCM2835/2836 watchdog + hardware, with a max timeout of ~15secs. + config ULP_WATCHDOG bool "i.MX7ULP watchdog" help diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index dfc7fbd..8378601 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o obj-$(CONFIG_WDT) += wdt-uclass.o obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o +obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c new file mode 100644 index 0000000..6f753ae --- /dev/null +++ b/drivers/watchdog/bcm2835_wdt.c @@ -0,0 +1,35 @@ +/* + * Watchdog driver for Broadcom BCM2835 + * + * Copyright (C) 2017 Paolo Pisati + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include + +#define SECS_TO_WDOG_TICKS(x) ((x) << 16) +#define MAX_TIMEOUT 0xf /* ~15s */ + +static __efi_runtime_data bool enabled = true; + +extern void reset_cpu(ulong ticks); + +void hw_watchdog_reset(void) +{ + if (enabled) + reset_cpu(SECS_TO_WDOG_TICKS(MAX_TIMEOUT)); +} + +void hw_watchdog_init(void) +{ + hw_watchdog_reset(); +} + +void __efi_runtime hw_watchdog_disable(void) +{ + enabled = false; +} -- 2.7.4