aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 19:21:54 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-22 19:21:54 -0700
commit8b0eaccab4584ace24d233214bfee3cb50e49a60 (patch)
treea22c53631041504f357f06e0ab779b3d3b283423 /arch/powerpc/platforms
parentMerge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus (diff)
parentMerge branch 'for-2.6.24' of git://git.secretlab.ca/git/linux-2.6-mpc52xx (diff)
downloadlinux-dev-8b0eaccab4584ace24d233214bfee3cb50e49a60.tar.xz
linux-dev-8b0eaccab4584ace24d233214bfee3cb50e49a60.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Enable restart support for lite5200 board [POWERPC] Add restart support for mpc52xx based platforms [POWERPC] Update device tree binding for mpc5200 gpt [POWERPC] Add mpc52xx_find_and_map_path(), refactor utility functions [POWERPC] bestcomm: Restrict bus prefetch bugfix to original mpc5200 silicon.
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/52xx/lite5200.c4
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c71
2 files changed, 71 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 65b7ae426238..25d2bfa3d9dc 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -145,6 +145,9 @@ static void __init lite5200_setup_arch(void)
/* Some mpc5200 & mpc5200b related configuration */
mpc5200_setup_xlb_arbiter();
+ /* Map wdt for mpc52xx_restart() */
+ mpc52xx_map_wdt();
+
#ifdef CONFIG_PM
mpc52xx_suspend.board_suspend_prepare = lite5200_suspend_prepare;
mpc52xx_suspend.board_resume_finish = lite5200_resume_finish;
@@ -183,5 +186,6 @@ define_machine(lite5200) {
.init = mpc52xx_declare_of_platform_devices,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
+ .restart = mpc52xx_restart,
.calibrate_decr = generic_calibrate_decr,
};
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 3bc201e07e6b..9850685c5429 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -18,15 +18,20 @@
#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;
-void __iomem *
-mpc52xx_find_and_map(const char *compatible)
+static void __iomem *
+mpc52xx_map_node(struct device_node *ofn)
{
- struct device_node *ofn;
const u32 *regaddr_p;
u64 regaddr64, size64;
- ofn = of_find_compatible_node(NULL, NULL, compatible);
if (!ofn)
return NULL;
@@ -42,8 +47,23 @@ mpc52xx_find_and_map(const char *compatible)
return ioremap((u32)regaddr64, (u32)size64);
}
+
+void __iomem *
+mpc52xx_find_and_map(const char *compatible)
+{
+ return mpc52xx_map_node(
+ of_find_compatible_node(NULL, NULL, compatible));
+}
+
EXPORT_SYMBOL(mpc52xx_find_and_map);
+void __iomem *
+mpc52xx_find_and_map_path(const char *path)
+{
+ return mpc52xx_map_node(of_find_node_by_path(path));
+}
+
+EXPORT_SYMBOL(mpc52xx_find_and_map_path);
/**
* mpc52xx_find_ipb_freq - Find the IPB bus frequency for a device
@@ -113,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);
+}