2 * drivers/watchdog/orion_wdt.c
4 * Watchdog driver for Orion/Kirkwood processors
6 * Authors: Tomas Hlavacek <tmshlvck@gmail.com>
7 * Sylver Bruneau <sylver.bruneau@googlemail.com>
8 * Marek Behun <marek.behun@nic.cz>
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
19 #include <asm/arch/cpu.h>
20 #include <asm/arch/soc.h>
22 DECLARE_GLOBAL_DATA_PTR
;
24 struct orion_wdt_priv
{
26 int wdt_counter_offset
;
28 void __iomem
*rstout_mask
;
32 #define RSTOUT_ENABLE_BIT BIT(8)
33 #define RSTOUT_MASK_BIT BIT(10)
34 #define WDT_ENABLE_BIT BIT(8)
36 #define TIMER_CTRL 0x0000
37 #define TIMER_A370_STATUS 0x04
39 #define WDT_AXP_FIXED_ENABLE_BIT BIT(10)
40 #define WDT_A370_EXPIRED BIT(31)
42 static int orion_wdt_reset(struct udevice
*dev
)
44 struct orion_wdt_priv
*priv
= dev_get_priv(dev
);
46 /* Reload watchdog duration */
47 writel(priv
->timeout
, priv
->reg
+ priv
->wdt_counter_offset
);
52 static int orion_wdt_start(struct udevice
*dev
, u64 timeout
, ulong flags
)
54 struct orion_wdt_priv
*priv
= dev_get_priv(dev
);
57 priv
->timeout
= (u32
) timeout
;
59 /* Enable the fixed watchdog clock input */
60 reg
= readl(priv
->reg
+ TIMER_CTRL
);
61 reg
|= WDT_AXP_FIXED_ENABLE_BIT
;
62 writel(reg
, priv
->reg
+ TIMER_CTRL
);
64 /* Set watchdog duration */
65 writel(priv
->timeout
, priv
->reg
+ priv
->wdt_counter_offset
);
67 /* Clear the watchdog expiration bit */
68 reg
= readl(priv
->reg
+ TIMER_A370_STATUS
);
69 reg
&= ~WDT_A370_EXPIRED
;
70 writel(reg
, priv
->reg
+ TIMER_A370_STATUS
);
72 /* Enable watchdog timer */
73 reg
= readl(priv
->reg
+ TIMER_CTRL
);
74 reg
|= WDT_ENABLE_BIT
;
75 writel(reg
, priv
->reg
+ TIMER_CTRL
);
77 /* Enable reset on watchdog */
78 reg
= readl(priv
->rstout
);
79 reg
|= RSTOUT_ENABLE_BIT
;
80 writel(reg
, priv
->rstout
);
82 reg
= readl(priv
->rstout_mask
);
83 reg
&= ~RSTOUT_MASK_BIT
;
84 writel(reg
, priv
->rstout_mask
);
89 static int orion_wdt_stop(struct udevice
*dev
)
91 struct orion_wdt_priv
*priv
= dev_get_priv(dev
);
94 /* Disable reset on watchdog */
95 reg
= readl(priv
->rstout_mask
);
96 reg
|= RSTOUT_MASK_BIT
;
97 writel(reg
, priv
->rstout_mask
);
99 reg
= readl(priv
->rstout
);
100 reg
&= ~RSTOUT_ENABLE_BIT
;
101 writel(reg
, priv
->rstout
);
103 /* Disable watchdog timer */
104 reg
= readl(priv
->reg
+ TIMER_CTRL
);
105 reg
&= ~WDT_ENABLE_BIT
;
106 writel(reg
, priv
->reg
+ TIMER_CTRL
);
111 static inline bool save_reg_from_ofdata(struct udevice
*dev
, int index
,
112 void __iomem
**reg
, int *offset
)
117 addr
= fdtdec_get_addr_size_auto_noparent(
118 gd
->fdt_blob
, dev_of_offset(dev
), "reg", index
, &off
, true);
120 if (addr
== FDT_ADDR_T_NONE
)
123 *reg
= (void __iomem
*) addr
;
130 static int orion_wdt_ofdata_to_platdata(struct udevice
*dev
)
132 struct orion_wdt_priv
*priv
= dev_get_priv(dev
);
134 if (!save_reg_from_ofdata(dev
, 0, &priv
->reg
,
135 &priv
->wdt_counter_offset
))
138 if (!save_reg_from_ofdata(dev
, 1, &priv
->rstout
, NULL
))
141 if (!save_reg_from_ofdata(dev
, 2, &priv
->rstout_mask
, NULL
))
146 debug("%s: Could not determine Orion wdt IO addresses\n", __func__
);
150 static int orion_wdt_probe(struct udevice
*dev
)
152 debug("%s: Probing wdt%u\n", __func__
, dev
->seq
);
158 static const struct wdt_ops orion_wdt_ops
= {
159 .start
= orion_wdt_start
,
160 .reset
= orion_wdt_reset
,
161 .stop
= orion_wdt_stop
,
164 static const struct udevice_id orion_wdt_ids
[] = {
165 { .compatible
= "marvell,armada-380-wdt" },
169 U_BOOT_DRIVER(orion_wdt
) = {
172 .of_match
= orion_wdt_ids
,
173 .probe
= orion_wdt_probe
,
174 .priv_auto_alloc_size
= sizeof(struct orion_wdt_priv
),
175 .ofdata_to_platdata
= orion_wdt_ofdata_to_platdata
,
176 .ops
= &orion_wdt_ops
,