欢迎光临
我们一直在努力

[V2X]按键(PWRKEY / RESETKEY)配置与加载流程


1. 平台按键概述

按键PMIC 信号电气特性用途
PWRKEY(电源键) KPDPWR_N 低有效,按下 = 下降沿 开机触发、S2 长按复位、OS 侧电源键事件
RESETKEY(复位/音量下) RESIN_N 低有效 单独复位(本项目关闭)/ 音量下键 / 组合键
组合键 KPDPWR_N + RESIN_N 两键同按 强制恢复类操作(s2-kpdpwr-resin)

按键功能全部由 PMIC PON(Power-On)外设 实现,软件链路分三层:

DT 配置 (pm.dtsi) → PmicLib 解析+编程 (PON 寄存器) → EFI 协议 (PmicDxe) → 各 DXE/库消费


2. DT 基本配置(pm.dtsi)

节点:&sw { pmic { pm { pon { … } } } },binding 为 qcom,pm-pon
文件:boot/Settings/Soc/Kuno/Core/PMIC/pm.dtsi,schema:boot/Settings/dtschema/Common/Core/PMIC/qcom,pm-pon.yaml(additionalProperties: false,节点内属性不可随意增加)

子节点属性当前值含义
pshold enable / reset-type PM_TRUE / PM_HARD_RESET PS_HOLD 使能;掉 PS_HOLD 时的复位类型
smpl enable / smpl-delay PM_FALSE / 800ms 电池突然拔出(SMPL)保护关机,当前关闭
s2-kpdpwr enable / reset-type PM_TRUE / PM_WARM_RESET 长按电源键两段复位总开关及复位类型
s1-ms 10256 第一段判键时间(按住这么久判定为"长按")
s2-ms 2000 第一段达成后再持续这么久触发复位
s2-kpdpwr-resin enable / reset-type PM_TRUE / PM_HARD_RESET 电源键+音量下(RESIN)组合键
s1-ms / s2-ms 10256 / 2000 同上
s2-resin enable PM_FALSE 单独按 RESIN 触发复位,当前关闭
s3-reset enable / s3-src / timer-value-ms PM_FALSE / KPDPWR / 16000 第三段复位(可选,Kuno 关闭)
uvlo-config / ovlo-config config-value 0 欠压/过压阈值(4-bit 编码)
long-pwrkey-dbnc-chk dbnc-time-ms / chk-at 200 / 2 boot 侧"有效长按启动"软校验(load-side 校验点)

宏定义(boot/Settings/Include/pm_defines.h):PM_WARM_RESET=0、PM_HARD_RESET=1、PM_PON_RESET_SOURCE_KPDPWR 等。

时长档位表(PON 定时器不是连续值,是硬件档位)

定时器档位表(ms)文件
S1 0,32,56,80,128,184,272,408,608,904,1352,2048,3072,4480,6720,10256 pm_pon.c:286-288
S2 0,10,50,100,250,500,1000,2000 pm_pon.c:290-292
S3 0,8,16,32,63,125,250,500,1000,2000,…,128000 pm_pon.c:294-296
PON 去抖 60,120,240,490,980,2000,3900,7800,…,250000 pm_pon.c:302-304

换算用 pm_utils_get_upper_idx()(PmicLib/utils/inc/pm_utils.h:111):取 ≥ 目标值 的最近档。
即 dtsi 里 s1-ms=10256、s2-ms=2000 都是各自档位表的最大档——长按电源键 10.256s 判定进入 S1,再保持 2s 才触发复位。


3. 按键行为映射

操作行为
开机态短按 PWRKEY PMIC 产生 KPDPWR_ON 中断 / OS 侧 input event(开机后由 kernel 负责)
开机态长按 10.256s PON S1 阶段达成(软件可据此开始关机/重启流程)
再持续 2s(累计 12.256s) S2 触发 → reset-type = PM_WARM_RESET(暖复位,SoC 重启)
电源键+音量下同时按 12.256s S2 触发 → PM_HARD_RESET(PMIC 级硬复位)
单独按 RESIN 无复位(s2-resin=关闭);boot 中当"音量下键"轮询
关机态按 PWRKEY 上电触发(当前默认下降沿,短按即开机,见第 6 节可改)

⚠️ S2 是"复位"不是"关机":触发后 PMIC 重新给系统上电。产品上"长按关机并保持关机"必须走正常软关机(PS_HOLD 拉低),不能依赖 S2 通路。
Kuno target 另有 target 级有效按键校验:pm_config_target.c:237(chk_at=CORE、dbnc=400ms,与 dtsi 的 200ms/LOADER 是两处独立软校验)。


4. 按键加载全过程(函数链)

4.1 PMIC DT 解析(PmicLib)

