iio: adc: break out common code from SPMI VADC
authorLinus Walleij <linus.walleij@linaro.org>
Tue, 4 Apr 2017 12:08:18 +0000 (14:08 +0200)
committerJonathan Cameron <jic23@kernel.org>
Sat, 8 Apr 2017 16:40:49 +0000 (17:40 +0100)
The SPMI VADC and the earlier XOADC share a subset of
common code, so to be able to use the same code in both
drivers, we break out a separate file with the common code,
prefix exported functions that are no longer static with
qcom_* and bake an object qcom-spmi-vadc.o that contains both
files: qcom-vadc-common.o and qcom-spmi-vadc-core.o.

As we need to follow the procedure for making a kernel module
or compiled in object from several files, but still want to
produce the same module name, rename the qcom-spmi-vadc.c
file to qcom-spmi-vadc-core.c so we can bake the two objects
into qcom-spmi-vadc.o

Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: Ivan T. Ivanov <iivanov.xz@gmail.com>
Cc: Andy Gross <andy.gross@linaro.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Cc: Rama Krishna Phani A <rphani@codeaurora.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/qcom-spmi-vadc.c
drivers/iio/adc/qcom-vadc-common.c [new file with mode: 0644]
drivers/iio/adc/qcom-vadc-common.h [new file with mode: 0644]

index f924fa0d4fd692eb53970dded323e9c73d81fd8a..d8ad694b47095ebaa102771632ca0b037b273aa4 100644 (file)
@@ -496,6 +496,9 @@ config PALMAS_GPADC
          is used in smartphones and tablets and supports a 16 channel
          general purpose ADC.
 
+config QCOM_VADC_COMMON
+       tristate
+
 config QCOM_SPMI_IADC
        tristate "Qualcomm SPMI PMIC current ADC"
        depends on SPMI
@@ -514,6 +517,7 @@ config QCOM_SPMI_VADC
        tristate "Qualcomm SPMI PMIC voltage ADC"
        depends on SPMI
        select REGMAP_SPMI
+       select QCOM_VADC_COMMON
        help
          This is the IIO Voltage ADC driver for Qualcomm QPNP VADC Chip.
 
index fe1ab3d9ac58d394d3da86860fcc0d7d22583814..50fb66b47f7e822b9bdea0aa4a363d574e13921a 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
 obj-$(CONFIG_NAU7802) += nau7802.o
 obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
 obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
+obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
 obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
index 0a19761d656c66ab8ae87d871556f1f4f13f4884..9e600bfd17652531f50bd7019854f53749e9b822 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <dt-bindings/iio/qcom,spmi-vadc.h>
 
+#include "qcom-vadc-common.h"
+
 /* VADC register and bit definitions */
 #define VADC_REVISION2                         0x1
 #define VADC_REVISION2_SUPPORTED_VADC          1
 
 #define VADC_DATA                              0x60    /* 16 bits */
 
-#define VADC_CONV_TIME_MIN_US                  2000
-#define VADC_CONV_TIME_MAX_US                  2100
-
-/* Min ADC code represents 0V */
-#define VADC_MIN_ADC_CODE                      0x6000
-/* Max ADC code represents full-scale range of 1.8V */
-#define VADC_MAX_ADC_CODE                      0xa800
-
-#define VADC_ABSOLUTE_RANGE_UV                 625000
-#define VADC_RATIOMETRIC_RANGE                 1800
-
-#define VADC_DEF_PRESCALING                    0 /* 1:1 */
-#define VADC_DEF_DECIMATION                    0 /* 512 */
-#define VADC_DEF_HW_SETTLE_TIME                        0 /* 0 us */
-#define VADC_DEF_AVG_SAMPLES                   0 /* 1 sample */
-#define VADC_DEF_CALIB_TYPE                    VADC_CALIB_ABSOLUTE
-
-#define VADC_DECIMATION_MIN                    512
-#define VADC_DECIMATION_MAX                    4096
-
-#define VADC_HW_SETTLE_DELAY_MAX               10000
-#define VADC_AVG_SAMPLES_MAX                   512
-
-#define KELVINMIL_CELSIUSMIL                   273150
-
-#define PMI_CHG_SCALE_1                                -138890
-#define PMI_CHG_SCALE_2                                391750000000LL
-
 #define VADC_CHAN_MIN                  VADC_USBIN
 #define VADC_CHAN_MAX                  VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM
 
