From d3e67c94e8f607ee90097d296deecf030af9b8ab Mon Sep 17 00:00:00 2001 From: Yuanjiang Yu Date: Tue, 15 Jan 2019 18:32:37 +0800 Subject: [PATCH] power: supply: sc27xx: Fix capacity saving function We found sometimes we can not get the saving capacity to initialize the battery capacity, the reason is the user area registers are put on power always-on region, so we need delay some time to wait until values are updated successfully. Moreover we also should clear the USER_AREA_CLEAR register after setting the USER_AREA_SET register, otherwise we can not save the values in the USER_AREA_SET register. Signed-off-by: Yuanjiang Yu Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- drivers/power/supply/sc27xx_fuel_gauge.c | 64 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index ea1349fe55a5..24895cc3b41e 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -171,10 +171,37 @@ static int sc27xx_fgu_save_boot_mode(struct sc27xx_fgu_data *data, if (ret) return ret; + /* + * Since the user area registers are put on power always-on region, + * then these registers changing time will be a little long. Thus + * here we should delay 200us to wait until values are updated + * successfully according to the datasheet. + */ + udelay(200); + + ret = regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_SET, + SC27XX_FGU_MODE_AREA_MASK, + boot_mode << SC27XX_FGU_MODE_AREA_SHIFT); + if (ret) + return ret; + + /* + * Since the user area registers are put on power always-on region, + * then these registers changing time will be a little long. Thus + * here we should delay 200us to wait until values are updated + * successfully according to the datasheet. + */ + udelay(200); + + /* + * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to + * make the user area data available, otherwise we can not save the user + * area data. + */ return regmap_update_bits(data->regmap, - data->base + SC27XX_FGU_USER_AREA_SET, - SC27XX_FGU_MODE_AREA_MASK, - boot_mode << SC27XX_FGU_MODE_AREA_SHIFT); + data->base + SC27XX_FGU_USER_AREA_CLEAR, + SC27XX_FGU_MODE_AREA_MASK, 0); } static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap) @@ -188,9 +215,36 @@ static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap) if (ret) return ret; + /* + * Since the user area registers are put on power always-on region, + * then these registers changing time will be a little long. Thus + * here we should delay 200us to wait until values are updated + * successfully according to the datasheet. + */ + udelay(200); + + ret = regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_SET, + SC27XX_FGU_CAP_AREA_MASK, cap); + if (ret) + return ret; + + /* + * Since the user area registers are put on power always-on region, + * then these registers changing time will be a little long. Thus + * here we should delay 200us to wait until values are updated + * successfully according to the datasheet. + */ + udelay(200); + + /* + * According to the datasheet, we should set the USER_AREA_CLEAR to 0 to + * make the user area data available, otherwise we can not save the user + * area data. + */ return regmap_update_bits(data->regmap, - data->base + SC27XX_FGU_USER_AREA_SET, - SC27XX_FGU_CAP_AREA_MASK, cap); + data->base + SC27XX_FGU_USER_AREA_CLEAR, + SC27XX_FGU_CAP_AREA_MASK, 0); } static int sc27xx_fgu_read_last_cap(struct sc27xx_fgu_data *data, int *cap) -- 2.39.5