power: supply: qti_battery_charger: add thermal mitigation support

Add "qcom,thermal-mitigation" property to specify charging
current thresholds for thermal mitigation levels. These values
will be passed on to the charger firmware running on a remote
subsystem when thermal SW sets CHARGE_CONTROL_LIMIT property in
battery power supply.

Change-Id: I67be3f9012718de9b2cd529ed6043fb54f503003
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
This commit is contained in:
Subbaraman Narayanamurthy 2020-02-25 18:37:26 -08:00 committed by Anjelique Melendez
parent e72f2c89ce
commit d88934ddf0

View File

@ -7,6 +7,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rpmsg.h>
#include <linux/mutex.h>
@ -144,6 +145,9 @@ struct battery_chg_dev {
struct mutex rw_lock;
struct completion ack;
struct psy_state psy_list[PSY_TYPE_MAX];
u32 *thermal_levels;
int curr_thermal_level;
int num_thermal_levels;
};
static const int battery_prop_map[BATT_PROP_MAX] = {
@ -616,6 +620,30 @@ static const struct power_supply_desc usb_psy_desc = {
.property_is_writeable = usb_psy_prop_is_writeable,
};
static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
int val)
{
int rc;
u32 fcc_ua;
if (!bcdev->num_thermal_levels)
return 0;
if (val < 0 || val > bcdev->num_thermal_levels)
return -EINVAL;
fcc_ua = bcdev->thermal_levels[val];
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY],
BATT_CHG_CTRL_LIM, fcc_ua);
if (!rc) {
bcdev->curr_thermal_level = val;
pr_debug("Set FCC to %u uA\n", fcc_ua);
}
return rc;
}
static int battery_psy_get_prop(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *pval)
@ -644,6 +672,12 @@ static int battery_psy_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_TEMP:
pval->intval = DIV_ROUND_CLOSEST((int)pst->prop[prop_id], 10);
break;
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
pval->intval = bcdev->curr_thermal_level;
break;
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
pval->intval = bcdev->num_thermal_levels;
break;
default:
pval->intval = pst->prop[prop_id];
break;
@ -656,12 +690,28 @@ static int battery_psy_set_prop(struct power_supply *psy,
enum power_supply_property prop,
const union power_supply_propval *pval)
{
struct battery_chg_dev *bcdev = power_supply_get_drvdata(psy);
switch (prop) {
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
return battery_psy_set_charge_current(bcdev, pval->intval);
default:
return -EINVAL;
}
return 0;
}
static int battery_psy_prop_is_writeable(struct power_supply *psy,
enum power_supply_property prop)
{
switch (prop) {
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
return 1;
default:
break;
}
return 0;
}
@ -867,6 +917,53 @@ static struct attribute *battery_class_attrs[] = {
};
ATTRIBUTE_GROUPS(battery_class);
static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
{
struct device_node *node = bcdev->dev->of_node;
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
int i, rc, len;
rc = of_property_count_elems_of_size(node, "qcom,thermal-mitigation",
sizeof(u32));
if (rc <= 0)
return 0;
len = rc;
bcdev->thermal_levels = devm_kcalloc(bcdev->dev, len + 1,
sizeof(*bcdev->thermal_levels),
GFP_KERNEL);
if (!bcdev->thermal_levels)
return -ENOMEM;
/*
* Element 0 is for normal charging current. Elements from index 1
* onwards is for thermal mitigation charging currents.
*/
rc = of_property_read_u32_array(node, "qcom,thermal-mitigation",
&bcdev->thermal_levels[1], len);
if (rc < 0) {
pr_err("Error in reading qcom,thermal-mitigation, rc=%d\n", rc);
return rc;
}
rc = read_property_id(bcdev, pst, BATT_CHG_CTRL_LIM_MAX);
if (rc < 0)
return rc;
bcdev->thermal_levels[0] = pst->prop[BATT_CHG_CTRL_LIM_MAX];
for (i = 1; i <= len; i++) {
if (bcdev->thermal_levels[i] > bcdev->thermal_levels[i - 1]) {
pr_err("Thermal levels should be in descending order\n");
return -EINVAL;
}
}
bcdev->num_thermal_levels = len;
return 0;
}
static int battery_chg_probe(struct platform_device *pdev)
{
struct battery_chg_dev *bcdev;
@ -905,7 +1002,10 @@ static int battery_chg_probe(struct platform_device *pdev)
if (!bcdev->psy_list[PSY_TYPE_BATTERY].model)
return -ENOMEM;
mutex_init(&bcdev->rw_lock);
init_completion(&bcdev->ack);
bcdev->dev = dev;
client_data.id = MSG_OWNER_BC;
client_data.name = "battery_charger";
client_data.msg_cb = battery_chg_callback;
@ -920,9 +1020,11 @@ static int battery_chg_probe(struct platform_device *pdev)
return rc;
}
rc = battery_chg_parse_dt(bcdev);
if (rc < 0)
goto error;
platform_set_drvdata(pdev, bcdev);
mutex_init(&bcdev->rw_lock);
init_completion(&bcdev->ack);
rc = battery_chg_init_psy(bcdev);
if (rc < 0)
goto error;