-/**
- * struct vadc_map_pt - Map the graph representation for ADC channel
- * @x: Represent the ADC digitized code.
- * @y: Represent the physical data which can be temperature, voltage,
- *     resistance.
- */
-struct vadc_map_pt {
-       s32 x;
-       s32 y;
-};
-
-/*
- * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels.
- * VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for
- * calibration.
- */
-enum vadc_calibration {
-       VADC_CALIB_ABSOLUTE = 0,
-       VADC_CALIB_RATIOMETRIC
-};
-
-/**
- * struct vadc_linear_graph - Represent ADC characteristics.
- * @dy: numerator slope to calculate the gain.
- * @dx: denominator slope to calculate the gain.
- * @gnd: A/D word of the ground reference used for the channel.
- *
- * Each ADC device has different offset and gain parameters which are
- * computed to calibrate the device.
- */
-struct vadc_linear_graph {
-       s32 dy;
-       s32 dx;
-       s32 gnd;
-};
-
-/**
- * struct vadc_prescale_ratio - Represent scaling ratio for ADC input.
- * @num: the inverse numerator of the gain applied to the input channel.
- * @den: the inverse denominator of the gain applied to the input channel.
- */
-struct vadc_prescale_ratio {
-       u32 num;
-       u32 den;
-};
-
 /**
  * struct vadc_channel_prop - VADC channel property.
  * @channel: channel number, refer to the channel list.
@@ -162,9 +90,8 @@ struct vadc_prescale_ratio {
  *     start of conversion.
  * @avg_samples: ability to provide single result from the ADC
  *     that is an average of multiple measurements.
- * @scale_fn: Represents the scaling function to convert voltage
+ * @scale_fn_type: Represents the scaling function to convert voltage
  *     physical units desired by the client for the channel.
- *     Referenced from enum vadc_scale_fn_type.
  */
 struct vadc_channel_prop {
        unsigned int channel;
@@ -173,7 +100,7 @@ struct vadc_channel_prop {
        unsigned int prescale;
        unsigned int hw_settle_time;
        unsigned int avg_samples;
-       unsigned int scale_fn;
+       enum vadc_scale_fn_type scale_fn_type;
 };
 
 /**
@@ -204,35 +131,6 @@ struct vadc_priv {
        struct mutex             lock;
 };
 
-/**
- * struct vadc_scale_fn - Scaling function prototype
- * @scale: Function pointer to one of the scaling functions
- *     which takes the adc properties, channel properties,
- *     and returns the physical result.
- */
-struct vadc_scale_fn {
-       int (*scale)(struct vadc_priv *, const struct vadc_channel_prop *,
-                    u16, int *);
-};
-
-/**
- * enum vadc_scale_fn_type - Scaling function to convert ADC code to
- *                             physical scaled units for the channel.
- * SCALE_DEFAULT: Default scaling to convert raw adc code to voltage (uV).
- * SCALE_THERM_100K_PULLUP: Returns temperature in millidegC.
- *                              Uses a mapping table with 100K pullup.
- * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
- * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
- * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
- */
-enum vadc_scale_fn_type {
-       SCALE_DEFAULT = 0,
-       SCALE_THERM_100K_PULLUP,
-       SCALE_PMIC_THERM,
-       SCALE_XOTHERM,
-       SCALE_PMI_CHG_TEMP,
-};
-
 static const struct vadc_prescale_ratio vadc_prescale_ratios[] = {
        {.num =  1, .den =  1},
        {.num =  1, .den =  3},
@@ -244,44 +142,6 @@ static const struct vadc_prescale_ratio vadc_prescale_ratios[] = {
        {.num =  1, .den = 10}
 };
 
-/* Voltage to temperature */
-static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
-       {1758,  -40},
-       {1742,  -35},
-       {1719,  -30},
-       {1691,  -25},
-       {1654,  -20},
-       {1608,  -15},
-       {1551,  -10},
-       {1483,  -5},
-       {1404,  0},
-       {1315,  5},
-       {1218,  10},
-       {1114,  15},
-       {1007,  20},
-       {900,   25},
-       {795,   30},
-       {696,   35},
-       {605,   40},
-       {522,   45},
-       {448,   50},
-       {383,   55},
-       {327,   60},
-       {278,   65},
-       {237,   70},
-       {202,   75},
-       {172,   80},
-       {146,   85},
-       {125,   90},
-       {107,   95},
-       {92,    100},
-       {79,    105},
-       {68,    110},
-       {59,    115},
-       {51,    120},
-       {44,    125}
-};
-
 static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data)
 {
        return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1);
