set_conduit(PSCI_CONDU..._mcu退出深度睡眠">
赞
踩
1. 硬件架构
arm64
2. 内核版本
4.19
3. 分析相关函数
setup_arch()
-> psci_dt_init()
-> psci_0_2_init()
-> get_set_conduit_method()
-> of_property_read_string(np, "method", &method))
-> set_conduit(PSCI_CONDUIT_HVC) 或set_conduit(PSCI_CONDUIT_SMC),根据设备树中的method属性来设定,
设定invoke_psci_fn回调函数(__invoke_psci_fn_smc或者__invoke_psci_fn_hvc)
-> psci_probe()
__invoke_psci_fn_smc()
-> arm_smccc_smc(),这是个宏定义,如下;
#define arm_smccc_smc(...) __arm_smccc_smc(__VA_ARGS__, NULL)
->__arm_smccc_smc(),定义在arch/arm64/kernel/smccc-call.S中:
.macro SMCCC instr
.cfi_startproc
instr #0
ldr x4, [sp]
stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
ldr x4, [sp, #8]
cbz x4, 1f /* no quirk structure */
ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6
b.ne 1f
str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
1: ret
.cfi_endproc
.endm
/*
* void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
* unsigned long a3, unsigned long a4, unsigned long a5,
* unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
* struct arm_smccc_quirk *quirk)
*/
ENTRY(__arm_smccc_smc)
SMCCC smc
ENDPROC(__arm_smccc_smc)
4. 相关变量
4.1 suspend_state_t mem_sleep_default = PM_SUSPEND_MAX; (kernel/power/suspend.c)
PM_SUSPEND_MAX的定义:
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
所以默认mem_sleep_default = 4;
4.2 suspend_state_t mem_sleep_current = PM_SUSPEND_TO_IDLE;
PM_SUSPEND_TO_IDLE的定义:
#define PM_SUSPEND_TO_IDLE ((__force suspend_state_t) 1)
所以默认mem_sleep_current = 1;
4.3 那么在哪里将mem_sleep_current的值改变了呢?
在suspend_set_ops()中改变了此值,调用路径如下:
psci_init_system_suspend()
-> psci_features()
-> suspend_set_ops()
4.4 psci的版本号是从哪里获取的?
是从TF-A获取的
4.5 TF-A中psci固件的版本获取
相关代码在TF-A仓库的lib/psci/psci_main.c文件中
unsigned int psci_version(void)
{return PSCI_MAJOR_VER |PSCI_MINOR_VER;
}
调用路径如下:
psci_smc_handler()
-> psci_version()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。