pm_dt_get_node(PMIC_DT_NODE_PM_PON) // pm_dt_parser.c:980
└─ pm_target_information_dt_init() // DT blob 初始化
└─ pm_dt_parse_pon_config(prop_id) // pm_dt_parser.c:268
├─ pm_get_uint8_value ( &hNode, "enable", …) // 各子节点 enable
├─ pm_get_uint8_value ( &hNode, "reset-type",…) // PM_WARM/HARD_RESET
├─ pm_get_uint32_value( &hNode, "s1-ms", …)
├─ pm_get_uint32_value( &hNode, "s2-ms", …)
├─ pm_get_uint32_value( &hNode, "smpl-delay",…)
├─ pm_get_uint8_value ( &hNode, "s3-src", …) + "timer-value-ms"
├─ pm_get_uint8_value ( &hNode, "chk-at", …) + "dbnc-time-ms"
└─ → 填充 pm_dt_pon_config 结构体 // pm_dt_parser.h:167-202

4.2 PON 配置(后初始化,XBL 启动时执行一次)

pm_device_post_init() // target/kuno/system/src/pm_sbl_boot_oem.c:531
├─ pm_print_psi_version()
├─ pm_sbl_boot_pon_reset_config() // pm_sbl_boot_oem.c:456
│ ├─ pon_dt = pm_dt_get_node(PMIC_DT_NODE_PM_PON)
│ ├─ pm_app_pon_pshold_cfg(ps_hold_reset_type) // app/pon/src/pm_app_pon.c:70
│ ├─ pm_app_pon_reset_cfg(PM_APP_PON_RESET_SOURCE_KPDPWR, // pm_app_pon.c:142
│ │ WARM_RESET, 10256, 2000)
│ │ ├─ pm_app_pon_map_app_level_reset_resource() // app→drv 资源映射
│ │ ├─ pm_tgt_get_kpdpwr_reset_cfg() // 每颗 PMIC 差异化配置
│ │ ├─ pm_pon_reset_source_cfg() // drivers/pon/src/pm_pon.c
│ │ │ ├─ pm_utils_get_upper_idx(s1, pon_s1_timer_val) // ms→档位
│ │ │ ├─ pm_utils_get_upper_idx(s2, pon_s2_timer_val)
│ │ │ ├─ 写 KPDPWR_N_RESET_S1_TIMER / S2_TIMER 寄存器
│ │ │ └─ 写 RESET_S2_SW_CTL: reset_type + S2_RESET_EN
│ │ └─ pm_pon_tgt_specific_kpd_reset_cfg()
│ ├─ pm_app_pon_reset_cfg(RESIN_AND_KPDPWR, HARD_RESET, 10256, 2000) // pwr+vol down
│ │ (disable 时改调 pm_pon_reset_source_ctl(PMIC_A, 源, PM_OFF))
│ ├─ pm_app_pon_reset_cfg(RESIN, …) / pm_pon_reset_source_ctl(RESIN, PM_OFF)
│ └─ pm_app_pon_s3_reset_timer_cfg(s3_src, timer_ms) // pm_app_pon.c:213
├─ pm_pon_tgt_uvlo_ovlo_cfg() // UVLO/OVLO config-value
└─ pm_app_pwrkey_long_press_check(PM_PON_PWRKEY_DBNC_CHK_AT_LOADER) // app/pon/src/pm_app_key_press.c:53
├─ 取 dbnc_chk 配置(chk_at / dbnc_time_msec)
├─ 读 PMIC PON 实时 IRQ 状态并等待 dbnc_time_msec
├─ 读 SDAM 按键按下/释放时间(pm_config_target.c: MEM_026/030)
└─ 判定本次启动是否为"有效长按"(影响 PON reason/特殊模式判定)

4.3 运行期按键消费(EFI 协议使用者)

ButtonsInit() // QcomPkg/Library/ButtonsLib/ButtonsLib.c:301
├─ gBS->LocateProtocol(PmicPONProtocol / PmicGpioProtocol / TLMMProtocol)
├─ 配置按键 GPIO
└─ ReadRealTimeIRQStatus(EFI_PM_PON_IRQ_KPDPWR_ON, …) // ButtonsLib.c:463
PollPowerKey() → 电源键 RT 状态 // ButtonsLib.c:459
PollButtonArray()→ pwr / vol+ / vol-(EFI_PM_PON_IRQ_RESIN_ON) / home / camera
↓ 被消费
ButtonsDxe DriverEntry → PollButtonArray() // Drivers/ButtonsDxe/ButtonsDxe.c:403(按键服务/热键)
KeypadDxe(Deprecated) → PollPowerKey() // Drivers/Deprecated/KeypadDxe/KeypadDxe.c:371

