183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
277331934SÁlvaro Fernández Rojas /*
377331934SÁlvaro Fernández Rojas * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
477331934SÁlvaro Fernández Rojas *
577331934SÁlvaro Fernández Rojas * Derived from linux/drivers/watchdog/bcm63xx_wdt.c:
677331934SÁlvaro Fernández Rojas * Copyright (C) 2007 Miguel Gaio <miguel.gaio@efixo.com>
777331934SÁlvaro Fernández Rojas * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
877331934SÁlvaro Fernández Rojas */
977331934SÁlvaro Fernández Rojas
1077331934SÁlvaro Fernández Rojas #include <common.h>
1177331934SÁlvaro Fernández Rojas #include <dm.h>
1277331934SÁlvaro Fernández Rojas #include <wdt.h>
1377331934SÁlvaro Fernández Rojas #include <asm/io.h>
1477331934SÁlvaro Fernández Rojas
1577331934SÁlvaro Fernández Rojas /* WDT Value register */
1677331934SÁlvaro Fernández Rojas #define WDT_VAL_REG 0x0
1777331934SÁlvaro Fernández Rojas #define WDT_VAL_MIN 0x00000002
1877331934SÁlvaro Fernández Rojas #define WDT_VAL_MAX 0xfffffffe
1977331934SÁlvaro Fernández Rojas
2077331934SÁlvaro Fernández Rojas /* WDT Control register */
2177331934SÁlvaro Fernández Rojas #define WDT_CTL_REG 0x4
2277331934SÁlvaro Fernández Rojas #define WDT_CTL_START1_MASK 0x0000ff00
2377331934SÁlvaro Fernández Rojas #define WDT_CTL_START2_MASK 0x000000ff
2477331934SÁlvaro Fernández Rojas #define WDT_CTL_STOP1_MASK 0x0000ee00
2577331934SÁlvaro Fernández Rojas #define WDT_CTL_STOP2_MASK 0x000000ee
2677331934SÁlvaro Fernández Rojas
2777331934SÁlvaro Fernández Rojas struct bcm6345_wdt_priv {
2877331934SÁlvaro Fernández Rojas void __iomem *regs;
2977331934SÁlvaro Fernández Rojas };
3077331934SÁlvaro Fernández Rojas
bcm6345_wdt_reset(struct udevice * dev)3177331934SÁlvaro Fernández Rojas static int bcm6345_wdt_reset(struct udevice *dev)
3277331934SÁlvaro Fernández Rojas {
3377331934SÁlvaro Fernández Rojas struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
3477331934SÁlvaro Fernández Rojas
35*771ee9b6SPhilippe Reynes writel(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG);
36*771ee9b6SPhilippe Reynes writel(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG);
3777331934SÁlvaro Fernández Rojas
3877331934SÁlvaro Fernández Rojas return 0;
3977331934SÁlvaro Fernández Rojas }
4077331934SÁlvaro Fernández Rojas
bcm6345_wdt_start(struct udevice * dev,u64 timeout,ulong flags)4177331934SÁlvaro Fernández Rojas static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
4277331934SÁlvaro Fernández Rojas {
4377331934SÁlvaro Fernández Rojas struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
4477331934SÁlvaro Fernández Rojas
4577331934SÁlvaro Fernández Rojas if (timeout < WDT_VAL_MIN) {
4677331934SÁlvaro Fernández Rojas debug("watchdog won't fire with less than 2 ticks\n");
4777331934SÁlvaro Fernández Rojas timeout = WDT_VAL_MIN;
4877331934SÁlvaro Fernández Rojas } else if (timeout > WDT_VAL_MAX) {
4977331934SÁlvaro Fernández Rojas debug("maximum watchdog timeout exceeded\n");
5077331934SÁlvaro Fernández Rojas timeout = WDT_VAL_MAX;
5177331934SÁlvaro Fernández Rojas }
5277331934SÁlvaro Fernández Rojas
53*771ee9b6SPhilippe Reynes writel(timeout, priv->regs + WDT_VAL_REG);
5477331934SÁlvaro Fernández Rojas
5577331934SÁlvaro Fernández Rojas return bcm6345_wdt_reset(dev);
5677331934SÁlvaro Fernández Rojas }
5777331934SÁlvaro Fernández Rojas
bcm6345_wdt_expire_now(struct udevice * dev,ulong flags)5877331934SÁlvaro Fernández Rojas static int bcm6345_wdt_expire_now(struct udevice *dev, ulong flags)
5977331934SÁlvaro Fernández Rojas {
6077331934SÁlvaro Fernández Rojas return bcm6345_wdt_start(dev, WDT_VAL_MIN, flags);
6177331934SÁlvaro Fernández Rojas }
6277331934SÁlvaro Fernández Rojas
bcm6345_wdt_stop(struct udevice * dev)6377331934SÁlvaro Fernández Rojas static int bcm6345_wdt_stop(struct udevice *dev)
6477331934SÁlvaro Fernández Rojas {
6577331934SÁlvaro Fernández Rojas struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
6677331934SÁlvaro Fernández Rojas
67*771ee9b6SPhilippe Reynes writel(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG);
68*771ee9b6SPhilippe Reynes writel(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG);
6977331934SÁlvaro Fernández Rojas
7077331934SÁlvaro Fernández Rojas return 0;
7177331934SÁlvaro Fernández Rojas }
7277331934SÁlvaro Fernández Rojas
7377331934SÁlvaro Fernández Rojas static const struct wdt_ops bcm6345_wdt_ops = {
7477331934SÁlvaro Fernández Rojas .expire_now = bcm6345_wdt_expire_now,
7577331934SÁlvaro Fernández Rojas .reset = bcm6345_wdt_reset,
7677331934SÁlvaro Fernández Rojas .start = bcm6345_wdt_start,
7777331934SÁlvaro Fernández Rojas .stop = bcm6345_wdt_stop,
7877331934SÁlvaro Fernández Rojas };
7977331934SÁlvaro Fernández Rojas
8077331934SÁlvaro Fernández Rojas static const struct udevice_id bcm6345_wdt_ids[] = {
8177331934SÁlvaro Fernández Rojas { .compatible = "brcm,bcm6345-wdt" },
8277331934SÁlvaro Fernández Rojas { /* sentinel */ }
8377331934SÁlvaro Fernández Rojas };
8477331934SÁlvaro Fernández Rojas
bcm6345_wdt_probe(struct udevice * dev)8577331934SÁlvaro Fernández Rojas static int bcm6345_wdt_probe(struct udevice *dev)
8677331934SÁlvaro Fernández Rojas {
8777331934SÁlvaro Fernández Rojas struct bcm6345_wdt_priv *priv = dev_get_priv(dev);
8877331934SÁlvaro Fernández Rojas
89aa8f8250SÁlvaro Fernández Rojas priv->regs = dev_remap_addr(dev);
90aa8f8250SÁlvaro Fernández Rojas if (!priv->regs)
9177331934SÁlvaro Fernández Rojas return -EINVAL;
9277331934SÁlvaro Fernández Rojas
9377331934SÁlvaro Fernández Rojas bcm6345_wdt_stop(dev);
9477331934SÁlvaro Fernández Rojas
9577331934SÁlvaro Fernández Rojas return 0;
9677331934SÁlvaro Fernández Rojas }
9777331934SÁlvaro Fernández Rojas
9877331934SÁlvaro Fernández Rojas U_BOOT_DRIVER(wdt_bcm6345) = {
9977331934SÁlvaro Fernández Rojas .name = "wdt_bcm6345",
10077331934SÁlvaro Fernández Rojas .id = UCLASS_WDT,
10177331934SÁlvaro Fernández Rojas .of_match = bcm6345_wdt_ids,
10277331934SÁlvaro Fernández Rojas .ops = &bcm6345_wdt_ops,
10377331934SÁlvaro Fernández Rojas .priv_auto_alloc_size = sizeof(struct bcm6345_wdt_priv),
10477331934SÁlvaro Fernández Rojas .probe = bcm6345_wdt_probe,
10577331934SÁlvaro Fernández Rojas };
106