@@ -553,159 +413,6 @@ err:
        return ret;
 }
 
-static int vadc_map_voltage_temp(const struct vadc_map_pt *pts,
-                                u32 tablesize, s32 input, s64 *output)
-{
-       bool descending = 1;
-       u32 i = 0;
-
-       if (!pts)
-               return -EINVAL;
-
-       /* Check if table is descending or ascending */
-       if (tablesize > 1) {
-               if (pts[0].x < pts[1].x)
-                       descending = 0;
-       }
-
-       while (i < tablesize) {
-               if ((descending) && (pts[i].x < input)) {
-                       /* table entry is less than measured*/
-                        /* value and table is descending, stop */
-                       break;
-               } else if ((!descending) &&
-                               (pts[i].x > input)) {
-                       /* table entry is greater than measured*/
-                       /*value and table is ascending, stop */
-                       break;
-               }
-               i++;
-       }
-
-       if (i == 0) {
-               *output = pts[0].y;
-       } else if (i == tablesize) {
-               *output = pts[tablesize - 1].y;
-       } else {
-               /* result is between search_index and search_index-1 */
-               /* interpolate linearly */
-               *output = (((s32)((pts[i].y - pts[i - 1].y) *
-                       (input - pts[i - 1].x)) /
-                       (pts[i].x - pts[i - 1].x)) +
-                       pts[i - 1].y);
-       }
-
-       return 0;
-}
-
-static void vadc_scale_calib(struct vadc_priv *vadc, u16 adc_code,
-                            const struct vadc_channel_prop *prop,
-                            s64 *scale_voltage)
-{
-       *scale_voltage = (adc_code -
-               vadc->graph[prop->calibration].gnd);
-       *scale_voltage *= vadc->graph[prop->calibration].dx;
-       *scale_voltage = div64_s64(*scale_voltage,
-               vadc->graph[prop->calibration].dy);
-       if (prop->calibration == VADC_CALIB_ABSOLUTE)
-               *scale_voltage +=
-               vadc->graph[prop->calibration].dx;
-
-       if (*scale_voltage < 0)
-               *scale_voltage = 0;
-}
-
-static int vadc_scale_volt(struct vadc_priv *vadc,
-                          const struct vadc_channel_prop *prop, u16 adc_code,
-                          int *result_uv)
-{
-       const struct vadc_prescale_ratio *prescale;
-       s64 voltage = 0, result = 0;
-
-       vadc_scale_calib(vadc, adc_code, prop, &voltage);
-
-       prescale = &vadc_prescale_ratios[prop->prescale];
-       voltage = voltage * prescale->den;
-       result = div64_s64(voltage, prescale->num);
-       *result_uv = result;
-
-       return 0;
-}
-
-static int vadc_scale_therm(struct vadc_priv *vadc,
-                           const struct vadc_channel_prop *prop, u16 adc_code,
-                           int *result_mdec)
-{
-       s64 voltage = 0, result = 0;
-
-       vadc_scale_calib(vadc, adc_code, prop, &voltage);
-
-       if (prop->calibration == VADC_CALIB_ABSOLUTE)
-               voltage = div64_s64(voltage, 1000);
-
-       vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
-                             ARRAY_SIZE(adcmap_100k_104ef_104fb),
-                             voltage, &result);
-       result *= 1000;
-       *result_mdec = result;
-
-       return 0;
-}
-
-static int vadc_scale_die_temp(struct vadc_priv *vadc,
-                              const struct vadc_channel_prop *prop,
-                              u16 adc_code, int *result_mdec)
-{
-       const struct vadc_prescale_ratio *prescale;
-       s64 voltage = 0;
-       u64 temp; /* Temporary variable for do_div */
-
-       vadc_scale_calib(vadc, adc_code, prop, &voltage);
-
-       if (voltage > 0) {
-               prescale = &vadc_prescale_ratios[prop->prescale];
-               temp = voltage * prescale->den;
-               do_div(temp, prescale->num * 2);
-               voltage = temp;
-       } else {
-               voltage = 0;
-       }
-
-       voltage -= KELVINMIL_CELSIUSMIL;
-       *result_mdec = voltage;
-
-       return 0;
-}
-
-static int vadc_scale_chg_temp(struct vadc_priv *vadc,
-                              const struct vadc_channel_prop *prop,
-                              u16 adc_code, int *result_mdec)
-{
-       const struct vadc_prescale_ratio *prescale;
-       s64 voltage = 0, result = 0;
-
-       vadc_scale_calib(vadc, adc_code, prop, &voltage);
-
-       prescale = &vadc_prescale_ratios[prop->prescale];
-       voltage = voltage * prescale->den;
-       voltage = div64_s64(voltage, prescale->num);
-       voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
-       voltage = (voltage + PMI_CHG_SCALE_2);
-       result =  div64_s64(voltage, 1000000);
-       *result_mdec = result;
-
-       return 0;
-}
-
-static int vadc_decimation_from_dt(u32 value)
-{
-       if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
-           value > VADC_DECIMATION_MAX)
-               return -EINVAL;
-
-       return __ffs64(value / VADC_DECIMATION_MIN);
-}
-
 static int vadc_prescaling_from_dt(u32 num, u32 den)
 {
        unsigned int pre;
@@ -742,14 +449,6 @@ static int vadc_avg_samples_from_dt(u32 value)
        return __ffs64(value);
 }
 