QcomChargerDxe(关机充电等场景,Drivers/QcomChargerDxe/WP/QcomChargerPlatform_Fw.c)
├─ SetIrqTriggerType(0, EFI_PM_PON_IRQ_KPDPWR_ON, RISING_EDGE) // L339 等"松手"判定
├─ EnableIrq(0, KPDPWR_ON, TRUE) // L340
└─ GetPonIrqStatus(LATCHED) / ClearIrq // L343/L463

ChargerExDxe / CrashDumpDxe 等:LocateProtocol(gQcomPmicPwrOnProtocolGuid) 后读
GetPonReason / GetAllPonReasons / GetAllFaultReasons 判定上次启动原因

4.4 协议层(PmicDxe → PmicLib)

协议安装:Drivers/PmicDxe/Pmic.c:180(gQcomPmicPwrOnProtocolGuid → PmicPwronProtocolImplementation)

协议成员(实现于 Drivers/PmicDxe/PmicPonProtocol.c)底层 PmicLib
GetPonRtStatus pm_pon_get_pon_rt_status
EnableEdgePonTrigger(L605) pm_pon_set_option_bit(上电触发沿,见第 6 节)
IrqEnable / IrqClear pm_pon_irq_enable(pm_pon.c:1289)/ pm_pon_irq_clear
IrqSetTrigger(L270) pm_pon_hlos_irq_set_trigger(pm_pon_hlos.c:229)/ PM8250 走 pm_pon_irq_set_trigger
GetPonIrqStatus pon_hlos_irq_map 映射(PmicPonProtocol.c:143)后读状态
GetPonReason / GetAllPonReasons / GetAllFaultReasons pm_pon_get_pon_reason(s) / fault reason
WarmResetStatus pm_pon_warm_reset_status
GetSpareReg / SetSpareReg pm_pon_get_spare_reg / pm_pon_set_spare_reg
PON IRQ 类型 EFI_PM_PON_IRQ_KPDPWR_ON、RESIN_ON、KPDPWR_RESIN_BARK;触发类型 PM_IRQ_TRIGGER_{RISING,FALLING,ACTIVE_LOW,ACTIVE_HIGH,DUAL}_EDGE(pm_resources_and_types.h:157)

5. Linux 侧补充说明

进入 kernel 后 pwrkey 事件由 qcom-pon / gpio-keys 驱动产生(interrupt-type 在 kernel dts 配),不属于 bp/boot 改动范围;boot 里配的内容(S2 复位、上电触发沿、去抖)在关机态依然由 PMIC 硬件执行。


6. 修改 PWRKEY 上电触发方式(沿触发 → 电平触发,实现"按住 2s 才开机")

6.1 原理

KPDPWR_N 低有效:按下 = 下降沿。上电触发类型由 PON option bit 决定(drivers/pon/src/pm_pon.c:1762-1767):

配置效果
pm_pon_set_option_bit(PMIC_A, PM_PON_OPTION_KPDPWR_FEDGE_PON, TRUE) set_type=edge + 低极性:按下瞬间即触发 PON(现状默认行为,短按就开机;关机后一按就亮)
pm_pon_set_option_bit(PMIC_A, PM_PON_OPTION_KPDPWR_FEDGE_PON, FALSE) set_type=level + 低极性清零:电平触发,必须持续按住才可能上电;中途松手/点按均不触发,再次按下硬件去抖计数器重新计时
pm_pon_debounce_ctl(PMIC_A, 2000) 写 PMIO_PON_PBS_DEBOUNCE_CTL(pm_pon.c:1268),档位表 pon_debounce_time_val[] 精确含 2000ms 档;电平模式下按住 ≥2s 才 PON

两个 API 配合 = 目标时序:关机态点按/按一下松手 → 保持关机;重新按下 → 重新计 2s;持续 2s → 开机。
(该函数同时把配置写入 SDAM 的 PON_TRIG_CFG 与 PMIC 中断寄存器,关机后仍生效。)

6.2 落点与示例

加在 pm_sbl_boot_pon_reset_config() 或 pm_device_post_init()(target/kuno/system/src/pm_sbl_boot_oem.c)末尾,每次开机执行一次最稳:

pm_err_flag_type
pm_device_post_init( void )
{
pm_err_flag_type err_flag = PM_ERR_FLAG_SUCCESS;

err_flag |= pm_print_psi_version();
err_flag |= pm_sbl_boot_pon_reset_config();
err_flag |= pm_pon_tgt_uvlo_ovlo_cfg();
err_flag |= pm_app_pwrkey_long_press_check(PM_PON_PWRKEY_DBNC_CHK_AT_LOADER);

/* === 新增:PWRKEY 上电改电平触发 + 2s 去抖 === */
err_flag |= pm_pon_set_option_bit(PMIC_A, PM_PON_OPTION_KPDPWR_FEDGE_PON, FALSE);
err_flag |= pm_pon_debounce_ctl(PMIC_A, 2000);

return err_flag;
}

