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;
}