OCP问题debug

问题重现:
在设备中设置alarm闹铃,然后选择震动和闹铃和屏幕最低亮度。确保进入vddmin后,当闹铃响的时候,会crash
OCP:
过电流保护OCP(英文名称:over current protection)
预定当被测电流增大超过允许值时执行相应保护动作(如使断路器跳闸)的一种措施保护。
log等级:
cat /proc/sys/kernel/printk
4 4 1 7
第一个参数表示console的loglevel,第二个参数表示prink的loglevel(只是表示不加参数,printk的默认loglevel),如果设置console的loglevel为8,则printk都会打印在console,否则0/1/2/3打在console。
echo 8 > /proc/sys/kernel/printk设置console的loglevel

分析:
在每次crash后,重启后抓取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
GP_FAULT0这个错误代表OCP错误
注意要抓取整份的log,如果不能用串口抓取整份log,可以用以下命令抓取尽量多的log:
adb wait-for-device & adb root & adb shell dmesg > ./dmesg3.txt —快速抓取log

这个时候就需要分析,在crash之前是什么原因导致的。一般OCP的问题,可以追踪crash之前最近的一次LDO使用情况,这样可以快速定位问题:
需要在kernel/drivers/regulator/core.c下加log,查看最后一个LDO的使用情况:
在这个函数里面一些函数的调用情况:
int regulator_enable(struct regulator *regulator) -----> Request that the regulator be enabled with the regulator output at the predefined voltage or current value.
每个LDO开启的时候,都会调用regulator_enable然后调用_regulator_enable(rdev);
然后在调用static void drms_uA_update(struct regulator_dev *rdev)
在static void drms_uA_update(struct regulator_dev *rdev)函数中

/* 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);
}

当出现Suspending console(s) (use no_console_suspend to debug)后,表明已经进入vdd min模式了
以下在响铃之后,出现的一段log,之后就crash
注意要加上echo 8 > /proc/sys/kernel/printk ,显示全部的log打印

[  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>;这就有问题了,分析如下:
每个LDO在enable的时候系统会给他们选择mode,有LPM,和NPM模式,分别代表低功耗和正常模式
当每个LDO所有consumer加起来的电流<LPM规定的某个值,即为LPM模式,否则为NPM模式。 --------------- 注意电流值是dts里面配置的,而不是实际电流
当处于LPM模式下的设备,此时的实际电流大于 这个LDO所有consumer加起来的电流(加起来的电流是设备树的电流,而不是实际电流),或者大于LPM模式下的阈值电流 ------------------- 就会发生OCP
如果consumer的电流>LPM规定的某个值,就会进入NPM模式,这个是正常模式,就不会产生OCP,
所以现在需要增加所有consumer的电流和,这样才符合实际电流,---------- 大于LPM模式的阈值 --------------- 不会进入LPM模式 ----------------- 电流高一点的时候不会产生OCP现象
所以把音频的喇叭电流增加,通过log可以发现主要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--------------

从中可以看到有两个地方更改了,
第一current_uA 10000,依据:qcom,cdc-vdd-digital-current = <5000>; -------------- <10000>
第二mode 2,依据:进入了NPM模式

问题:LPM模式的阈值电流在哪里设置,一共有多少模式,在npm模式下实际电流大于consumer的电流会发生ocp吗
在平常模式下:
[ 295.169003] xhlin drms_uA_update: rdev name pm660_l11, current_uA 105000, mode 2 -----

现在不妨换换思路,瞧点文学东西

如果你喜欢,聊历史,思哲学,品诗集,赏国学。

那就关注公众号:二校五叔

这个是博主的文学公众号啦

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值