Charge IC 是负责管理外部供电以及电池充放电,在MDM平台上采用的是比较便宜的ChargeIC,MP2617, 其作用也仅限于控制对电池充放电。下面就简单的介绍下内核中关于chargeIC的驱动,以及dts配置
关于chargeIC的配置在mdmxx_mtp.dtsi
mp2617 {
cell-index = <0>;
compatible = "mps,mp2617";//match name
mps,chg-current-ma = <1000>;//充电电流1A
mps,chg-vbat-div = <3>;
mps,chg-en-gpio = <&msm_gpio 86 0>; //充电使能
mps,chg-ok-gpio = <&msm_gpio 83 0>;//充电OK
mps,ac-ok-gpio = <&msm_gpio 84 0>;//充电检测
mps,chg-m0-gpio = <&msm_gpio 85 0>;//充电电流
qcom,client-vadc = <&pmd9635_vadc>//PMIC
};
compatible 后续再驱动挂载的时候platform_driver_register 会匹配,如果匹配ok后调用驱动的probe函数,驱动在drivers/power中注明了compatible:
static const struct of_device_id mp2617_match[] = {
{ .compatible = "mps,mp2617", },
{ },
};
mps,chg-en-gpio 、mps,chg-ok-gpio、 mps,ac-ok-gpio 、mps,chg-m0-gpio 为GPIO值
qcom,client-vadc 指定了PMIC的node,同样也是在mdmxx_mtp.dtsi中,详细的在PMIC的部分再说。
主体在probe函数中,接下来对该函数简单的分析下:
static int mp2617_probe(struct platform_device *pdev)
{
rc = mp2617_gpio_configs(chip);//读取dts中的gpio配置
if (rc) {
return rc;
}
rc = mp2617_apply_dt_configs(chip);//读取dts中其他配置,PMIC设备
if (rc) {
return rc;
}
rc = qpnp_vadc_read(chip->vadc_dev, P_MUX1_1_1, &results);//读取pmic中电压值
init_voltage = ((int)(results.physical * chip->charging_vbat_div)/1000);
chip->psy.name = "battery";
chip->psy.type = POWER_SUPPLY_TYPE_BATTERY;
chip->psy.properties = mp2617_power_properties;
chip->psy.num_properties = ARRAY_SIZE(mp2617_power_properties);
chip->psy.get_property = mp2617_power_get_property;
chip->psy.set_property = mp2617_power_set_property;
chip->psy.property_is_writeable = mp2617_property_is_writeable;
chip->psy.external_power_changed = mp2617_external_power_changed;//配置变化后重新配置IC
rc = power_supply_register(dev, &chip->psy);//注册power supply
mp2617_external_power_changed(&chip->psy);//开始充电配置
rc = mp2617_init_usb_detect(chip);//注册充电自动检测
return rc;
}
mp2617_gpio_configs 函数是读取DTS中的gpio值
mp2617_apply_dt_configs 这个函数比较重要,他需要获取dts中配置的PMIC设备qcom,client-vadc = <&pmd9635_vadc>,后续可以从PMIC中获取相应的电压值。
qpnp_vadc_read就是从PMIC中获取电池电压
mp2617_external_power_changed 开始充电配置,这个是主要控制充电的步骤,初始化时不充电,后面中断函数中会再次调用
mp2617_init_usb_detect 初始化自动检测电池的中断以及相应的work
mp2617_init_usb_detect 中schedule_work(&chip->usb_plug_det.work),handler就是mp2617_usb_det_work_func
static void mp2617_usb_det_work_func(struct work_struct *work)
{
struct mp2617_usb_plug_det_st *bdata =
container_of(work, struct mp2617_usb_plug_det_st, work);
int state = ((gpio_get_value_cansleep(bdata->gpio) ? 1 : 0) ^ bdata->active_low);//读取GPIO值
if(bdata->usb_online != state) {
if(1 == state) {
handle_usb_insertion(bdata->chip);//usb插入
} else {
handle_usb_removal(bdata->chip);//usb移除
}
bdata->usb_online = state;
} else {
dev_err(&bdata->chip->client->dev, "some usb hotplug event may be lost\n");
}
}
如果启动时未插入USB,那么就什么都不做,而是等待GPIO 中断,也是在mp2617_init_usb_detect注册的
static int mp2617_init_usb_detect(struct mp2617_chip *chip)
{
chip->usb_plug_det.gpio = chip->charging_ac_ok_gpio;
chip->usb_plug_det.irq = gpio_to_irq(chip->usb_plug_det.gpio);
isr = mp2617_usb_det_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
request_any_context_irq(chip->usb_plug_det.irq, isr, irqflags, "usb_plug_detect", (void *)&chip->usb_plug_det);
}
不管是启动就有USB,还是中断响应处理函数mp2617_usb_det_isr,最后都会调用上面det 的handler,mp2617_usb_det_work_func调用栈如下:
mp2617_usb_det_work_func
---handle_usb_insertion
---power_supply_set_present
---mp2617_power_set_property
---power_supply_changed
---mp2617_external_power_changed//开始充电
probe函数中已定义了支持的sys fs参数值
static enum power_supply_property mp2617_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_CHG_OK,
};
对应的get set handler分别为mp2617_power_get_property & mp2617_power_set_property
对应的sysfs为
charging_enabled 可以开关充电
temp 读取温度
current_max 最大充电电流
voltage_now 电池电压