int of_batterydata_read_data(struct device_node *batterydata_container_node, struct bms_battery_data *batt_data, int batt_id_uv) { struct device_node *node, *best_node, *df_node; struct batt_id_rng id_range; size_t sz = sizeof(struct batt_id_rng) / sizeof(int); struct batt_ids batt_ids; int delta, best_delta, batt_id_kohm, rpull_up_kohm, vadc_vdd_uv, best_id_kohm, i, rc = 0; int default_kohm; node = batterydata_container_node; OF_PROP_READ(rpull_up_kohm, "rpull-up-kohm", node, rc, false); OF_PROP_READ(vadc_vdd_uv, "vref-batt-therm-uv", node, rc, false); if (rc) return rc; OF_PROP_READ(default_kohm, "default-kohm", node, rc, true); df_node = NULL; batt_id_kohm = of_batterydata_convert_battery_id_kohm(batt_id_uv, rpull_up_kohm, vadc_vdd_uv); best_node = NULL; best_delta = 0; best_id_kohm = 0; /* * Find the battery data with a battery id resistor closest to this one */ for_each_child_of_node(batterydata_container_node, node) { 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); if (delta < best_delta || !best_node) { best_node = node; best_delta = delta; best_id_kohm = batt_ids.kohm[i]; } if ((default_kohm != -EINVAL) && (batt_ids.kohm[i] == default_kohm)) df_node = node; } }
int of_batterydata_read_data(struct device_node *batterydata_container_node, struct bms_battery_data *batt_data, int batt_id_uv) { struct device_node *node, *best_node; struct batt_ids batt_ids; const char *battery_type = NULL; int delta, best_delta, batt_id_kohm, rpull_up_kohm, vadc_vdd_uv, best_id_kohm, i, rc = 0; node = batterydata_container_node; OF_PROP_READ(rpull_up_kohm, "rpull-up-kohm", node, rc, false); OF_PROP_READ(vadc_vdd_uv, "vref-batt-therm", node, rc, false); if (rc) return rc; batt_id_kohm = of_batterydata_convert_battery_id_kohm(batt_id_uv, rpull_up_kohm, vadc_vdd_uv); pr_info("[BATT][BMS] batt_id_kohm=%d\n",batt_id_kohm); best_node = NULL; best_delta = 0; best_id_kohm = 0; /* * Find the battery data with a battery id resistor closest to this one */ for_each_child_of_node(batterydata_container_node, node) { 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); if (delta < best_delta || !best_node) { best_node = node; best_delta = delta; best_id_kohm = batt_ids.kohm[i]; } } }
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; psy = power_supply_get_by_name(psy_name); 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; /* * 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); if (!rc && strcmp(battery_type, batt_type) == 0) { best_node = node; best_id_kohm = batt_id_kohm; break; } } else { 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); if (delta < best_delta || !best_node) { 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; } /* read battery id value for best profile */ rc = of_property_read_u32(batterydata_container_node, "qcom,batt-id-range-pct", &id_range_pct); if (!rc) { /* 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; } } else if (rc == -EINVAL) { rc = 0; } else { pr_err("failed to read battery id range\n"); return ERR_PTR(-ENXIO); } 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; }
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, *default_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 = power_supply_get_by_name(psy_name); 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; /* read battery id range percentage for best profile */ rc = of_property_read_u32(batterydata_container_node, "qcom,batt-id-range-pct", &id_range_pct); if (rc) { if (rc == -EINVAL) { id_range_pct = 0; } else { pr_err("failed to read battery id range\n"); return ERR_PTR(-ENXIO); } } /* * 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); if (!rc && strcmp(battery_type, batt_type) == 0) { best_node = node; best_id_kohm = batt_id_kohm; break; } } else { 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; 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. */ if ((delta < best_delta || !best_node) && in_range) { best_node = node; best_delta = delta; best_id_kohm = batt_ids.kohm[i]; } if (batt_ids.kohm[i] == DEFAULT_BATT_ID) default_node = node; } } } if (best_node == NULL) { pr_err("No battery data found\n"); /* if no battery id is matched, we will use default */ /* qcom profile (itech-3000mah) which's id is 1000k */ best_node = default_node; pr_info("use default battery data\n"); return best_node; } /* 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; } 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; }