x86: allow both old and new grub signatures in sysupgrade
[openwrt.git] / target / linux / coldfire / patches / 031-Add-watchdog-driver-support-for-MCF5445x-and-MCF547x.patch
1 From 42bf8a598049f6cb3c90b1f28a2f1b8daebe3de8 Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:47 +0800
4 Subject: [PATCH 31/52] Add watchdog driver support for MCF5445x and MCF547x/MCF548x
5
6 Add watchdog driver support for MCF5445x and MCF547x/MCF548x.
7
8 Signed-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 +