diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2008-02-15 17:33:52 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2008-02-15 17:33:52 +0000 |
commit | b5174efd7ebd1275b5c3a617479f985e029b1c24 (patch) | |
tree | ee5bb8636d8f98e631964a4fb7220192de58e2d9 /sys | |
parent | 3ef5d239792f55f60b07a3c528e30d23068187b9 (diff) |
Reenable idle modes on powerpc. Tested by kettenis and myself.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/macppc/macppc/cpu.c | 17 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/locore.S | 75 |
2 files changed, 79 insertions, 13 deletions
diff --git a/sys/arch/macppc/macppc/cpu.c b/sys/arch/macppc/macppc/cpu.c index 9b2aa5676cc..f8dba0689a6 100644 --- a/sys/arch/macppc/macppc/cpu.c +++ b/sys/arch/macppc/macppc/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.45 2007/12/04 22:36:39 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.46 2008/02/15 17:33:51 drahn Exp $ */ /* * Copyright (c) 1997 Per Fogelstrom @@ -55,6 +55,7 @@ #define HID0_LRSTK (1 << (31-27)) #define HID0_FOLD (1 << (31-28)) #define HID0_BHT (1 << (31-29)) +extern u_int32_t hid0_idle; /* SCOM addresses (24-bit) */ #define SCOM_PCR 0x0aa001 /* Power Control Register */ @@ -376,16 +377,18 @@ cpuattach(struct device *parent, struct device *dev, void *aux) case PPC_CPU_IBM750FX: case PPC_CPU_MPC7410: /* select DOZE mode */ - hid0 &= ~(HID0_NAP | HID0_SLEEP); - hid0 |= HID0_DOZE | HID0_DPM; + hid0 &= ~(HID0_NAP | HID0_DOZE | HID0_SLEEP); + hid0_idle = HID0_DOZE; + hid0 |= HID0_DPM; break; case PPC_CPU_MPC7447A: case PPC_CPU_MPC7450: case PPC_CPU_MPC7455: case PPC_CPU_MPC7457: /* select NAP mode */ - hid0 &= ~(HID0_DOZE | HID0_SLEEP); - hid0 |= HID0_NAP | HID0_DPM; + hid0 &= ~(HID0_NAP | HID0_DOZE | HID0_SLEEP); + hid0_idle = HID0_NAP; + hid0 |= HID0_DPM; /* try some other flags */ hid0 |= HID0_SGE | HID0_BTIC; hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; @@ -395,8 +398,8 @@ cpuattach(struct device *parent, struct device *dev, void *aux) break; case PPC_CPU_IBM970FX: /* select NAP mode */ - hid0 &= ~(HID0_DOZE | HID0_SLEEP); - hid0 |= HID0_NAP | HID0_DPM; + hid0 &= ~(HID0_NAP | HID0_DOZE | HID0_SLEEP); + hid0 |= HID0_DPM; break; } if (ppc_proc_is_64b == 0) diff --git a/sys/arch/macppc/macppc/locore.S b/sys/arch/macppc/macppc/locore.S index eeb12cc195d..04e3fe67283 100644 --- a/sys/arch/macppc/macppc/locore.S +++ b/sys/arch/macppc/macppc/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.35 2007/12/04 22:36:39 kettenis Exp $ */ +/* $OpenBSD: locore.S,v 1.36 2008/02/15 17:33:51 drahn Exp $ */ /* $NetBSD: locore.S,v 1.2 1996/10/16 19:33:09 ws Exp $ */ /* @@ -60,6 +60,9 @@ fwargsave: .long 0 .long 0 + .globl _C_LABEL(hid0_idle), + .type _C_LABEL(hid0_idle),@object +_C_LABEL(hid0_idle): .long 0 /* hid0 bits to set on idle, DOZE/NAP * /* * Startup entry */ @@ -215,19 +218,66 @@ switch_exited: blr _ENTRY(_C_LABEL(cpu_idle_enter)) + /* must disable external interrupts during idle queue checking */ + mfmsr %r3 + andi. %r3,%r3,~PSL_EE@l + mtmsr %r3 blr _ENTRY(_C_LABEL(cpu_idle_cycle)) -#if 0 - /* low power mode */ + /* + * interrupts were disabled in cpu_idle_enter, but must be enabled + * for sleeping + */ + lis %r4, _C_LABEL(hid0_idle)@ha + lwz %r4, _C_LABEL(hid0_idle)@l(%r4) mfmsr %r3 - oris %r3, %r3, PSL_POW@h - mtmsr %r3 + //* if hid0_idle is 0, no low power */ + cmpwi %r4, 0 + beq idledone + /* set HID0_(HID|NAP|DOZ) as appropriate in hid0 */ + mfspr %r5, 1008 + or %r5, %r5, %r4 + mtspr 1008, %r5 isync -#endif + /* enable interrupts, required before setting POW */ + ori %r5,%r3,PSL_EE@l + mtmsr %r5 + oris %r5, %r5, PSL_POW@h + sync + /* low power mode */ + mtmsr %r5 + sync + isync + + /* + * restore interrupts to disabled, so hid0 is only modified with + * interrupts disabled. + */ + mtmsr %r3 + isync + + /* clear HID0_(HID|NAP|DOZ) since sleeping is over */ + mfspr %r5, 1008 + andc %r5, %r5, %r4 + mtspr 1008, %r5 +idledone: + /* + * enable interrupts for a small window here to catch machines + * that do not have any sleep mode + */ + ori %r5,%r3,PSL_EE@l + mtmsr %r5 + isync + mtmsr %r3 blr + _ENTRY(_C_LABEL(cpu_idle_leave)) + /* enable interrupts disabled in cpu_idle_enter. */ + mfmsr %r3 + ori %r3,%r3,PSL_EE@l + mtmsr %r3 blr /* @@ -684,6 +734,18 @@ nop32_7e: _C_LABEL(ddbsize) = .-_C_LABEL(ddblow) #endif /* DDB */ +#define HID_IDLE_CHECK(sr1,sr2,sr3,rSRR0) \ + /* detect if interrupt occurred from idle */ \ + mfspr sr1, 1008; \ + lis sr2,_C_LABEL(hid0_idle)@ha; \ + lwz sr2,_C_LABEL(hid0_idle)@l(sr2); \ + and. sr3,sr1,sr2; \ + andc sr1,sr1,sr2; \ + beq+ 1f; \ + mtspr 1008, sr1; \ + lis rSRR0,_C_LABEL(idledone)@ha; \ + addi rSRR0,rSRR0,_C_LABEL(idledone)@l; \ +1: /* * FRAME_SETUP assumes: @@ -745,6 +807,7 @@ _C_LABEL(ddbsize) = .-_C_LABEL(ddblow) stw %r5,FRAME_EXC+8(%r1); \ stw %r28,FRAME_DAR+8(%r1); \ stw %r29,FRAME_DSISR+8(%r1); \ + HID_IDLE_CHECK(%r5,%r6,%r0,%r30) \ stw %r30,FRAME_SRR0+8(%r1); \ stw %r31,FRAME_SRR1+8(%r1) |