]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - drivers/acpi/pmic/intel_pmic_xpower.c
Merge v5.0-rc7 into drm-next
[thirdparty/linux.git] / drivers / acpi / pmic / intel_pmic_xpower.c
index 1b49cbb1e21e85377e7474b7b2f00231e5ed2dce..a091d5a8392c62fef8a3b480995e0b72c229774e 100644 (file)
 #define GPI1_LDO_ON            (3 << 0)
 #define GPI1_LDO_OFF           (4 << 0)
 
-#define AXP288_ADC_TS_PIN_GPADC        0xf2
-#define AXP288_ADC_TS_PIN_ON   0xf3
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 static struct pmic_table power_table[] = {
        {
@@ -212,22 +215,44 @@ out:
  */
 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg)
 {
+       int ret, adc_ts_pin_ctrl;
        u8 buf[2];
-       int ret;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL,
-                          AXP288_ADC_TS_PIN_GPADC);
+       /*
+        * The current-source used for the battery temp-sensor (TS) is shared
+        * with the GPADC. For proper fuel-gauge and charger operation the TS
+        * current-source needs to be permanently on. But to read the GPADC we
+        * need to temporary switch the TS current-source to ondemand, so that
+        * the GPADC can use it, otherwise we will always read an all 0 value.
+        *
+        * Note that the switching from on to on-ondemand is not necessary
+        * when the TS current-source is off (this happens on devices which
+        * do not use the TS-pin).
+        */
+       ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl);
        if (ret)
                return ret;
 
-       /* After switching to the GPADC pin give things some time to settle */
-       usleep_range(6000, 10000);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON_ONDEMAND);
+               if (ret)
+                       return ret;
+
+               /* Wait a bit after switching the current-source */
+               usleep_range(6000, 10000);
+       }
 
        ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2);
        if (ret == 0)
                ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f);
 
-       regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                  AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                  AXP288_ADC_TS_CURRENT_ON);
+       }
 
        return ret;
 }