首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

s3c2440 省电模式开发详解(3)

s3c2440 省电模式开发详解(3)

nop
nop
nop         /* wait until upll has the effect */
nop
nop

/* PLL setup */
ldr r1, =_mpllcon
str r1, [r0, #oMPLLCON]
/* configure memory */
bl    memset
/* Power Manage  Check if this is a wake-up from sleep */
ldr r1, PMST_ADDR
ldr r0, [r1]
@bic r0,r0,#0xfffffffd
tst r0, #(0x02)
bne WakeupStart
WakeupStart:
    /* Clear sleep reset bit */   
    ldr r0, PMST_ADDR
    mov r1, #0x0       @PMST_SMR
    str r1, [r0]
   
    ldr r0, PMCTL1_ADDR  /* Release the SDRAM signal protections */
    ldr r1, =0x00010330
   str r1, [r0]
   
    ldr r0, =0x48000024
    ldr r1, [r0]
    bic r1, r1, #0x400000
    str r1, [r0]
      
   mov r1, #0x1000
1: subs r1, r1, #1 /* wait until the SelfRefresh is released. */
    bne 1b
   
    /* Go... */   
    ldr r0, =0x560000B8 /* read a return address  go to s3c2410_cpu_resume*/
    ldr r1, [r0]
      
    mov pc, r1
    nop
    nop
1: b   1b      /* infinite loop */

2、Kernel部分

1.       唤醒程序汇编部分(arch/arm/mach-s3c2410/sleep.s)
resume_with_mmu:
ldmfd       sp!, { r4 - r12, pc }
.ltorg

.data
.global     s3c2410_sleep_save_phys
s3c2410_sleep_save_phys:
.word       0

ENTRY(s3c2410_cpu_resume)
mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
msr cpsr_c, r0

mov r2, #S3C24XX_PA_UART & 0xff000000
orr   r2, r2, #S3C24XX_PA_UART & 0xff000

#if 0
/* SMDK2440 LED set */
mov r14, #S3C24XX_PA_GPIO
ldr   r12, [ r14, #0x54 ]
bic   r12, r12, #3<<4
orr   r12, r12, #1<<7
str    r12, [ r14, #0x54 ]
#endif

#ifdef CONFIG_DEBUG_RESUME
mov r3, #'L'
strb r3, [ r2, #S3C2410_UTXH ]
1001:
ldrb r14, [ r3, #S3C2410_UTRSTAT ]
tst    r14, #S3C2410_UTRSTAT_TXE
beq 1001b
#endif /* CONFIG_DEBUG_RESUME */

mov r1, #0
mcr p15, 0, r1, c8, c7, 0              @@ invalidate I & D TLBs
mcr p15, 0, r1, c7, c7, 0              @@ invalidate I & D caches

ldr   r0, s3c2410_sleep_save_phys @ address of restore block
ldmia      r0, { r4 - r13 }

mcr p15, 0, r4, c15, c1, 0            @ CP access register
mcr p15, 0, r5, c13, c0, 0            @ PID
mcr p15, 0, r6, c3, c0, 0              @ Domain ID
mcr p15, 0, r7, c2, c0, 0              @ translation table base

#ifdef CONFIG_DEBUG_RESUME
mov r3, #'R'
strb r3, [ r2, #S3C2410_UTXH ]
#endif

ldr   r2, =resume_with_mmu
mcr p15, 0, r8, c1, c0, 0              @ turn on MMU, etc
nop                              @ second-to-last before mmu
mov pc, r2                           @ go back to virtual address

.ltorg

2.       唤醒恢复设置阶段(arch/arm/mach-s3c2410/pm.c)

static int s3c2410_pm_enter(suspend_state_t state) //该函数后半部分引导配置系统

cpu_init(); //CPU初始化
tmp = __raw_readl(S3C2410_GSTATUS2);
tmp &= S3C2410_GSTATUS2_OFFRESET;
__raw_writel(tmp, S3C2410_GSTATUS2); //清除唤醒复位标记

s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); //恢复核心配置
s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));       //恢复io口配置
s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));            //恢复中断配置
s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));         //恢复串口配置

s3c2410_pm_debug_init(); //串口调试函数初始化

DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
    __raw_readl(S3C2410_SRCPND),
    __raw_readl(S3C2410_EINTPEND)); //打印信息

s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
                          s3c_irqwake_intmask); //查看中断唤醒源信息
s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
                          s3c_irqwake_eintmask); //查看中断唤醒源信息

DBG("post sleep, preparing to return\n");

s3c2410_pm_check_restore();//如果需要在sleep前检查ram则此函数会运行,否则此函数为空,即如果CONFIG_S3C2410_PM_CHECK被定义。

DBG("S3C2410 PM Resume (post-restore)\n");
return 0;

3.       恢复系统

A.开启外设驱动电源(drivers/base/power/resume.c)
int device_power_up(pm_message_t state) //该函数使所有设备驱动sleep
B.启动系统进程(kernel/power/ console.c)
void pm_restore_console(void) //该函数使所有系统进程休眠或关闭。

4.       内核接口文件(arch/arm/kernel/apm.c)
由原接口退出sleep模式。
继承事业,薪火相传
返回列表