Root/target/linux/coldfire/patches/031-Add-watchdog-driver-support-for-MCF5445x-and-MCF547x.patch

1From 42bf8a598049f6cb3c90b1f28a2f1b8daebe3de8 Mon Sep 17 00:00:00 2001
2From: Alison Wang <b18965@freescale.com>
3Date: Thu, 4 Aug 2011 09:59:47 +0800
4Subject: [PATCH 31/52] Add watchdog driver support for MCF5445x and MCF547x/MCF548x
5
6Add watchdog driver support for MCF5445x and MCF547x/MCF548x.
7
8Signed-off-by: Alison Wang <b18965@freescale.com>
9---
10 drivers/watchdog/Kconfig | 9 ++
11 drivers/watchdog/Makefile | 1 +
12 drivers/watchdog/mcf_wdt.c | 292 ++++++++++++++++++++++++++++++++++++++++++++
13 3 files changed, 302 insertions(+), 0 deletions(-)
14 create mode 100644 drivers/watchdog/mcf_wdt.c
15
16--- a/drivers/watchdog/Kconfig
17+++ b/drivers/watchdog/Kconfig
18@@ -974,6 +974,15 @@ config BCM63XX_WDT
19 
20 # PARISC Architecture
21 
22+# ColdFire Architecture
23+
24+config COLDFIRE_WATCHDOG
25+ tristate "ColdFire watchdog support"
26+ depends on M547X_8X || M5445X || M5441X
27+ help
28+ To compile this driver as a module, choose M here: the
29+ module will be called softdog.
30+
31 # POWERPC Architecture
32 
33 config GEF_WDT
34--- a/drivers/watchdog/Makefile
35+++ b/drivers/watchdog/Makefile
36@@ -107,6 +107,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc
37 
38 # M68K Architecture
39 obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o
40+obj-$(CONFIG_COLDFIRE_WATCHDOG) += mcf_wdt.o
41 
42 # MIPS Architecture
43 obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o
44--- /dev/null
45+++ b/drivers/watchdog/mcf_wdt.c
46@@ -0,0 +1,292 @@
47+/*
48+ * drivers/watchdog/mcf_wdt.c
49+ *
50+ * Watchdog driver for ColdFire processors
51+ *
52+ * Copyright (C) 2006-2007, 2009-2011 Freescale Semiconductor, Inc.
53+ * All Rights Reserved.
54+ *
55+ * Author: Shrek Wu<B16972@freesale.com>
56+ * ChengJu Cai<B22600@freesale.com>
57+ *
58+ * This file is licensed under the terms of the GNU General Public
59+ * License version 2. This program is licensed "as is" without any
60+ * warranty of any kind, whether express or implied.
61+ */
62+
63+#include <linux/module.h>
64+#include <linux/moduleparam.h>
65+#include <linux/types.h>
66+#include <linux/kernel.h>
67+#include <linux/fs.h>
68+#include <linux/miscdevice.h>
69+#include <linux/watchdog.h>
70+#include <linux/init.h>
71+#include <linux/bitops.h>
72+
73+#include <linux/uaccess.h>
74+#include <asm/coldfire.h>
75+#include <asm/mcfsim.h>
76+
77+static int nowayout;
78+static unsigned int heartbeat = MCF_GPT_MAX_TIMEOUT;
79+static unsigned long wdt_status;
80+
81+#define WDT_IN_USE 0
82+#define WDT_OK_TO_CLOSE 1
83+
84+static unsigned long wdt_tick_rate;
85+
86+#ifdef CONFIG_M547X_8X
87+static int
88+wdt_enable(int time)
89+{
90+ if (time > 30 || time < 1)
91+ return -EINVAL;
92+
93+ heartbeat = time;
94+
95+ MCF_GPT_GMS0 = 0;
96+ MCF_GPT_GCIR0 = MCF_GPT_GCIR_PRE(heartbeat * wdt_tick_rate) |
97+ MCF_GPT_GCIR_CNT(0xffff);
98+ MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN |
99+ MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS_GPIO;
100+
101+ return 0;
102+}
103+
104+static void
105+wdt_disable(void)
106+{
107+ MCF_GPT_GMS0 = 0;
108+}
109+
110+static void
111+wdt_keepalive(void)
112+{
113+ MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS0;
114+}
115+
116+#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
117+
118+/* Enable watchdog and set time-out */
119+static int
120+wdt_enable(int time)
121+{
122+ unsigned int sign = 0x01 << 31;
123+ int i = 0, timeout_n = 31;
124+ int max_timeout = sign / MCF_BUSCLK;
125+ unsigned int count;
126+
127+ if (time > max_timeout || time < 1)
128+ return -EINVAL;
129+
130+ count = time * MCF_BUSCLK;
131+
132+ for (i = 0; i < 31; i++) {
133+ if (count & (sign >> i)) {
134+ if ((count & (~(sign >> i))) == 0)
135+ timeout_n = 31 - i;
136+ else
137+ timeout_n = 31 - i + 1;
138+ break;
139+ }
140+ }
141+
142+ heartbeat = (unsigned int)(0x01 << timeout_n) / MCF_BUSCLK;
143+
144+ MCF_SCM_CWCR = MCF_SCM_CWCR_CWE
145+ | MCF_SCM_CWCR_CWRI(0x02)
146+ | MCF_SCM_CWCR_CWT(timeout_n);
147+
148+ return 0;
149+}
150+
151+/* Disable the watchdog */
152+static void
153+wdt_disable(void)
154+{
155+ MCF_SCM_CWCR = 0x00;
156+}
157+
158+/* Reset the watchdog timer counter */
159+static void
160+wdt_keepalive(void)
161+{
162+ MCF_SCM_CWSR = 0x55;
163+ MCF_SCM_CWSR = 0xAA;
164+}
165+#endif
166+
167+static int
168+mcf_wdt_open(struct inode *inode, struct file *file)
169+{
170+ int ret;
171+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
172+ return -EBUSY;
173+
174+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
175+
176+ ret = wdt_enable(heartbeat);
177+ if (ret)
178+ return ret;
179+
180+ return nonseekable_open(inode, file);
181+}
182+
183+static ssize_t
184+mcf_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
185+{
186+ if (len) {
187+ if (!nowayout) {
188+ size_t i;
189+
190+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
191+
192+ for (i = 0; i != len; i++) {
193+ char c;
194+
195+ if (get_user(c, data + i))
196+ return -EFAULT;
197+ if (c == 'V')
198+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
199+ }
200+ }
201+ wdt_keepalive();
202+ }
203+
204+ return len;
205+}
206+
207+
208+static struct watchdog_info ident = {
209+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
210+ WDIOF_KEEPALIVEPING,
211+ .identity = "Coldfire Watchdog",
212+};
213+
214+static long
215+mcf_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long __user arg)
216+{
217+ long ret = -ENOIOCTLCMD;
218+ int time = 0;
219+
220+ switch (cmd) {
221+ case WDIOC_GETSUPPORT:
222+ ret = copy_to_user((struct watchdog_info *)arg, &ident,
223+ sizeof(ident)) ? -EFAULT : 0;
224+ break;
225+
226+ case WDIOC_GETSTATUS:
227+ ret = put_user(0, (int *)arg);
228+ break;
229+
230+ case WDIOC_GETBOOTSTATUS:
231+ ret = put_user(0, (int *)arg);
232+ break;
233+
234+ case WDIOC_SETTIMEOUT:
235+ ret = get_user(time, (int *)arg);
236+ if (ret)
237+ break;
238+
239+ ret = wdt_enable(time);
240+ if (ret)
241+ break;
242+ ret = put_user(heartbeat, (int *)arg);
243+ break;
244+
245+ case WDIOC_GETTIMEOUT:
246+ ret = put_user(heartbeat, (int *)arg);
247+ break;
248+
249+ case WDIOC_KEEPALIVE:
250+ wdt_keepalive();
251+ ret = 0;
252+ break;
253+ }
254+
255+ return ret;
256+}
257+
258+static int
259+mcf_wdt_release(struct inode *inode, struct file *file)
260+{
261+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
262+#ifdef CONFIG_M547X_8X
263+ MCF_GPT_GCIR0 = (0x0A << 16) | 0x09;
264+ MCF_GPT_GMS0 = MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS0;
265+#else
266+ wdt_keepalive();
267+#endif
268+ } else {
269+ printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly\n");
270+ wdt_disable();
271+ }
272+
273+ clear_bit(WDT_IN_USE, &wdt_status);
274+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
275+
276+#ifdef CONFIG_M547X_8X
277+ /*disable the XLB priority, otherwise the watchdog reset may fail*/
278+ MCF_XARB_PRIEN = 0;
279+ /* Also disable the PCI, Ugly! But there is issue between PCI and
280+ * watchdog. Otherwise the watchdog reset may fail, only valuable
281+ * for testing!
282+ */
283+ MCF_SPCR &= ~0x02;
284+ asm("tpf");
285+#endif
286+
287+ return 0;
288+}
289+
290+
291+static const struct file_operations mcf_wdt_fops = {
292+ .owner = THIS_MODULE,
293+ .llseek = no_llseek,
294+ .write = mcf_wdt_write,
295+ .unlocked_ioctl = mcf_wdt_ioctl,
296+ .open = mcf_wdt_open,
297+ .release = mcf_wdt_release,
298+};
299+
300+static struct miscdevice mcf_wdt_miscdev = {
301+ .minor = WATCHDOG_MINOR,
302+ .name = "watchdog",
303+ .fops = &mcf_wdt_fops,
304+};
305+
306+static int __init mcf_wdt_init(void)
307+{
308+ wdt_tick_rate = MCF_BUSCLK/0xffff;
309+#ifdef CONFIG_WATCHDOG_NOWAYOUT
310+ nowayout = 1;
311+#else
312+ nowayout = 0;
313+#endif
314+ printk(KERN_INFO "ColdFire watchdog driver is loaded.\n");
315+
316+ return misc_register(&mcf_wdt_miscdev);
317+}
318+
319+static void __exit mcf_wdt_exit(void)
320+{
321+ misc_deregister(&mcf_wdt_miscdev);
322+}
323+
324+module_init(mcf_wdt_init);
325+module_exit(mcf_wdt_exit);
326+
327+MODULE_AUTHOR("Deepak Saxena");
328+MODULE_DESCRIPTION("ColdFire Watchdog");
329+
330+module_param(heartbeat, int, 0);
331+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 60s)");
332+
333+module_param(nowayout, int, 0);
334+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
335+
336+MODULE_LICENSE("GPL");
337+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
338+
339

Archive Download this file



interactive