⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sleep.s

📁 the attached file is the power mangement for MP201
💻 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 + -