1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <log.h>
18#include <asm/global_data.h>
19#include <asm/io.h>
20#include <asm/arch/at91_wdt.h>
21#include <common.h>
22#include <div64.h>
23#include <dm.h>
24#include <errno.h>
25#include <wdt.h>
26
27DECLARE_GLOBAL_DATA_PTR;
28
29
30
31
32
33
34#define WDT_SEC2TICKS(s) (((s) << 8) - 1)
35
36
37
38
39
40static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
41{
42 struct at91_wdt_priv *priv = dev_get_priv(dev);
43 u64 timeout;
44 u32 ticks;
45
46
47 timeout = timeout_ms;
48 do_div(timeout, 1000);
49 timeout = min_t(u64, timeout, WDT_MAX_TIMEOUT);
50 ticks = WDT_SEC2TICKS(timeout);
51
52
53 if (readl(priv->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) {
54 printf("sorry, watchdog is disabled\n");
55 return -1;
56 }
57
58
59
60
61
62
63
64 priv->regval = AT91_WDT_MR_WDRSTEN
65 | AT91_WDT_MR_WDDBGHLT
66 | AT91_WDT_MR_WDD(0xfff)
67 | AT91_WDT_MR_WDV(ticks);
68 writel(priv->regval, priv->regs + AT91_WDT_MR);
69
70 return 0;
71}
72
73static int at91_wdt_stop(struct udevice *dev)
74{
75 struct at91_wdt_priv *priv = dev_get_priv(dev);
76
77
78 priv->regval |= AT91_WDT_MR_WDDIS;
79 writel(priv->regval, priv->regs + AT91_WDT_MR);
80
81 return 0;
82}
83
84static int at91_wdt_reset(struct udevice *dev)
85{
86 struct at91_wdt_priv *priv = dev_get_priv(dev);
87
88 writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, priv->regs + AT91_WDT_CR);
89
90 return 0;
91}
92
93static const struct wdt_ops at91_wdt_ops = {
94 .start = at91_wdt_start,
95 .stop = at91_wdt_stop,
96 .reset = at91_wdt_reset,
97};
98
99static const struct udevice_id at91_wdt_ids[] = {
100 { .compatible = "atmel,at91sam9260-wdt" },
101 {}
102};
103
104static int at91_wdt_probe(struct udevice *dev)
105{
106 struct at91_wdt_priv *priv = dev_get_priv(dev);
107
108 priv->regs = dev_remap_addr(dev);
109 if (!priv->regs)
110 return -EINVAL;
111
112 debug("%s: Probing wdt%u\n", __func__, dev_seq(dev));
113
114 return 0;
115}
116
117U_BOOT_DRIVER(atmel_at91sam9260_wdt) = {
118 .name = "atmel_at91sam9260_wdt",
119 .id = UCLASS_WDT,
120 .of_match = at91_wdt_ids,
121 .priv_auto = sizeof(struct at91_wdt_priv),
122 .ops = &at91_wdt_ops,
123 .probe = at91_wdt_probe,
124};
125