1 // SPDX-License-Identifier: GPL-2.0+
3 * Watchdog driver for SBSA
10 #include <dm/device.h>
11 #include <dm/fdtaddr.h>
13 #include <linux/bitops.h>
14 #include <linux/err.h>
18 DECLARE_GLOBAL_DATA_PTR;
20 /* SBSA Generic Watchdog register definitions */
22 #define SBSA_GWDT_WRR 0x000
25 #define SBSA_GWDT_WCS 0x000
26 #define SBSA_GWDT_WOR 0x008
27 #define SBSA_GWDT_WCV 0x010
29 /* refresh/control frame */
30 #define SBSA_GWDT_W_IIDR 0xfcc
31 #define SBSA_GWDT_IDR 0xfd0
33 /* Watchdog Control and Status Register */
34 #define SBSA_GWDT_WCS_EN BIT(0)
35 #define SBSA_GWDT_WCS_WS0 BIT(1)
36 #define SBSA_GWDT_WCS_WS1 BIT(2)
38 struct sbsa_gwdt_priv {
39 void __iomem *reg_refresh;
40 void __iomem *reg_control;
43 static int sbsa_gwdt_reset(struct udevice *dev)
45 struct sbsa_gwdt_priv *priv = dev_get_priv(dev);
47 writel(0, priv->reg_refresh + SBSA_GWDT_WRR);
52 static int sbsa_gwdt_start(struct udevice *dev, u64 timeout, ulong flags)
54 struct sbsa_gwdt_priv *priv = dev_get_priv(dev);
58 * it work in the single stage mode in u-boot,
59 * The first signal (WS0) is ignored,
60 * the timeout is (WOR * 2), so the WOR should be configured
61 * to half value of timeout.
64 writel(clk / 2 * timeout,
65 priv->reg_control + SBSA_GWDT_WOR);
67 /* writing WCS will cause an explicit watchdog refresh */
68 writel(SBSA_GWDT_WCS_EN, priv->reg_control + SBSA_GWDT_WCS);
73 static int sbsa_gwdt_stop(struct udevice *dev)
75 struct sbsa_gwdt_priv *priv = dev_get_priv(dev);
77 writel(0, priv->reg_control + SBSA_GWDT_WCS);
82 static int sbsa_gwdt_expire_now(struct udevice *dev, ulong flags)
84 sbsa_gwdt_start(dev, 0, flags);
89 static int sbsa_gwdt_probe(struct udevice *dev)
91 debug("%s: Probing wdt%u (sbsa-gwdt)\n", __func__, dev->seq);
96 static int sbsa_gwdt_ofdata_to_platdata(struct udevice *dev)
98 struct sbsa_gwdt_priv *priv = dev_get_priv(dev);
100 priv->reg_control = (void __iomem *)dev_read_addr_index(dev, 0);
101 if (IS_ERR(priv->reg_control))
102 return PTR_ERR(priv->reg_control);
104 priv->reg_refresh = (void __iomem *)dev_read_addr_index(dev, 1);
105 if (IS_ERR(priv->reg_refresh))
106 return PTR_ERR(priv->reg_refresh);
111 static const struct wdt_ops sbsa_gwdt_ops = {
112 .start = sbsa_gwdt_start,
113 .reset = sbsa_gwdt_reset,
114 .stop = sbsa_gwdt_stop,
115 .expire_now = sbsa_gwdt_expire_now,
118 static const struct udevice_id sbsa_gwdt_ids[] = {
119 { .compatible = "arm,sbsa-gwdt" },
123 U_BOOT_DRIVER(sbsa_gwdt) = {
126 .of_match = sbsa_gwdt_ids,
127 .probe = sbsa_gwdt_probe,
128 .priv_auto = sizeof(struct sbsa_gwdt_priv),
129 .ofdata_to_platdata = sbsa_gwdt_ofdata_to_platdata,
130 .ops = &sbsa_gwdt_ops,