赞
踩
rk平台支持二级休眠,即SOC大部分电都关了,只留下唤醒源需要的电.
rk3588 evb1因为蓝牙相关的部分大部分IO没有接到PMU电源域,所以调试起来需要另外配置,以方便快速验证.
下面,我们以博通AP6275p芯片为例, 分析下快速验证蓝牙休眠唤醒需要的设定(前提是蓝牙已经正常bringup能工作的情况下).
为了方便只要答案的同学, 这里直接给出配置:
Subject: [PATCH] dts:arm64:rk3588:config for bt wake up from deep sleep Change-Id: Ia382dbf9860a76d2558f6f6f5f330cd46f58689d --- .../boot/dts/rockchip/rk3588-evb1-bt-wakeup.dtsi | 52 ++++++++++++++++++++++ .../boot/dts/rockchip/rk3588-evb1-lp4-v10.dts | 1 + 2 files changed, 53 insertions(+) create mode 100755 arch/arm64/boot/dts/rockchip/rk3588-evb1-bt-wakeup.dtsi diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-bt-wakeup.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb1-bt-wakeup.dtsi new file mode 100755 index 0000000..75f79b8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-bt-wakeup.dtsi @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + * + */ + +&rockchip_suspend { + rockchip,sleep-mode-config = < + (0 + | RKPM_SLP_ARMOFF_DDRPD + ) + >; + rockchip,wakeup-config = < + (0 + | RKPM_CPU0_WKUP_EN + | RKPM_GPIO_WKUP_EN + ) + >; + + status = "okay"; +}; + +&vdd_log_s0 { + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; +}; + +&vcc_3v3_s0 { + regulator-state-mem { + regulator-on-in-suspend; + }; +}; + +&vcc_1v8_s0 { + regulator-state-mem { + regulator-on-in-suspend; + }; +}; + +&vdd_1v8_pll_s0 { + regulator-state-mem { + regulator-on-in-suspend; + }; +}; + +&wireless_bluetooth { + interrupt-parent = <&gpio3>; + interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>; + wakeup-source; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10.dts index d1a264f..ecfbad8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10.dts @@ -8,6 +8,7 @@ #include "rk3588-evb1-lp4.dtsi" #include "rk3588-evb1-imx415.dtsi" +#include "rk3588-evb1-bt-wakeup.dtsi" #include "rk3588-android.dtsi"
+&rockchip_suspend {
+ rockchip,sleep-mode-config = <
+ (0
+ | RKPM_SLP_ARMOFF_DDRPD
+ )
+ >;
+ rockchip,wakeup-config = <
+ (0
+ | RKPM_CPU0_WKUP_EN
+ | RKPM_GPIO_WKUP_EN
+ )
+ >;
+
+ status = "okay";
+};
这里解释下RKPM_GPIO_WKUP_EN节点, 这里是因为唤醒源是BT_WAKE_HOST_H,即GPIO3_A0. 所以RKPM_GPIO_WKUP_EN唤醒源需要开启.
其他修改部分不是很清晰, 比如sleep-mode-config少休眠了很多模块, 待以后进一步澄清.
为了支持休眠唤醒, IC部分,至少BT_WAKE_HOST, UART_RTS, BT_REG_ON(图中1,2,3)几个引脚所在的IC模块要有电.
BT_WAKE_HOST因为是中断源.
UART_RTS是为了保持高电平, 不让外部蓝牙模块发信号(这里存疑, 可能是错的. 因为IC没电也可能可以钳住这个电平).
BT_REG_ON是为了保持高电平让外部蓝牙模块不掉电(同上, 可能是错的).
查3588 TRM, 以上电源域都在VD_LOGIC, 所以以下配置打开:
+&vdd_log_s0 {
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+};
查图1 BT_WAKE_HOST, UART_RTS, BT_REG_ON外部电源域, 就是图1中的4部分, 即VCC_1V8_S0. 所以这个电源域打开.
+&vcc_1v8_s0 {
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+};
如上, VCC_3V3_S0(1)和VCC_1V8_S0(2)要有电, 所以对应节点要打开.VCC_1V8_S0已经打开, 所以还需要打开VCC_3V3_S0.
+&vcc_3v3_s0 {
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+};
这里需要说明的是, 假设蓝牙模块外部32K晶振是3588供电, 那对应的3588模块内部外部电源域都要打开, 但我们是8563供32K.
但是如下配置现在已经无法解释了, 不知道当初为啥要配置. (也许是当初看错, 也许是忘了, 这怪开始没总结. 要验证只能重新搭环境看看这个配置是否必要, 等验证了再回来更新)
+&vdd_1v8_pll_s0 {
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+};
如下, 意思是打开中断源. 当然, 即使不需要中断唤醒, "BT,wake_host_irq"节点还是需要配置.
+&wireless_bluetooth {
+ interrupt-parent = <&gpio3>;
+ interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-source;
+};
在调试rtk 8852be芯片蓝牙唤醒过程中,发现Host系统唤醒后,收不到正确的按键值,从而导致系统重新进休眠.
其原因是芯片驱动不完善,醒来后没法通过蓝牙H5协议和Host蓝牙协议栈握手(博通芯片使用H4协议,并用RTS引脚控制蓝牙芯片的数据发送,所以无此问题).
目前解决办法是,在蓝牙唤醒过程中, rfkill-bt.c的驱动中,发送power up按键,这样,系统就能亮屏.不过, 这里有一个side-effect: 唤醒后因为无法握手会重启蓝牙协议栈,导致蓝牙遥控器连上时间会延迟.
diff --git a/net/rfkill/rfkill-bt.c b/net/rfkill/rfkill-bt.c index 719a23d..e5209e98 100644 --- a/net/rfkill/rfkill-bt.c +++ b/net/rfkill/rfkill-bt.c @@ -39,7 +39,7 @@ #include <linux/of_device.h> #include <linux/of_gpio.h> #endif - +#include <linux/input.h> #if 0 #define DBG(x...) pr_info("[BT_RFKILL]: " x) #else @@ -72,6 +72,7 @@ struct rfkill_rk_data { }; static struct rfkill_rk_data *g_rfkill = NULL; +static struct input_dev *power_key_dev; static const char bt_name[] = #if defined(CONFIG_BCM4330) @@ -721,6 +722,26 @@ static int rfkill_rk_probe(struct platform_device *pdev) LOG("%s device registered.\n", pdata->name); + /* register input device */ + power_key_dev = input_allocate_device(); + if (!power_key_dev) { + LOG("ir_dev: not enough memory for input device\n"); + return -ENOMEM; + } + + power_key_dev->name = "bt-powerkey"; + power_key_dev->id.bustype = BUS_HOST; + + power_key_dev->evbit[0] = BIT_MASK(EV_KEY); + set_bit(KEY_POWER, power_key_dev->keybit); + + ret = input_register_device(power_key_dev); + if (ret) { + input_free_device(power_key_dev); + LOG("ir_rx_init: register input device exception, exit\n"); + return -EBUSY; + } + return 0; fail_rfkill: @@ -776,9 +797,32 @@ static int rfkill_rk_remove(struct platform_device *pdev) return 0; } +static int rfkill_rk_pm_resume(struct device *pdev) +{ + LOG("%s, wake up now send power key.....", __func__); + + input_report_key(power_key_dev, KEY_POWER, 1); + input_sync(power_key_dev); + msleep(1); + input_report_key(power_key_dev, KEY_POWER, 0); + input_sync(power_key_dev); + + return 0; +} + +static int rfkill_rk_pm_suspend(struct device *pdev) +{ + LOG("%s", __func__); + + return 0; +} + + static const struct dev_pm_ops rfkill_rk_pm_ops = { .prepare = rfkill_rk_pm_prepare, .complete = rfkill_rk_pm_complete, + .suspend = rfkill_rk_pm_suspend, + .resume = rfkill_rk_pm_resume, }; #ifdef CONFIG_OF
完.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。