-static struct vadc_scale_fn scale_fn[] = {
-       [SCALE_DEFAULT] = {vadc_scale_volt},
-       [SCALE_THERM_100K_PULLUP] = {vadc_scale_therm},
-       [SCALE_PMIC_THERM] = {vadc_scale_die_temp},
-       [SCALE_XOTHERM] = {vadc_scale_therm},
-       [SCALE_PMI_CHG_TEMP] = {vadc_scale_chg_temp},
-};
-
 static int vadc_read_raw(struct iio_dev *indio_dev,
                         struct iio_chan_spec const *chan, int *val, int *val2,
                         long mask)
@@ -766,7 +465,13 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
                if (ret)
                        break;
 
-               scale_fn[prop->scale_fn].scale(vadc, prop, adc_code, val);
+               ret = qcom_vadc_scale(prop->scale_fn_type,
+                               &vadc->graph[prop->calibration],
+                               &vadc_prescale_ratios[prop->prescale],
+                               (prop->calibration == VADC_CALIB_ABSOLUTE),
+                               adc_code, val);
+               if (ret)
+                       break;
 
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_RAW:
@@ -809,7 +514,7 @@ struct vadc_channels {
        unsigned int prescale_index;
        enum iio_chan_type type;
        long info_mask;
-       unsigned int scale_fn;
+       enum vadc_scale_fn_type scale_fn_type;
 };
 
 #define VADC_CHAN(_dname, _type, _mask, _pre, _scale)                  \