注意:

  • pm_pon_set_option_bit() 已在 Include/api/pmic/pm/pm_pon.h:1148 导出;pm_pon_debounce_ctl() 未在任何头文件导出(全树仅定义处一处),调用处需 extern 声明:extern pm_err_flag_type pm_pon_debounce_ctl(uint32 pmic_device_index, uint32 time_delay);
  • EFI 协议侧等价接口:PmicPwrOnProtocol->EnableEdgePonTrigger(0, EFI_PM_PON_OPTION_KPDPWR_FEDGE_PON, FALSE)(PmicPonProtocol.c:605)
  • 也可不改 XBL,在 kernel 侧写相同寄存器(PMIC PON/SDAM regmap),但推荐 XBL 一次配好,POR 之前即生效
  • 只改 KPDPWR 一路,USB 插入 / DC 充电等其它 PON 源不受影响
  • 与 S2 长按复位(s1/s2 定时器)是独立通路,互不影响

6.3 验证(冷关机后)

  • 关机态点按(<2s)→ 无反应,保持关机 ✓
  • 按下立即松手 → 无反应 ✓
  • 按下保持 2s → 开机 ✓
  • 中途松手再按 → 重新从 0 计 2s ✓
  • 插 USB/DC → 开机/充电行为不变 ✓
  • 长按 12.256s → 仍按 S2 warm reset(如产品需要)✓

  • 7. 文件速查表

    文件作用
    boot/Settings/Soc/Kuno/Core/PMIC/pm.dtsi PON DT 配置(pshold/smpl/s2-*/s3/long-pwrkey-dbnc-chk)
    boot/Settings/dtschema/Common/Core/PMIC/qcom,pm-pon.yaml binding schema(属性封闭,不可随意加属性)
    boot/Settings/Include/pm_defines.h PM_ENABLE/PM_WARM_RESET/PM_PON_RESET_SOURCE_* 宏
    QcomPkg/Library/PmicLib/utils/src/pm_dt_parser.c DT 解析 pm_dt_parse_pon_config / pm_dt_get_node
    QcomPkg/Library/PmicLib/utils/inc/pm_dt_parser.h pm_dt_pon_config 结构体
    QcomPkg/Library/PmicLib/target/kuno/system/src/pm_sbl_boot_oem.c PON 后初始化入口 pm_device_post_init / pm_sbl_boot_pon_reset_config
    QcomPkg/Library/PmicLib/app/pon/src/pm_app_pon.c pm_app_pon_reset_cfg / pm_app_pon_pshold_cfg / pm_app_pon_s3_reset_timer_cfg
    QcomPkg/Library/PmicLib/app/pon/src/pm_app_key_press.c pm_app_pwrkey_long_press_check(有效长按校验)
    QcomPkg/Library/PmicLib/app/pon/src/pm_shutdown.c 关机/复位序列(pm_app_pon_pshold_cfg(PON_SHDN/PON_WARM_RST/…))
    QcomPkg/Library/PmicLib/drivers/pon/src/pm_pon.c PON 寄存器驱动:定时器档位表、pm_pon_reset_source_cfg/ctl、pm_pon_set_option_bit、pm_pon_debounce_ctl
    QcomPkg/Library/PmicLib/drivers/pon/src/pm_pon_hlos.c HLOS PON IRQ:pm_pon_hlos_irq_set_trigger 等
    QcomPkg/Library/PmicLib/drivers/pon/src/pmio_pon.h / pmic5/pmio_pon_pmic5.h PON 寄存器地址/位定义(S1/S2/S3_TIMER、DEBOUNCE_CTL、OPTION_BIT…)
    QcomPkg/Library/PmicLib/target/kuno/settings/pm_config_target.c Kuno target 参数(有效按键 400ms@CORE、SDAM 偏移等)
    QcomPkg/Library/PmicLib/target/kuno/system/src/pm_pon_target.c PON trigger 配置表 pm_pon_target_get_pon_trigger_config
    QcomPkg/Drivers/PmicDxe/PmicPonProtocol.c EFI PWRON 协议实现(option bit / IRQ 触发沿 / PON reason)
    QcomPkg/Drivers/PmicDxe/Pmic.c PmicDxe 入口、协议安装(L180)
    QcomPkg/Library/ButtonsLib/ButtonsLib.c boot 按键轮询(PollPowerKey / PollButtonArray)
    QcomPkg/Drivers/ButtonsDxe/ButtonsDxe.c 按键服务 DXE(消费 PollButtonArray)
    QcomPkg/Drivers/QcomChargerDxe/WP/QcomChargerPlatform_Fw.c 关机充电场景的 KPDPWR IRQ 配置(L339 RISING_EDGE)

    赞(0)
    未经允许不得转载:171主机测评 » [V2X]按键(PWRKEY / RESETKEY)配置与加载流程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址