Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73001273 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "of: batterydata: Add support to get best battery profile based on age level"

parents 8ee5bf05 570376d8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -139,6 +139,8 @@ Profile data node optional properties:
			JEITA conditions (cool/warm).
			Element 0 - FV value for soft cool.
			Element 1 - FV value for soft warm.
- qcom,batt-age-level:  Battery age level. This is used only when multiple
			profile loading is supported.
Profile data node required subnodes:
- qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes
			temperature to fcc lookup. The units for this lookup
+78 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -398,6 +398,83 @@ struct device_node *of_batterydata_get_best_profile(
	return best_node;
}

struct device_node *of_batterydata_get_best_aged_profile(
		const struct device_node *batterydata_container_node,
		int batt_id_kohm, int batt_age_level, int *avail_age_level)
{
	struct batt_ids batt_ids;
	struct device_node *node, *best_node = NULL;
	const char *battery_type = NULL;
	int delta = 0, best_id_kohm = 0, id_range_pct, i = 0, rc = 0, limit = 0;
	u32 val;
	bool in_range = false;

	/* 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_available_child_of_node(batterydata_container_node, node) {
		val = 0;
		of_property_read_u32(node, "qcom,batt-age-level", &val);
		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 battery aging level matches and the
			 * limits are in range before selecting the best node.
			 */
			if ((batt_age_level == val || !best_node) && in_range) {
				best_node = node;
				best_id_kohm = batt_ids.kohm[i];
				*avail_age_level = val;
				break;
			}
		}
	}

	if (best_node == NULL) {
		pr_err("No battery data found\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 age level %d found\n", battery_type,
			*avail_age_level);
	else
		pr_info("%s age level %d found\n", best_node->name,
			*avail_age_level);

	return best_node;
}

int of_batterydata_read_data(struct device_node *batterydata_container_node,
				struct bms_battery_data *batt_data,
				int batt_id_uv)
+1 −0
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ static struct device_attribute power_supply_attrs[] = {
	POWER_SUPPLY_ATTR(fg_reset),
	POWER_SUPPLY_ATTR(qc_opti_disable),
	POWER_SUPPLY_ATTR(cc_soc),
	POWER_SUPPLY_ATTR(batt_age_level),
	/* Charge pump properties */
	POWER_SUPPLY_ATTR(cp_status1),
	POWER_SUPPLY_ATTR(cp_status2),
+23 −2
Original line number Diff line number Diff line
/* Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -48,6 +48,21 @@ int of_batterydata_read_data(struct device_node *container_node,
struct device_node *of_batterydata_get_best_profile(
		struct device_node *batterydata_container_node,
		int batt_id_kohm, const char *batt_type);

/**
 * of_batterydata_get_best_aged_profile() - Find best aged battery profile
 * @batterydata_container_node: pointer to the battery-data container device
 *		node containing the profile nodes.
 * @batt_id_kohm: Battery ID in KOhms for which we want to find the profile.
 * @batt_age_level: Battery age level.
 * @avail_age_level: Available battery age level.
 *
 * This routine returns a device_node pointer to the closest match battery data
 * from device tree based on the battery id reading and age level.
 */
struct device_node *of_batterydata_get_best_aged_profile(
		const struct device_node *batterydata_container_node,
		int batt_id_kohm, int batt_age_level, int *avail_age_level);
#else
static inline int of_batterydata_read_data(struct device_node *container_node,
				struct bms_battery_data *batt_data,
@@ -59,6 +74,12 @@ static inline struct device_node *of_batterydata_get_best_profile(
		struct device_node *batterydata_container_node,
		int batt_id_kohm, const char *batt_type)
{
	return -ENXIO;
	return NULL;
}
static inline struct device_node *of_batterydata_get_best_aged_profile(
		const struct device_node *batterydata_container_node,
		int batt_id_kohm, u32 batt_age_level)
{
	return NULL;
}
#endif /* CONFIG_OF_QPNP */
+1 −0
Original line number Diff line number Diff line
@@ -321,6 +321,7 @@ enum power_supply_property {
	POWER_SUPPLY_PROP_FG_RESET,
	POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
	POWER_SUPPLY_PROP_CC_SOC,
	POWER_SUPPLY_PROP_BATT_AGE_LEVEL,
	/* Charge pump properties */
	POWER_SUPPLY_PROP_CP_STATUS1,
	POWER_SUPPLY_PROP_CP_STATUS2,