在产品设计中,为防备系统跑挂了,需要设计通过长按电源键实现硬关机和重启。这里简单介绍RK809实现长按电源键关机和重启功能。
通过查阅RK809手册PMIC_PWEON_KEY寄存器,可以设置长按电源键PMIC的响应事件有两种:关机和重启。响应时间有6s、8s、10s、12s。
分析驱动代码rk8xx.c可以发现代码中配好了设备树接口,只需要在设备树中添加相应的属性即可设置长按电源键PMIC的响应时间和响应事件。
// u-boot/drivers/power/pmic/rk8xx.c
static int rk8xx_ofdata_to_platdata(struct udevice *dev)
{
struct rk8xx_priv *rk8xx = dev_get_priv(dev);
u32 interrupt, phandle, val;
int ret;
phandle = dev_read_u32_default(dev, "interrupt-parent", -ENODATA);
if (phandle == -ENODATA) {
printf("Read 'interrupt-parent' failed, ret=%d\n", phandle);
return phandle;
}
ret = dev_read_u32_array(dev, "interrupts", &interrupt, 1);
if (ret) {
printf("Read 'interrupts' failed, ret=%d\n", ret);
return ret;
}
rk8xx->irq = phandle_gpio_to_irq(phandle, interrupt);
if (rk8xx->irq < 0) {
printf("Failed to request rk8xx irq, ret=%d\n", rk8xx->irq);
return rk8xx->irq;
}
val = dev_read_u32_default(dev, "long-press-off-time-sec", 0); //解析long-press-off-time-sec属性
if (val <= 6)
rk8xx->lp_off_time = RK8XX_LP_TIME_6S;
else if (val <= 8)
rk8xx->lp_off_time = RK8XX_LP_TIME_8S;
else if (val <= 10)
rk8xx->lp_off_time = RK8XX_LP_TIME_10S;
else
rk8xx->lp_off_time = RK8XX_LP_TIME_12S;
val = dev_read_u32_default(dev, "long-press-restart", 0); //解析long-press-restart属性
if (val)
rk8xx->lp_action = RK8XX_LP_RESTART;
else
rk8xx->lp_action = RK8XX_LP_OFF;
val = dev_read_u32_default(dev, "not-save-power-en", 0);
rk8xx->not_save_power_en = val;
return 0;
}
根据驱动,只需要在dts文件中的rk809节点中添加long-press-off-time-sec和long-press-restart属性。
rk809: pmic@20 {
compatible = "rockchip,rk809";
reg = <0x20>;
...
long-press-off-time-sec = <6>; //长按电源键PMIC响应时间,可以设置6s,8s,10s,12s
long-press-restart = <1>; //长按电源键PMIC响应事件,0:关机 1:重启
...
pwrkey {
status = "okay";
};
同样通过RK809手册发现短按电源键开机的响应时间可以设置500ms和100ms。驱动中每发现有设置该功能的接口,可以仿照长按电源键的响应时间来实现短按电源键开机的响应时间。
1)头文件添加寄存器地址
diff --git a/u-boot/include/power/rk8xx_pmic.h b/u-boot/include/power/rk8xx_pmic.h
index aa51e887e4..7274a7dc46 100644
--- a/u-boot/include/power/rk8xx_pmic.h
+++ b/u-boot/include/power/rk8xx_pmic.h
@@ -219,6 +219,9 @@ enum {
#define RK8XX_DEVCTRL_REG 0x4b
#define RK817_PWRON_KEY 0xf7
+#define RK8XX_ON_TIME BIT(7)
+#define RK8XX_ON_TIME_500MS (0 << 7)
+#define RK8XX_ON_TIME_100MS (1 << 7)
#define RK8XX_LP_ACTION_MSK BIT(6)
#define RK8XX_LP_OFF (0 << 6)
#define RK8XX_LP_RESTART (1 << 6)
@@ -282,6 +285,7 @@ struct rk8xx_priv {
struct spi_slave *slave;
int variant;
int irq;
+ int on_time_ms;
int lp_off_time;
int lp_action;
uint8_t sleep_pin;
2)代码功能实现
diff --git a/u-boot/drivers/power/pmic/rk8xx.c b/u-boot/drivers/power/pmic/rk8xx.c
index b11695562b..e2e4c66566 100644
--- a/u-boot/drivers/power/pmic/rk8xx.c
+++ b/u-boot/drivers/power/pmic/rk8xx.c
@@ -404,6 +404,12 @@ static int rk8xx_ofdata_to_platdata(struct udevice *dev)
rk8xx->lp_action = RK8XX_LP_RESTART;
else
rk8xx->lp_action = RK8XX_LP_OFF;
+
+ val = dev_read_u32_default(dev, "press-on-time", 0);
+ if(val)
+ rk8xx->on_time_ms = RK8XX_ON_TIME_100MS;
+ else
+ rk8xx->on_time_ms = RK8XX_ON_TIME_500MS;
val = dev_read_u32_default(dev, "not-save-power-en", 0);
rk8xx->not_save_power_en = val;
@@ -478,7 +484,7 @@ static int rk8xx_probe(struct udevice *dev)
int ret = 0, i, show_variant;
uint8_t msb, lsb, id_msb, id_lsb;
uint8_t on_source = 0, off_source = 0;
- uint8_t pwron_key = 0, lp_off_msk = 0, lp_act_msk = 0;
+ uint8_t pwron_key = 0, on_time = 0, lp_off_msk = 0, lp_act_msk = 0;
uint8_t power_en0, power_en1, power_en2, power_en3;
uint8_t on, off;
uint8_t value;
@@ -533,6 +539,7 @@ static int rk8xx_probe(struct udevice *dev)
on_source = RK817_ON_SOURCE;
off_source = RK817_OFF_SOURCE;
pwron_key = RK817_PWRON_KEY;
+ on_time = RK8XX_ON_TIME;
lp_off_msk = RK8XX_LP_OFF_MSK;
lp_act_msk = RK8XX_LP_ACTION_MSK;
init_data = rk817_init_reg;
@@ -601,7 +608,9 @@ static int rk8xx_probe(struct udevice *dev)
ret = rk8xx_read(dev, pwron_key, &value, 1);
if (ret)
return ret;
- value &= ~(lp_off_msk | lp_act_msk);
+ value &= ~(on_time | lp_off_msk | lp_act_msk);
+ if (on_time)
+ value |= priv->on_time_ms;
if (lp_off_
3)设备树中选择响应时间
diff --git a/kernel/arch/arm64/boot/dts/rockchip/t5.dts b/kernel/arch/arm64/boot/dts/rockchip/t5.dts
index bd32081563..86b6cc9f6a 100755
--- a/kernel/arch/arm64/boot/dts/rockchip/t5.dts
+++ b/kernel/arch/arm64/boot/dts/rockchip/t5.dts
@@ -864,6 +864,7 @@
pmic-reset-func = <0>;
/* not save the PMIC_POWER_EN register in uboot */
not-save-power-en = <1>;
+ press-on-time = <0>; // 0: 500ms 1: 100ms
long-press-off-time-sec = <6>;
long-press-restart = <1>;