aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-07-31 13:39:52 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-31 13:39:52 -0700
commit49b1e3ea19b1c95c2f012b8331ffb3b169e4c042 (patch)
tree4ccf519a20c9b5bb3701c8b4d38b01af8bef854e /arch/powerpc/platforms
parentce38cac48209d270d07fd6d1a8e94446b37abcd5 (diff)
parent8d950cb8896fc95a9444d190885779438bb9d01c (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Minor comment fix for misc_64.S [POWERPC] Use H_CEDE on non-SMT [POWERPC] force 64bit mode in fwnmi handlers to workaround firmware bugs [POWERPC] PMAC_APM_EMU should depend on ADB_PMU [POWERPC] Fix new interrupt code (MPIC detection) [POWERPC] Fix new interrupt code (MPIC endianness) [POWERPC] Add cpufreq support for Xserve G5 [POWERPC] Xserve G5 thermal control fixes [POWERPC] Fix mem= handling when the memory limit is > RMO size [POWERPC] More offb/bootx fixes [POWERPC] Fix legacy_serial.c error handling on 32 bits [POWERPC] Fix default clock for udbg_16550 [POWERPC] Fix non-MPIC CHRPs with CONFIG_SMP set [POWERPC] Fix 32 bits warning in prom_init.c [POWERPC] Workaround Pegasos incorrect ISA "ranges" [POWERPC] fix up front-LED Kconfig
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/chrp/setup.c12
-rw-r--r--arch/powerpc/platforms/maple/setup.c17
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c35
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c78
-rw-r--r--arch/powerpc/platforms/pseries/setup.c6
5 files changed, 98 insertions, 50 deletions
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 538e337d63e..9c08ff32229 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -291,10 +291,6 @@ void __init chrp_setup_arch(void)
pci_create_OF_bus_map();
-#ifdef CONFIG_SMP
- smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
/*
* Print the banner, then scroll down so boot progress
* can be printed. -- Cort
@@ -479,6 +475,14 @@ void __init chrp_init_IRQ(void)
chrp_find_openpic();
chrp_find_8259();
+#ifdef CONFIG_SMP
+ /* Pegasos has no MPIC, those ops would make it crash. It might be an
+ * option to move setting them to after we probe the PIC though
+ */
+ if (chrp_mpic != NULL)
+ smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
if (_chrp_type == _CHRP_Pegasos)
ppc_md.get_irq = i8259_irq;
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index cb528c9de4c..57567dfb981 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -221,10 +221,17 @@ static void __init maple_init_IRQ(void)
* in Maple device-tree where the type of the controller is
* open-pic and not interrupt-controller
*/
- for_each_node_by_type(np, "open-pic") {
- mpic_node = np;
- break;
- }
+
+ for_each_node_by_type(np, "interrupt-controller")
+ if (device_is_compatible(np, "open-pic")) {
+ mpic_node = np;
+ break;
+ }
+ if (mpic_node == NULL)
+ for_each_node_by_type(np, "open-pic") {
+ mpic_node = np;
+ break;
+ }
if (mpic_node == NULL) {
printk(KERN_ERR
"Failed to locate the MPIC interrupt controller\n");
@@ -252,6 +259,8 @@ static void __init maple_init_IRQ(void)
/* XXX Maple specific bits */
flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+ /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
+ flags |= MPIC_BIG_ENDIAN;
/* Setup the openpic driver. More device-tree junks, we hard code no
* ISUs for now. I'll have to revisit some stuffs with the folks doing
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index 871b002c9f9..6a026c733f6 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -181,13 +181,18 @@ static void __init bootx_add_chosen_props(unsigned long base,
}
static void __init bootx_add_display_props(unsigned long base,
- unsigned long *mem_end)
+ unsigned long *mem_end,
+ int has_real_node)
{
boot_infos_t *bi = bootx_info;
u32 tmp;
- bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
- bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+ if (has_real_node) {
+ bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
+ bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+ } else
+ bootx_dt_add_prop("linux,bootx-noscreen", NULL, 0, mem_end);
+
tmp = bi->dispDeviceDepth;
bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end);
tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0];
@@ -241,11 +246,6 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
DBG(" detected display ! adding properties names !\n");
bootx_dt_add_string("linux,boot-display", mem_end);
bootx_dt_add_string("linux,opened", mem_end);
- bootx_dt_add_string("linux,bootx-depth", mem_end);
- bootx_dt_add_string("linux,bootx-width", mem_end);
- bootx_dt_add_string("linux,bootx-height", mem_end);
- bootx_dt_add_string("linux,bootx-linebytes", mem_end);
- bootx_dt_add_string("linux,bootx-addr", mem_end);
strncpy(bootx_disp_path, namep, 255);
}
@@ -329,10 +329,13 @@ static void __init bootx_scan_dt_build_struct(unsigned long base,
ppp = &pp->next;
}
- if (node == bootx_node_chosen)
+ if (node == bootx_node_chosen) {
bootx_add_chosen_props(base, mem_end);
- if (node == bootx_info->dispDeviceRegEntryOffset)
- bootx_add_display_props(base, mem_end);
+ if (bootx_info->dispDeviceRegEntryOffset == 0)
+ bootx_add_display_props(base, mem_end, 0);
+ }
+ else if (node == bootx_info->dispDeviceRegEntryOffset)
+ bootx_add_display_props(base, mem_end, 1);
/* do all our children */
cpp = &np->child;
@@ -374,6 +377,14 @@ static unsigned long __init bootx_flatten_dt(unsigned long start)
mem_end += 4;
bootx_dt_strend = mem_end;
bootx_scan_dt_build_strings(base, 4, &mem_end);
+ /* Add some strings */
+ bootx_dt_add_string("linux,bootx-noscreen", &mem_end);
+ bootx_dt_add_string("linux,bootx-depth", &mem_end);
+ bootx_dt_add_string("linux,bootx-width", &mem_end);
+ bootx_dt_add_string("linux,bootx-height", &mem_end);
+ bootx_dt_add_string("linux,bootx-linebytes", &mem_end);
+ bootx_dt_add_string("linux,bootx-addr", &mem_end);
+ /* Wrap up strings */
hdr->off_dt_strings = bootx_dt_strbase - mem_start;
hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase;
@@ -471,6 +482,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
if (bi->dispDeviceDepth == 16)
bi->dispDeviceDepth = 15;
+
#ifdef CONFIG_BOOTX_TEXT
ptr = (unsigned long)bi->logicalDisplayBase;
ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
@@ -508,6 +520,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
#ifdef CONFIG_BOOTX_TEXT
btext_welcome(bi);
#endif
+
/* New BootX enters kernel with MMU off, i/os are not allowed
* here. This hack will have been done by the boostrap anyway.
*/
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index f08a1451613..7b1156ea534 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -10,6 +10,8 @@
* that is iMac G5 and latest single CPU desktop.
*/
+#undef DEBUG
+
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
@@ -30,13 +32,7 @@
#include <asm/smu.h>
#include <asm/pmac_pfunc.h>
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#define DBG(fmt...) pr_debug(fmt)
/* see 970FX user manual */
@@ -82,8 +78,6 @@ static struct freq_attr* g5_cpu_freqs_attr[] = {
/* Power mode data is an array of the 32 bits PCR values to use for
* the various frequencies, retrieved from the device-tree
*/
-static u32 *g5_pmode_data;
-static int g5_pmode_max;
static int g5_pmode_cur;
static void (*g5_switch_volt)(int speed_mode);
@@ -93,6 +87,11 @@ static int (*g5_query_freq)(void);
static DEFINE_MUTEX(g5_switch_mutex);
+#ifdef CONFIG_PMAC_SMU
+
+static u32 *g5_pmode_data;
+static int g5_pmode_max;
+
static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */
static int g5_fvt_count; /* number of op. points */
static int g5_fvt_cur; /* current op. point */
@@ -210,6 +209,16 @@ static int g5_scom_query_freq(void)
}
/*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+#endif /* CONFIG_PMAC_SMU */
+
+/*
* Platform function based voltage switching for PowerMac7,2 & 7,3
*/
@@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode)
struct pmf_args args;
u32 done = 0;
unsigned long timeout;
+ int rc;
+
+ DBG("g5_pfunc_switch_freq(%d)\n", speed_mode);
/* If frequency is going up, first ramp up the voltage */
if (speed_mode < g5_pmode_cur)
@@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode)
/* Do it */
if (speed_mode == CPUFREQ_HIGH)
- pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+ rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
else
- pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+ rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+ if (rc)
+ printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
/* It's an irq GPIO so we should be able to just block here,
* I'll do that later after I've properly tested the IRQ code for
@@ -296,13 +311,6 @@ static int g5_pfunc_query_freq(void)
return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
}
-/*
- * Fake voltage switching for platforms with missing support
- */
-
-static void g5_dummy_switch_volt(int speed_mode)
-{
-}
/*
* Common interface to the cpufreq core
@@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = {
};
+#ifdef CONFIG_PMAC_SMU
+
static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
{
struct device_node *cpunode;
@@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
return rc;
}
+#endif /* CONFIG_PMAC_SMU */
+
+
static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
{
struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
@@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
u64 max_freq, min_freq, ih, il;
int has_volt = 1, rc = 0;
+ DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
+ " RackMac3,1...\n");
+
/* Get first CPU node */
for (cpunode = NULL;
(cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
@@ -636,6 +652,15 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
*/
ih = *((u32 *)(eeprom + 0x10));
il = *((u32 *)(eeprom + 0x20));
+
+ /* Check for machines with no useful settings */
+ if (il == ih) {
+ printk(KERN_WARNING "cpufreq: No low frequency mode available"
+ " on this model !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
min_freq = 0;
if (ih != 0 && il != 0)
min_freq = (max_freq * il) / ih;
@@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
/* Sanity check */
if (min_freq >= max_freq || min_freq < 1000) {
printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
- rc = -ENODEV;
+ rc = -ENXIO;
goto bail;
}
g5_cpu_freqs[0].frequency = max_freq;
@@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
return rc;
}
-static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
-{
- /* NYI */
- return 0;
-}
-
static int __init g5_cpufreq_init(void)
{
struct device_node *cpus;
- int rc;
+ int rc = 0;
cpus = of_find_node_by_path("/cpus");
if (cpus == NULL) {
@@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void)
}
if (machine_is_compatible("PowerMac7,2") ||
- machine_is_compatible("PowerMac7,3"))
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
rc = g5_pm72_cpufreq_init(cpus);
- else if (machine_is_compatible("RackMac3,1"))
- rc = g5_rm31_cpufreq_init(cpus);
+#ifdef CONFIG_PMAC_SMU
else
rc = g5_neo2_cpufreq_init(cpus);
+#endif /* CONFIG_PMAC_SMU */
of_node_put(cpus);
return rc;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 54a52437265..71c634e0b87 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -501,7 +501,8 @@ static void pseries_dedicated_idle_sleep(void)
}
/*
- * Cede if the other thread is not idle, so that it can
+ * If not SMT, cede processor. If CPU is running SMT
+ * cede if the other thread is not idle, so that it can
* go single-threaded. If the other thread is idle,
* we ask the hypervisor if it has pending work it
* wants to do and cede if it does. Otherwise we keep
@@ -514,7 +515,8 @@ static void pseries_dedicated_idle_sleep(void)
* very low priority. The cede enables interrupts, which
* doesn't matter here.
*/
- if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+ if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
+ || poll_pending() == H_PENDING)
cede_processor();
out: