RK3568 Android12 红外遥控器待机唤醒问题

Platform: RK3568
OS: Android 12
Kernel: v4.19.206
SDK Version:android-12.0-mid-rkr1
Module: suspend


问题

红外遥控器待机后无法唤醒,只能用板载电源键唤醒,但是唤醒后红外遥控不能操作

解决方案

dts中如下配置:

&vdd_logic {
        regulator-state-mem {
                regulator-on-in-suspend;
        };  
};

&rockchip_suspend {
        status = "okay";
        rockchip,sleep-mode-config = < 
                (0
                | RKPM_SLP_CENTER_OFF
                | RKPM_SLP_HW_PLLS_OFF
                | RKPM_SLP_PMUALIVE_32K
                | RKPM_SLP_PMIC_LP
                | RKPM_SLP_32K_PVTM
                )
        >;

        rockchip,wakeup-config = < 
                (0
                | RKPM_PWM0_WKUP_EN
                | RKPM_CPU0_WKUP_EN
                )
        >;
};

简单分析

  1. 用板载电源按键唤醒后,红外遥控操作无效。此时用getevent命令看没有input事件上报,用echo 1 > sys/module/rockchip_pwm_remotectl/parameters/code_print命令看也没有键值打印。怀疑是待机后对应的pwm没有重新上电导致无法工作。

  2. 红外遥控待机唤醒功能在box产品中应该是标准功能,但目前我们使用的是非box版本的SDK。参考了box的dtsi,设置&rockchip_suspend 节点属性,但测试发现非但遥控不能唤醒,连板载电源键也不能唤醒了,只能重新上电。

  3. 根据rk曾工的指导,要保持休眠时logic不掉电,并修改以下配置,测试待机唤醒功能可用,并且唤醒后红外遥控可以正常工作。

rockchip,sleep-mode-config = <
(0 
| RKPM_SLP_CENTER_OFF 
| RKPM_SLP_HW_PLLS_OFF
)

>;

rockchip,wakeup-config = <
(0 | RKPM_PWM0_WKUP_EN | RKPM_CPU0_WKUP_EN
)
  1. 又经过一些对比验证,发现问题关键是需要设置好&rockchip_suspend节点属性和&vdd_logic节点中的regulator-on-in-suspend使其待机不断电。
  2. 相关驱动可见drivers/soc/rockchip/rockchip_pm_config.c
node = of_find_node_by_name(NULL, "rockchip-suspend");

        if (IS_ERR_OR_NULL(node)) {
                dev_err(&pdev->dev, "%s dev node err\n",  __func__);
                return -ENODEV;
        }   

        if (of_property_read_u32_array(node,
                                       "rockchip,sleep-mode-config",
                                       &mode_config, 1)) 
                dev_warn(&pdev->dev, "not set sleep mode config\n");
        else
                sip_smc_set_suspend_mode(SUSPEND_MODE_CONFIG, mode_config, 0); 

        if (of_property_read_u32_array(node,
                                       "rockchip,wakeup-config",
                                       &wakeup_config, 1)) 
                dev_warn(&pdev->dev, "not set wakeup-config\n");
        else
                sip_smc_set_suspend_mode(WKUP_SOURCE_CONFIG, wakeup_config, 0); 

        if (of_property_read_u32_array(node,
                                       "rockchip,pwm-regulator-config",
                                       &pwm_regulator_config, 1)) 
                dev_warn(&pdev->dev, "not set pwm-regulator-config\n");
else
                sip_smc_set_suspend_mode(PWM_REGULATOR_CONFIG,
                                         pwm_regulator_config,
                                         0);
                

其中可以看到从dts中解析到属性值后是通过sip_smc_set_suspend_mode()函数进行设置的。
继续跟下去来到drivers/firmware/rockchip_sip.c

static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
                                                unsigned long arg0,
                                                unsigned long arg1,
                                                unsigned long arg2)
{
        struct arm_smccc_res res;

        arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
        return res;
}

……

int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
{
        struct arm_smccc_res res;

        res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
        return res.a0;
}
EXPORT_SYMBOL_GPL(sip_smc_set_suspend_mode);

这里的arm_smccc_smc定义在 arch/arm64/kernel/smccc-call.S,这是汇编的代码,超出我目前的水平了,还涉及到了ATF(ARM Trusted firmware)的领域。需要再看看参考资料12加深理解。

        .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)


如有谬误欢迎指正,感谢阅读~

参考资料


  1. linux内核是如何支持深度睡眠(deep sleep)方式的? ↩︎

  2. [ATF]-smc指令详解 ↩︎

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值