马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在荣品 PRO-RK3566 开发板上跑 Android 13,把开机改成"长按 2 秒"牵动的不只是一行参数,而是 PMIC 的整个上电时序。这篇记录我在 U-Boot 2017.09 里改 drivers/power/pmic/rk8xx.c 的做法和踩到的坑:长按开机的补丁做完,插上适配器后板子却不再自动开机,最后靠 RK809 的 PMIC_ON_SOURCE 寄存器才把上电来源理顺。
RK809 的开机时序约定
先把硬件约定说清楚。按 RK809 的 DATASHEET,短按开机是【100ms/500ms】,长按关机分成 6s/8s/10s 几档。我在网上找到的 DATASHEET 是 V1.0 版,听说还有 V1.4 或者更新的版本,手上有新版的方便的话发我一份。
我们的目标是把开机改成长按 2s。如果 RK809 的开机模式是写死的,那就只能在软件里多等 2s 再判一次,避免误操作触发。上电逻辑可以这么走:
- 先让 RK809 检测到 500ms 的开机指令;
- 检测到之后先把寄存器里的开机指示清掉;
- 再让 RK809 等 1.5s,也就是 1500ms;
- 等完重新读电源键是不是还按着;
- 还按着就走正常开机流程,已经松开就判为误操作,直接关机。
这块如果你有更干净的上电逻辑或者别的做法,欢迎回帖交流。
U-Boot 侧的补丁实现
下面这个 patch 已经实测可以把按键 2s 开机跑通,改动的文件是 Z:\Android13.0\u-boot\drivers\power\pmic\rk8xx.c:
- diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
- old mode 100644
- new mode 100755
- index e361015337..e44c38448a
- --- a/drivers/power/pmic/rk8xx.c
- +++ b/drivers/power/pmic/rk8xx.c
- @@ -6,6 +6,7 @@
- */
- #include <common.h>
- +#include <boot_rkimg.h>
- #include <dm.h>
- #include <errno.h>
- #include <irq-generic.h>
- @@ -486,6 +487,8 @@ static int rk8xx_probe(struct udevice *dev)
- uint8_t power_en0, power_en1, power_en2, power_en3;
- uint8_t on, off;
- uint8_t value;
- + int mode;
- +
- /* read Chip variant */
- if (device_is_compatible(dev, "rockchip,rk817") ||
- @@ -618,6 +621,31 @@ static int rk8xx_probe(struct udevice *dev)
- printf("IRQ chip initial failed\n");
- return ret;
- }
- + /* 10*100ms */
- + mode = rockchip_get_boot_mode();
- + printf("xxxx: mode: %d\n", mode);
- + value=pmic_reg_read(dev, 0xf0)&0x80;
- + printf("value=0x%x\n",value );
- + if((pmic_reg_read(dev, 0xf0)&0x80) && mode == BOOT_MODE_UNDEFINE )
- + {
- + printf("xxxx: power off\n");
- + rk8xx_shutdown(dev);
- + }
- + if ((pmic_reg_read(dev, 0xf0) & 0x80)==0 &&
- + mode == BOOT_MODE_UNDEFINE) {
- + i = 0;
- + while (i < 10) {
- + value = pmic_reg_read(dev, 0xf0) & 0x80;
- + printf("value=0x%x\n",value );
- + if ((value & 0x80)) {
- + printf("xxxx: power off\n");
- + rk8xx_shutdown(dev);
- + }
- + mdelay(100);
- + i++;
- + }
- + printf("xxxx: power on\n");
- + }
- return 0;
- }
复制代码
改完之后 rk8xx_probe 里在 rk8xx_irq_chip_init 返回之后插入的这一段,就是上面那套"先等 1.5s 再看按键"的逻辑:
- ret = rk8xx_irq_chip_init(dev);
- if (ret) {
- printf("IRQ chip initial failed\n");
- return ret;
- }
- /* 10*100ms */
- mode = rockchip_get_boot_mode();
- printf("xxxx: mode: %d\n", mode);
- for j = 0;
- //for(j=0; j<256; j++)
- //{
- // //printf("0x%02x, ", pmic_reg_read(dev, j) );
- // printf("0x%02x = 0x%02x\n", j, pmic_reg_read(dev, j) );
- //}
- //if( 0x82 == pmic_reg_read(dev, 0xf0) )
- if( 0x40 == pmic_reg_read(dev, 0xf5) )
- //if( 0 )
- {
- printf("**** Success 2025/6/5 20:12 %s %s %d have +12V !\n", __FILE__, __FUNCTION__, __LINE__);
- }
- else
- {
- value=pmic_reg_read(dev, 0xf0)&0x80;
- printf("value=0x%x\n",value );
- if((pmic_reg_read(dev, 0xf0)&0x80) && mode == BOOT_MODE_UNDEFINE )
- {
- printf("xxxx: power off\n");
- rk8xx_shutdown(dev);
- }
- if ((pmic_reg_read(dev, 0xf0) & 0x80)==0 &&
- mode == BOOT_MODE_UNDEFINE) {
- i = 0;
- //while (i < 30) {
- //while (i < 5) {
- while (i < 2) {
- value = pmic_reg_read(dev, 0xf0) & 0x80;
- printf("value=0x%x\n",value );
- if ((value & 0x80)) {
- printf("xxxx: power off\n");
- rk8xx_shutdown(dev);
- }
- mdelay(10);
- printf("**** wyb 2025/6/4 17:43 %s %s %d i=%d s! loop 2 ---- mdelay 10ms\n", __FILE__, __FUNCTION__, __LINE__, i);
- //mdelay(1000);
- i++;
- }
- printf("xxxx: power on\n");
- }
- }
- return 0;
- }
复制代码
实测启动日志与环境信息
- U-Boot 2017.09 (Jun 07 2025 - 17:34:50 +0800)
- Model: Rockchip RK3568 Evaluation Board
- MPIDR: 0x81000000
- PreSerial: 2, raw, 0xfe660000
- DRAM: 4 GiB
- Sysmem: init
- Relocation Offset: ed218000
- Relocation fdt: eb9f8aa8 - eb9fecd0
- CR: M/C/I
- Using default environment
- optee api revision: 2.0
- dwmmc@fe2b0000: 1, dwmmc@fe2c0000: 2, sdhci@fe310000: 0
- Bootdev(atags): mmc 0
- MMC0: HS200, 200Mhz
- PartType: EFI
- DM: v1
- Android 13.0, Build 2023.8, v2
- boot mode: None
- RESC: 'boot', blk@0x0001da6c
- Device is: UNLOCKED
- DTB: rk-kernel.dtb
- HASH(c): OK
- ANDROID: fdt overlay OK
- **** wyb 2025/5/30 17:47 drivers/power/pmic/rk8xx.c rk8xx_bind 334
- I2c0 speed: 100000Hz
- **** wyb 2025/5/30 17:47 drivers/power/pmic/rk8xx.c rk8xx_ofdata_to_platdata 389
- **** wyb 2025/5/30 17:47 drivers/power/pmic/rk8xx.c rk8xx_probe 521
- PMIC: RK8090 (on=0x40, off=0x80)
- **** wyb 2025/5/30 17:47 drivers/power/pmic/rk8xx.c rk8xx_irq_chip_init 447
- xxxx: mode: 11
- value=0x80
- xxxx: power off
- **** wyb 2025/5/30 17:47 drivers/power/pmic/rk8xx.c rk8xx_shutdown 293
复制代码
版本号和时序都对得上:U-Boot 2017.09、Android 13.0 Build 2023.8、DRAM 4 GiB,PMIC 打印成 RK8090(on=0x40, off=0x80)。但日志最后停在 xxxx: mode: 11 → value=0x80 → xxxx: power off,说明这次上电被流程判成了"该关机"。
已知问题:插适配器之后不自动开机
这个 patch 已经能做到按键 2s 开机,但留下一个明确的 BUG:现在插电或者插适配器之后,RK3566 不会自动开机了。这一步正好和"插上电就自己起来"相反,所以想请教一下这里能不能修,还是说要实现这个行为必须再补别的条件。
对着原理图找放电路径
把原理图对了一遍,逻辑本身是成立的:VDC 应该只在 DC 上电的那一瞬间有电压导通启动,之后靠其他电路把它放掉。也就是说手动按开机键这条路径和插适配器那条路径,在 PMIC 看来不是一回事,不能用同一套判断套在一起。
用 PMIC_ON_SOURCE 区分上电方式
翻手册时看到可以用 PMIC_ON_SOURCE 寄存器拿到当前的启动方式,把这次的启动来源区分开:
- 读 0xf5 寄存器的第 6 位,就能知道现在是哪种方式启动;
- 这一位读出来是 1,说明这次是 DC 触发开机;
- 既然是 DC 触发,就不要再跑后面那套 power 判定逻辑;
- 只有不是 DC 上电的情况,才走长按 2s 的按键判断。
这样处理的话,插适配器直接自动开机和长按按键开机两条路径就不会互相打架。
RK809 开机时序这套改动目前还停在 U-Boot 阶段,判别条件依赖 BOOT_MODE_UNDEFINE 和 0xf5 第 6 位这两个点,改之前先把 DATASHEET 新版拿到手对一遍。
编辑提示:要做长按开机的可以先照着 patch 改 rk8xx.c,但务必先确认自己板子的 VDC 放电电路,否则插适配器不自动开机的问题只会更明显。
|