From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vladimir Olovyannikov Date: Fri, 22 Nov 2019 15:23:29 -0800 Subject: [U-Boot] [PATCH 2/2] drivers: watchdog: Add brcm iproc sp805 watchdog driver In-Reply-To: <20191122232329.30992-1-vladimir.olovyannikov@broadcom.com> References: <20191122232329.30992-1-vladimir.olovyannikov@broadcom.com> Message-ID: <20191122232329.30992-3-vladimir.olovyannikov@broadcom.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Pramod Kumar Add sp805 watchdog driver for Broadcom iproc socs (DM). Signed-off-by: Pramod Kumar Signed-off-by: Vladimir Olovyannikov --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sp805_wdt_dm.c | 181 ++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 drivers/watchdog/sp805_wdt_dm.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 8c16d69d33..74a5319467 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -40,6 +40,16 @@ config OMAP_WATCHDOG help Say Y here to enable the OMAP3+ watchdog driver. +config SP805_WATCHDOG + bool "Enable ARM SP805 watchdog driver (DM)" + depends on WDT + imply WATCHDOG + help + Say Y here to enable the sp805 watchdog (DM) + + This provides basic infrastructure to support sp805 watchdog + hardware; driver model. + config ULP_WATCHDOG bool "i.MX7ULP watchdog" help diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 955caef815..aacabf1f2e 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_S5P) += s5p_wdt.o obj-$(CONFIG_XILINX_TB_WATCHDOG) += xilinx_tb_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o +obj-$(CONFIG_SP805_WATCHDOG) += sp805_iproc_dm.o obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o diff --git a/drivers/watchdog/sp805_wdt_dm.c b/drivers/watchdog/sp805_wdt_dm.c new file mode 100644 index 0000000000..56d0e77080 --- /dev/null +++ b/drivers/watchdog/sp805_wdt_dm.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* SP805 register offset */ +#define SP805_WDOG_LOAD_OFF 0x000 +#define SP805_WDOG_CTR_OFF 0x008 +#define SP805_WDOG_CLR_OFF 0x00c +#define SP805_WDOG_LOCK_OFF 0xc00 + +/* Magic word to unlock the wd registers */ +#define WDOG_UNLOCK_KEY 0x1ACCE551 + +/* Register field definitions */ +#define SP805_CTR_RESEN BIT(1) +#define SP805_CTR_INTEN BIT(0) + +struct sp805_wdt_platdata { + void __iomem *regs; + u32 timeout_msec; + u32 clk_mhz; +}; + +/* Inline register access functions */ + +static inline void sp805_write_wdog_load(void __iomem *base, u32 value) +{ + writel(value, base + SP805_WDOG_LOAD_OFF); +} + +static inline void sp805_write_wdog_ctrl(void __iomem *base, u32 value) +{ + writel(value, base + SP805_WDOG_CTR_OFF); +} + +static inline void sp805_write_wdog_lock(void __iomem *base, u32 value) +{ + writel(value, base + SP805_WDOG_LOCK_OFF); +} + +static inline void sp805_write_wdog_kick(void __iomem *base, u32 value) +{ + writel(value, base + SP805_WDOG_CLR_OFF); +} + +static u32 msec_to_ticks(struct udevice *dev) +{ + u32 timeout_msec; + u32 msec; + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + + timeout_msec = env_get_ulong("wdt_timeout_msec", 16, 0); + if (timeout_msec) { + dev_dbg(dev, "Overriding timeout :%u\n", timeout_msec); + msec = timeout_msec; + } else { + msec = pd->timeout_msec; + } + + timeout_msec = (msec / 2) * (pd->clk_mhz / 1000); + + dev_dbg(dev, "ticks :%u\n", timeout_msec); + + return timeout_msec; +} + +static int sp805_wdt_expire_now(struct udevice *dev, ulong flags) +{ + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + + sp805_write_wdog_lock(pd->regs, WDOG_UNLOCK_KEY); + sp805_write_wdog_load(pd->regs, 0); + sp805_write_wdog_lock(pd->regs, 0); + + return 0; +} + +static int sp805_wdt_reset(struct udevice *dev) +{ + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + u32 ticks; + + ticks = msec_to_ticks(dev); + + sp805_write_wdog_lock(pd->regs, WDOG_UNLOCK_KEY); + sp805_write_wdog_load(pd->regs, ticks); + sp805_write_wdog_lock(pd->regs, 0); + + dev_dbg(dev, "%s ", __func__); + + return 0; +} + +static int sp805_wdt_stop(struct udevice *dev) +{ + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + + sp805_write_wdog_lock(pd->regs, WDOG_UNLOCK_KEY); + sp805_write_wdog_ctrl(pd->regs, 0); + + dev_dbg(dev, "Watchdog disabled!\n"); + + return 0; +} + +static int sp805_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + u32 ticks; + + ticks = msec_to_ticks(dev); + + dev_dbg(dev, "%s:\n", __func__); + + sp805_write_wdog_load(pd->regs, ticks); + sp805_write_wdog_ctrl(pd->regs, SP805_CTR_RESEN | SP805_CTR_INTEN); + /* Lock registers access */ + sp805_write_wdog_lock(pd->regs, 0); + + return 0; +} + +static int sp805_wdt_probe(struct udevice *dev) +{ + dev_dbg(dev, "%s: Probing wdt%u\n", __func__, dev->seq); + + return 0; +} + +static int sp805_wdt_ofdata_to_platdata(struct udevice *dev) +{ + struct sp805_wdt_platdata *pd = dev_get_platdata(dev); + + dev_dbg(dev, "%s->\n", __func__); + pd->regs = dev_read_addr_ptr(dev); + if (!pd->regs) + return -ENODEV; + + if (dev_read_u32(dev, "timeout-msec", &pd->timeout_msec)) + return -ENODATA; + + if (dev_read_u32(dev, "clk-mhz", &pd->clk_mhz)) + return -ENODATA; + + dev_dbg(dev, "%s: regs:%p, msec :%u, clk %u\n", __func__, + pd->regs, pd->timeout_msec, pd->clk_mhz); + + return 0; +} + +static const struct wdt_ops sp805_wdt_ops = { + .start = sp805_wdt_start, + .reset = sp805_wdt_reset, + .stop = sp805_wdt_stop, + .expire_now = sp805_wdt_expire_now, +}; + +static const struct udevice_id sp805_wdt_ids[] = { + { .compatible = "arm,sp805-wdt" }, + {} +}; + +U_BOOT_DRIVER(sp805_wdt) = { + .name = "sp805_wdt", + .id = UCLASS_WDT, + .of_match = sp805_wdt_ids, + .probe = sp805_wdt_probe, + .platdata_auto_alloc_size = sizeof(struct sp805_wdt_platdata), + .ofdata_to_platdata = sp805_wdt_ofdata_to_platdata, + .ops = &sp805_wdt_ops, +}; -- 2.17.1