From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 29 Feb 2020 01:04:33 -0600
Subject: power: supply: axp20x_battery: Monitor battery health

Signed-off-by: Samuel Holland <samuel@sholland.org>
---
 drivers/power/supply/axp20x_battery.c | 58 +++++++++-
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
index a9e577768c90..97b11f05803e 100644
--- a/drivers/power/supply/axp20x_battery.c
+++ b/drivers/power/supply/axp20x_battery.c
@@ -81,6 +81,7 @@ struct axp20x_batt_ps {
 	struct iio_channel *batt_chrg_i;
 	struct iio_channel *batt_dischrg_i;
 	struct iio_channel *batt_v;
+	int health;
 	/* Maximum constant charge current */
 	unsigned int max_ccc;
 	const struct axp_data	*data;
@@ -272,7 +273,7 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
 			return 0;
 		}
 
-		val->intval = POWER_SUPPLY_HEALTH_GOOD;
+		val->intval = axp20x_batt->health;
 		break;
 
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
@@ -564,6 +565,39 @@ static irqreturn_t axp20x_battery_changed_irq(int irq, void *devid)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t axp20x_battery_temp_cold_irq(int irq, void *devid)
+{
+	struct axp20x_batt_ps *axp20x_batt = devid;
+
+	axp20x_batt->health = POWER_SUPPLY_HEALTH_COLD;
+
+	power_supply_changed(axp20x_batt->batt);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t axp20x_battery_temp_hot_irq(int irq, void *devid)
+{
+	struct axp20x_batt_ps *axp20x_batt = devid;
+
+	axp20x_batt->health = POWER_SUPPLY_HEALTH_OVERHEAT;
+
+	power_supply_changed(axp20x_batt->batt);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t axp20x_battery_temp_normal_irq(int irq, void *devid)
+{
+	struct axp20x_batt_ps *axp20x_batt = devid;
+
+	axp20x_batt->health = POWER_SUPPLY_HEALTH_GOOD;
+
+	power_supply_changed(axp20x_batt->batt);
+
+	return IRQ_HANDLED;
+}
+
 static const struct axp_irq_data axp20x_irqs[] = {
 	{ "BATT_PLUGIN",		axp20x_battery_changed_irq },
 	{ "BATT_REMOVAL",		axp20x_battery_changed_irq },
@@ -574,6 +608,24 @@ static const struct axp_irq_data axp20x_irqs[] = {
 	{}
 };
 
+static const struct axp_irq_data axp813_irqs[] = {
+	{ "BATT_PLUGIN",		axp20x_battery_changed_irq },
+	{ "BATT_REMOVAL",		axp20x_battery_changed_irq },
+	{ "BATT_HEALTH_DEAD",		axp20x_battery_changed_irq },
+	{ "BATT_HEALTH_GOOD",		axp20x_battery_changed_irq },
+	{ "BATT_CHARGING",		axp20x_battery_changed_irq },
+	{ "BATT_CHARGING_DONE",		axp20x_battery_changed_irq },
+	{ "BATT_CHG_TEMP_HIGH",		axp20x_battery_temp_hot_irq },
+	{ "BATT_CHG_TEMP_HIGH_END",	axp20x_battery_temp_normal_irq },
+	{ "BATT_CHG_TEMP_LOW",		axp20x_battery_temp_cold_irq },
+	{ "BATT_CHG_TEMP_LOW_END",	axp20x_battery_temp_normal_irq },
+	{ "BATT_ACT_TEMP_HIGH",		axp20x_battery_temp_hot_irq },
+	{ "BATT_ACT_TEMP_HIGH_END",	axp20x_battery_temp_normal_irq },
+	{ "BATT_ACT_TEMP_LOW",		axp20x_battery_temp_cold_irq },
+	{ "BATT_ACT_TEMP_LOW_END",	axp20x_battery_temp_normal_irq },
+	{}
+};
+
 static const struct axp_data axp209_data = {
 	.ccc_scale = 100000,
 	.ccc_offset = 300000,
@@ -597,7 +649,7 @@ static const struct axp_data axp813_data = {
 	.has_fg_valid = true,
 	.get_max_voltage = axp813_battery_get_max_voltage,
 	.set_max_voltage = axp20x_battery_set_max_voltage,
-	.irqs = axp20x_irqs,
+	.irqs = axp813_irqs,
 };
 
 static const struct of_device_id axp20x_battery_ps_id[] = {
@@ -674,6 +726,8 @@ static int axp20x_power_probe(struct platform_device *pdev)
 		return PTR_ERR(axp20x_batt->batt);
 	}
 
+	axp20x_batt->health = POWER_SUPPLY_HEALTH_GOOD;
+
 	if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
 		int vmin = info->voltage_min_design_uv;
 		int ccc = info->constant_charge_current_max_ua;
-- 
Armbian

