1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
5 * Derived from linux/drivers/watchdog/bcm63xx_wdt.c:
6 * Copyright (C) 2007 Miguel Gaio <miguel.gaio@efixo.com>
7 * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
16 /* WDT Value register */
17 #define WDT_VAL_REG 0x0
18 #define WDT_VAL_MIN 0x00000002
19 #define WDT_VAL_MAX 0xfffffffe
21 /* WDT Control register */
22 #define WDT_CTL_REG 0x4
23 #define WDT_CTL_START1_MASK 0x0000ff00
24 #define WDT_CTL_START2_MASK 0x000000ff
25 #define WDT_CTL_STOP1_MASK 0x0000ee00
26 #define WDT_CTL_STOP2_MASK 0x000000ee
28 struct bcm6345_wdt_priv
{
30 unsigned long clk_rate
;
33 static int bcm6345_wdt_reset(struct udevice
*dev
)
35 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
37 writel(WDT_CTL_START1_MASK
, priv
->regs
+ WDT_CTL_REG
);
38 writel(WDT_CTL_START2_MASK
, priv
->regs
+ WDT_CTL_REG
);
43 static int bcm6345_wdt_start(struct udevice
*dev
, u64 timeout
, ulong flags
)
45 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
46 u32 val
= priv
->clk_rate
/ 1000 * timeout
;
48 if (val
< WDT_VAL_MIN
) {
49 debug("watchdog won't fire with less than 2 ticks\n");
51 } else if (val
> WDT_VAL_MAX
) {
52 debug("maximum watchdog timeout exceeded\n");
56 writel(val
, priv
->regs
+ WDT_VAL_REG
);
58 return bcm6345_wdt_reset(dev
);
61 static int bcm6345_wdt_expire_now(struct udevice
*dev
, ulong flags
)
63 return bcm6345_wdt_start(dev
, WDT_VAL_MIN
, flags
);
66 static int bcm6345_wdt_stop(struct udevice
*dev
)
68 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
70 writel(WDT_CTL_STOP1_MASK
, priv
->regs
+ WDT_CTL_REG
);
71 writel(WDT_CTL_STOP2_MASK
, priv
->regs
+ WDT_CTL_REG
);
76 static const struct wdt_ops bcm6345_wdt_ops
= {
77 .expire_now
= bcm6345_wdt_expire_now
,
78 .reset
= bcm6345_wdt_reset
,
79 .start
= bcm6345_wdt_start
,
80 .stop
= bcm6345_wdt_stop
,
83 static const struct udevice_id bcm6345_wdt_ids
[] = {
84 { .compatible
= "brcm,bcm6345-wdt" },
88 static int bcm6345_wdt_probe(struct udevice
*dev
)
90 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
94 priv
->regs
= dev_remap_addr(dev
);
98 ret
= clk_get_by_index(dev
, 0, &clk
);
100 priv
->clk_rate
= clk_get_rate(&clk
);
104 bcm6345_wdt_stop(dev
);
109 U_BOOT_DRIVER(wdt_bcm6345
) = {
110 .name
= "wdt_bcm6345",
112 .of_match
= bcm6345_wdt_ids
,
113 .ops
= &bcm6345_wdt_ops
,
114 .priv_auto_alloc_size
= sizeof(struct bcm6345_wdt_priv
),
115 .probe
= bcm6345_wdt_probe
,