summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/pervasive.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-04 19:22:33 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-04 19:22:33 -0800
commit15a4cb9c25df05a5d4844e80a1aea83d66165868 (patch)
treebcb4f7c6e84f501ee6ce8c7a740cc7c4ec92447d /arch/powerpc/platforms/cell/pervasive.c
parentff51a98799931256b555446b2f5675db08de6229 (diff)
parentd8594d639135b500bf6010f981ea854092d54030 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc
* master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc: (194 commits) [POWERPC] Add missing EXPORTS for mpc52xx support [POWERPC] Remove obsolete PPC_52xx and update CLASSIC32 comment [POWERPC] ps3: add a default zImage target [POWERPC] Add of_platform_bus support to mpc52xx psc uart driver [POWERPC] typo fix and whitespace cleanup on mpc52xx-uart driver [POWERPC] Fix debug printks for 32-bit resources in the PCI code [POWERPC] Replace kmalloc+memset with kzalloc [POWERPC] Linkstation / kurobox support [POWERPC] Add the e300c3 core to the CPU table. [POWERPC] ppc: m48t35 add missing bracket [POWERPC] iSeries: don't build head_64.o unnecessarily [POWERPC] iSeries: stop dt_mod.o being rebuilt unnecessarily [POWERPC] Fix cputable.h for combined build [POWERPC] Allow CONFIG_BOOTX_TEXT on iSeries [POWERPC] Allow xmon to build on legacy iSeries [POWERPC] Change ppc64_defconfig to use AUTOFS_V4 not V3 [POWERPC] Tell firmware we can handle POWER6 compatible mode [POWERPC] Clean images in arch/powerpc/boot [POWERPC] Fix OF pci flags parsing [POWERPC] defconfig for lite5200 board ...
Diffstat (limited to 'arch/powerpc/platforms/cell/pervasive.c')
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c101
1 files changed, 34 insertions, 67 deletions
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 9f2e4ed20a5..8c20f0fb865 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,32 +38,25 @@
#include "pervasive.h"
#include "cbe_regs.h"
-static DEFINE_SPINLOCK(cbe_pervasive_lock);
-
-static void __init cbe_enable_pause_zero(void)
+static void cbe_power_save(void)
{
- unsigned long thread_switch_control;
- unsigned long temp_register;
- struct cbe_pmd_regs __iomem *pregs;
-
- spin_lock_irq(&cbe_pervasive_lock);
- pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
- if (pregs == NULL)
- goto out;
+ unsigned long ctrl, thread_switch_control;
- pr_debug("Power Management: CPU %d\n", smp_processor_id());
-
- /* Enable Pause(0) control bit */
- temp_register = in_be64(&pregs->pm_control);
+ /*
+ * We need to hard disable interrupts, but we also need to mark them
+ * hard disabled in the PACA so that the local_irq_enable() done by
+ * our caller upon return propertly hard enables.
+ */
+ hard_irq_disable();
+ get_paca()->hard_enabled = 0;
- out_be64(&pregs->pm_control,
- temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
+ ctrl = mfspr(SPRN_CTRLF);
/* Enable DEC and EE interrupt request */
thread_switch_control = mfspr(SPRN_TSC_CELL);
thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
- switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) {
+ switch (ctrl & CTRL_CT) {
case CTRL_CT0:
thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
break;
@@ -75,58 +68,21 @@ static void __init cbe_enable_pause_zero(void)
__FUNCTION__);
break;
}
-
mtspr(SPRN_TSC_CELL, thread_switch_control);
-out:
- spin_unlock_irq(&cbe_pervasive_lock);
-}
-
-static void cbe_idle(void)
-{
- unsigned long ctrl;
+ /*
+ * go into low thread priority, medium priority will be
+ * restored for us after wake-up.
+ */
+ HMT_low();
- /* Why do we do that on every idle ? Couldn't that be done once for
- * all or do we lose the state some way ? Also, the pm_control
- * register setting, that can't be set once at boot ? We really want
- * to move that away in order to implement a simple powersave
+ /*
+ * atomically disable thread execution and runlatch.
+ * External and Decrementer exceptions are still handled when the
+ * thread is disabled but now enter in cbe_system_reset_exception()
*/
- cbe_enable_pause_zero();
-
- while (1) {
- if (!need_resched()) {
- local_irq_disable();
- while (!need_resched()) {
- /* go into low thread priority */
- HMT_low();
-
- /*
- * atomically disable thread execution
- * and runlatch.
- * External and Decrementer exceptions
- * are still handled when the thread
- * is disabled but now enter in
- * cbe_system_reset_exception()
- */
- ctrl = mfspr(SPRN_CTRLF);
- ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
- mtspr(SPRN_CTRLT, ctrl);
- }
- /* restore thread prio */
- HMT_medium();
- local_irq_enable();
- }
-
- /*
- * turn runlatch on again before scheduling the
- * process we just woke up
- */
- ppc64_runlatch_on();
-
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
+ ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
+ mtspr(SPRN_CTRLT, ctrl);
}
static int cbe_system_reset_exception(struct pt_regs *regs)
@@ -158,9 +114,20 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
void __init cbe_pervasive_init(void)
{
+ int cpu;
if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
return;
- ppc_md.idle_loop = cbe_idle;
+ for_each_possible_cpu(cpu) {
+ struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
+ if (!regs)
+ continue;
+
+ /* Enable Pause(0) control bit */
+ out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
+ CBE_PMD_PAUSE_ZERO_CONTROL);
+ }
+
+ ppc_md.power_save = cbe_power_save;
ppc_md.system_reset_exception = cbe_system_reset_exception;
}