@@ -818,7 +523,7 @@ struct vadc_channels {
                .prescale_index = _pre,                                 \
                .type = _type,                                          \
                .info_mask = _mask,                                     \
-               .scale_fn = _scale                                      \
+               .scale_fn_type = _scale                                 \
        },                                                              \
 
 #define VADC_NO_CHAN(_dname, _type, _mask, _pre)                       \
@@ -976,7 +681,7 @@ static int vadc_get_dt_channel_data(struct device *dev,
 
        ret = of_property_read_u32(node, "qcom,decimation", &value);
        if (!ret) {
-               ret = vadc_decimation_from_dt(value);
+               ret = qcom_vadc_decimation_from_dt(value);
                if (ret < 0) {
                        dev_err(dev, "%02x invalid decimation %d\n",
                                chan, value);
@@ -1068,7 +773,7 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node)
                        return ret;
                }
 
-               prop.scale_fn = vadc_chans[prop.channel].scale_fn;
+               prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type;
                vadc->chan_props[index] = prop;
 
                vadc_chan = &vadc_chans[prop.channel];
diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c
new file mode 100644 (file)
index 0000000..102fc51
--- /dev/null
@@ -0,0 +1,230 @@
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/math64.h>
+#include <linux/log2.h>
+#include <linux/err.h>
+
+#include "qcom-vadc-common.h"
+
+/* Voltage to temperature */
+static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
+       {1758,  -40},
+       {1742,  -35},
+       {1719,  -30},
+       {1691,  -25},
+       {1654,  -20},
+       {1608,  -15},
+       {1551,  -10},
+       {1483,  -5},
+       {1404,  0},
+       {1315,  5},
+       {1218,  10},
+       {1114,  15},
+       {1007,  20},
+       {900,   25},
+       {795,   30},
+       {696,   35},
+       {605,   40},
+       {522,   45},
+       {448,   50},
+       {383,   55},
+       {327,   60},
+       {278,   65},
+       {237,   70},
+       {202,   75},
+       {172,   80},
+       {146,   85},
+       {125,   90},
+       {107,   95},
+       {92,    100},
+       {79,    105},
+       {68,    110},
+       {59,    115},
+       {51,    120},
+       {44,    125}
+};
+
+static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
+                                     u32 tablesize, s32 input, s64 *output)
+{
+       bool descending = 1;
+       u32 i = 0;
+
+       if (!pts)
+               return -EINVAL;
+
+       /* Check if table is descending or ascending */
+       if (tablesize > 1) {
+               if (pts[0].x < pts[1].x)
+                       descending = 0;
+       }
+
+       while (i < tablesize) {
+               if ((descending) && (pts[i].x < input)) {
+                       /* table entry is less than measured*/
+                        /* value and table is descending, stop */
+                       break;
+               } else if ((!descending) &&
+                               (pts[i].x > input)) {
+                       /* table entry is greater than measured*/
+                       /*value and table is ascending, stop */
+                       break;
+               }
+               i++;
+       }
+
+       if (i == 0) {
+               *output = pts[0].y;
+       } else if (i == tablesize) {
+               *output = pts[tablesize - 1].y;
+       } else {
+               /* result is between search_index and search_index-1 */
+               /* interpolate linearly */
+               *output = (((s32)((pts[i].y - pts[i - 1].y) *
+                       (input - pts[i - 1].x)) /
+                       (pts[i].x - pts[i - 1].x)) +
+                       pts[i - 1].y);
+       }
+
+       return 0;
+}
+
+static void qcom_vadc_scale_calib(const struct vadc_linear_graph *calib_graph,
+                                 u16 adc_code,
+                                 bool absolute,
+                                 s64 *scale_voltage)
+{
+       *scale_voltage = (adc_code - calib_graph->gnd);
+       *scale_voltage *= calib_graph->dx;
+       *scale_voltage = div64_s64(*scale_voltage, calib_graph->dy);
+       if (absolute)
+               *scale_voltage += calib_graph->dx;
+
+       if (*scale_voltage < 0)
+               *scale_voltage = 0;
+}
+
+static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph,
+                               const struct vadc_prescale_ratio *prescale,
+                               bool absolute, u16 adc_code,
+                               int *result_uv)
+{
+       s64 voltage = 0, result = 0;
+
+       qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
+
+       voltage = voltage * prescale->den;
+       result = div64_s64(voltage, prescale->num);
+       *result_uv = result;
+
+       return 0;
+}
+
+static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
+                                const struct vadc_prescale_ratio *prescale,
+                                bool absolute, u16 adc_code,
+                                int *result_mdec)
+{
+       s64 voltage = 0, result = 0;
+       int ret;
+
+       qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
+
+       if (absolute)
+               voltage = div64_s64(voltage, 1000);
+
+       ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
+                                        ARRAY_SIZE(adcmap_100k_104ef_104fb),
+                                        voltage, &result);
+       if (ret)
+               return ret;
+
+       result *= 1000;
+       *result_mdec = result;
+
+       return 0;
+}
+
+static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph,
+                                   const struct vadc_prescale_ratio *prescale,
+                                   bool absolute,
+                                   u16 adc_code, int *result_mdec)
+{
+       s64 voltage = 0;
+       u64 temp; /* Temporary variable for do_div */
+
+       qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
+
+       if (voltage > 0) {
+               temp = voltage * prescale->den;
+               do_div(temp, prescale->num * 2);
+               voltage = temp;
+       } else {
+               voltage = 0;
+       }
+
+       voltage -= KELVINMIL_CELSIUSMIL;
+       *result_mdec = voltage;
+
+       return 0;
+}
+
+static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph,
+                                   const struct vadc_prescale_ratio *prescale,
+                                   bool absolute,
+                                   u16 adc_code, int *result_mdec)
+{
+       s64 voltage = 0, result = 0;
+
+       qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
+
+       voltage = voltage * prescale->den;
+       voltage = div64_s64(voltage, prescale->num);
+       voltage = ((PMI_CHG_SCALE_1) * (voltage * 2));
+       voltage = (voltage + PMI_CHG_SCALE_2);
+       result =  div64_s64(voltage, 1000000);
+       *result_mdec = result;
+
+       return 0;
+}
+
+int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
+                   const struct vadc_linear_graph *calib_graph,
+                   const struct vadc_prescale_ratio *prescale,
+                   bool absolute,
+                   u16 adc_code, int *result)
+{
+       switch (scaletype) {
+       case SCALE_DEFAULT:
+               return qcom_vadc_scale_volt(calib_graph, prescale,
+                                           absolute, adc_code,
+                                           result);
+       case SCALE_THERM_100K_PULLUP:
+       case SCALE_XOTHERM:
+               return qcom_vadc_scale_therm(calib_graph, prescale,
+                                            absolute, adc_code,
+                                            result);
+       case SCALE_PMIC_THERM:
+               return qcom_vadc_scale_die_temp(calib_graph, prescale,
+                                               absolute, adc_code,
+                                               result);
+       case SCALE_PMI_CHG_TEMP:
+               return qcom_vadc_scale_chg_temp(calib_graph, prescale,
+                                               absolute, adc_code,
+                                               result);
+       default:
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL(qcom_vadc_scale);
+
+int qcom_vadc_decimation_from_dt(u32 value)
+{
+       if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
+           value > VADC_DECIMATION_MAX)
+               return -EINVAL;
+
+       return __ffs64(value / VADC_DECIMATION_MIN);
+}
+EXPORT_SYMBOL(qcom_vadc_decimation_from_dt);
diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h
new file mode 100644 (file)
index 0000000..63c872a
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Code shared between the different Qualcomm PMIC voltage ADCs
+ */
+
+#ifndef QCOM_VADC_COMMON_H
+#define QCOM_VADC_COMMON_H
+
+#define VADC_CONV_TIME_MIN_US                  2000
+#define VADC_CONV_TIME_MAX_US                  2100
+
+/* Min ADC code represents 0V */
+#define VADC_MIN_ADC_CODE                      0x6000
+/* Max ADC code represents full-scale range of 1.8V */
+#define VADC_MAX_ADC_CODE                      0xa800
+
+#define VADC_ABSOLUTE_RANGE_UV                 625000
+#define VADC_RATIOMETRIC_RANGE                 1800
+
+#define VADC_DEF_PRESCALING                    0 /* 1:1 */
+#define VADC_DEF_DECIMATION                    0 /* 512 */
+#define VADC_DEF_HW_SETTLE_TIME                        0 /* 0 us */
+#define VADC_DEF_AVG_SAMPLES                   0 /* 1 sample */
+#define VADC_DEF_CALIB_TYPE                    VADC_CALIB_ABSOLUTE
+
+#define VADC_DECIMATION_MIN                    512
+#define VADC_DECIMATION_MAX                    4096
+
+#define VADC_HW_SETTLE_DELAY_MAX               10000
+#define VADC_AVG_SAMPLES_MAX                   512
+
+#define KELVINMIL_CELSIUSMIL                   273150
+
+#define PMI_CHG_SCALE_1                                -138890
+#define PMI_CHG_SCALE_2                                391750000000LL
+
+/**
+ * struct vadc_map_pt - Map the graph representation for ADC channel
+ * @x: Represent the ADC digitized code.
+ * @y: Represent the physical data which can be temperature, voltage,
+ *     resistance.
+ */
+struct vadc_map_pt {
+       s32 x;
+       s32 y;
+};
+
+/*
+ * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels.
+ * VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for
+ * calibration.
+ */
+enum vadc_calibration {
+       VADC_CALIB_ABSOLUTE = 0,
+       VADC_CALIB_RATIOMETRIC
+};
+
+/**
+ * struct vadc_linear_graph - Represent ADC characteristics.
+ * @dy: numerator slope to calculate the gain.
+ * @dx: denominator slope to calculate the gain.
+ * @gnd: A/D word of the ground reference used for the channel.
+ *
+ * Each ADC device has different offset and gain parameters which are
+ * computed to calibrate the device.
+ */
+struct vadc_linear_graph {
+       s32 dy;
+       s32 dx;
+       s32 gnd;
+};
+
+/**
+ * struct vadc_prescale_ratio - Represent scaling ratio for ADC input.
+ * @num: the inverse numerator of the gain applied to the input channel.
+ * @den: the inverse denominator of the gain applied to the input channel.
+ */
+struct vadc_prescale_ratio {
+       u32 num;
+       u32 den;
+};
+
+/**
+ * enum vadc_scale_fn_type - Scaling function to convert ADC code to
+ *                             physical scaled units for the channel.
+ * SCALE_DEFAULT: Default scaling to convert raw adc code to voltage (uV).
+ * SCALE_THERM_100K_PULLUP: Returns temperature in millidegC.
+ *                              Uses a mapping table with 100K pullup.
+ * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
+ * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
+ * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
+ */
+enum vadc_scale_fn_type {
+       SCALE_DEFAULT = 0,
+       SCALE_THERM_100K_PULLUP,
+       SCALE_PMIC_THERM,
+       SCALE_XOTHERM,
+       SCALE_PMI_CHG_TEMP,
+};
+
+int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
+                   const struct vadc_linear_graph *calib_graph,
+                   const struct vadc_prescale_ratio *prescale,
+                   bool absolute,
+                   u16 adc_code, int *result_mdec);
+
+int qcom_vadc_decimation_from_dt(u32 value);
+
+#endif /* QCOM_VADC_COMMON_H */