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

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

Merge "of_batterydata: add functions to support SOH based profile loading"

parents 54fa48d1 c2da7953
Loading
Loading
Loading
Loading
+130 −0
Original line number Diff line number Diff line
@@ -468,6 +468,136 @@ struct device_node *of_batterydata_get_best_aged_profile(
	return best_node;
}

int of_batterydata_get_aged_profile_count(
		const struct device_node *batterydata_node,
		int batt_id_kohm, int *count)
{
	struct device_node *node;
	int id_range_pct, i = 0, rc = 0, limit = 0, delta = 0;
	bool in_range = false;
	u32 batt_id;

	/* read battery id range percentage for best profile */
	rc = of_property_read_u32(batterydata_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 -ENXIO;
		}
	}

	for_each_available_child_of_node(batterydata_node, node) {
		if (!of_find_property(node, "qcom,batt-age-level", NULL))
			continue;

		if (!of_find_property(node, "qcom,soh-range", NULL))
			continue;

		rc = of_property_read_u32(node, "qcom,batt-id-kohm", &batt_id);
		if (rc)
			continue;

		delta = abs(batt_id_kohm - batt_id);
		limit = (batt_id_kohm * id_range_pct) / 100;
		in_range = (delta <= limit);

		if (!in_range) {
			pr_debug("not in range batt_id: %d\n", batt_id);
			continue;
		}

		i++;
	}

	if (i <= 1) {
		pr_err("Less number of profiles to support SOH\n");
		return -EINVAL;
	}

	*count = i;
	return 0;
}

int of_batterydata_read_soh_aged_profiles(
		const struct device_node *batterydata_node,
		int batt_id_kohm, struct soh_range *soh_data)
{
	struct device_node *node;
	u32 val, temp[2], i = 0;
	int rc, batt_id, id_range_pct, limit = 0, delta = 0;
	bool in_range = false;

	if (!batterydata_node || !soh_data)
		return -ENODEV;

	/* read battery id range percentage for best profile */
	rc = of_property_read_u32(batterydata_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 -ENXIO;
		}
	}

	for_each_available_child_of_node(batterydata_node, node) {
		rc = of_property_read_u32(node, "qcom,batt-age-level", &val);
		if (rc)
			continue;

		rc = of_property_read_u32(node, "qcom,batt-id-kohm", &batt_id);
		if (rc)
			continue;

		delta = abs(batt_id_kohm - batt_id);
		limit = (batt_id_kohm * id_range_pct) / 100;
		in_range = (delta <= limit);

		if (!in_range) {
			pr_debug("not in range batt_id: %d\n", batt_id);
			continue;
		}

		if (!of_find_property(node, "qcom,soh-range", NULL))
			continue;

		rc = of_property_count_elems_of_size(node, "qcom,soh-range",
						sizeof(u32));
		if (rc != 2) {
			pr_err("Incorrect element size for qcom,soh-range, rc=%d\n",
				rc);
			return -EINVAL;
		}

		rc = of_property_read_u32_array(node, "qcom,soh-range", temp,
						2);
		if (rc < 0) {
			pr_err("Error in reading qcom,soh-range, rc=%d\n", rc);
			return rc;
		}

		if (temp[0] > 100 || temp[1] > 100 || (temp[0] > temp[1])) {
			pr_err("Incorrect SOH range [%d %d]\n", temp[0],
				temp[1]);
			return -ERANGE;
		}

		pr_debug("batt_age_level: %d soh: [%d %d]\n", val, temp[0],
			temp[1]);
		soh_data[i].batt_age_level = val;
		soh_data[i].soh_min = temp[0];
		soh_data[i].soh_max = temp[1];
		i++;
	}

	return 0;
}

int of_batterydata_read_data(struct device_node *batterydata_container_node,
				struct bms_battery_data *batt_data,
				int batt_id_uv)
+16 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2015, 2017, 2019 The Linux Foundation.
 * All rights reserved.
 */

#ifndef __BMS_BATTERYDATA_H
@@ -137,6 +138,20 @@ struct bms_battery_data {
	const char		*battery_type;
};

/**
 * struct soh_range -
 * @batt_age_level:	Battery age level (e.g. 0, 1 etc.,)
 * @soh_min:		Minimum SOH (state of health) level that this battery
 *			profile can support.
 * @soh_max:		Maximum SOH (state of health) level that this battery
 *			profile can support.
 */
struct soh_range {
	int	batt_age_level;
	int	soh_min;
	int	soh_max;
};

#define is_between(left, right, value) \
		(((left) >= (right) && (left) >= (value) \
			&& (value) >= (right)) \
+39 −0
Original line number Diff line number Diff line
@@ -56,6 +56,33 @@ struct device_node *of_batterydata_get_best_profile(
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);

/**
 * of_batterydata_get_aged_profile_count() - Gets the number of aged profiles
 * @batterydata_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.
 * @count: Number of aged profiles available to support SOH based profile
 * loading.
 *
 * This routine returns zero if valid number of aged profiles are available.
 */
int of_batterydata_get_aged_profile_count(
		const struct device_node *batterydata_node,
		int batt_id_kohm, int *count);

/**
 * of_batterydata_read_soh_aged_profiles() - Reads the data from aged profiles
 * @batterydata_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.
 * @soh_data: SOH data from the profile if it is found to be valid.
 *
 * This routine returns zero if SOH data of aged profiles is valid.
 */
int of_batterydata_read_soh_aged_profiles(
		const struct device_node *batterydata_node,
		int batt_id_kohm, struct soh_range *soh_data);
#else
static inline int of_batterydata_read_data(struct device_node *container_node,
				struct bms_battery_data *batt_data,
@@ -75,4 +102,16 @@ static inline struct device_node *of_batterydata_get_best_aged_profile(
{
	return NULL;
}
static inline int of_batterydata_get_aged_profile_count(
		const struct device_node *batterydata_node,
		int batt_id_kohm, int *count)
{
	return -EINVAL;
}
static inline int of_batterydata_read_soh_aged_profiles(
		const struct device_node *batterydata_node,
		int batt_id_kohm, struct soh_range *soh_data)
{
	return -EINVAL;
}
#endif /* CONFIG_OF_BATTERYDATA */