diff options
author | Konrad Dybcio <konrad.dybcio@linaro.org> | 2023-09-16 02:31:59 +0200 |
---|---|---|
committer | Sebastian Reichel <sebastian.reichel@collabora.com> | 2023-09-17 00:42:12 +0200 |
commit | e39257cde7e8ceec6165f54b6e20c72e2862a0b1 (patch) | |
tree | f23365168e9526340ffb5f76f11cacd44ca47522 /drivers/power | |
parent | f8d7a3d21160a0cab4d15b81231f2a76b0fcee13 (diff) | |
download | lwn-e39257cde7e8ceec6165f54b6e20c72e2862a0b1.tar.gz lwn-e39257cde7e8ceec6165f54b6e20c72e2862a0b1.zip |
power: supply: mm8013: Add more properties
While scanning the internet for MM8013 PDFs, I found one for a different
IC from Mitsumi, MM8118 at [1]. It turned out however, that when you
search through the PDF, the MM8118 text has an invsible text layer
containing "MM8013" underneath..
With some elbow grease, I was able to confirm that most of the registers
match between the two ICs. Based on that finding, introduce live battery
voltage readout, hw-decided charge behavior readout and max current
readout. Also, expand the existing POWER_SUPPLY_HEALTH reporting.
[1] https://product.minebeamitsumi.com/en/product/category/ics/battery/fuel_gauge/parts/download/__icsFiles/afieldfile/2023/07/12/1_download_01_12.pdf
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20230916-topic-mm8013_2-v1-1-02495e07fca0@linaro.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/supply/mm8013.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c index bd8d54d6597f..ddac40ef9ae5 100644 --- a/drivers/power/supply/mm8013.c +++ b/drivers/power/supply/mm8013.c @@ -17,13 +17,21 @@ #define MM8013_FLAG_OTC BIT(15) #define MM8013_FLAG_OTD BIT(14) #define MM8013_FLAG_BATHI BIT(13) + #define MM8013_FLAG_BATLOW BIT(12) + #define MM8013_FLAG_CHG_INH BIT(11) #define MM8013_FLAG_FC BIT(9) #define MM8013_FLAG_CHG BIT(8) + #define MM8013_FLAG_OCC BIT(6) + #define MM8013_FLAG_ODC BIT(5) + #define MM8013_FLAG_OT BIT(4) + #define MM8013_FLAG_UT BIT(3) #define MM8013_FLAG_DSG BIT(0) #define REG_FULL_CHARGE_CAPACITY 0x0e +#define REG_NOMINAL_CHARGE_CAPACITY 0x0c #define REG_AVERAGE_CURRENT 0x14 #define REG_AVERAGE_TIME_TO_EMPTY 0x16 #define REG_AVERAGE_TIME_TO_FULL 0x18 +#define REG_MAX_LOAD_CURRENT 0x1e #define REG_CYCLE_COUNT 0x2a #define REG_STATE_OF_CHARGE 0x2c #define REG_DESIGN_CAPACITY 0x3c @@ -63,8 +71,11 @@ static int mm8013_checkdevice(struct mm8013_chip *chip) static enum power_supply_property mm8013_battery_props[] = { POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_HEALTH, @@ -92,6 +103,16 @@ static int mm8013_get_property(struct power_supply *psy, val->intval = regval; break; + case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR: + ret = regmap_read(chip->regmap, REG_FLAGS, ®val); + if (ret < 0) + return ret; + + if (regval & MM8013_FLAG_CHG_INH) + val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE; + else + val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO; + break; case POWER_SUPPLY_PROP_CHARGE_FULL: ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val); if (ret < 0) @@ -106,6 +127,20 @@ static int mm8013_get_property(struct power_supply *psy, val->intval = 1000 * regval; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = regmap_read(chip->regmap, REG_NOMINAL_CHARGE_CAPACITY, ®val); + if (ret < 0) + return ret; + + val->intval = 1000 * regval; + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + ret = regmap_read(chip->regmap, REG_MAX_LOAD_CURRENT, ®val); + if (ret < 0) + return ret; + + val->intval = -1000 * (s16)regval; + break; case POWER_SUPPLY_PROP_CURRENT_NOW: ret = regmap_read(chip->regmap, REG_AVERAGE_CURRENT, ®val); if (ret < 0) @@ -125,9 +160,15 @@ static int mm8013_get_property(struct power_supply *psy, if (ret < 0) return ret; - if (regval & MM8013_FLAG_BATHI) + if (regval & MM8013_FLAG_UT) + val->intval = POWER_SUPPLY_HEALTH_COLD; + else if (regval & (MM8013_FLAG_ODC | MM8013_FLAG_OCC)) + val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT; + else if (regval & (MM8013_FLAG_BATLOW)) + val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + else if (regval & MM8013_FLAG_BATHI) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; - else if (regval & (MM8013_FLAG_OTD | MM8013_FLAG_OTC)) + else if (regval & (MM8013_FLAG_OT | MM8013_FLAG_OTD | MM8013_FLAG_OTC)) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; else val->intval = POWER_SUPPLY_HEALTH_GOOD; |