2 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
4 * Derived from linux/drivers/watchdog/bcm63xx_wdt.c:
5 * Copyright (C) 2007 Miguel Gaio <miguel.gaio@efixo.com>
6 * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
8 * SPDX-License-Identifier: GPL-2.0+
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
{
32 static int bcm6345_wdt_reset(struct udevice
*dev
)
34 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
36 writel_be(WDT_CTL_START1_MASK
, priv
->regs
+ WDT_CTL_REG
);
37 writel_be(WDT_CTL_START2_MASK
, priv
->regs
+ WDT_CTL_REG
);
42 static int bcm6345_wdt_start(struct udevice
*dev
, u64 timeout
, ulong flags
)
44 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
46 if (timeout
< WDT_VAL_MIN
) {
47 debug("watchdog won't fire with less than 2 ticks\n");
48 timeout
= WDT_VAL_MIN
;
49 } else if (timeout
> WDT_VAL_MAX
) {
50 debug("maximum watchdog timeout exceeded\n");
51 timeout
= WDT_VAL_MAX
;
54 writel_be(timeout
, priv
->regs
+ WDT_VAL_REG
);
56 return bcm6345_wdt_reset(dev
);
59 static int bcm6345_wdt_expire_now(struct udevice
*dev
, ulong flags
)
61 return bcm6345_wdt_start(dev
, WDT_VAL_MIN
, flags
);
64 static int bcm6345_wdt_stop(struct udevice
*dev
)
66 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
68 writel_be(WDT_CTL_STOP1_MASK
, priv
->regs
+ WDT_CTL_REG
);
69 writel_be(WDT_CTL_STOP2_MASK
, priv
->regs
+ WDT_CTL_REG
);
74 static const struct wdt_ops bcm6345_wdt_ops
= {
75 .expire_now
= bcm6345_wdt_expire_now
,
76 .reset
= bcm6345_wdt_reset
,
77 .start
= bcm6345_wdt_start
,
78 .stop
= bcm6345_wdt_stop
,
81 static const struct udevice_id bcm6345_wdt_ids
[] = {
82 { .compatible
= "brcm,bcm6345-wdt" },
86 static int bcm6345_wdt_probe(struct udevice
*dev
)
88 struct bcm6345_wdt_priv
*priv
= dev_get_priv(dev
);
92 addr
= devfdt_get_addr_size_index(dev
, 0, &size
);
93 if (addr
== FDT_ADDR_T_NONE
)
96 priv
->regs
= ioremap(addr
, size
);
98 bcm6345_wdt_stop(dev
);
103 U_BOOT_DRIVER(wdt_bcm6345
) = {
104 .name
= "wdt_bcm6345",
106 .of_match
= bcm6345_wdt_ids
,
107 .ops
= &bcm6345_wdt_ops
,
108 .priv_auto_alloc_size
= sizeof(struct bcm6345_wdt_priv
),
109 .probe
= bcm6345_wdt_probe
,