lkml.org 
[lkml]   [2017]   [Nov]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL for-4.9 28/53] power: supply: axp288_fuel_gauge: Read 15 bit values 2 registers at a time
    Date
    From: Hans de Goede <hdegoede@redhat.com>

    [ Upstream commit 4949fc5e071f8e8d8122e0b16cf6a2ec1ca36258 ]

    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: Hans de Goede <hdegoede@redhat.com>
    Signed-off-by: Sebastian Reichel <sre@kernel.org>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    ---
    drivers/power/supply/axp288_fuel_gauge.c | 63 +++++++++++++++++---------------
    1 file changed, 34 insertions(+), 29 deletions(-)

    diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
    index f62f9dfea984..99d6d3030731 100644
    --- a/drivers/power/supply/axp288_fuel_gauge.c
    +++ b/drivers/power/supply/axp288_fuel_gauge.c
    @@ -29,6 +29,7 @@
    #include <linux/iio/consumer.h>
    #include <linux/debugfs.h>
    #include <linux/seq_file.h>
    +#include <asm/unaligned.h>

    #define CHRG_STAT_BAT_SAFE_MODE (1 << 3)
    #define CHRG_STAT_BAT_VALID (1 << 4)
    @@ -73,17 +74,15 @@
    #define FG_CNTL_CC_EN (1 << 6)
    #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_VAL_MASK 0x7F

    #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_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_OCV_CAP_VALID (1 << 7)
    @@ -189,6 +188,28 @@ static int fuel_gauge_reg_writeb(struct axp288_fg_info *info, int reg, u8 val)
    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,
    struct axp288_fg_info *info)
    {
    @@ -255,18 +276,12 @@ static int fuel_gauge_debug_show(struct seq_file *s, void *data)
    seq_printf(s, " FG_OCVL[%02x] : %02x\n",
    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,
    - fuel_gauge_reg_readb(info, AXP288_FG_DES_CAP1_REG));
    - seq_printf(s, "FG_DES_CAP0[%02x] : %02x\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",
    + fuel_gauge_read_15bit_word(info, AXP288_FG_DES_CAP1_REG));
    + seq_printf(s, " FG_CC_MTR[%02x] : %04x\n",
    AXP288_FG_CC_MTR1_REG,
    - fuel_gauge_reg_readb(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));
    + fuel_gauge_read_15bit_word(info, AXP288_FG_CC_MTR1_REG));
    seq_printf(s, " FG_OCV_CAP[%02x] : %02x\n",
    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,
    val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
    break;
    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)
    goto fuel_gauge_read_err;

    - value = (ret & FG_CC_MTR1_VAL_MASK) << 8;
    - 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;
    + val->intval = ret * FG_DES_CAP_RES_LSB;
    break;
    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)
    goto fuel_gauge_read_err;

    - value = (ret & FG_DES_CAP1_VAL_MASK) << 8;
    - 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;
    + val->intval = ret * FG_DES_CAP_RES_LSB;
    break;
    case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
    val->intval = PROP_CURR(info->pdata->design_cap);
    --
    2.11.0
    \
     
     \ /
      Last update: 2017-11-08 22:08    [W:3.939 / U:0.832 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site