]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
power: supply: sc27xx: Fix capacity saving function
authorYuanjiang Yu <yuanjiang.yu@unisoc.com>
Tue, 15 Jan 2019 10:32:37 +0000 (18:32 +0800)
committerSebastian Reichel <sre@kernel.org>
Wed, 23 Jan 2019 20:26:56 +0000 (21:26 +0100)
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 <yuanjiang.yu@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/sc27xx_fuel_gauge.c

index ea1349fe55a537268afbdd8855ae913757412688..24895cc3b41e0c55210aef317c3d4fb65ab13592 100644 (file)
@@ -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)