From 6e44bb0c10f684a7cdb66af21ba5bc66410fe5d3 Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Wed, 12 Apr 2023 14:01:58 +0300 Subject: [PATCH] watchdog: ftwdt010: return a previously deleted driver now ported to DM The ftwdt010 watchdog driver was deleted by commit 11232139e399 ("nds32: Remove the architecture") Return it to the codebase in a DM compatible form. Enable it in sandbox_defconfig to test compilability. Another platform using ftwdt010 will be submitted later. Signed-off-by: Sergei Antonov Reviewed-by: Stefan Roese --- configs/sandbox_defconfig | 1 + drivers/watchdog/Kconfig | 7 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/ftwdt010_wdt.c | 132 ++++++++++++++++++++++++++++++++ include/faraday/ftwdt010_wdt.h | 3 - 5 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 drivers/watchdog/ftwdt010_wdt.c diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index ca95b2c5d2..ae27cac240 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -323,6 +323,7 @@ CONFIG_WDT=y CONFIG_WDT_GPIO=y CONFIG_WDT_SANDBOX=y CONFIG_WDT_ALARM_SANDBOX=y +CONFIG_WDT_FTWDT010=y CONFIG_FS_CBFS=y CONFIG_FS_CRAMFS=y CONFIG_ADDR_MAP=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 35c42dd1fc..668942e977 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -368,4 +368,11 @@ config SPL_WDT Enable driver model for watchdog timer in SPL. This is similar to CONFIG_WDT in U-Boot. +config WDT_FTWDT010 + bool "Faraday Technology ftwdt010 watchdog timer support" + depends on WDT + imply WATCHDOG + help + Faraday Technology ftwdt010 watchdog is an architecture independent + watchdog. It is usually used in SoC chip design. endmenu diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f99915960c..fd795b2e18 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o obj-$(CONFIG_WDT_ORION) += orion_wdt.o obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o +obj-$(CONFIG_WDT_FTWDT010) += ftwdt010_wdt.o obj-$(CONFIG_WDT_GPIO) += gpio_wdt.o obj-$(CONFIG_WDT_MAX6370) += max6370_wdt.o obj-$(CONFIG_WDT_MESON_GXBB) += meson_gxbb_wdt.o diff --git a/drivers/watchdog/ftwdt010_wdt.c b/drivers/watchdog/ftwdt010_wdt.c new file mode 100644 index 0000000000..a6b33b1720 --- /dev/null +++ b/drivers/watchdog/ftwdt010_wdt.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Watchdog driver for the FTWDT010 Watch Dog Driver + * + * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com) + * Based on sa1100_wdt.c by Oleg Drokin + * Based on SoftDog driver by Alan Cox + * + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation + * + * 27/11/2004 Initial release, Faraday. + * 12/01/2011 Port to u-boot, Macpaul Lin. + * 22/08/2022 Port to DM + */ + +#include +#include +#include +#include +#include +#include + +struct ftwdt010_wdt_priv { + struct ftwdt010_wdt __iomem *regs; +}; + +/* + * Set the watchdog time interval. + * Counter is 32 bit. + */ +static int ftwdt010_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct ftwdt010_wdt_priv *priv = dev_get_priv(dev); + struct ftwdt010_wdt *wd = priv->regs; + unsigned int reg; + + debug("Activating WDT %llu ms\n", timeout_ms); + + /* Check if disabled */ + if (readl(&wd->wdcr) & ~FTWDT010_WDCR_ENABLE) { + printf("sorry, watchdog is disabled\n"); + return -1; + } + + /* + * In a 66MHz system, + * if you set WDLOAD as 0x03EF1480 (66000000) + * the reset timer is 1 second. + */ + reg = FTWDT010_WDLOAD(timeout_ms * FTWDT010_TIMEOUT_FACTOR); + + writel(reg, &wd->wdload); + + return 0; +} + +static int ftwdt010_wdt_reset(struct udevice *dev) +{ + struct ftwdt010_wdt_priv *priv = dev_get_priv(dev); + struct ftwdt010_wdt *wd = priv->regs; + + /* clear control register */ + writel(0, &wd->wdcr); + + /* Write Magic number */ + writel(FTWDT010_WDRESTART_MAGIC, &wd->wdrestart); + + /* Enable WDT */ + writel((FTWDT010_WDCR_RST | FTWDT010_WDCR_ENABLE), &wd->wdcr); + + return 0; +} + +static int ftwdt010_wdt_stop(struct udevice *dev) +{ + struct ftwdt010_wdt_priv *priv = dev_get_priv(dev); + struct ftwdt010_wdt *wd = priv->regs; + + debug("Deactivating WDT..\n"); + + /* + * It was defined with CONFIG_WATCHDOG_NOWAYOUT in Linux + * + * Shut off the timer. + * Lock it in if it's a module and we defined ...NOWAYOUT + */ + writel(0, &wd->wdcr); + return 0; +} + +static int ftwdt010_wdt_expire_now(struct udevice *dev, ulong flags) +{ + struct ftwdt010_wdt_priv *priv = dev_get_priv(dev); + struct ftwdt010_wdt *wd = priv->regs; + + debug("Expiring WDT..\n"); + writel(FTWDT010_WDLOAD(0), &wd->wdload); + return ftwdt010_wdt_reset(dev); +} + +static int ftwdt010_wdt_probe(struct udevice *dev) +{ + struct ftwdt010_wdt_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) + return -EINVAL; + + return 0; +} + +static const struct wdt_ops ftwdt010_wdt_ops = { + .start = ftwdt010_wdt_start, + .reset = ftwdt010_wdt_reset, + .stop = ftwdt010_wdt_stop, + .expire_now = ftwdt010_wdt_expire_now, +}; + +static const struct udevice_id ftwdt010_wdt_ids[] = { + { .compatible = "faraday,ftwdt010" }, + {} +}; + +U_BOOT_DRIVER(ftwdt010_wdt) = { + .name = "ftwdt010_wdt", + .id = UCLASS_WDT, + .of_match = ftwdt010_wdt_ids, + .ops = &ftwdt010_wdt_ops, + .probe = ftwdt010_wdt_probe, + .priv_auto = sizeof(struct ftwdt010_wdt_priv), +}; diff --git a/include/faraday/ftwdt010_wdt.h b/include/faraday/ftwdt010_wdt.h index 804907d645..d4c11e39a0 100644 --- a/include/faraday/ftwdt010_wdt.h +++ b/include/faraday/ftwdt010_wdt.h @@ -89,7 +89,4 @@ struct ftwdt010_wdt { */ #define FTWDT010_TIMEOUT_FACTOR (get_board_sys_clk() / 1000) /* 1 ms */ -void ftwdt010_wdt_reset(void); -void ftwdt010_wdt_disable(void); - #endif /* __FTWDT010_H */ -- 2.39.5