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.
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
index 5f7d536..5e03610 100644
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
@@ -185,7 +185,7 @@
Recommended soc5200 child nodes; populate as needed for your board
name device_type compatible Description
---- ----------- ---------- -----------
-gpt@<addr> gpt mpc5200-gpt General purpose timers
+gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers
rtc@<addr> rtc mpc5200-rtc Real time clock
mscan@<addr> mscan mpc5200-mscan CAN bus controller
pci@<addr> pci mpc5200-pci PCI bridge
@@ -213,7 +213,7 @@
5) General Purpose Timer nodes (child of soc5200 node)
On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
design supports the internal wdt, then the device node for GPT0 should
-include the empty property 'has-wdt'.
+include the empty property 'fsl,has-wdt'.
6) PSC nodes (child of soc5200 node)
PSC nodes can define the optional 'port-number' property to force assignment
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index bc45f5f..6731763 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -70,18 +70,16 @@
};
gpt@600 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <0>;
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <&mpc5200_pic>;
- has-wdt;
+ fsl,has-wdt;
};
gpt@610 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <1>;
reg = <610 10>;
interrupts = <1 a 0>;
@@ -89,8 +87,7 @@
};
gpt@620 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <2>;
reg = <620 10>;
interrupts = <1 b 0>;
@@ -98,8 +95,7 @@
};
gpt@630 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <3>;
reg = <630 10>;
interrupts = <1 c 0>;
@@ -107,8 +103,7 @@
};
gpt@640 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <4>;
reg = <640 10>;
interrupts = <1 d 0>;
@@ -116,8 +111,7 @@
};
gpt@650 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <5>;
reg = <650 10>;
interrupts = <1 e 0>;
@@ -125,8 +119,7 @@
};
gpt@660 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <6>;
reg = <660 10>;
interrupts = <1 f 0>;
@@ -134,8 +127,7 @@
};
gpt@670 { // General Purpose Timer
- compatible = "mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200-gpt";
cell-index = <7>;
reg = <670 10>;
interrupts = <1 10 0>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index 6582c9a..b540388 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -70,18 +70,16 @@
};
gpt@600 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <0>;
reg = <600 10>;
interrupts = <1 9 0>;
interrupt-parent = <&mpc5200_pic>;
- has-wdt;
+ fsl,has-wdt;
};
gpt@610 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <1>;
reg = <610 10>;
interrupts = <1 a 0>;
@@ -89,8 +87,7 @@
};
gpt@620 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <2>;
reg = <620 10>;
interrupts = <1 b 0>;
@@ -98,8 +95,7 @@
};
gpt@630 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <3>;
reg = <630 10>;
interrupts = <1 c 0>;
@@ -107,8 +103,7 @@
};
gpt@640 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <4>;
reg = <640 10>;
interrupts = <1 d 0>;
@@ -116,8 +111,7 @@
};
gpt@650 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <5>;
reg = <650 10>;
interrupts = <1 e 0>;
@@ -125,8 +119,7 @@
};
gpt@660 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <6>;
reg = <660 10>;
interrupts = <1 f 0>;
@@ -134,8 +127,7 @@
};
gpt@670 { // General Purpose Timer
- compatible = "mpc5200b-gpt","mpc5200-gpt";
- device_type = "gpt";
+ compatible = "fsl,mpc5200b-gpt","fsl,mpc5200-gpt";
cell-index = <7>;
reg = <670 10>;
interrupts = <1 10 0>;
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 65b7ae4..25d2bfa 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -145,6 +145,9 @@
/* 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 @@
.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 3bc201e..9850685 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 @@
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 @@
"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/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
index 48492a8..740ad73 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -269,6 +269,7 @@
int task;
phys_addr_t tdt_pa, ctx_pa, var_pa, fdt_pa;
unsigned int tdt_size, ctx_size, var_size, fdt_size;
+ u16 regval;
/* Allocate & clear SRAM zones for FDT, TDTs, contexts and vars/incs */
tdt_size = BCOM_MAX_TASKS * sizeof(struct bcom_tdt);
@@ -319,9 +320,11 @@
/* Init 'always' initiator */
out_8(&bcom_eng->regs->ipr[BCOM_INITIATOR_ALWAYS], BCOM_IPR_ALWAYS);
- /* Disable COMM Bus Prefetch, apparently it's not reliable yet */
- /* FIXME: This should be done on 5200 and not 5200B ... */
- out_be16(&bcom_eng->regs->PtdCntrl, in_be16(&bcom_eng->regs->PtdCntrl) | 1);
+ /* Disable COMM Bus Prefetch on the original 5200; it's broken */
+ if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR) {
+ regval = in_be16(&bcom_eng->regs->PtdCntrl);
+ out_be16(&bcom_eng->regs->PtdCntrl, regval | 1);
+ }
/* Init lock */
spin_lock_init(&bcom_eng->lock);
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c
index 9cfb975..11f6a11 100644
--- a/drivers/watchdog/mpc5200_wdt.c
+++ b/drivers/watchdog/mpc5200_wdt.c
@@ -176,6 +176,8 @@
has_wdt = of_get_property(op->node, "has-wdt", NULL);
if (!has_wdt)
+ has_wdt = of_get_property(op->node, "fsl,has-wdt", NULL);
+ if (!has_wdt)
return -ENODEV;
wdt = kzalloc(sizeof(*wdt), GFP_KERNEL);
@@ -254,6 +256,7 @@
static struct of_device_id mpc5200_wdt_match[] = {
{ .compatible = "mpc5200-gpt", },
+ { .compatible = "fsl,mpc5200-gpt", },
{},
};
static struct of_platform_driver mpc5200_wdt_driver = {
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 568135f..fcb2ebb 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -20,6 +20,11 @@
#include <linux/suspend.h>
+/* Variants of the 5200(B) */
+#define MPC5200_SVR 0x80110010
+#define MPC5200_SVR_MASK 0xfffffff0
+#define MPC5200B_SVR 0x80110020
+#define MPC5200B_SVR_MASK 0xfffffff0
/* ======================================================================== */
/* Structures mapping of some unit register set */
@@ -244,6 +249,7 @@
#ifndef __ASSEMBLY__
extern void __iomem * mpc52xx_find_and_map(const char *);
+extern void __iomem * mpc52xx_find_and_map_path(const char *path);
extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
extern void mpc5200_setup_xlb_arbiter(void);
extern void mpc52xx_declare_of_platform_devices(void);
@@ -253,6 +259,9 @@
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