summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac/smp.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-01-07 11:41:02 +1100
committerPaul Mackerras <paulus@samba.org>2006-01-09 15:47:18 +1100
commit5b9ca526917b7bc7d1da3beaccb2251a8f0b5fe2 (patch)
treef345cbb73a4c5bb4c5645d53df2653c916e54172 /arch/powerpc/platforms/powermac/smp.c
parenta28d3af2a26c89aaa6470ca36edb212e05143d67 (diff)
downloadlinux-5b9ca526917b7bc7d1da3beaccb2251a8f0b5fe2.tar.gz
linux-5b9ca526917b7bc7d1da3beaccb2251a8f0b5fe2.tar.bz2
linux-5b9ca526917b7bc7d1da3beaccb2251a8f0b5fe2.zip
[PATCH] 3/5 powerpc: Add platform functions interpreter
This is the platform function interpreter itself along with the backends for UniN/U3/U4, mac-io, GPIOs and i2c. It adds the ability to execute those do-platform-* scripts in the device-tree (at least for most devices for which a backend is provided). This should replace the clock spreading hacks properly. It might also have an impact on all sort of machines since some of the scripts marked "at init" will now be executed on boot (or some other on sleep/wakeup), those will possibly do things that the kernel didn't do at all, like setting some values into some i2c devices (changing thermal sensor calibration or conversion rate) etc... Thus regression testing is MUCH welcome. Also loook for errors in dmesg. That's also why I've left rather verbose debugging enabled in this version of the patch. (I do expect some Windtunnel G4s to show some errors as they have an i2c clock chip on the PMU bus that uses some primitives that the i2c backend doesn't implement yet. I really need users that have one of those machine to come back to me so we can get that done right, though the errors themselves should be harmless, I suspect the machine might not run at full speed). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac/smp.c')
-rw-r--r--arch/powerpc/platforms/powermac/smp.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index ab72ba86be1e..0df2cdcd805c 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -52,8 +52,9 @@
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
#include <asm/pmac_low_i2c.h>
+#include <asm/pmac_pfunc.h>
-#undef DEBUG
+#define DEBUG
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -62,6 +63,7 @@
#endif
extern void __secondary_start_pmac_0(void);
+extern int pmac_pfunc_base_install(void);
#ifdef CONFIG_PPC32
@@ -602,11 +604,29 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus)
pmac_tb_clock_chip_host = NULL;
}
-#endif /* CONFIG_PPC64 */
/*
- * SMP G4 and newer G5 use a GPIO to enable/disable the timebase.
+ * Newer G5s uses a platform function
+ */
+
+static void smp_core99_pfunc_tb_freeze(int freeze)
+{
+ struct device_node *cpus;
+ struct pmf_args args;
+
+ cpus = of_find_node_by_path("/cpus");
+ BUG_ON(cpus == NULL);
+ args.count = 1;
+ args.u[0].v = !freeze;
+ pmf_call_function(cpus, "cpu-timebase", &args);
+ of_node_put(cpus);
+}
+
+#else /* CONFIG_PPC64 */
+
+/*
+ * SMP G4 use a GPIO to enable/disable the timebase.
*/
static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */
@@ -620,6 +640,9 @@ static void smp_core99_gpio_tb_freeze(int freeze)
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
}
+
+#endif /* !CONFIG_PPC64 */
+
/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
volatile static long int core99_l2_cache;
volatile static long int core99_l3_cache;
@@ -665,19 +688,15 @@ static void __init smp_core99_setup(int ncpus)
machine_is_compatible("RackMac3,1"))
smp_core99_setup_i2c_hwsync(ncpus);
- /* GPIO based HW sync on recent G5s */
+ /* pfunc based HW sync on recent G5s */
if (pmac_tb_freeze == NULL) {
- struct device_node *np =
- of_find_node_by_name(NULL, "timebase-enable");
- u32 *reg = (u32 *)get_property(np, "reg", NULL);
-
- if (np && reg && !strcmp(np->type, "gpio")) {
- core99_tb_gpio = *reg;
- if (core99_tb_gpio < 0x50)
- core99_tb_gpio += 0x50;
- pmac_tb_freeze = smp_core99_gpio_tb_freeze;
+ struct device_node *cpus =
+ of_find_node_by_path("/cpus");
+ if (cpus &&
+ get_property(cpus, "platform-cpu-timebase", NULL)) {
+ pmac_tb_freeze = smp_core99_pfunc_tb_freeze;
printk(KERN_INFO "Processor timebase sync using"
- " GPIO 0x%02x\n", core99_tb_gpio);
+ " platform function\n");
}
}
@@ -746,6 +765,7 @@ static int __init smp_core99_probe(void)
/* We need to perform some early initialisations before we can start
* setting up SMP as we are running before initcalls
*/
+ pmac_pfunc_base_install();
pmac_i2c_init();
/* Setup various bits like timebase sync method, ability to nap, ... */