1. compatible节点:
qpnp-vm-bms.c使用来控制电池曲线的和BMS功能的,其compatible节点是"qcom,qpnp-vm-bms"
2. probe函数:
qpnp_vm_bms_probe函数如下:
static int qpnp_vm_bms_probe(struct spmi_device *spmi)
{
struct qpnp_bms_chip *chip;
struct device_node *revid_dev_node;
int rc, vbatt = 0;
chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
if (!chip) {
pr_err("kzalloc() failed.\n");
return -ENOMEM;
}
//获取ADC的值,ADC是电流的大小,绑定vadc,并且获取温度,设备列表
rc = bms_get_adc(chip, spmi);
if (rc < 0) {
pr_err("Failed to get adc rc=%d\n", rc);
return rc;
}
//指向revision外围节点的phandle,vm-bus需要配置这个节点
revid_dev_node = of_parse_phandle(spmi->dev.of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
pr_err("Missing qcom,pmic-revid property\n");
return -EINVAL;
}
//返回pmic的修订信息
chip->revid_data = get_revid_data(revid_dev_node);
if (IS_ERR(chip->revid_data)) {
pr_err("revid error rc = %ld\n", PTR_ERR(chip->revid_data));
return -EINVAL;
}
if ((chip->revid_data->pmic_subtype == PM8916_V2P0_SUBTYPE) &&
chip->revid_data->rev4 == PM8916_V2P0_REV4)
chip->workaround_flag |= WRKARND_PON_OCV_COMP;
//查看是否是热启动的,热启动就是在不关闭设备的情况下,重启电脑
rc = qpnp_pon_is_warm_reset();
if (rc < 0) {
pr_err("Error reading warm reset status rc=%d\n", rc);
return rc;
}
chip->warm_reset = !!rc;
//解析spmi设备的内容,并且在其中寻找它的中断基地址
rc = parse_spmi_dt_properties(chip, spmi);
if (rc) {
pr_err("Error registering spmi resource rc=%d\n", rc);
return rc;
}
//解析电池的参数,如v-cutoff-uv,关机电压,它不会读qcom的内容,会直接读qcom,后面的内容会有仔细说
rc = parse_bms_dt_properties(chip);
if (rc) {
pr_err("Unable to read all bms properties, rc = %d\n", rc);
return rc;
}
//查询错误的原因
if (chip->dt.cfg_disable_bms) {
pr_info("VMBMS disabled (disable-bms = 1)\n");
rc = qpnp_masked_write_base(chip, chip->base + EN_CTL_REG,
BMS_EN_BIT, 0);
if (rc)
pr_err("Unable to disable VMBMS rc=%d\n", rc);
return -ENODEV;
}
//读取存在pm?PM里读出来的未经修正的原始数据?
rc = qpnp_read_wrapper(chip, chip->revision,
chip->base + REVISION1_REG, 2);
if (rc) {
pr_err("Error reading version register rc=%d\n", rc);
return rc;
}
pr_debug("BMS version: %hhu.%hhu\n",
chip->revision[1], chip->revision[0]);
dev_set_drvdata(&spmi->dev, chip);
device_init_wakeup(&spmi->dev, 1);
mutex_init(&chip->bms_data_mutex);
mutex_init(&chip->bms_device_mutex);
mutex_init(&chip->last_soc_mutex);
mutex_init(&chip->state_change_mutex);
init_waitqueue_head(&chip->bms_wait_q); //初始化队列
/* read battery-id and select the battery profile */
//设置电池数据,也就是电池曲线
rc = set_battery_data(chip);
if (rc) {
pr_err("Unable to read battery data %d\n", rc);
goto fail_init;
}
/* set the battery profile */
//设置电池的配置文件,其实也就是配置刚刚设置好的全局变量了
rc = config_battery_data(chip->batt_data);
if (rc) {
pr_err("Unable to config battery data %d\n", rc);
goto fail_init;
}
//初始化wakeup_source,内核睡眠机制
wakeup_source_init(&chip->vbms_lv_wake_source.source, "vbms_lv_wake");
wakeup_source_init(&chip->vbms_cv_wake_source.source, "vbms_cv_wake");
wakeup_source_init(&ch