struct device_node *of_batterydata_get_best_profile(
const struct device_node *batterydata_container_node,
const char *psy_name, const char *batt_type)
{
struct batt_ids batt_ids;
struct device_node *node, *best_node = NULL;
struct power_supply *psy;
const char *battery_type = NULL;
union power_supply_propval ret = {0, };
int delta = 0, best_delta = 0, best_id_kohm = 0, id_range_pct,
batt_id_kohm = 0, i = 0, rc = 0, limit = 0;
bool in_range = false;
// 找到psy_name注册的句柄
psy = power_supply_get_by_name(psy_name); // "bms"
if (!psy) {
pr_err("%s supply not found. defer\n", psy_name);
return ERR_PTR(-EPROBE_DEFER);
}
// 获得获得某一个属性的值
rc = psy->get_property(psy, POWER_SUPPLY_PROP_RESISTANCE_ID, &ret);
if (rc) {
pr_err("failed to retrieve resistance value rc=%d\n", rc);
return ERR_PTR(-ENOSYS);
}
batt_id_kohm = ret.intval / 1000;
pr_info("battery_id_ohm : %d (kohm) \n",batt_id_kohm);
// 读取差异百分比
/* read battery id range percentage for best profile */
rc = of_property_read_u32(batterydata_container_node,
"qcom,batt-id-range-pct", &id_range_pct); // 成功返回0 id_range_pct = 15 ??
if (rc) {
if (rc == -EINVAL) {
id_range_pct = 0;
} else {
pr_err("failed to read battery id range\n");
return ERR_PTR(-ENXIO);
}
}
/* 读取电池类型 10k 220k
* Find the battery data with a battery id resistor closest to this one
*/
for_each_child_of_node(batterydata_container_node, node) {
if (batt_type != NULL) {
rc = of_property_read_string(node, "qcom,battery-type",
&battery_type); // 读取dts中类型
if (!rc && strcmp(battery_type, batt_type) == 0) {// 在batt_type已知的情况下,匹配则赋值
best_node = node;
best_id_kohm = batt_id_kohm; // 10 or 220
break;
}
} else { //在batt_type未知的情况下,遍历 然后赋值
rc = of_batterydata_read_batt_id_kohm(node,
"qcom,batt-id-kohm",
&batt_ids);
if (rc)
continue;
for (i = 0; i < batt_ids.num; i++) {
delta = abs(batt_ids.kohm[i] - batt_id_kohm);
limit = (batt_ids.kohm[i] * id_range_pct) / 100; // 15%
in_range = (delta <= limit); // 是否再范围内 如果不在范围内 则下面的判断直接出局
/*
* Check if the delta is the lowest one
* and also if the limits are in range
* before selecting the best node.
*/
in_range = true; /*2017.1.13 terry add:use first node as default*/
if ((delta < best_delta || !best_node) // best_node为假 或者delta小于最优delta
&& in_range) { // 很精华
best_node = node;
best_delta = delta;
best_id_kohm = batt_ids.kohm[i];
}
}
}
}
if (best_node == NULL) {
pr_err("No battery data found\n");
return best_node;
}
// 当找到与这个物理ID最接近的电池参数后,再来检查一遍 为什么还要再检查一遍的 前面难道不能保证?
#if 0
/* check that profile id is in range of the measured batt_id */
if (abs(best_id_kohm - batt_id_kohm) >
((best_id_kohm * id_range_pct) / 100)) {
pr_err("out of range: profile id %d batt id %d pct %d",
best_id_kohm, batt_id_kohm, id_range_pct);
return NULL;
}
#endif
rc = of_property_read_string(best_node, "qcom,battery-type",
&battery_type);
if (!rc)
pr_info("%s found\n", battery_type);
else
pr_info("%s found\n", best_node->name);
return best_node;
}
get best profile
最新推荐文章于 2024-01-20 11:55:07 发布