diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 74b4b418384232c474e2c2f153d4fb98c6c98bcd..9850685c542999c69a89ee65c94cba2b750e7b5e 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 8e428466a60f8e48f82f7a377293756320c01b75..fcb2ebbfddbcd2d0d4c2aa4704cdffed236207a9 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