xref: /openbmc/u-boot/drivers/watchdog/bcm6345_wdt.c (revision 2e8560797fc69a34c330a875da4f5d2992452f1e)
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