iio:adc:axp20x: add support for NTC thermistor
authorEvgeny Boger <boger@wirenboard.com>
Thu, 18 Nov 2021 14:12:32 +0000 (17:12 +0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 4 Dec 2021 15:34:18 +0000 (15:34 +0000)
Most AXPxxx-based reference designs place a 10k NTC thermistor on a
TS pin. When appropriately configured, AXP PMICs will inject fixed
current (80uA by default) into TS pin and measure the voltage across a
thermistor. The PMIC itself will by default compare this voltage with
predefined thresholds  and disable battery charging whenever
the battery is too hot or too cold.

Alternatively, the TS pin can be configured as general-purpose
ADC input. This mode is not supported by the driver.

This patch allows reading the voltage on the TS pin. It can be then
either processed by userspace or used by kernel consumer like hwmon
ntc thermistor driver.

Signed-off-by: Evgeny Boger <boger@wirenboard.com>
Acked-by: Maxime Ripard <maxime@cerno.tech>
Reviewed-by: Quentin Schulz <foss+kernel@0leil.net>
Link: https://lore.kernel.org/r/20211118141233.247907-2-boger@wirenboard.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/axp20x_adc.c

index 3e0c0233b43156c899398c34b240001097d40058..12d469a52ceac659b3598b61ce7311dbc419af5e 100644 (file)
@@ -186,6 +186,8 @@ static const struct iio_chan_spec axp20x_adc_channels[] = {
                           AXP20X_BATT_CHRG_I_H),
        AXP20X_ADC_CHANNEL(AXP20X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
                           AXP20X_BATT_DISCHRG_I_H),
+       AXP20X_ADC_CHANNEL(AXP20X_TS_IN, "ts_v", IIO_VOLTAGE,
+                          AXP20X_TS_IN_H),
 };
 
 static const struct iio_chan_spec axp22x_adc_channels[] = {
@@ -203,6 +205,8 @@ static const struct iio_chan_spec axp22x_adc_channels[] = {
                           AXP20X_BATT_CHRG_I_H),
        AXP20X_ADC_CHANNEL(AXP22X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
                           AXP20X_BATT_DISCHRG_I_H),
+       AXP20X_ADC_CHANNEL(AXP22X_TS_IN, "ts_v", IIO_VOLTAGE,
+                          AXP22X_TS_ADC_H),
 };
 
 static const struct iio_chan_spec axp813_adc_channels[] = {
@@ -222,6 +226,8 @@ static const struct iio_chan_spec axp813_adc_channels[] = {
                           AXP20X_BATT_CHRG_I_H),
        AXP20X_ADC_CHANNEL(AXP22X_BATT_DISCHRG_I, "batt_dischrg_i", IIO_CURRENT,
                           AXP20X_BATT_DISCHRG_I_H),
+       AXP20X_ADC_CHANNEL(AXP813_TS_IN, "ts_v", IIO_VOLTAGE,
+                          AXP288_TS_ADC_H),
 };
 
 static int axp20x_adc_raw(struct iio_dev *indio_dev,
@@ -307,11 +313,36 @@ static int axp20x_adc_scale_voltage(int channel, int *val, int *val2)
                *val2 = 400000;
                return IIO_VAL_INT_PLUS_MICRO;
 
+       case AXP20X_TS_IN:
+               /* 0.8 mV per LSB */
+               *val = 0;
+               *val2 = 800000;
+               return IIO_VAL_INT_PLUS_MICRO;
+
        default:
                return -EINVAL;
        }
 }
 
+static int axp22x_adc_scale_voltage(int channel, int *val, int *val2)
+{
+       switch (channel) {
+       case AXP22X_BATT_V:
+               /* 1.1 mV per LSB */
+               *val = 1;
+               *val2 = 100000;
+               return IIO_VAL_INT_PLUS_MICRO;
+
+       case AXP22X_TS_IN:
+               /* 0.8 mV per LSB */
+               *val = 0;
+               *val2 = 800000;
+               return IIO_VAL_INT_PLUS_MICRO;
+
+       default:
+               return -EINVAL;
+       }
+}
 static int axp813_adc_scale_voltage(int channel, int *val, int *val2)
 {
        switch (channel) {
@@ -325,6 +356,12 @@ static int axp813_adc_scale_voltage(int channel, int *val, int *val2)
                *val2 = 100000;
                return IIO_VAL_INT_PLUS_MICRO;
 
+       case AXP813_TS_IN:
+               /* 0.8 mV per LSB */
+               *val = 0;
+               *val2 = 800000;
+               return IIO_VAL_INT_PLUS_MICRO;
+
        default:
                return -EINVAL;
        }
@@ -378,12 +415,7 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val,
 {
        switch (chan->type) {
        case IIO_VOLTAGE:
-               if (chan->channel != AXP22X_BATT_V)
-                       return -EINVAL;
-
-               *val = 1;
-               *val2 = 100000;
-               return IIO_VAL_INT_PLUS_MICRO;
+               return axp22x_adc_scale_voltage(chan->channel, val, val2);
 
        case IIO_CURRENT:
                *val = 0;
@@ -488,6 +520,7 @@ static int axp22x_read_raw(struct iio_dev *indio_dev,
 {
        switch (mask) {
        case IIO_CHAN_INFO_OFFSET:
+               /* For PMIC temp only */
                *val = -2677;
                return IIO_VAL_INT;