2012/5/3 Neil Zhang <zhangwm@xxxxxxxxxxx>: > From: Wenzeng Chen <wzch@xxxxxxxxxxx> > > VPF/CPU mode/CP15 saved and restored by open source code > L2$ controller/debug register/performance monitor saved > and restored by our own code. > > Change-Id: I5bd5209d1ca6ca79e9bba30c48b677934fd5f205 > Signed-off-by: Wenzeng Chen <wzch@xxxxxxxxxxx> > --- > arch/arm/mach-pxa/ca9_asm.S | 541 ++++------------------------ > arch/arm/mach-pxa/cmd_ca9_idle.c | 79 +++-- > arch/arm/mach-pxa/dvfm.c | 3 - > arch/arm/mach-pxa/include/mach/ca9_asm.h | 12 +- > arch/arm/mach-pxa/include/mach/ca9_regs.h | 82 ----- > arch/arm/mach-pxa/include/mach/pxa95x_pm.h | 10 +- > arch/arm/mach-pxa/mspm_idle.c | 8 +- > arch/arm/mach-pxa/pxa95x_pm.c | 27 +- > 8 files changed, 142 insertions(+), 620 deletions(-) > delete mode 100644 arch/arm/mach-pxa/include/mach/ca9_regs.h > > diff --git a/arch/arm/mach-pxa/ca9_asm.S b/arch/arm/mach-pxa/ca9_asm.S > index 62bad28..dc74715 100644 > --- a/arch/arm/mach-pxa/ca9_asm.S > +++ b/arch/arm/mach-pxa/ca9_asm.S > @@ -1,15 +1,8 @@ > -#define PWRMODE_REG 0x40f40080 > - > -#define mode_usr 0x10 > -#define mode_fiq 0x11 > -#define mode_irq 0x12 > -#define mode_svc 0x13 > -#define mode_abt 0x17 > -#define mode_und 0x1b > -#define mode_sys 0x1f > - > - > - > +#include <asm/hardware/cache-l2x0.h> > +#define PXA978_L2CACHE_BASE 0x58120000 > +#define OSCR_PHY_ADDR 0x40A00010 > +#define OSCR_VIRTUAL_ADDR 0xF2A00010 > +#define POWER_MODE_BASE 0x40F40080 > .global dump_cop_regs > dump_cop_regs: > stmfd sp!, {r4-r12,lr} > @@ -68,137 +61,18 @@ dump_cop_regs: > > ldmfd sp!,{r4-r12,pc} > > - .global save_pl310 > -save_pl310: > - stmfd sp!, {r4-r12,lr} @r0 context, r1 pl310 virtual address > - ldr r2, [r1, #0x100] @ control > - str r2, [r0] > - ldr r2, [r1, #0x104] @aux_control > - str r2, [r0, #4] > - ldr r2, [r1, #0x108] @tag_ram_control > - str r2, [r0, #8] > - ldr r2, [r1, #0x10C] @data_ram_control > - str r2, [r0, #12] > - ldr r2, [r1, #0x200] @ev_counter_ctrl > - str r2, [r0, #16] > - ldr r2, [r1, #0x204] @ev_counter1_cfg > - str r2, [r0, #20] > - ldr r2, [r1, #0x208] @ev_counter0_cfg > - str r2, [r0, #24] > - ldr r2, [r1, #0x20C] @ev_counter1 > - str r2, [r0, #28] > - ldr r2, [r1, #0x210] @ev_counter0 > - str r2, [r0, #32] > - ldr r2, [r1, #0x214] @int_mask > - str r2, [r0, #36] > - ldr r2, [r1, #0x950] @lock_line_en > - str r2, [r0, #40] > - > - mov r2, r0 > - mov r3, #0 > -LOOP1: > - add r4, r3, #288 @lockdown_reg > - add r3, r3, #1 > - cmp r3, #8 > - add r5, r1,r4, lsl #3 > - ldr r6, [r5] > - ldr r4, [r5, #4] > - str r6, [r2, #44] > - str r4, [r2, #48] > - add r2, r2,#8 > - bne LOOP1 > - ldr r2, [r1, #0xF40] @debug_ctrl > - str r2, [r0, #120] > - ldr r2, [r1, #0xF60] @prefetch_ctrl > - str r2, [r0, #124] > - ldr r2, [r1, #0xF80] @power_ctrl > - str r2, [r0, #128] > - add r1, r0, #132 @ the size of pl310_context > - @.extern flushL2VaRange @ we call clean all before WFI, so this one is uncessary > - @bl flushL2VaRange > - ldmfd sp!, {r4-r12,pc} > - > - .global restore_pl310 > -restore_pl310: > - @r0 context, r1 pl310 virtual address > - ldr r3, [r1, #0x100] @control > - cmp r3, #0 > - beq restore_reg > - mov r3, #0 > - str r3, [r1, #0x730] @cache sync > + .global pxa978_enter_c1 > +pxa978_enter_c1: > dsb > - str r3, [r1, #0x100] @control > -restore_reg: > - ldr r3, [r0, #4] @aux control > - str r3, [r1, #0x104] > - ldr r3, [r0, #8] @tag_ram_control > - str r3, [r1, #0x108] > - ldr r3, [r0, #12] @data_ram_control > - str r3, [r1, #0x10C] > - ldr r3, [r0, #16] @ev_counter_ctrl > - str r3, [r1, #0x200] > - ldr r3, [r0, #20] @ev_counter1_cfg > - str r3, [r1, #0x204] > - ldr r3, [r0, #24] @ev_counter0_cfg > - str r3, [r1, #0x208] > - ldr r3, [r0, #28] @ev_counter1 > - str r3, [r1, #0x20C] > - ldr r3, [r0, #32] @ev_counter0 > - str r3, [r1, #0x210] > - ldr r3, [r0, #36] @int_mask > - str r3, [r1, #0x214] > - ldr r3, [r0, #40] @lock_line_en > - str r3, [r1, #0x950] > - mov r3, #0 > - mov r5, r0 > -LOOP2: > - add r4, r3, #288 @lockdown_reg > - ldr r6, [r5, #44] > - ldr r7, [r5, #48] > - add r3, r3, #1 > - add r8, r1, r4, lsl #3 > - cmp r3, #8 > - str r6, [r8] > - str r7, [r8, #4] > - add r5, r5, #8 > - bne LOOP2 > - ldr r3, [r0, #120] @debug_ctrl > - str r3, [r1, #0xF40] > - ldr r3, [r0, #124] @prefetch_ctrl > - str r3, [r1, #0xF60] > - ldr r3, [r0, #128] @power_ctrl > - str r3, [r1, #0xF80] > - dsb > - mov r4, r0 > - mov r5, r1 > - cmp r2, #0 > - .extern invalidL2All > - blne invalidL2All > - ldr r3, [r4] > - str r3, [r5, #0x100] > - dsb > - pop {r4-r12,pc} > - > - .global ca9_enter_c2_wrapper > -ca9_enter_c2_wrapper: > - push {r4-r12,lr} > - mov r4,r0 > - mov r5,r1 > - mov r6,r2 > - mov r7,r3 > - bl save_pl310 > - mov r0, r7 > - bl ca9_enter_c2 > - mov r0, r4 > - mov r1, r5 > - mov r2, r6 > - b restore_pl310 > - > - .global ca9_enter_c2 > -ca9_enter_c2: > - stmfd sp!, {r4-r12,lr} > - @ align: [13..0]=0 > + wfi > + bx lr > > + .global pxa978_cpu_suspend > +pxa978_cpu_suspend: > + cmp r2, #0x0 > + beq pxa978_enter_c1 > + mov r6, r1 @l2c base address virtual > + mov r7, r3 @PWR_MODE > mov r2, r0, lsr #14 > mov r2, r2, lsl #14 > @ copy reset handler to SRAM > @@ -206,262 +80,75 @@ ca9_enter_c2: > ldrd r0, [r3] > strd r0, [r2] > > - adr r0, ca9_c2_restore > - bl VirtualToPhysical @ modified r0,r1 > + adr r0, pxa978_c2_restore > + bl VirtualToPhysical @ modified r0,r1 > str r0, [r2, #0x08] > > add r0, r2, #0x10 > mov r5, r0 > - bl VirtualToPhysical @ modified r0,r1 > + bl VirtualToPhysical @ modified r0,r1 > str r0, [r2, #0x0c] > mov r0, r5 > - > -@ Save CPU registers > - cps #mode_abt > - mrs r1, spsr > - stm r0!,{r1,sp,lr} > - cps #mode_und > - mrs r1, spsr > - stm r0!,{r1,sp,lr} > - cps #mode_sys > - stm r0!,{sp,lr} > - cps #mode_irq > - mrs r1, spsr > - stm r0!,{r1,sp,lr} > - cps #mode_fiq > - mrs r1, spsr > - stm r0!,{r1,r8-r12,sp,lr} > - cps #mode_svc > - mrs r1,spsr > - stm r0!,{r1,sp} @ others will be restored from stack when exiting > - bic r1, r1, #0x1f @ clear mode > - orr r1, r1, #mode_usr > - msr spsr, r1 > - stm r0,{sp,lr}^ @ fetch user mode regs as spsr is set to user mode > - add r0,r0,#8 @ Cannot use base register update in stm above > - @ don't restore svc mode spsr as we won't need it until restored later > -@ Save cp15 > - mrc p15,2,r1,c0,c0,0 @ CSSELR > - mrc p15,0,r2,c1,c0,1 @ ACTLR > - mrc p15,0,r3,c1,c0,0 @ SCTLR > - mrc p15,0,r4,c1,c0,2 @ CPACR > - stm r0!, {r1-r4} > - > - mrc p15,0,r1,c1,c0,0 @ SCTLR disable L1 cache > - bic r1, r1, #0x1000 > - bic r1, r1, #0x0004 > - mcr p15,0,r1,c1,c0,0 > - > - mrc p15,0,r1,c12,c0,0 @ VBAR > - mrc p15,0,r2,c2,c0,0 @ TTBR0 > - mrc p15,0,r3,c2,c0,1 @ TTBR1 > - mrc p15,0,r4,c2,c0,2 @ TTBCR > - stm r0!, {r1-r4} > - > - mrc p15,0,r1,c3,c0,0 @ DACR > - mrc p15,0,r2,c7,c4,0 @ PAR > - mrc p15,0,r3,c10,c2,0 @ PRRR > - mrc p15,0,r4,c10,c2,1 @ NMRR > - stm r0!, {r1-r4} > - > - @ TBD: CP15 registers 9 and 11 > - mrc p15,0,r1,c13,c0,1 @ CONTEXTIDR > - mrc p15,0,r2,c13,c0,2 @ TPIDRURW > - mrc p15,0,r3,c13,c0,3 @ TPIDRURO > - mrc p15,0,r4,c13,c0,4 @ TPIDRPRW > - stm r0!, {r1-r4} > - > - @ Adding new coop regs ASTODO > - mrc p15,0,r1,c12,c0,1 @ MVBAR > - mrc p15,5,r2,c15,c5,2 @ Main TLB VA register > - mrc p15,5,r3,c15,c6,2 @ Main TLB PA register > - mrc p15,5,r4,c15,c7,2 @ Main TLB Attribute > - stm r0!, {r1-r4} > - > - @ Adding new coop regs ASTODO > - mrc p15,0,r1,c1,c1,0 @ SCRd > - mrc p15,0,r2,c1,c1,1 @ SDERc > - mrc p15,0,r3,c1,c1,2 @ NSACR > - mrc p15,0,r4,c1,c1,3 @ VCR > - stm r0!, {r1-r4} > - > - @ Adding new coop regs ASTODO > - mrc p15,0,r1,c10,c0,0 @ TLB Lockdown Register > - mrc p15,0,r2,c12,c1,1 @ Virtualization Interrupt Register > - mrc p15,0,r3,c13,c0,0 @ FCSEIDR > - mrc p15,0,r4,c13,c0,1 @ CONTEXTIDR > - stm r0!, {r1-r4} > - > - mrc p15,0,r1,c15,c0,0 @ power control reg > - str r1, [r0], #4 > - mrc p15,0,r1,c0,c0,0 @ Read Main ID Register > - ubfx r1, r1, #20, #4 @ Extract major version number > - cmp r3, #2 > - blt savenople @ PLE only possible in r2p0 onwards > - mrc p15,0,r1,c11,c0,0 @ Read PLE IDR > - cmp r3, #0 > - beq savenople @ No PLE present > - > - mrc p15,0,r1,c11,c1,0 @ Read PLE UAR > - mrc p15,0,r2,c11,c1,1 @ Read PLE PCR > - stm r0!, {r1, r2} > -savenople: > -@ Clean and invalidate L1 D-cache: this does not survive C2 > -@ .extern cleanAndInvalidateCache > -@ bl cleanAndInvalidateCache > - > -@ v7_flush_dcache_all corrupts r0-r7, r9-r11 > - .extern v7_flush_dcache_all > - push {r0-r7,r9-r11} > - bl v7_flush_dcache_all > - pop {r0-r7,r9-r11} > - > - .extern v7_flush_icache_all > - bl v7_flush_icache_all > - @ Clean L2 areas that will be used on restore before L2 is reenabled > - @mov r0, sp > - @add r1, r0, #0x40 @ actually 9 regs saved on stack > - @.extern flushL2VaRange > - @bl flushL2VaRange > - @mmu page table may in L2 cache, it is diffcult to get page table addr > - @so we clean all L2 cache as a temp WR > - .extern cleanL2VaRange > - bl cleanL2VaRange > -@ C2 entry > +save_pl310: > + ldr r1, [r6, #L2X0_CTRL] > + ldr r2, [r6, #L2X0_AUX_CTRL] > + ldr r3, [r6, #L2X0_TAG_LATENCY_CTRL] > + ldr r4, [r6, #L2X0_DATA_LATENCY_CTRL] > + stm r0!,{r1-r4} > + ldr r1, [r6, #L2X0_PREFETCH_CTRL] > + ldr r2, [r6, #L2X0_POWER_CTRL] > + stm r0!,{r1-r2} > +/*C2 entry*/ > dsb > wfi > -@ in case a wakeup is pending, CPU will fall through without being reset! > +/*in case a wakeup is pending, CPU will fall through without being reset!*/ > .align 5 > - mov r0, r5 @ setup the saved register base and restore as usual > - ldr r8, =0xf2e0011c > - mov r9, #0x2000 > - str r9, [r8] > - mov r5, #0x1 > + mov r0, r5 @ setup the saved register base and restore as usual > + ldr r1, =OSCR_VIRTUAL_ADDR > b set_l2_redundency > -@ return here from reset chunk > -ca9_c2_restore: > +/*return here from reset chunk*/ > +pxa978_c2_restore: > + ldr r6, =PXA978_L2CACHE_BASE > + ldr r1, =OSCR_PHY_ADDR > + ldr r2, =POWER_MODE_BASE > + ldr r7, [r2] > + and r7, r7, #0x40 > set_l2_redundency: > -@ mov r2, #0xC3 @60usec > + mov r2, #0xC3 @60usec > @ mov r2, #0x140 > -@ orr r2, #0x5 @100usec > - mov r2, #0x790 > - orr r2, #0xE @600usec > - > - cmp r5, #0x1 > - bne no_mmu > - ldr r1,=0xf2a00010 > +@ orr r2, #0x5 @100usec > +@ mov r2, #0x790 > +@ orr r2, #0xE @600usec > ldr r3, [r1] > - b loop > - > -no_mmu: > - ldr r1,=0x40a00010 > - ldr r3, [r1] > - b loop > loop: > ldr r4, [r1] > sub r4, r4, r3 > cmp r4, r2 > ble loop > - cps #mode_abt > - ldm r0!,{r1,sp,lr} > - msr spsr, r1 > - cps #mode_und > - ldm r0!,{r1,sp,lr} > - msr spsr, r1 > - cps #mode_sys > - ldm r0!,{sp,lr} > - msr spsr, r1 > - cps #mode_irq > - ldm r0!,{r1,sp,lr} > - msr spsr, r1 > - cps #mode_fiq > - ldm r0!,{r1,r8-r12,sp,lr} > - msr spsr, r1 > - cps #mode_svc > - ldm r0!,{r1,sp} @ others will be restored from stack when exiting > - mov r2, r1 > - bic r1, r1, #0x1f @ clear mode > - orr r1, r1, #mode_usr > - msr spsr, r1 > - ldm r0,{sp,lr}^ @ set user mode regs as spsr is set to user mode > - add r0,r0,#8 @ cannot use base register update in ldm above > - msr spsr, r2 @ now restore the svc mode spsr > -@ Restore cp15 > - ldm r0!, {r1-r4} > - mcr p15,2,r1,c0,c0,0 @ CSSELR > - mcr p15,0,r2,c1,c0,1 @ ACTLR > - @ mcr p15,0,r3,c1,c0,0 @ SCTLR > - mov r5, r3 @ keep until ready to enable MMU > - mcr p15,0,r4,c1,c0,2 @ CPACR > - > - ldm r0!, {r1-r4} > - mcr p15,0,r1,c12,c0,0 @ VBAR > - mcr p15,0,r2,c2,c0,0 @ TTBR0 > - mcr p15,0,r3,c2,c0,1 @ TTBR1 > - mcr p15,0,r4,c2,c0,2 @ TTBCR > - > - ldm r0!, {r1-r4} > - mcr p15,0,r1,c3,c0,0 @ DACR > - mcr p15,0,r2,c7,c4,0 @ PAR > - mcr p15,0,r3,c10,c2,0 @ PRRR > - mcr p15,0,r4,c10,c2,1 @ NMRR > - > - @ TBD: CP15 registers 9 and 11 > - ldm r0!, {r1-r4} > - mcr p15,0,r1,c13,c0,1 @ CONTEXTIDR > - mcr p15,0,r2,c13,c0,2 @ TPIDRURW > - mcr p15,0,r3,c13,c0,3 @ TPIDRURO > - mcr p15,0,r4,c13,c0,4 @ TPIDRPRW > - > - @ Adding new coop regs ASTODO > - ldm r0!, {r1-r4} > - mcr p15,0,r1,c12,c0,1 @ MVBAR > - mcr p15,5,r2,c15,c5,2 @ Main TLB VA register > - mcr p15,5,r3,c15,c6,2 @ Main TLB PA register > - mcr p15,5,r4,c15,c7,2 @ Main TLB Attribute > - > - @ Adding new coop regs ASTODO > - ldm r0!, {r1-r4} > - mcr p15,0,r1,c1,c1,0 @ SCRd > - mcr p15,0,r2,c1,c1,1 @ SDERc > - mcr p15,0,r3,c1,c1,2 @ NSACR > - mcr p15,0,r4,c1,c1,3 @ VCR > - > - @ Adding new coop regs ASTODO > - ldm r0!, {r1-r4} > - mrc p15,0,r1,c10,c0,0 @ TLB Lockdown Register > - mrc p15,0,r2,c12,c1,1 @ Virtualization Interrupt Register > - mrc p15,0,r3,c13,c0,0 @ FCSEIDR > - mrc p15,0,r4,c13,c0,1 @ CONTEXTIDR > - > - @ others > - ldr r1, [r0], #4 > - mcr p15,0,r1,c15,c0,0 @ power control reg > - mrc p15,0,r1,c0,c0,0 @ Read Main ID Register > - ubfx r1, r1, #20, #4 @ Extract major version number > - cmp r3, #2 > - blt restorenople @ PLE only possible in r2p0 onwards > - mrc p15,0,r1,c11,c0,0 @ Read PLE IDR > - cmp r3, #0 > - beq restorenople @ No PLE present > - > - ldm r0!, {r1, r2} > - mcr p15,0,r1,c11,c1,0 @ set PLE UAR > - mcr p15,0,r2,c11,c1,1 @ set PLE PCR > -restorenople: > - @ Enable MMU now > - ldr r0, return_addr @ this addr is with MMU on > - b cont > -.align 5 > -cont: > - mcr p15,0,r5,c1,c0,0 @ SCTLR > - bx r0 > -return_on_exit: > - ldmfd sp!,{r4-r12,pc} > -return_addr: > - .long return_on_exit > - > -@ reset handler for C2 exit > + cmp r7, #0 > + beq restore_pl310 > +pl310_inv_all: > + mov r1, #0xFF > + str r1, [r6, #L2X0_INV_WAY] > +inv_wait: > + ldr r2, [r6,#L2X0_INV_WAY] > + and r2, r2, r1 > + cmp r2, #0 > + bne inv_wait > + str r2, [r6, #L2X0_CACHE_SYNC] > +restore_pl310: > + ldm r0!, {r2-r5} > + str r3, [r6, #L2X0_AUX_CTRL] > + str r4, [r6, #L2X0_TAG_LATENCY_CTRL] > + str r5, [r6, #L2X0_DATA_LATENCY_CTRL] > + ldm r0!, {r3-r4} > + str r3, [r6, #L2X0_PREFETCH_CTRL] > + str r4, [r6, #L2X0_POWER_CTRL] > + mov r2, #1 > + str r2, [r6, #L2X0_CTRL] @enable L2$ > + b cpu_resume > + > +/*reset handler for C2 exit */ > reset_chunk: > ldr r0, c2_data > ldr pc, c2_restore > @@ -483,94 +170,6 @@ VirtualToPhysical: > orr r0, r0, r1 > bx lr > > - .fpu neon > -/* See arch/arm/include/asm/vfp.h */ > -#define FPEXC cr8 > -#define FPSCR cr1 > -#define MVFR0 cr7 > - .macro VMRS, rd, sysreg, cond > - MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg > - .endm > - > - .macro VMSR, sysreg, rd, cond > - MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd > - .endm > - > - .global save_vfp > -save_vfp: > - @ FPU state save/restore. > - @ FPSID,MVFR0 and MVFR1 don't get serialized/saved (Read Only). > - MRC p15,0,r3,c1,c0,2 @ CPACR allows CP10 and CP11 access > - ORR r2,r3,#0xF00000 > - MCR p15,0,r2,c1,c0,2 > - ISB > - MRC p15,0,r2,c1,c0,2 > - AND r2,r2,#0xF00000 > - CMP r2,#0xF00000 > - BEQ L000 > - MOVS r2, #0 > - @ Override to 0 to indicate that no FPU is present > - @ STR r2,[r11,#DM_VFP] ; TODO: autodetect VFP in C!! > - B L001 > - > -L000: @ Save configuration registers and enable. > - VMRS r12,FPEXC > - STR r12,[r0],#4 @ Save the FPEXC > - @ Enable FPU access to save/restore the other registers. > - LDR r2,=0x40000000 > - VMSR FPEXC,r2 > - VMRS r2,FPSCR > - STR r2,[r0],#4 @ Save the FPSCR > - @ Store the VFP-D16 registers. > - VSTM r0!, {D0-D15} > - @ Check for Advanced SIMD/VFP-D32 support > - VMRS r2,MVFR0 > - AND r2,r2,#0xF @ extract the A_SIMD bitfield > - CMP r2, #0x2 > - BLT L001 > - @ Store the Advanced SIMD/VFP-D32 additional registers. > - VSTM r0!, {D16-D31} > - > - @ IMPLEMENTATION DEFINED: save any subarchitecture defined state > - @ NOTE: Don't change the order of the FPEXC and CPACR restores > - VMSR FPEXC,r10 @ Restore the original En bit of FPU. > -L001: > - MCR p15,0,r3,c1,c0,2 @ Restore the original CPACR value. > - BX lr > - > - .global restore_vfp > -restore_vfp: > - @ FPU state save/restore. Obviously FPSID,MVFR0 and MVFR1 don't get > - @ serialized (RO). > - @ Modify CPACR to allow CP10 and CP11 access > - MRC p15,0,r2,c1,c0,2 > - ORR r2,r2,#0x00F00000 > - MCR p15,0,r2,c1,c0,2 > - @ Enable FPU access to save/restore the rest of registers. > - LDR r2,=0x40000000 > - VMSR FPEXC, r2 > - @ Recover FPEXC and FPSCR. These will be restored later. > - LDM r0!,{r3,r12} > - @ Restore the VFP-D16 registers. > - VLDM r0!, {D0-D15} > - @ Check for Advanced SIMD/VFP-D32 support > - VMRS r2, MVFR0 > - AND r2,r2,#0xF @ extract the A_SIMD bitfield > - CMP r2, #0x2 > - BLT L0000 > - > - @ Store the Advanced SIMD/VFP-D32 additional registers. > - VLDM r0!, {D16-D31} > - > - @ IMPLEMENTATION DEFINED: restore any subarchitecture defined state > - > -L0000: @ Restore configuration registers and enable. > - @ Restore FPSCR _before_ FPEXC since FPEXC could disable FPU > - @ and make setting FPSCR unpredictable. > - VMSR FPSCR,r12 > - VMSR FPEXC,r3 @ Restore FPEXC after FPSCR > - BX lr > - > .global save_performance_monitors > save_performance_monitors: > PUSH {r4, r8, r9, r10} > @@ -690,8 +289,8 @@ L40: MCR p15,0,r1,c9,c12,0 @ clear the PMCR global enable bit > POP {r4-r5, r8-r10, pc} > > @ Debug: see DDI0388F, 10.2.1 > - .global save_ca9_debug > -save_ca9_debug: > + .global save_pxa978_debug > +save_pxa978_debug: > @ push {r4} > push {r1-r4} > mrc p14, 0, r1, c0, c6, 0 > @@ -731,8 +330,8 @@ save_ca9_debug: > @ pop {r4} > pop {r1-r4} > bx lr > - .global restore_ca9_debug > -restore_ca9_debug: > + .global restore_pxa978_debug > +restore_pxa978_debug: > @ push {r4} > push {r1-r4} > ldm r0!,{r1-r4} > diff --git a/arch/arm/mach-pxa/cmd_ca9_idle.c b/arch/arm/mach-pxa/cmd_ca9_idle.c > index 992d9e1..3849da9 100644 > --- a/arch/arm/mach-pxa/cmd_ca9_idle.c > +++ b/arch/arm/mach-pxa/cmd_ca9_idle.c > @@ -17,12 +17,17 @@ > * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > * > */ > - > #include <mach/ca9_asm.h> > -#include <mach/ca9_regs.h> > -#include <mach/pxa95x_pm.h> > #include <asm/outercache.h> > +#include <linux/suspend.h> > +#include <asm/cacheflush.h> > +#include <asm/suspend.h> > +#include <linux/cpu_pm.h> > +#include <mach/pxa95x_pm.h> > +#include <asm/io.h> > #include <mach/pxa3xx-regs.h> > +#include <linux/delay.h> > + > /* Part of the code based on the below ARM code and modified */ > /* > * Copyright (C) 2008-2010 ARM Limited > @@ -44,43 +49,53 @@ > * misrepresented as being the original software. > * 3. This notice may not be removed or altered from any source distribution. > */ > - > -#define __nop() do { asm volatile ("nop" : : : "memory"); } while (0) > - > -void flushL2VaRange(phys_addr_t start, phys_addr_t end) > +#define PWRMODE_L2_DIS_IN_C2 0x40 > +static int pxa978_suspend_finish(unsigned int core_mode) > { > - outer_flush_range(VirtualToPhysical(start), VirtualToPhysical(end)); > + unsigned int power_mode = PWRMODE; > + if (power_mode & PWRMODE_L2_DIS_IN_C2) { > + /* In L2$ non-retentive mode, two option: > + *1. clean all before c2, inv all after c2 > + *2. flush all before c2 > + *but we mush use the first one. for after power on, L2 is > + *in an unpredicatable state of all data, tag, status bit > + */ > + /*this will actually call clean_all() */ > + outer_clean_range(0, 0xFFFFFFFF); > + } > + pxa978_cpu_suspend(get_c2_sram_base(), pl310_membase, core_mode, > + power_mode & PWRMODE_L2_DIS_IN_C2); > + return 0; > } > > -void cleanL2VaRange(phys_addr_t start, phys_addr_t end) > +void c2_address_unremap(void) > { > - /*actually this will clean all because the range > L2 cache size*/ > - outer_clean_range(0, 0x10000000); > + __raw_writel(0, remap_c2_reg); > } > -void invalidL2All(void) > + > +void c2_address_remap(void) > { > - outer_inv_all(); > + unsigned c2_addr = VirtualToPhysical(get_c2_sram_base()); > + __raw_writel(((c2_addr >> 13) | 1) & 0x1FFF, remap_c2_reg); > } > > -#define PWRMODE_L2_DIS_IN_C2 0x40 > - > -void ca9_enter_idle(unsigned int pwrmode, unsigned int sramaddr, unsigned int l2c_base_address) > +void pxa978_pm_enter(unsigned int core_mode) > { > - struct pl310_context pl310; > - unsigned int remap_addr = VirtualToPhysical(sramaddr); > - unsigned int pmu_context[PMU_DATA_SIZE/sizeof(unsigned int)]; > - unsigned int vfp_context[VFP_DATA_SIZE/sizeof(unsigned int)]; > - unsigned int debug_context[DEBUG_DATA_SIZE/sizeof(unsigned int)]; > - /* Remap 0 physical to SRAM so reset will runs the C2 restore code */ > - *remap_c2_reg = ((remap_addr>>13)|1)&0x1fff; > - save_vfp((unsigned int *)&vfp_context); > - save_ca9_debug((unsigned int *)&debug_context); > - save_performance_monitors((unsigned int *)&pmu_context); > - > - ca9_enter_c2_wrapper(&pl310, l2c_base_address, pwrmode & PWRMODE_L2_DIS_IN_C2, sramaddr); > + unsigned int debug_context[DEBUG_DATA_SIZE / sizeof(unsigned int)]; > + unsigned int pmu_context[PMU_DATA_SIZE / sizeof(unsigned int)]; > + if (core_mode == PWRDM_POWER_C2) { > + c2_address_remap(); > + save_pxa978_debug((unsigned int *)&debug_context); > + save_performance_monitors((unsigned int *)&pmu_context); > + cpu_pm_enter(); > + cpu_suspend(core_mode, pxa978_suspend_finish); > + } else if (core_mode == PWRDM_POWER_C1) > + pxa978_suspend_finish(core_mode); > > - restore_performance_monitors((unsigned int *)&pmu_context); > - restore_ca9_debug((unsigned int *)&debug_context); > - restore_vfp((unsigned int *)&vfp_context); > - *remap_c2_reg = 0; > + if (core_mode == PWRDM_POWER_C2) { > + cpu_pm_exit(); > + restore_performance_monitors((unsigned int *)&pmu_context); > + restore_pxa978_debug((unsigned int *)&debug_context); > + c2_address_unremap(); > + } > } > diff --git a/arch/arm/mach-pxa/dvfm.c b/arch/arm/mach-pxa/dvfm.c > index 90d8517..ed76ba1 100644 > --- a/arch/arm/mach-pxa/dvfm.c > +++ b/arch/arm/mach-pxa/dvfm.c > @@ -285,14 +285,11 @@ static ssize_t dvfm_c2_allow_store(struct sys_device *sys_dev, > return len; > } > > -extern unsigned int *remap_c2_reg; > - > static ssize_t dvfm_c2_allow_show(struct sys_device *sys_dev, > struct sysdev_attribute *attr, char *buf) > { > unsigned int len; > printk("\n [%s] c2_allow = %d", __func__, c2_allow); > - printk("\n [%s] REMAP reg = 0x%x, value = 0x%x", __func__, remap_c2_reg, *remap_c2_reg); > return len; > } > SYSDEV_ATTR(c2_allow, 0644, dvfm_c2_allow_show, dvfm_c2_allow_store); > diff --git a/arch/arm/mach-pxa/include/mach/ca9_asm.h b/arch/arm/mach-pxa/include/mach/ca9_asm.h > index 350daa9..db3e354 100644 > --- a/arch/arm/mach-pxa/include/mach/ca9_asm.h > +++ b/arch/arm/mach-pxa/include/mach/ca9_asm.h > @@ -1,21 +1,17 @@ > - > unsigned VirtualToPhysical(unsigned); > /*-----------------------------------------------------------------*/ > #define PMU_DATA_SIZE 128 > void save_performance_monitors(unsigned int *pointer); > void restore_performance_monitors(unsigned int *pointer); > /*-----------------------------------------------------------------*/ > -#define VFP_DATA_SIZE 288 > -void save_vfp(unsigned int *pointer); > -void restore_vfp(unsigned int *pointer); > -/*-----------------------------------------------------------------*/ > #define DEBUG_DATA_SIZE 128 > -void save_ca9_debug(unsigned int *pointer); > -void restore_ca9_debug(unsigned int *pointer); > +void save_pxa978_debug(unsigned int *pointer); > +void restore_pxa978_debug(unsigned int *pointer); > /*-----------------------------------------------------------------*/ > /* Critical registers saved/restored inside one assembly function. > sramaddr[13..0]=0 is enforced. > These registers are saved in SRAM at the given address, > right after the reset vector code. Aproximae size: 0xc0 bytes. > */ > -void ca9_enter_c2_wrapper(struct pl310_context *pl310, unsigned l2c_base_address, unsigned pwrmode, unsigned sramaddr); > +void pxa978_cpu_suspend(unsigned int sramaddr, unsigned int l2c_base_address, > + unsigned int core_mode, unsigned int pwrmode); > diff --git a/arch/arm/mach-pxa/include/mach/ca9_regs.h b/arch/arm/mach-pxa/include/mach/ca9_regs.h > deleted file mode 100644 > index b259185..0000000 > --- a/arch/arm/mach-pxa/include/mach/ca9_regs.h > +++ /dev/null > @@ -1,82 +0,0 @@ > - > -#include <linux/kernel.h> > - > -#define L2310_ADDR_START 0x58120000 > -#define L2310_ADDR_END 0x58120FFF > - > -struct lockdown_regs { > - unsigned int d, i; > -}; > - > -struct pl310_registers { > - const unsigned cache_id; > - const unsigned cache_type; > - char padding1[0x0F8]; > - volatile unsigned control; > - volatile unsigned aux_control; > - volatile unsigned tag_ram_control; > - volatile unsigned data_ram_control; > - char padding2[0x0F0]; > - volatile unsigned ev_counter_ctrl; > - volatile unsigned ev_counter1_cfg; > - volatile unsigned ev_counter0_cfg; > - volatile unsigned ev_counter1; > - volatile unsigned ev_counter0; > - volatile unsigned int_mask; > - const volatile unsigned int_mask_status; > - const volatile unsigned int_raw_status; > - volatile unsigned int_clear; > - char padding3[0x50C]; > - volatile unsigned cache_sync; > - char padding4[0x03C]; > - volatile unsigned inv_pa; > - char padding5[0x008]; > - volatile unsigned inv_way; > - char padding6[0x030]; > - volatile unsigned clean_pa; > - char padding7[0x004]; > - volatile unsigned clean_index; > - volatile unsigned clean_way; > - char padding8[0x030]; > - volatile unsigned clean_inv_pa; > - char padding9[0x004]; > - volatile unsigned clean_inv_index; > - volatile unsigned clean_inv_way; > - char paddinga[0x100]; > - volatile struct lockdown_regs lockdown[8]; > - char paddingb[0x010]; > - volatile unsigned lock_line_en; > - volatile unsigned unlock_way; > - char paddingc[0x2A8]; > - volatile unsigned addr_filtering_start; > - volatile unsigned addr_filtering_end; > - char paddingd[0x338]; > - volatile unsigned debug_ctrl; > - char paddinge[0x01C]; > - volatile unsigned prefetch_ctrl; > - char paddingf[0x01C]; > - volatile unsigned power_ctrl; > - unsigned int *memset; > -}; > - > - > -struct pl310_context { > - unsigned int control; > - unsigned int aux_control; > - unsigned int tag_ram_control; > - unsigned int data_ram_control; > - unsigned int ev_counter_ctrl; > - unsigned int ev_counter1_cfg; > - unsigned int ev_counter0_cfg; > - unsigned int ev_counter1; > - unsigned int ev_counter0; > - unsigned int int_mask; > - unsigned int lock_line_en; > - struct lockdown_regs lockdown[8]; > - unsigned int unlock_way; > - unsigned int addr_filtering_start; > - unsigned int addr_filtering_end; > - unsigned int debug_ctrl; > - unsigned int prefetch_ctrl; > - unsigned int power_ctrl; > -}; > diff --git a/arch/arm/mach-pxa/include/mach/pxa95x_pm.h b/arch/arm/mach-pxa/include/mach/pxa95x_pm.h > index 7163df6..642bab1 100644 > --- a/arch/arm/mach-pxa/include/mach/pxa95x_pm.h > +++ b/arch/arm/mach-pxa/include/mach/pxa95x_pm.h > @@ -371,6 +371,11 @@ > #define SleepState_end (SleepState_flushFunc + WORD_SIZE) > #define SleepState_size (SleepState_end - SleepState_begin) > > +/*pxa978 core power mode*/ > +#define PWRDM_POWER_C1 0x0 > +#define PWRDM_POWER_C2 0x1 > + > + > #ifndef __ASSEMBLY__ > > typedef struct { > @@ -565,6 +570,7 @@ struct pxa95x_peripheral_wakeup_ops { > int (*cmwdt) (pm_wakeup_src_t src, int enable); > }; > extern unsigned int *remap_c2_reg; > +extern unsigned int *pl310_membase; > > #define GC_PWR_ENABLE (1) > #define GC_PWR_DISABLE (0) > @@ -578,8 +584,8 @@ extern unsigned int pm_core_pwdn(unsigned int powerState); > extern unsigned int pm_enter_cgm_deepidle(unsigned int); > extern int pxa95x_query_gwsr(int); > extern u32 get_mipi_reference_control(void); > -extern void ca9_enter_idle(unsigned int pwrmode, unsigned int sramaddr, unsigned int l2c_base_address); > - > +extern unsigned int get_c2_sram_base(void); > +extern void pxa978_pm_enter(unsigned int save_mode); > #endif > #endif > #endif > diff --git a/arch/arm/mach-pxa/mspm_idle.c b/arch/arm/mach-pxa/mspm_idle.c > index 79ad678..e1750e4 100644 > --- a/arch/arm/mach-pxa/mspm_idle.c > +++ b/arch/arm/mach-pxa/mspm_idle.c > @@ -32,7 +32,6 @@ > #include <mach/regs-ost.h> > #include <mach/pxa95x_dvfm.h> > #include <mach/mspm_prof.h> > -#include <mach/ca9_regs.h> > #ifdef CONFIG_ISPT > #include <mach/pxa_ispt.h> > #endif > @@ -120,15 +119,12 @@ static unsigned int pm_enter_deepidle(unsigned int x) > BUG_ON(1); > } > #endif > -extern unsigned int get_sram_base(void); > -extern struct pl310_registers pl310_regs; > extern unsigned int c2_allow; > static void pxa95x_cpu_idle(void) > { > unsigned int c1_enter_time, c1_exit_time, pollreg; > struct op_info *info = NULL; > int op; > - unsigned int sram_base = get_sram_base(); > static unsigned int counter, counter2; > DVFMLPMGlobalCount.D0C1_Enter_count++; > op = dvfm_get_op(&info); > @@ -151,14 +147,14 @@ static void pxa95x_cpu_idle(void) > mipsram_disable_counter(); > #endif > if (cpu_is_pxa978()) { > - if (sram_base && c2_allow) { > + if (c2_allow) { > PWRMODE = 0x0; > PWRMODE = (PXA978_PM_S0D0CG | PXA95x_PM_I_Q_BIT); > do { > pollreg = PWRMODE; > } while (pollreg != > (PXA978_PM_S0D0CG | PXA95x_PM_I_Q_BIT)); > - ca9_enter_idle(pollreg, sram_base + 0x8000, (unsigned int)pl310_regs.memset); > + pxa978_pm_enter(PWRDM_POWER_C2); > counter++; > if (counter == 10000) { > counter2++; > diff --git a/arch/arm/mach-pxa/pxa95x_pm.c b/arch/arm/mach-pxa/pxa95x_pm.c > index 9935840..e3e599f 100644 > --- a/arch/arm/mach-pxa/pxa95x_pm.c > +++ b/arch/arm/mach-pxa/pxa95x_pm.c > @@ -34,7 +34,6 @@ > #include <mach/mfp-pxa3xx.h> > #include <mach/gpio.h> > #include <mach/debug_pm.h> > -#include <mach/ca9_regs.h> > #ifdef CONFIG_ISPT > #include <mach/pxa_ispt.h> > #endif > @@ -54,7 +53,6 @@ > /* mtd.h declares another DEBUG macro definition */ > #undef DEBUG > #include <linux/mtd/mtd.h> > - > /* The first 32KB is reserved and can't be accessed by kernel. > * This restrict is only valid on BootROM V2. > */ > @@ -187,8 +185,8 @@ EXPORT_SYMBOL(dmc_membase); > unsigned char __iomem *ost_membase; > EXPORT_SYMBOL(ost_membase); > unsigned char __iomem *pm_membase; > - > -unsigned int *remap_c2_reg; > +unsigned int __iomem *pl310_membase; > +unsigned int __iomem *remap_c2_reg; > > extern void pxa95x_cpu_sleep(unsigned int, unsigned int); > extern void pxa95x_cpu_resume(void); > @@ -458,8 +456,6 @@ static void pxa95x_gpio_restore(struct gpio_regs *context) > GFER2 = context->gfer2; > GFER3 = context->gfer3; > } > - > -struct pl310_registers pl310_regs; > static void pxa95x_sysbus_init(struct pxa95x_pm_regs *context) > { > context->smc.membase = ioremap(SMC_START, SMC_END - SMC_START + 1); > @@ -477,9 +473,7 @@ static void pxa95x_sysbus_init(struct pxa95x_pm_regs *context) > */ > context->data_pool = (unsigned char *)0xC0000000; > if (cpu_is_pxa978()) { > - pl310_regs.memset = ioremap(L2310_ADDR_START, L2310_ADDR_END - L2310_ADDR_START + 1); > - printk(KERN_DEBUG "pl310_regs.memset = 0x%lx, Start: 0x%lx END: 0x%lx\n", > - pl310_regs.memset, L2310_ADDR_START, L2310_ADDR_END); > + pl310_membase = ioremap(0x58120000, 0x1000); > } > } > > @@ -1249,6 +1243,11 @@ unsigned int get_sram_base(void) > | VLSCR_LVL3_SINGLE_RAIL | VLSCR_LVL0_SINGLE_RAIL \ > | VLSCR_VCT0_LVL0_REMAP_MASK | VLSCR_VCT0_LVL1_REMAP_MASK \ > | VLSCR_VCT0_LVL2_REMAP_MASK | VLSCR_VCT0_LVL3_REMAP_MASK) > +unsigned int get_c2_sram_base(void) > +{ > + return (unsigned int) (pxa95x_pm_regs.sram_map + 0x8000); > +} > + > void enter_lowpower_mode(int state) > { > unsigned int start_tick = 0, end_tick = 0; > @@ -1342,9 +1341,7 @@ void enter_lowpower_mode(int state) > vlscr &= ~(VLSCR_SINGLE_RAIL_MASK); > vlscr |= (VLSCR_D1_VALUE); > VLSCR = vlscr; > - > - ca9_enter_idle(pollreg, sram + 0x8000, > - (u32)pl310_regs.memset); > + pxa978_pm_enter(PWRDM_POWER_C2); > } else { > pxa95x_cpu_standby(sram + 0x8000, > sram + 0xa000 - 4, > @@ -1454,9 +1451,8 @@ void enter_lowpower_mode(int state) > vlscr &= ~(VLSCR_SINGLE_RAIL_MASK); > vlscr |= (VLSCR_D2_VALUE); > VLSCR = vlscr; > + pxa978_pm_enter(PWRDM_POWER_C2); > > - ca9_enter_idle(pollreg, sram + 0x8000, > - (u32)pl310_regs.memset); > } else { > pxa95x_cpu_standby(sram + 0x8000, > sram + 0xa000 - 4, > @@ -1619,8 +1615,7 @@ void enter_lowpower_mode(int state) > */ > sram = (unsigned int) pxa95x_pm_regs.sram_map; > if (cpu_is_pxa978()) { > - ca9_enter_idle(pollreg, sram + 0x8000, > - (u32)pl310_regs.memset); > + pxa978_pm_enter(PWRDM_POWER_C2); > } else { > if (cur_op < 2) > pm_enter_cgm_deepidle > -- > 1.7.4.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-usb" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html Sorry to sent a wrong set of patches. Please ignore this patch. Best Regards, Neil Zhang -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html