`
womendu
  • 浏览: 1513436 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

标准linu休眠和唤醒机制分析(四)

阅读更多

suspend第三、四、五阶段:platformprocessorcore

static int suspend_enter(suspend_state_t state)

{

int error;

if (suspend_ops->prepare) {

// 平台特定的函数,mtkpm.c, 有定义,对pmiccpu dll的一些设置

error = suspend_ops->prepare();

if (error)

return error;

}

error = dpm_suspend_noirq(PMSG_SUSPEND);

// 对于一些non-sysdev devices,需要调用禁止中断的dpm_suspend函数来suspend那些设备

if (error) {

printk(KERN_ERR "PM: Some devices failed to power down\n");

goto Platfrom_finish;

}

if (suspend_ops->prepare_late) { // 这里没定义

error = suspend_ops->prepare_late();

if (error)

goto Power_up_devices;

}

if (suspend_test(TEST_PLATFORM)) // suspend3阶段到此为止

goto Platform_wake;

error = disable_nonboot_cpus(); // disable nonboot cpus

if (error || suspend_test(TEST_CPUS)) // suspend4阶段到此为止

goto Enable_cpus;

arch_suspend_disable_irqs(); // 中断禁止

BUG_ON(!irqs_disabled());

error = sysdev_suspend(PMSG_SUSPEND); // kernel/driver/base/sys.c

// suspend system devices

if (!error) {

if (!suspend_test(TEST_CORE)) // suspend5阶段到此为止

error = suspend_ops->enter(state);

// 真正才进入suspend,调用的函数时平台特定的suspend enter函数, // mtkpm.c, 在下面列出mtk平台的该函数实现,供分析:

// 如果有唤醒源被操作,那么处理将会被wakeup,先做一些平台相 // 关的动作,最后从函数suspend_ops->enter()中返回,这之后的唤 // 醒操作实际上是按照suspend流程的相反顺序的来走的。

sysdev_resume(); // resuem system devices

// 跳到本文档最后面,将会有一个总结,这里会展示出正常的suspendresume的时候函数调用

}

arch_suspend_enable_irqs();

BUG_ON(irqs_disabled());

Enable_cpus:

enable_nonboot_cpus();

Platform_wake:

if (suspend_ops->wake) // 平台无定义

suspend_ops->wake();

Power_up_devices:

dpm_resume_noirq(PMSG_RESUME);

Platfrom_finish:

if (suspend_ops->finish) // 做和函数suspend_ops->prepare()相反的工作

suspend_ops->finish();

return error;

}

static int mtk_pm_enter(suspend_state_t state)

{

_Chip_pm_enter(state);

return 0;

}

int _Chip_pm_enter(suspend_state_t state)

{

MSG_FUNC_ENTRY();

printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

printk("_Chip_pm_enter @@@@@@@@@@@@@@@@@@@@@@\n");

printk(" @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

/* ensure the debug is initialised (if enabled) */

switch (state)

{

case PM_SUSPEND_ON:

MSG(SUSP,"mt6516_pm_enter PM_SUSPEND_ON\n\r");

break;

case PM_SUSPEND_STANDBY:

MSG(SUSP,"mt6516_pm_enter PM_SUSPEND_STANDBY\n\r");

break;

case PM_SUSPEND_MEM: // 只支持mem的系统省电模式

MSG(SUSP,"mt6516_pm_enter PM_SUSPEND_MEM\n\r");

if (g_ChipVer == CHIP_VER_ECO_2)

mt6516_pm_SuspendEnter();

// cpu进入省电模式的函数,真正休眠之后,执行的代码会停在这个函数中,直到外部有EINT将其cpu唤醒,停下来的代码才继续执行,也就是正常按下了唤醒键的时候。

break;

case PM_SUSPEND_MAX:

MSG(SUSP,"mt6516_pm_enter PM_SUSPEND_MAX\n\r");

MSG(SUSP,"Not support for MT6516\n\r");

break;

default:

MSG(SUSP,"mt6516_pm_enter Error state\n\r");

break;

}

return 0;

}

void mt6516_pm_SuspendEnter(void)

{

UINT32 u32TCM = 0xF0400000;

UINT32 u4SuspendAddr = 0;

UINT32 u4Status, u4BATVol;

UINT32 counter = 0;

/* Check Chip Version*/

if (g_ChipVer == CHIP_VER_ECO_1)

u4SuspendAddr = u32TCM;

else if(g_ChipVer == CHIP_VER_ECO_2)

u4SuspendAddr = __virt_to_phys((unsigned long)MT6516_CPUSuspend);

/*wifi low power optimization : shutdown MCPLL & VSDIO */

wifi_lowpower_opt(TRUE);

/* Check PM related register*/

mt6516_pm_RegDump();

//mt6326_check_power();

DRV_WriteReg32(APMCUSYS_PDN_SET0,0x04200000);

/* STEP7: Set AP_SM_CNF(DxF003C22C) to wanted wake-up source. 设置唤醒源*/

#if defined(PLATFORM_EVB)

mt6516_pm_SetWakeSrc((1<< WS_KP)|(1<<WS_EINT)|(1<<WS_RTC));

#elif defined(PMIC_BL_SETTING)

mt6516_pm_SetWakeSrc((1<<

WS_KP)|(1<<WS_EINT)|(1<<WS_CCIF)|(1<<WS_SM)|(1<<WS_RTC));

#else

mt6516_pm_SetWakeSrc((1<<WS_EINT)|(1<<WS_CCIF)|(1<<WS_SM)|(1<<WS_RTC));

//mt6516_pm_SetWakeSrc((1<<WS_SM));

#endif

/* Save interrupt masks*/

irqMask_L = *MT6516_IRQ_MASKL;

irqMask_H = *MT6516_IRQ_MASKH;

mt6516_pm_Maskinterrupt(); // 20100316 James

while(1)

{

#ifdef AP_MD_EINT_SHARE_DATA

/* Update Sleep flag*/

mt6516_EINT_SetMDShareInfo();

mt6516_pm_SleepWorkAround();

#endif

/* Enter suspend mode, mt6516_slpctrl.s */

if ( g_Sleep_lock <= 0 )

u4Status = MT6516_CPUSuspend (u4SuspendAddr, u32TCM);

else

MSG(SUSP,"Someone lock sleep\n\r");

#ifdef AP_MD_EINT_SHARE_DATA

mt6516_pm_SleepWorkAroundUp();

#endif

/* Check Sleep status*/

u4Status = mt6516_pm_CheckStatus();

if (u4Status == RET_WAKE_TIMEOUT)

{

#ifndef PLATFORM_EVB

DRV_WriteReg32(APMCUSYS_PDN_CLR0,0x04200000);

u4BATVol = (mt6516_pm_GetOneChannelValue(VBAT_CHANNEL,VBAT_COUNT)/VBAT_COUNT);

DRV_WriteReg32(APMCUSYS_PDN_SET0,0x04200000);

MSG(SUSP,"counter = %d, vbat = %d\n\r",counter++, u4BATVol);

if(u4BATVol <= LOW_BAT_ALARM)

{

MSG(SUSP,"Battery Low!!Power off\n\r");

bBAT_UVLO = TRUE;

goto SLP_EXIT;

}

#endif

}

else

{

MSG(SUSP,"leave sleep, wakeup!!\n\r");

goto SLP_EXIT;

//break;

}

}

SLP_EXIT:

wifi_lowpower_opt(FALSE);

/* Restore interrupt mask ; */

*MT6516_IRQ_MASKL = irqMask_L;

*MT6516_IRQ_MASKH = irqMask_H;

}

函数MT6516_CPUSuspend (u4SuspendAddr, u32TCM)是一段汇编代码,在文件:

Kernel/arch/arm/amch-mt6516/mt6516_slpctrl.S中。下面是这段汇编代码片段,看一看也蛮有意思,因为处理进入low power模式之后,是停留在该函数之中的。

ENTRY(MT6516_CPUSuspend)

stmfd sp!, {r4-r12, lr}

// r0 = MT6516_CPUSuspend physical address,

// r1 = TCM address

mov r4, r0

mov r9, r1

// Set SVC mode

mrs r0, cpsr

bic r0, r0, #MODE_MASK1

orr r1, r0, #Mode_SVC

// Set I/F bit, disable IRQ and FIQ

orr r1, r1, #I_Bit|F_Bit

// Update CPSR

msr cpsr_cxsf, r1

// calculate the physical address of instruction after disable MMU

ldr r0, =PhysicalPart

ldr r1, =MT6516_CPUSuspend

sub r0, r0, r1

mov r1, r4

// Now r0 is the physical address of PhysicalPart

add r0, r0, r1

...

...

// Power down Cache and MMU, MCU_MEM_PDN

ldr r0, =0xF0001308

ldr r1, [r0]

// ldr r1, =0xFFFFFFFF

orr r1, r1, #0x0F

str r1, [r0]

// STEP1: Set AP SLEEP (IRQ CODE: 0x36) to level sensitive on CIRQ.

// already done when system start.

// STEP2: Unmask AP SLEEP CTRL interrupt.

// already done at mt6516_pm_Maskinterrupt.

// STEP3: EOI AP SLEEP interrupt.

// already done at mt6516_pm_Maskinterrupt.

// STEP4: Read clear AP_SM_STA (OxF003C21C).

// already done at mt6516_pm_Maskinterrupt.

font-fami

分享到:
评论

相关推荐

    Linu内核分析

    综上所述,《Linux内核分析》一书从Linux内核的历史背景、开发模式、结构特征、硬件基础、中断机制以及进程管理等方面,提供了深入浅出的讲解,对于想要深入了解Linux内核工作原理的读者来说,是一本不可多得的技术...

    特色平台前端linu移植项目可行性分析报告.pdf

    特色平台前端linu移植项目可行性分析报告.pdf

    Linux内核QoS实现机制.doc

    Linux内核QoS(服务质量)实现机制是网络管理和优化的关键组成部分,它确保了不同类型的网络服务得到合理且优先级适中的资源分配。QoS的主要目标是通过控制带宽、延迟、丢包率和抖动来提升网络性能和用户体验。在...

    嵌入式linu学习规划

    1. **数字电路与模拟电路**:理解数字电路的基本原理,掌握模拟电路的工作机制。 2. **计算机组成原理**:熟悉计算机系统的各个组成部分及其工作原理。 3. **微机原理与接口技术**:掌握微型计算机的基本原理及接口...

    Linu系统安全配置标准V.pdf

    Linu系统安全配置标准V.pdf

    Linu系统安全配置标准.pdf

    这份"Linu系统安全配置标准.pdf"文档提供了一系列针对Linux服务器的安全加固技术要求,以增强系统的稳定性和防止未授权访问。以下是根据文档内容提炼出的关键知识点: 1. **补丁管理**: - **系统补丁**:建议定期...

    vstock61.zip_palm recognition_主成分分析_小波 人脸识别_小波 分析 人脸识别_模式识别 linu

    1. **掌纹识别(Palm Recognition)**:这是一种生物特征识别技术,通过分析和比较个人的掌纹特征来进行身份验证。掌纹具有独特的纹理、线形结构和细节,使其成为生物识别系统中的一个可靠选项。在实现时,通常需要...

    Linu系统配置DNS服务器

    ### Linu系统配置DNS服务器知识点详解 #### 一、实验环境 - **操作系统**: CentOS 6.4 - **DNS服务器软件**: BIND (Berkeley Internet Name Domain) #### 二、DNS服务器配置概述 DNS服务器(Domain Name System)...

    linu下cadence的patch包

    总的来说,这个"linu下cadence的patch包"是一个用于提升Linux环境下Cadence工具性能和稳定性的更新,对于那些依赖Cadence进行复杂电路设计的专业人士来说,定期检查和应用这些补丁是保持工作效率和数据安全的重要...

    支持qt和linu通信的qssh库

    支持qt和linu通信的qssh库

    《LINU系统及其编程》考试复习重点.docx

    四、 LINU 系统的编程工具和语言 * C 语言:是系统中最常用的编程语言,提供了系统编程的接口。 * C++ 语言:是系统中的一种高级编程语言,提供了面向对象的编程接口。 * Python 语言:是系统中的一种高级编程语言...

    linu学习资料

    "奔跑吧"可能代表了作者希望读者能积极主动地深入学习和理解Linux内核,而“基于Linux 4.x内核源代码问题分析”则表明该书将详细探讨Linux 4.x版本的内核源代码,帮助读者理解内核的工作原理和解决实际问题。...

    Windows客户端访问Linu服务器NFS.doc

    "Windows客户端访问Linu服务器NFS" 本文档主要讲解Windows客户端如何访问Linux服务器的NFS(Network File System),以解决异构环境中的文件共享问题。文中介绍了跨平台通讯工具SFU(Services For Unix),它能够...

    Linu编程GCC手册

    ### Linu编程GCC手册知识点概览 #### 一、GCC简介 GCC(GNU Compiler Collection)是一套由GNU项目开发的编译器集合,它支持多种编程语言,包括但不限于C、C++、Objective-C、Fortran、Ada、Go等。本手册主要介绍了...

    myself linu x(2)

    myself linu x(2)myself linu x(2)myself linu x(2)myself linu x(2)myself linu x(2)

    Linu0.01内核分析与操作系统设计4/4

    《Linux0.01内核分析与操作系统设计》介绍LINUX0.01的内核,0.01是拥有比较少的代码,对于初学者来说容易理解。(共4个文件,第1个文件扣分,其余不扣。4/4)

    linu 下安装 websphere 手册

    linu下安装websphere手册,一目了然

    linu字符设备开发.ppt

    linu字符设备开发

    linu 搭建ELK(es+kibana+logstash)安装包

    它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。 Logstash 主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。一般

Global site tag (gtag.js) - Google Analytics