1 From 24d99ffc4b22e45721e74bfc10717cc5bacdbfc4 Mon Sep 17 00:00:00 2001
2 From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
3 Date: Wed, 14 Nov 2012 19:17:47 +0800
4 Subject: [PATCH 2/4] watchdog: add at91sam9 watchdog support
6 with keep alive support
8 Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
9 Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
11 drivers/watchdog/Kconfig | 8 +++
12 drivers/watchdog/Makefile | 1 +
13 drivers/watchdog/at91sam9_wdt.c | 131 ++++++++++++++++++++++++++++++++++++++++
14 drivers/watchdog/at91sam9_wdt.h | 38 ++++++++++++
15 4 files changed, 178 insertions(+)
16 create mode 100644 drivers/watchdog/at91sam9_wdt.c
17 create mode 100644 drivers/watchdog/at91sam9_wdt.h
19 diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
20 index 7ebff89b9..479e737f0 100644
21 --- a/drivers/watchdog/Kconfig
22 +++ b/drivers/watchdog/Kconfig
23 @@ -11,12 +11,20 @@ menuconfig WATCHDOG
27 +config WATCHDOG_AT91SAM9X
28 + tristate "AT91SAM9X / AT91CAP9 watchdog"
29 + depends on ARCH_AT91
31 + Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will
32 + reboot your system when the timeout is reached.
34 config WATCHDOG_DAVINCI
36 depends on ARCH_DAVINCI
38 Add support for watchdog on the TI Davinci SoC.
42 bool "Synopsys DesignWare watchdog"
43 select RESET_CONTROLLER
44 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
45 index 5fca4c368..245a5c84a 100644
46 --- a/drivers/watchdog/Makefile
47 +++ b/drivers/watchdog/Makefile
49 obj-$(CONFIG_WATCHDOG) += wd_core.o
50 +obj-$(CONFIG_WATCHDOG_AT91SAM9X) += at91sam9_wdt.o
51 obj-$(CONFIG_WATCHDOG_DAVINCI) += davinci_wdt.o
52 obj-$(CONFIG_WATCHDOG_OMAP) += omap_wdt.o
53 obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o
54 diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
56 index 000000000..203d83aff
58 +++ b/drivers/watchdog/at91sam9_wdt.c
61 + * (c) 2012 Juergen Beisert <kernel@pengutronix.de>
63 + * This program is free software; you can redistribute it and/or modify
64 + * it under the terms of the GNU General Public License as published by
65 + * the Free Software Foundation; either version 2 of the License, or
66 + * (at your option) any later version.
68 + * This program is distributed in the hope that it will be useful,
69 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
70 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71 + * GNU General Public License for more details.
73 + * Note: this driver works for the i.MX28 SoC. It might work for the
74 + * i.MX23 Soc as well, but is not tested yet.
82 +#include <watchdog.h>
84 +#include "at91sam9_wdt.h"
86 +struct at91sam9_wdt {
87 + struct watchdog wdt;
91 +#define to_at91sam9_wdt(h) container_of(h, struct at91sam9_wdt, wdt)
93 +#define wdt_read(at91wdt, field) \
94 + __raw_readl(at91wdt->base + field)
95 +#define wdt_write(at91wdt, field, val) \
96 + __raw_writel((val), at91wdt->base + field)
98 +static void at91sam9_wdt_keep_alive(struct watchdog *wdt)
100 + struct at91sam9_wdt *at91wdt = to_at91sam9_wdt(wdt);
102 + wdt_write(at91wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
105 +static int at91sam9_wdt_settimeout(struct watchdog *wdt, unsigned int timeout)
107 + struct at91sam9_wdt *at91wdt = to_at91sam9_wdt(wdt);
111 + /* Check if disabled */
112 + mr = wdt_read(at91wdt, AT91_WDT_MR);
113 + if (mr & AT91_WDT_WDDIS) {
114 + pr_err("sorry, watchdog is disabled\n");
119 + wdt_write(at91wdt, AT91_WDT_MR, AT91_WDT_WDDIS);
124 + * All counting occurs at SLOW_CLOCK / 128 = 256 Hz
126 + * Since WDV is a 12-bit counter, the maximum period is
127 + * 4096 / 256 = 16 seconds.
129 + reg = AT91_WDT_WDRSTEN /* causes watchdog reset */
130 + /* | AT91_WDT_WDRPROC causes processor reset only */
131 + | AT91_WDT_WDDBGHLT /* disabled in debug mode */
132 + | AT91_WDT_WDD /* restart at any time */
133 + | (timeout & AT91_WDT_WDV); /* timer value */
134 + wdt_write(at91wdt, AT91_WDT_MR, reg);
139 +static int at91sam9_wdt_probe(struct device_d *dev)
141 + struct at91sam9_wdt *priv;
142 + struct watchdog *wdt;
146 + priv = xzalloc(sizeof(struct at91sam9_wdt));
147 + priv->base = dev_request_mem_region(dev, 0);
150 + wdt->set_timeout = at91sam9_wdt_settimeout;
151 + wdt->keep_alive = at91sam9_wdt_keep_alive;
153 + /* Check if disabled */
154 + mr = wdt_read(priv, AT91_WDT_MR);
155 + if (mr & AT91_WDT_WDDIS) {
156 + dev_err(dev, "sorry, watchdog is disabled\n");
161 + ret = watchdog_register(wdt);
173 +static void at91sam9_wdt_remove(struct device_d *dev)
175 + struct at91sam9_wdt *priv= dev->priv;
176 + watchdog_deregister(&priv->wdt);
180 +static struct driver_d at91sam9_wdt_driver = {
181 + .name = "at91sam9_wdt",
182 + .probe = at91sam9_wdt_probe,
183 + .remove = at91sam9_wdt_remove,
186 +static int at91sam9_wdt_init(void)
188 + return platform_driver_register(&at91sam9_wdt_driver);
190 +coredevice_initcall(at91sam9_wdt_init);
191 diff --git a/drivers/watchdog/at91sam9_wdt.h b/drivers/watchdog/at91sam9_wdt.h
193 index 000000000..2b68c1a2a
195 +++ b/drivers/watchdog/at91sam9_wdt.h
198 + * drivers/watchdog/at91sam9_wdt.h
200 + * Copyright (C) 2007 Andrew Victor
201 + * Copyright (C) 2007 Atmel Corporation.
203 + * Watchdog Timer (WDT) - System peripherals regsters.
204 + * Based on AT91SAM9261 datasheet revision D.
206 + * This program is free software; you can redistribute it and/or modify
207 + * it under the terms of the GNU General Public License as published by
208 + * the Free Software Foundation; either version 2 of the License, or
209 + * (at your option) any later version.
215 +#define AT91_WDT_CR 0x00 /* Watchdog Control Register */
216 +#define AT91_WDT_WDRSTT (1 << 0) /* Restart */
217 +#define AT91_WDT_KEY (0xa5 << 24) /* KEY Password */
219 +#define AT91_WDT_MR 0x04 /* Watchdog Mode Register */
220 +#define AT91_WDT_WDV (0xfff << 0) /* Counter Value */
221 +#define AT91_WDT_WDFIEN (1 << 12) /* Fault Interrupt Enable */
222 +#define AT91_WDT_WDRSTEN (1 << 13) /* Reset Processor */
223 +#define AT91_WDT_WDRPROC (1 << 14) /* Timer Restart */
224 +#define AT91_WDT_WDDIS (1 << 15) /* Watchdog Disable */
225 +#define AT91_WDT_WDD (0xfff << 16) /* Delta Value */
226 +#define AT91_WDT_WDDBGHLT (1 << 28) /* Debug Halt */
227 +#define AT91_WDT_WDIDLEHLT (1 << 29) /* Idle Halt */
229 +#define AT91_WDT_SR 0x08 /* Watchdog Status Register */
230 +#define AT91_WDT_WDUNF (1 << 0) /* Watchdog Underflow */
231 +#define AT91_WDT_WDERR (1 << 1) /* Watchdog Error */