aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2008-07-04 02:51:36 -0400
committerWim Van Sebroeck <wim@iguana.be>2008-08-06 09:08:47 -0400
commit0d7b101404f7bedcf3f448c1667c3744551cd9ee (patch)
treeb38363e88e0b02c4bdbc265c05b3fb770fe0b143 /drivers/watchdog
parentcb55d282a0d2156e7d40ee81726ab16b569e96d7 (diff)
[WATCHDOG] mpc8xxx_wdt: add support for MPC8xx watchdogs
The mpc8xxx_wdt driver is using two registers: SWSRR to push magic numbers, and SWCRR to control the watchdog. Both registers are available on the MPC8xx, and seem to have the same offsets and semantics as in MPC83xx/MPC86xx watchdogs. The only difference is prescale value. So this driver simply works on the MPC8xx CPUs. One quirk is needed for the MPC8xx, though. It has small prescale value and slow CPU, so the watchdog resets board prior to the driver has time to load. To solve this we should split initialization in two steps: start ping the watchdog early, and register the watchdog userspace interface later. MPC823 seem to be the first CPU in MPC8xx line, so we use fsl,mpc823-wdt compatible matching. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Tested-by: Jochen Friedrich <jochen@scram.de> Cc: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/Kconfig3
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c44
2 files changed, 35 insertions, 12 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 01e33e80eac0..50d44b4b466b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -697,10 +697,11 @@ config 8xx_WDT
697 697
698config 8xxx_WDT 698config 8xxx_WDT
699 tristate "MPC8xxx Platform Watchdog Timer" 699 tristate "MPC8xxx Platform Watchdog Timer"
700 depends on PPC_83xx || PPC_86xx 700 depends on PPC_8xx || PPC_83xx || PPC_86xx
701 help 701 help
702 This driver is for a SoC level watchdog that exists on some 702 This driver is for a SoC level watchdog that exists on some
703 Freescale PowerPC processors. So far this driver supports: 703 Freescale PowerPC processors. So far this driver supports:
704 - MPC8xx watchdogs
704 - MPC83xx watchdogs 705 - MPC83xx watchdogs
705 - MPC86xx watchdogs 706 - MPC86xx watchdogs
706 707
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 3c5ed9e26226..f2094960e662 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * mpc8xxx_wdt.c - MPC83xx/MPC86xx watchdog userspace interface 2 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface
3 * 3 *
4 * Authors: Dave Updegraff <dave@cray.org> 4 * Authors: Dave Updegraff <dave@cray.org>
5 * Kumar Gala <galak@kernel.crashing.org> 5 * Kumar Gala <galak@kernel.crashing.org>
@@ -207,13 +207,6 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
207 goto err_unmap; 207 goto err_unmap;
208 } 208 }
209 209
210 ret = misc_register(&mpc8xxx_wdt_miscdev);
211 if (ret) {
212 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
213 WATCHDOG_MINOR, ret);
214 goto err_unmap;
215 }
216
217 /* Calculate the timeout in seconds */ 210 /* Calculate the timeout in seconds */
218 if (prescale) 211 if (prescale)
219 timeout_sec = (timeout * wdt_type->prescaler) / freq; 212 timeout_sec = (timeout * wdt_type->prescaler) / freq;
@@ -234,6 +227,7 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev,
234 return 0; 227 return 0;
235err_unmap: 228err_unmap:
236 iounmap(wd_base); 229 iounmap(wd_base);
230 wd_base = NULL;
237 return ret; 231 return ret;
238} 232}
239 233
@@ -261,6 +255,12 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
261 .hw_enabled = true, 255 .hw_enabled = true,
262 }, 256 },
263 }, 257 },
258 {
259 .compatible = "fsl,mpc823-wdt",
260 .data = &(struct mpc8xxx_wdt_type) {
261 .prescaler = 0x800,
262 },
263 },
264 {}, 264 {},
265}; 265};
266MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); 266MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
@@ -275,20 +275,42 @@ static struct of_platform_driver mpc8xxx_wdt_driver = {
275 }, 275 },
276}; 276};
277 277
278/*
279 * We do wdt initialization in two steps: arch_initcall probes the wdt
280 * very early to start pinging the watchdog (misc devices are not yet
281 * available), and later module_init() just registers the misc device.
282 */
283static int __init mpc8xxx_wdt_init_late(void)
284{
285 int ret;
286
287 if (!wd_base)
288 return -ENODEV;
289
290 ret = misc_register(&mpc8xxx_wdt_miscdev);
291 if (ret) {
292 pr_err("cannot register miscdev on minor=%d (err=%d)\n",
293 WATCHDOG_MINOR, ret);
294 return ret;
295 }
296 return 0;
297}
298module_init(mpc8xxx_wdt_init_late);
299
278static int __init mpc8xxx_wdt_init(void) 300static int __init mpc8xxx_wdt_init(void)
279{ 301{
280 return of_register_platform_driver(&mpc8xxx_wdt_driver); 302 return of_register_platform_driver(&mpc8xxx_wdt_driver);
281} 303}
304arch_initcall(mpc8xxx_wdt_init);
282 305
283static void __exit mpc8xxx_wdt_exit(void) 306static void __exit mpc8xxx_wdt_exit(void)
284{ 307{
285 of_unregister_platform_driver(&mpc8xxx_wdt_driver); 308 of_unregister_platform_driver(&mpc8xxx_wdt_driver);
286} 309}
287
288subsys_initcall(mpc8xxx_wdt_init);
289module_exit(mpc8xxx_wdt_exit); 310module_exit(mpc8xxx_wdt_exit);
290 311
291MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); 312MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
292MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx/MPC86xx uProcessors"); 313MODULE_DESCRIPTION("Driver for watchdog timer in MPC8xx/MPC83xx/MPC86xx "
314 "uProcessors");
293MODULE_LICENSE("GPL"); 315MODULE_LICENSE("GPL");
294MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 316MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);