diff options
author | Dima Zavin <dima@android.com> | 2011-08-25 15:28:59 -0700 |
---|---|---|
committer | Dima Zavin <dima@android.com> | 2011-08-25 15:47:06 -0700 |
commit | ba91b173ad2c548ddb86a59d3996366d211d7694 (patch) | |
tree | 318e0796edd685f95dbc065aa1da279d1b971068 /drivers/power | |
parent | e0af0b0ad22b1ad1c3837c0224498c18cebe29fc (diff) | |
download | kernel_samsung_tuna-ba91b173ad2c548ddb86a59d3996366d211d7694.zip kernel_samsung_tuna-ba91b173ad2c548ddb86a59d3996366d211d7694.tar.gz kernel_samsung_tuna-ba91b173ad2c548ddb86a59d3996366d211d7694.tar.bz2 |
power: max17040: add support for scaling the reported capacity
The battery capacity reported may not always be representative of
how much charge is actually remaining. When the battery is almost empty,
the output voltage may dip and go below the threshold for safe operation.
The "almost empty" watermark will be different for different designs so it
needs to be passed through platform data.
The battery reported capacity is thus scaled from [min,~100] to [0,100].
Change-Id: I257c67bcc9b47d833f0bcea9831f6c4a4486a58b
Signed-off-by: Dima Zavin <dima@android.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/max17040_battery.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c index 68322b3..895f207 100644 --- a/drivers/power/max17040_battery.c +++ b/drivers/power/max17040_battery.c @@ -139,16 +139,32 @@ static void max17040_get_vcell(struct i2c_client *client) chip->vcell = ((msb << 4) + (lsb >> 4)) * 1250; } +#define TO_FIXED(a,b) (((a) << 8) + (b)) +#define FIXED_TO_INT(x) ((int)((x) >> 8)) +#define FIXED_MULT(x,y) ((((u32)(x) * (u32)(y)) + (1 << 7)) >> 8) +#define FIXED_DIV(x,y) ((((u32)(x) << 8) + ((u32)(y) >> 1)) / (u32)(y)) + static void max17040_get_soc(struct i2c_client *client) { struct max17040_chip *chip = i2c_get_clientdata(client); u8 msb; u8 lsb; + u32 val; + u32 fmin_cap = TO_FIXED(chip->pdata->min_capacity, 0); msb = max17040_read_reg(client, MAX17040_SOC_MSB); lsb = max17040_read_reg(client, MAX17040_SOC_LSB); - chip->soc = min(msb, (u8)100); + /* convert msb.lsb to Q8.8 */ + val = TO_FIXED(msb, lsb); + if (val <= fmin_cap) { + chip->soc = 0; + return; + } + + val = FIXED_MULT(TO_FIXED(100, 0), val - fmin_cap); + val = FIXED_DIV(val, TO_FIXED(100, 0) - fmin_cap); + chip->soc = clamp(FIXED_TO_INT(val), 0, 100); } static void max17040_get_version(struct i2c_client *client) |