PMIC 介绍

最近看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加起来的电流 当处于LPM模式下的设备,此时的实际电流大于 这个LDO所有consumer加起来的电流(加起来的电流是设备树的电流,而不是实际电流)就会发生OCP

因此修改调整如下:解决问题
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/

你可能感兴趣的:(PMIC 介绍)