From 86b92cdda9e997dd305851cb16292c67076d58cb Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 19 Oct 2007 04:44:33 +1000 Subject: [PATCH] [POWERPC] Add restart support for mpc52xx based platforms Add common helper routines: mpc52xx_map_wdt() and mpc52xx_restart(). Signed-off-by: Marian Balakowicz Signed-off-by: Sascha Hauer Signed-off-by: Grant Likely --- arch/powerpc/platforms/52xx/mpc52xx_common.c | 50 ++++++++++++++++++++++++++++ include/asm-powerpc/mpc52xx.h | 3 ++ 2 files changed, 53 insertions(+) diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 74b4b41..9850685 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -18,6 +18,13 @@ #include #include +/* + * This variable is mapped in mpc52xx_map_wdt() and used in mpc52xx_restart(). + * Permanent mapping is required because mpc52xx_restart() can be called + * from interrupt context while node mapping (which calls ioremap()) + * cannot be used at such point. + */ +static volatile struct mpc52xx_gpt *mpc52xx_wdt = NULL; static void __iomem * mpc52xx_map_node(struct device_node *ofn) @@ -126,3 +133,46 @@ mpc52xx_declare_of_platform_devices(void) "Error while probing of_platform bus\n"); } +void __init +mpc52xx_map_wdt(void) +{ + const void *has_wdt; + struct device_node *np; + + /* mpc52xx_wdt is mapped here and used in mpc52xx_restart, + * possibly from a interrupt context. wdt is only implement + * on a gpt0, so check has-wdt property before mapping. + */ + for_each_compatible_node(np, NULL, "fsl,mpc5200-gpt") { + has_wdt = of_get_property(np, "fsl,has-wdt", NULL); + if (has_wdt) { + mpc52xx_wdt = mpc52xx_map_node(np); + return; + } + } + for_each_compatible_node(np, NULL, "mpc5200-gpt") { + has_wdt = of_get_property(np, "has-wdt", NULL); + if (has_wdt) { + mpc52xx_wdt = mpc52xx_map_node(np); + return; + } + } +} + +void +mpc52xx_restart(char *cmd) +{ + local_irq_disable(); + + /* Turn on the watchdog and wait for it to expire. + * It effectively does a reset. */ + if (mpc52xx_wdt) { + out_be32(&mpc52xx_wdt->mode, 0x00000000); + out_be32(&mpc52xx_wdt->count, 0x000000ff); + out_be32(&mpc52xx_wdt->mode, 0x00009004); + } else + printk("mpc52xx_restart: Can't access wdt. " + "Restart impossible, system halted.\n"); + + while (1); +} diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h index 8e42846..fcb2ebb 100644 --- a/include/asm-powerpc/mpc52xx.h +++ b/include/asm-powerpc/mpc52xx.h @@ -259,6 +259,9 @@ extern unsigned int mpc52xx_get_irq(void); extern int __init mpc52xx_add_bridge(struct device_node *node); +extern void __init mpc52xx_map_wdt(void); +extern void mpc52xx_restart(char *cmd); + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PM -- 2.7.4