power: supply: ab8500_charger: Fix VBAT interval check
authorLinus Walleij <linus.walleij@linaro.org>
Sat, 29 Jan 2022 00:49:25 +0000 (01:49 +0100)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Fri, 11 Feb 2022 19:24:54 +0000 (20:24 +0100)
When using USB charging, the AB8500 charger is periodically
checking VBAT for a threshold at 3.8V.

This crashes badly, as the class_for_each_device() was passed
the wrong argument. I think this has maybe worked by chance
in the past because of how the structs were arranged but it
is leading to crashes now.

Fix this up and also switch to using microvolts for the
voltages like the rest of the code.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/ab8500_charger.c

index 681b53b..88099cd 100644 (file)
@@ -163,7 +163,7 @@ enum ab8500_usb_state {
 #define USB_CH_IP_CUR_LVL_1P4          1400000
 #define USB_CH_IP_CUR_LVL_1P5          1500000
 
-#define VBAT_TRESH_IP_CUR_RED          3800
+#define VBAT_TRESH_IP_CUR_RED          3800000
 
 #define to_ab8500_charger_usb_device_info(x) container_of((x), \
        struct ab8500_charger, usb_chg)
@@ -1920,7 +1920,11 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
 
        di = to_ab8500_charger_usb_device_info(usb_chg);
 
-       /* For all psy where the driver name appears in any supplied_to */
+       /*
+        * For all psy where the driver name appears in any supplied_to
+        * in practice what we will find will always be "ab8500_fg" as
+        * the fuel gauge is responsible of keeping track of VBAT.
+        */
        j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
        if (j < 0)
                return 0;
@@ -1937,7 +1941,10 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
                case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                        switch (ext->desc->type) {
                        case POWER_SUPPLY_TYPE_BATTERY:
-                               di->vbat = ret.intval / 1000;
+                               /* This will always be "ab8500_fg" */
+                               dev_dbg(di->dev, "get VBAT from %s\n",
+                                       dev_name(&ext->dev));
+                               di->vbat = ret.intval;
                                break;
                        default:
                                break;
@@ -1966,7 +1973,7 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
                struct ab8500_charger, check_vbat_work.work);
 
        class_for_each_device(power_supply_class, NULL,
-               di->usb_chg.psy, ab8500_charger_get_ext_psy_data);
+                             &di->usb_chg, ab8500_charger_get_ext_psy_data);
 
        /* First run old_vbat is 0. */
        if (di->old_vbat == 0)
@@ -1991,8 +1998,8 @@ static void ab8500_charger_check_vbat_work(struct work_struct *work)
         * No need to check the battery voltage every second when not close to
         * the threshold.
         */
-       if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100) &&
-               (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100)))
+       if (di->vbat < (VBAT_TRESH_IP_CUR_RED + 100000) &&
+               (di->vbat > (VBAT_TRESH_IP_CUR_RED - 100000)))
                        t = 1;
 
        queue_delayed_work(di->charger_wq, &di->check_vbat_work, t * HZ);