最近看reboot 问题, 对PMIC 概念一头雾水
QCOM:掉电分析:
VPH_PWR【主要供电,接入电源后,PMU ,默认点】
--->VDD_CORE 【CPU 上电,发送PS_HOLD】
---->PS_HOLD 【PMU 收到PS_HOLD 之后才真正启动,与CPU 沟通】
PON_RST_IN 是PMU 给出让CPU 复位的。【如果runing 时候,PON_RST_IN 复位,查看PMU 哪里出现了问题】
PON_RST_OUT 这个给用户控制使用的
CPU 出现问题,可以关闭控制PMIC 中某个部分的电源
reboot 问题分析,保存重启之前的log,pstore . 开启更多的log日志
qcom 平台开启更多的log 日志
echo -n "file dp_display.c +p" > /d/dynamic_debug/control
echo -n "file dp_drm.c +p" > /d/dynamic_debug/control
echo -n "file dp_link.c +p" > /d/dynamic_debug/control
echo -n "file dp_ctrl.c +p" > /d/dynamic_debug/control
echo -n "file dp_catalog.c +p" > /d/dynamic_debug/control
echo -n "file dp_usbpd.c +p" > /d/dynamic_debug/control
echo -n "file dp_aux.c +p" > /d/dynamic_debug/control
echo -n "file dp_panel.c +p" > /d/dynamic_debug/control
echo -n "file dp_audio.c +p" > /d/dynamic_debug/control
echo -n "file sde_edid_parser.c +p" > /d/dynamic_debug/control
echo 'file qpnp-pdphy.c +p' > /d/dynamic_debug/control
echo 'file policy_engine.c +p' > /d/dynamic_debug/control
echo 'file phy-msm-ssusb-qmp.c +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file dwc3-msm.c +p' > /sys/kernel/debug/dynamic_debug/control
1-基础功能
PMIC(Power Management IC)又称电源管理IC,是一种特定用途的集成电路,其功能是为主系统作管理电源等工作。PMIC常用于以电池作为电源的装置,例如移动电话或便携式媒体播放器。由于这类装置一般有多于一个电源(例如电池及USB电源),系统又需要多个不同电压的电源,加上要控制电池的充放电,以传统方式满足这样的需求会占用不少空间,同时增加产品开发时间,因此造就了PMIC的出现。
PMIC 主要功能:[电源管理,充电控制,开关机控制电路]
- 直流-直流转换器
- 低压差稳压器(LDO)
- 电池充电器
- 电源选择
- 动态电压调节
- 各电源开启、关闭次序控制
- 各电源电压检测
- 温度检测
- 其他功能
外还整合了过/欠压(OVP/UVP)、过温(OTP)、过流(OCP)等保护电路
主要意义:调整充电电流和系统电流分配关系,最大程度保证系统的正常工作
LDO是利用较低的工作压差,通过负反馈调整输出电压使之保持不变的稳压器件。压差小的话用LDO,带可关断功能便于电源管理。压差大的还是用DC-DC效率高。
从PMIC 看开机流程:
POWER 按键
-->LDO ,DC-DC开启
-->CPU 上电 复位
--> CPU PS_HOLD 输出到PMIC
--> PMIC 正常工作。
关机的时候:CPU将PS_HOLD拉低电,PMIC关闭进入关机
CPU工作正常后,可以通过I2C接口对PMIC的各个模块进行控制。比如系统变频的时候,不同的工作频率要调整core电压到对应的电压。RTC时间的设置和ALARM的时钟。同时PMIC可以将异常事件产生中断信号给CPU,CPU再进行中断处理。因此bug 有可能是PMIC 中断CPU ,CPU PS HOLD 通知PMIC 导致关机
PMIC的电源越多,对系统的模块供电就越细,各个模块的电源受牵连就小,所以就越省电。
2-PMIC 框架:
PMIC 模块功能实现角度考虑
a . input power management
b . output power management
c . genera housekeeping
d . user Interface
e . IC Interface
f . configurable pins - functions within other categories(Multipurpose pins (MPP) and General Purpose Input Output (GPIO)).
Linux PMIC software architecture
3- OCP 例子
在设备中设置alarm闹铃,然后选择震动和闹铃和屏幕最低亮度。确保进入vddmin后,当闹铃响的时候,会crash,OCP:过电流保护OCP(英文名称:over current protection)
预定当被测电流增大超过允许值时执行相应保护动作(如使断路器跳闸)的一种措施保护。
kernel log :
[ 0.722600] qcom,qpnp-power-on qpnp-power-on-2: PMIC@SID0 Power-on reason: Triggered from KPD (power key press) and 'cold' boot
[ 0.722638] qcom,qpnp-power-on qpnp-power-on-2: PMIC@SID0: Power-off reason: Triggered from GP_FAULT0
Power-off reason: Triggered from GP_FAULT0
流程:
kernel/drivers/regulator/core.c
regulator_enable
---->_regulator_enable
--->drms_uA_update
/* Calculate the new optimum regulator operating mode based on the new total
* consumer load. All locks held by caller */
static void drms_uA_update(struct regulator_dev *rdev)
{
struct regulator *sibling;
int current_uA = 0, output_uV, input_uV, err;
unsigned int regulator_curr_mode, mode;
err = regulator_check_drms(rdev);
/* get output voltage */
output_uV = _regulator_get_voltage(rdev); //得到需要的输出电压
printk("xhlin %s: output voltage: %d\n",__func__,output_uV);
/* get input voltage */
input_uV = 0; //得到输入电压,不明白什么是输入电压,回来要看?
if (rdev->supply)input_uV = regulator_get_voltage(rdev->supply);
if (input_uV <= 0)input_uV = rdev->constraints->input_uV;
if (input_uV <= 0)return;
printk("xhlin %s: input voltage: %d\n",__func__,input_uV);
/* calc total requested load */------------------计算每个LDO所需要的全部电流,就是把每个consumer的电流全部加起来,注意这些电流都软件写死的,不是瞬时电流
list_for_each_entry(sibling, &rdev->consumer_list, list)
{
printk("xhlin %s: rdev name %s, current_uA %d, sib_ua_load %d\n",__func__, rdev->desc->name, current_uA, sibling->uA_load);
current_uA += sibling->uA_load;
}
/* now get the optimum mode for our new total regulator load */
mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, current_uA);--------------------------根据以上的数据确定mode,注意有LPM和NPM两种模式
/* check the new mode is allowed */
err = regulator_mode_constrain(rdev, &mode);
//重要,这个就是加log的重点:得到OPC之前的LDO是什么状态,是哪一个LDO
printk("xhlin %s: rdev name %s, current_uA %d, mode %d\n",__func__, rdev->desc->name, current_uA, mode);
/* return if the same mode is requested */
if (rdev->desc->ops->get_mode) {
regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
printk("xhlin %s: -------regulator_curr_mode = %d-----------1--------------\n",__func__,regulator_curr_mode);
if (regulator_curr_mode == mode)
{
printk("xhlin %s: -------regulator_curr_mode = %d-----------2--------------\n",__func__,regulator_curr_mode);
return;}
} else
return;
if (err == 0)
rdev->desc->ops->set_mode(rdev, mode);
}
调试之后:
[ 110.800881] CPU1: Booted secondary processor
[ 110.810993] xhlin drms_uA_update: output voltage: 1800000
[ 110.815515] xhlin drms_uA_update: input voltage: 1800000
[ 110.820766] xhlin drms_uA_update: rdev name pm660_l11, current_uA 0, sib_ua_load 5000 ---- 第一个consumer为5ma,后面会分析它从哪里来
[ 110.828744] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5000, sib_ua_load 100 ---- 第二个consumer为0.1ma
[ 110.836586] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5100, sib_ua_load 0 ---- 第三个consumer为0ma,说明不需要用到电流,跟硬件对应吗?
[ 110.844596] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5100, mode 4,err=0 ---- 进入的mode 为4 ,这个应该对应LPM,低功耗模式?
[ 110.852124] xhlin drms_uA_update: -------regulator_curr_mode = 4-----------1--------------
[ 110.860441] xhlin drms_uA_update: -------regulator_curr_mode = 4-----------2--------------
根据最后出现的LDO为:pm660_l11,可以判断LDO11引起了OCP问题。
通过检查硬件原理图,发现LDO11被以下三个部件使用:SPKR,SNS和DISP,分别为音频的喇叭,sensor和显示部分,因为闹铃只用到喇叭和显示器,所以sensor的电流应该为0
通过查找dts发现:
msm_digital_codec: msm-dig-codec@771c000 {
compatible = "qcom,msm-digital-codec";
reg = <0x0771c000 0x0>;
cdc-vdd-digital-supply = <&pm660_l11>;
qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
qcom,cdc-vdd-digital-current = <5000>;
qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
qcom,subsys-name = "modem";
};
qcom,cdc-vdd-digital-current = <5000>;可以看出DTS 配置电流是5000
注意电流值是dts里面配置的,而不是实际电流
当每个LDO所有consumer加起来的电流
因此修改调整如下:解决问题
qcom,cdc-vdd-digital-current = <5000>; -------------- <10000>
获取新的Log:
[ 108.034455] xhlin drms_uA_update: output voltage: 1800000
[ 108.038821] xhlin drms_uA_update: input voltage: 1800000
[ 108.044198] xhlin drms_uA_update: rdev name pm660_l11, current_uA 0, sib_ua_load 10000
[ 108.052081] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10000, sib_ua_load 100
[ 108.060132] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10100, sib_ua_load 0
[ 108.068005] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10100, mode 2,err=0
[ 108.075861] xhlin drms_uA_update: -------regulator_curr_mode = 2-----------1--------------
[ 108.080439] CPU2: Booted secondary processor
[ 108.088345] xhlin drms_uA_update: -------regulator_curr_mode = 2-----------2--------------
REF:
https://zh.wikipedia.org/wiki/%E9%9B%BB%E6%BA%90%E7%AE%A1%E7%90%86IC
https://blog.csdn.net/m0_37166404/article/details/80807252
http://huaqianlee.github.io/2015/06/24/Android/qcom-pmic-driver/