[POWERPC] Add restart support for mpc52xx based platforms
authorMarian Balakowicz <m8@semihalf.com>
Thu, 18 Oct 2007 18:44:33 +0000 (04:44 +1000)
committerGrant Likely <grant.likely@secretlab.ca>
Sun, 21 Oct 2007 18:43:04 +0000 (12:43 -0600)
Add common helper routines: mpc52xx_map_wdt() and mpc52xx_restart().

Signed-off-by: Marian Balakowicz <m8@semihalf.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
arch/powerpc/platforms/52xx/mpc52xx_common.c
include/asm-powerpc/mpc52xx.h

index 74b4b418384232c474e2c2f153d4fb98c6c98bcd..9850685c542999c69a89ee65c94cba2b750e7b5e 100644 (file)
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
 
+/*
+ * 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);
+}
index 8e428466a60f8e48f82f7a377293756320c01b75..fcb2ebbfddbcd2d0d4c2aa4704cdffed236207a9 100644 (file)
@@ -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