Commit 4949fc5e authored by Hans de Goede's avatar Hans de Goede Committed by Sebastian Reichel

power: supply: axp288_fuel_gauge: Read 15 bit values 2 registers at a time

In order for the MSB -> LSB latching to work correctly we must read the
2 8 bit registers of a 15 bit value in one consecutive read.

This fixes charge_full reporting 3498768 on some reads and 3354624 one
other reads on my tablet (for the 3354624 value the raw LSB is 0x00).
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
parent 6f074bc8
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/iio/consumer.h> #include <linux/iio/consumer.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm/unaligned.h>
#define CHRG_STAT_BAT_SAFE_MODE (1 << 3) #define CHRG_STAT_BAT_SAFE_MODE (1 << 3)
#define CHRG_STAT_BAT_VALID (1 << 4) #define CHRG_STAT_BAT_VALID (1 << 4)
...@@ -73,17 +74,15 @@ ...@@ -73,17 +74,15 @@
#define FG_CNTL_CC_EN (1 << 6) #define FG_CNTL_CC_EN (1 << 6)
#define FG_CNTL_GAUGE_EN (1 << 7) #define FG_CNTL_GAUGE_EN (1 << 7)
#define FG_15BIT_WORD_VALID (1 << 15)
#define FG_15BIT_VAL_MASK 0x7fff
#define FG_REP_CAP_VALID (1 << 7) #define FG_REP_CAP_VALID (1 << 7)
#define FG_REP_CAP_VAL_MASK 0x7F #define FG_REP_CAP_VAL_MASK 0x7F
#define FG_DES_CAP1_VALID (1 << 7) #define FG_DES_CAP1_VALID (1 << 7)
#define FG_DES_CAP1_VAL_MASK 0x7F
#define FG_DES_CAP0_VAL_MASK 0xFF
#define FG_DES_CAP_RES_LSB 1456 /* 1.456mAhr */ #define FG_DES_CAP_RES_LSB 1456 /* 1.456mAhr */
#define FG_CC_MTR1_VALID (1 << 7)
#define FG_CC_MTR1_VAL_MASK 0x7F
#define FG_CC_MTR0_VAL_MASK 0xFF
#define FG_DES_CC_RES_LSB 1456 /* 1.456mAhr */ #define FG_DES_CC_RES_LSB 1456 /* 1.456mAhr */
#define FG_OCV_CAP_VALID (1 << 7) #define FG_OCV_CAP_VALID (1 << 7)
...@@ -189,6 +188,28 @@ static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val) ...@@ -189,6 +188,28 @@ static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val)
return ret; return ret;
} }
static int fuel_gauge_read_15bit_word(struct axp288_fg_info *info, int reg)
{
unsigned char buf[2];
int ret;
ret = regmap_bulk_read(info->regmap, reg, buf, 2);
if (ret < 0) {
dev_err(&info->pdev->dev, "Error reading reg 0x%02x err: %d\n",
reg, ret);
return ret;
}
ret = get_unaligned_be16(buf);
if (!(ret & FG_15BIT_WORD_VALID)) {
dev_err(&info->pdev->dev, "Error reg 0x%02x contents not valid\n",
reg);
return -ENXIO;
}
return ret & FG_15BIT_VAL_MASK;
}
static int pmic_read_adc_val(const char *name, int *raw_val, static int pmic_read_adc_val(const char *name, int *raw_val,
struct axp288_fg_info *info) struct axp288_fg_info *info)
{ {
...@@ -255,18 +276,12 @@ static int fuel_gauge_debug_show(struct seq_file *s, void *data) ...@@ -255,18 +276,12 @@ static int fuel_gauge_debug_show(struct seq_file *s, void *data)
seq_printf(s, " FG_OCVL[%02x] : %02x\n", seq_printf(s, " FG_OCVL[%02x] : %02x\n",
AXP288_FG_OCVL_REG, AXP288_FG_OCVL_REG,
fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG)); fuel_gauge_reg_readb(info, AXP288_FG_OCVL_REG));
seq_printf(s, "FG_DES_CAP1[%02x] : %02x\n", seq_printf(s, " FG_DES_CAP[%02x] : %04x\n",
AXP288_FG_DES_CAP1_REG, AXP288_FG_DES_CAP1_REG,
fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG)); fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG));
seq_printf(s, "FG_DES_CAP0[%02x] : %02x\n", seq_printf(s, " FG_CC_MTR[%02x] : %04x\n",
AXP288_FG_DES_CAP0_REG,
fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG));
seq_printf(s, " FG_CC_MTR1[%02x] : %02x\n",
AXP288_FG_CC_MTR1_REG, AXP288_FG_CC_MTR1_REG,
fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG)); fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG));
seq_printf(s, " FG_CC_MTR0[%02x] : %02x\n",
AXP288_FG_CC_MTR0_REG,
fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG));
seq_printf(s, " FG_OCV_CAP[%02x] : %02x\n", seq_printf(s, " FG_OCV_CAP[%02x] : %02x\n",
AXP288_FG_OCV_CAP_REG, AXP288_FG_OCV_CAP_REG,
fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG)); fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG));
...@@ -663,28 +678,18 @@ static int fuel_gauge_get_property(struct power_supply *ps, ...@@ -663,28 +678,18 @@ static int fuel_gauge_get_property(struct power_supply *ps,
val->intval = POWER_SUPPLY_TECHNOLOGY_LION; val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break; break;
case POWER_SUPPLY_PROP_CHARGE_NOW: case POWER_SUPPLY_PROP_CHARGE_NOW:
ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR1_REG); ret = fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG);
if (ret < 0) if (ret < 0)
goto fuel_gauge_read_err; goto fuel_gauge_read_err;
value = (ret & FG_CC_MTR1_VAL_MASK) << 8; val->intval = ret * FG_DES_CAP_RES_LSB;
ret = fuel_gauge_reg_readb(info, AXP288_FG_CC_MTR0_REG);
if (ret < 0)
goto fuel_gauge_read_err;
value |= (ret & FG_CC_MTR0_VAL_MASK);
val->intval = value * FG_DES_CAP_RES_LSB;
break; break;
case POWER_SUPPLY_PROP_CHARGE_FULL: case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG); ret = fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG);
if (ret < 0) if (ret < 0)
goto fuel_gauge_read_err; goto fuel_gauge_read_err;
value = (ret & FG_DES_CAP1_VAL_MASK) << 8; val->intval = ret * FG_DES_CAP_RES_LSB;
ret = fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP0_REG);
if (ret < 0)
goto fuel_gauge_read_err;
value |= (ret & FG_DES_CAP0_VAL_MASK);
val->intval = value * FG_DES_CAP_RES_LSB;
break; break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
val->intval = PROP_CURR(info->pdata->design_cap); val->intval = PROP_CURR(info->pdata->design_cap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment