📄 sleep.s
字号:
/* * File Name : linux/arch/arm/mach-mp200/sleep.S * Function : pm * Release Version : Ver 1.02 * Release Date : 2006/03/08 * * Copyright (C) NEC Electronics Corporation 2005-2006 * * * This program is free software;you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by Free Softwere Foundation; either version 2 * of License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warrnty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * */#include <linux/linkage.h>#include <asm/assembler.h>#include <asm/hardware.h>#include <asm/arch/smu.h>#include <asm/arch/mp201_mem.h>/* #define PM_DEBUG_CHGPLL *//* #define PM_PLL_OFF_DISABLE */#include "pm.h" .text/* * warm boot handler() */ .align 5ENTRY(warmboot_handler) ldr r0, val_cpu_state msr cpsr_c, r0 mov r1, #0 mcr p15, 0, r1, c7, c7, 0 @ invalidate I,D caches mcr p15, 0, r1, c7, c10, 4 @ drain write buffer mcr p15, 0, r1, c8, c7, 0 @ invalidate I,D TLBs @ load address, cp regs and virt stack ptr ldr r1, warm_add ldr r2, vpc_add ldr r4, domain_back ldr r5, tlb_back ldr r6, pid_back ldr r7, contreg_back ldr sp, vsp_back /* * calculate the virtual pc from physical pc on SDRAM * r3 = 0xea03f000 + (switch_virtual_pc - warmboot_handler) */ sub r2, r2, r1 @ r2 = (switch_virtual_pc - warmboot_handler) ldr r3, val_warmboot_addr @ r3 = (0xea03f000) add r3, r3, r2 @ r3 = (0xea03f000 + r2) mcr p15, 0, r4, c3, c0, 0 @ domain ID mcr p15, 0, r5, c2, c0, 0 @ translation table base addr mcr p15, 0, r6, c13, c0, 0 @ PID @ icache enable mrc p15, 0, r1, c1, c0, 0 orr r1, r1, #0x00001000 mcr p15, 0, r1, c1, c0, 0 b resume_turn_on_mmu @ cache align execution .align 5resume_turn_on_mmu: mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc. nop mov pc, r3 @ jump to virtual addr nop nopswitch_virtual_pc: ldmfd sp!, {r0 - r12, pc} @ restore registers and return/* save area */ @ store general regs for suspenddomain_back: .word 0tlb_back: .word 0pid_back: .word 0contreg_back: .word 0vsp_back: .word 0 @ store label address (sdram address)warm_add: .word warmboot_handlervpc_add: .word switch_virtual_pcval_warmboot_addr: .word WARMBOOT_ADDRval_cpu_state: .word (PSR_I_BIT | PSR_F_BIT | MODE_SVC)/* * mp200_cpu_suspend() */ENTRY(mp200_cpu_suspend) stmfd sp!, {r0 - r12, lr} @ save registers on stack @ get coprocessor registers mrc p15, 0, r4, c3, c0, 0 @ domain ID mrc p15, 0, r5, c2, c0, 0 @ translation table base addr mrc p15, 0, r6, c13, c0, 0 @ PID mrc p15, 0, r7, c1, c0, 0 @ control reg @ store them plus current virtual stack ptr on stack mov r8, sp str r4, domain_back str r5, tlb_back str r6, pid_back str r7, contreg_back str r8, vsp_back @ clean data cache and invalidate WB ldr r1, cache_clean_ptr mov lr, pc mov pc, r1 @ call mp200_pm_cache_clean() ldr r4, reg_fif_wbufctrl ldr r5, val_write_through str r5, [r4] ldr r4, reg_fif_wbufstate ldr r5, val_write_buffer_emptywrite_buffer_empty_loop: ldr r6, [r4] cmp r6, r5 bne write_buffer_empty_loop ldr r4, reg_fif_sdrcmdctrl ldr r5, val_selfrefresh str r5, [r4] @ wait for interrupt mcr p15, 0, r0, c7, c0, 4 mov pc, lrcache_clean_ptr: .word mp200_pm_cache_clean @ register address (virtual address)reg_fif_wbufctrl: .word FIF_WBUFCTRLreg_fif_wbufstate: .word FIF_WBUFSTATEreg_fif_sdrcmdctrl: .word FIF_SDRCMDCTRL @ register valueval_write_through: .word FIF_WRITE_THROUGHval_write_buffer_empty: .word FIF_WRITE_BUFFER_EMPTYval_selfrefresh: .word DDR_SELFREFRESHreg_smu_reset_state: .word SMU_SMU_RESET_STATEreg_smu_pll_sel: .word SMU_PLLSELreg_smu_pll_sel2: .word SMU_PLLSEL2#ifndef PM_PLL_OFF_DISABLEreg_smu_lpll_ctrl2: .word SMU_LPLL_CTRL2reg_smu_hpll_ctrl4: .word SMU_HPLL_CTRL4#endif /* !PM_PLL_OFF_DISABLE */reg_smu_auto_frq_change: .word SMU_AUTO_FRQ_CHANGEreg_smu_clk_domain_div: .word SMU_CLK_DOMAIN_DIVreg_fif_sdrconfigb: .word FIF_SDRCONFIGBreg_smu_int_clear: .word SMU_INT_CLEARreg_smu_int_raw_status: .word SMU_INT_RAW_STATUS/* * mp200_change_osc() */ENTRY(mp200_change_osc) stmfd sp!, {r0 - r12, lr} @ save registers on stack @ clean data cache and invalidate WB ldr r1, cache_clean_ptr mov lr, pc mov pc, r1 @ call mp200_pm_cache_clean() ldr r4, reg_fif_wbufctrl ldr r5, val_write_through str r5, [r4] ldr r4, reg_fif_wbufstate ldr r5, val_write_buffer_emptyosc_buff_readwait: ldr r6, [r4] cmp r6, r5 bne osc_buff_readwait ldr r4, reg_smu_int_clear @outl(SMU_INT_MASK, SMU_INT_CLEAR); mov r5, #SMU_INT_MASK str r5, [r4] @outl((inl(SMU_PLLSEL) & ~MASK_SMU_PLLSEL) | SMU_PLLSEL_OSC, SMU_PLLSEL); ldr r4, reg_smu_pll_sel ldr r5, [r4] bic r5, r5, #MASK_SMU_PLLSEL mov r6, #SMU_PLLSEL_OSC orr r5, r5, r6 str r5, [r4] @while (inl(SMU_INT_RAW_STATUS) != SMU_INT_MASK) {}; ldr r4, reg_smu_int_raw_statusosc_raw_wait: ldr r5, [r4] cmp r5, #SMU_INT_MASK bne osc_raw_wait#ifndef PM_PLL_OFF_DISABLE ldr r6, reg_smu_lpll_ctrl2 @outl( SMU_PLL_STANDBY, SMU_LPLL_CTRL2 ); mov r5, #SMU_PLL_STANDBY str r5, [r6] ldr r6, reg_smu_hpll_ctrl4 @outl( SMU_PLL_STANDBY, SMU_HPLL_CTRL4 ); mov r5, #SMU_PLL_STANDBY str r5, [r6]#endif /* !PM_PLL_OFF_DISABLE */ ldmfd sp!, {r0 - r12, pc} @ restore registers and return/* * mp200_change_pll() */ENTRY(mp200_change_pll) stmfd sp!, {r0 - r12, lr} @ save registers on stack mov r8, r0 ldr r5, [r8] @PLLSEL2 add r8, r8, #4 ldr r6, [r8] @AUTO_FRQ_CHANGE add r8, r8, #4 ldr r7, [r8] @FIF_SDRConfigB @ clean data cache and invalidate WB ldr r8, cache_clean_ptr mov lr, pc mov pc, r8 @ call mp200_pm_cache_clean() ldr r10, reg_fif_wbufctrl ldr r8, val_write_through str r8, [r10] ldr r10, reg_fif_wbufstate ldr r8, val_write_buffer_emptypll_buff_readwait: ldr r9, [r10] cmp r9, r8 bne pll_buff_readwait#ifdef PM_DEBUG_CHGPLL mov r12, #0#endif /* PM_DEBUG_CHGPLL */ @if((inl(SMU_PLLSEL)& MASK_SMU_PLLSEL) == SMU_PLLSEL_OSC); ldr r10, reg_smu_pll_sel ldr r8, [r10] mov r9, #MASK_SMU_PLLSEL and r8, r8, r9 cmp r8, #SMU_PLLSEL_OSC beq pll_rcsel_set#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0001#endif /* PM_DEBUG_CHGPLL */ @if((inl(SMU_PLLSEL2) & SMU_NRM_CK_SEL) != set PLLSEL2) ldr r9, reg_smu_pll_sel2 ldr r8, [r9] mov r9, #SMU_NRM_CK_SEL and r8, r8, r9 and r10, r5, r9 cmp r10, r8 bne pll_osc_change#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0002#endif /* PM_DEBUG_CHGPLL */ ldr r9, reg_fif_sdrconfigb @if(old RCSel == Set RCSel) ldr r8, [r9] @ goto pll_div_set mov r9, #FIF_CONFIGB_RCSEL_MASK and r8, r8, r9 and r10, r7, r9 cmp r10, r8 beq pll_div_set#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0004#endif /* PM_DEBUG_CHGPLL */pll_osc_change:#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0080#endif /* PM_DEBUG_CHGPLL */ ldr r9, reg_smu_int_clear @outl(SMU_INT_MASK, SMU_INT_CLEAR); mov r8, #SMU_INT_MASK str r8, [r9] @outl((inl(SMU_PLLSEL) & ~MASK_SMU_PLLSEL) | SMU_PLLSEL_OSC, SMU_PLLSEL); ldr r10, reg_smu_pll_sel ldr r8, [r10] bic r8, r8, #MASK_SMU_PLLSEL mov r9, #SMU_PLLSEL_OSC orr r8, r8, r9 str r8, [r10] @while (inl(SMU_INT_RAW_STATUS) != SMU_INT_MASK) {}; ldr r9, reg_smu_int_raw_statuspll_osc_change_raw_wait: ldr r8, [r9] cmp r8, #SMU_INT_MASK bne pll_osc_change_raw_waitpll_rcsel_set: ldr r9, reg_fif_sdrconfigb @RCsel set ldr r8, [r9] bic r8, r8, #FIF_CONFIGB_RCSEL_MASK orr r8, r8, r7 str r8, [r9]pll_div_set: ldr r10, reg_smu_auto_frq_change @r6 = PLL_NRM_DIV ldr r11, [r10] bic r11, r11, #SMU_PLL_NRM_DIV_MASK bic r11, r11, #SMU_PLL_DOWN_DIV_MASK orr r11, r11, r6 str r11, [r10] @if((inl(SMU_PLLSEL)& MASK_SMU_PLLSEL) != SMU_PLLSEL_PLL); ldr r10, reg_smu_pll_sel ldr r8, [r10] mov r9, #MASK_SMU_PLLSEL and r8, r8, r9 cmp r8, #SMU_PLLSEL_PLL beq pll_end#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x00008#endif /* PM_DEBUG_CHGPLL */pll_set:#ifndef PM_PLL_OFF_DISABLE mov r8, #SMU_NRM_CK_SEL @if(set PLLSEL2 == LPLL) and r9, r8, r5 cmp r9, r8 bne pll_hpll_set#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0010#endif /* PM_DEBUG_CHGPLL */ ldr r7, reg_smu_lpll_ctrl2 @outl( SMU_PLL_ON, SMU_LPLL_CTRL2 ); mov r8, #SMU_PLL_ON str r8, [r7] ldr r9, reg_smu_hpll_ctrl4 @outl( SMU_PLL_STANDBY, SMU_HPLL_CTRL4 ); mov r10, #SMU_PLL_STANDBY str r10, [r9]pll_lpll_wait: @do { ldr r9, [r7] cmp r8, r9 bne pll_lpll_wait @} while( inl( SMU_LPLL_CTRL2 ) == SMU_PLL_STANDBY ); b pll_set_end @goto pll_set_endpll_hpll_set: ldr r7, reg_smu_hpll_ctrl4 @outl( SMU_PLL_ON, SMU_HPLL_CTRL4 ); mov r8, #SMU_PLL_ON str r8, [r7] ldr r9, reg_smu_lpll_ctrl2 @outl( SMU_PLL_STANDBY, SMU_LPLL_CTRL2 ); mov r10, #SMU_PLL_STANDBY str r10, [r9]pll_hpll_wait: @do { ldr r9, [r7] cmp r8, r9 bne pll_hpll_wait @} while( inl( SMU_HPLL_CTRL4 ) == SMU_PLL_STANDBY );pll_set_end:#endif /* !PM_PLL_OFF_DISABLE */ @outl( (inl( SMU_PLLSEL2 ) & ~SMU_NRM_CK_SEL) | set_data, SMU_PLLSEL2 ); ldr r7, reg_smu_pll_sel2 ldr r8, [r7] bic r8, r8, #SMU_NRM_CK_SEL orr r8, r8, r5 str r8, [r7] ldr r7, reg_smu_int_clear @outl(SMU_INT_MASK, SMU_INT_CLEAR); mov r8, #SMU_INT_MASK str r8, [r7] @outl((inl(SMU_PLLSEL) & ~MASK_SMU_PLLSEL) | SMU_PLLSEL_PLL, SMU_PLLSEL); ldr r7, reg_smu_pll_sel ldr r8, [r7] bic r8, r8, #MASK_SMU_PLLSEL mov r9, #SMU_PLLSEL_PLL orr r8, r8, r9 str r8, [r7] @while (inl(SMU_INT_RAW_STATUS) != SMU_INT_MASK) {}; ldr r7, reg_smu_int_raw_statuspll_set_raw_wait: ldr r8, [r7] cmp r8, #SMU_INT_MASK bne pll_set_raw_waitpll_end:#ifdef PM_DEBUG_CHGPLL orr r12, r12, #0x0020 ldr r8, reg_smu_reset_state str r12, [r8]#endif /* PM_DEBUG_CHGPLL */ ldmfd sp!, {r0 - r12, pc} @ restore registers and return/* * dummy function for getting warmboot_handler's size */ENTRY(warmboot_handler_size) .word . - warmboot_handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -