build/patch/kernel/archive/sunxi-6.4/patches.megous/power-supply-ip5xxx-Report-remaining-battery-capacity.patch

128 lines
3.8 KiB
Diff

From dbc533df603115a5e91b9b333ede234b40ffcc75 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Wed, 16 Feb 2022 18:12:56 +0100
Subject: [PATCH 382/469] power: supply: ip5xxx: Report remaining battery
capacity
This uses OCV tables from device tree. Internal resistance value used
by the chip is not very precise. Use the value from DT, too.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
drivers/power/supply/ip5xxx_power.c | 43 +++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/drivers/power/supply/ip5xxx_power.c b/drivers/power/supply/ip5xxx_power.c
index 00221e9c0bfc..7f79644a976a 100644
--- a/drivers/power/supply/ip5xxx_power.c
+++ b/drivers/power/supply/ip5xxx_power.c
@@ -76,6 +76,8 @@
struct ip5xxx {
struct regmap *regmap;
+ struct power_supply_battery_info *bat;
+ int r_int;
bool initialized;
};
@@ -171,6 +173,8 @@ static const enum power_supply_property ip5xxx_battery_properties[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CALIBRATE,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_OCV,
@@ -316,6 +320,7 @@ static int ip5xxx_battery_get_property(struct power_supply *psy,
struct ip5xxx *ip5xxx = power_supply_get_drvdata(psy);
int raw, ret, vmax;
unsigned int rval;
+ union power_supply_propval cur, vol;
ret = ip5xxx_initialize(psy);
if (ret)
@@ -331,6 +336,23 @@ static int ip5xxx_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_HEALTH:
return ip5xxx_battery_get_health(ip5xxx, &val->intval);
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = ip5xxx_battery_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &vol);
+ if (ret)
+ return ret;
+
+ ret = ip5xxx_battery_get_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &cur);
+ if (ret)
+ return ret;
+
+ ret = power_supply_batinfo_ocv2cap(ip5xxx->bat,
+ vol.intval - cur.intval * ip5xxx->r_int / 1000, 20);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
+ return 0;
+
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
return ip5xxx_battery_get_voltage_max(ip5xxx, &val->intval);
@@ -389,6 +411,10 @@ static int ip5xxx_battery_get_property(struct power_supply *psy,
val->intval = vmax + 14000 * 3;
return 0;
+ case POWER_SUPPLY_PROP_CALIBRATE:
+ val->intval = ip5xxx->r_int;
+ return 0;
+
default:
return -EINVAL;
}
@@ -472,6 +498,12 @@ static int ip5xxx_battery_set_property(struct power_supply *psy,
return ip5xxx_update_bits(ip5xxx, IP5XXX_CHG_CTL2,
IP5XXX_CHG_CTL2_CONST_VOLT_SEL, rval);
+ case POWER_SUPPLY_PROP_CALIBRATE:
+ if (val->intval < 0 || val->intval > 1000)
+ return -EINVAL;
+ ip5xxx->r_int = val->intval;
+ return 0;
+
default:
return -EINVAL;
}
@@ -482,6 +514,7 @@ static int ip5xxx_battery_property_is_writeable(struct power_supply *psy,
{
return psp == POWER_SUPPLY_PROP_STATUS ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
+ psp == POWER_SUPPLY_PROP_CALIBRATE ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
}
@@ -592,6 +625,7 @@ static int ip5xxx_power_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct power_supply *psy;
struct ip5xxx *ip5xxx;
+ int ret;
ip5xxx = devm_kzalloc(dev, sizeof(*ip5xxx), GFP_KERNEL);
if (!ip5xxx)
@@ -612,6 +646,15 @@ static int ip5xxx_power_probe(struct i2c_client *client)
if (IS_ERR(psy))
return PTR_ERR(psy);
+ ret = power_supply_get_battery_info(psy, &ip5xxx->bat);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get battery info\n");
+
+ if (ip5xxx->bat->factory_internal_resistance_uohm >= 0)
+ ip5xxx->r_int = ip5xxx->bat->factory_internal_resistance_uohm / 1000;
+ else
+ ip5xxx->r_int = 120;
+
return 0;
}
--
2.34.1