aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiddartha Mohanadoss <smohanad@codeaurora.org>2018-08-02 21:43:53 -0400
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2018-08-18 13:11:43 -0400
commite13d757279bbc59776c8435fb94e54b5a58bdd0b (patch)
tree82a059a180b0dae280fe34239114a15ee4f6be18
parent2fca585502716c25c52ad4fe54207f80762bc7b4 (diff)
iio: adc: Add QCOM SPMI PMIC5 ADC driver
This patch adds support for QCOM SPMI PMIC5 family of ADC driver that supports hardware based offset and gain compensation. The ADC peripheral can measure both voltage and current channels whose input signal is connected to the PMIC ADC AMUX. The register set and configuration has been refreshed compared to the prior QCOM PMIC ADC family. Register ADC5 as part of the IIO framework. Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-rw-r--r--drivers/iio/adc/Kconfig20
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c788
-rw-r--r--drivers/iio/adc/qcom-vadc-common.c189
-rw-r--r--drivers/iio/adc/qcom-vadc-common.h54
5 files changed, 1047 insertions, 5 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4a754921fb6f..690fdb249565 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -596,6 +596,26 @@ config QCOM_SPMI_VADC
596 To compile this driver as a module, choose M here: the module will 596 To compile this driver as a module, choose M here: the module will
597 be called qcom-spmi-vadc. 597 be called qcom-spmi-vadc.
598 598
599config QCOM_SPMI_ADC5
600 tristate "Qualcomm Technologies Inc. SPMI PMIC5 ADC"
601 depends on SPMI
602 select REGMAP_SPMI
603 select QCOM_VADC_COMMON
604 help
605 This is the IIO Voltage PMIC5 ADC driver for Qualcomm Technologies Inc.
606
607 The driver supports multiple channels read. The ADC is a 16-bit
608 sigma-delta ADC. The hardware supports calibrated results for
609 conversion requests and clients include reading voltage phone
610 power, on board system thermistors connected to the PMIC ADC,
611 PMIC die temperature, charger temperature, battery current, USB voltage
612 input, voltage signals connected to supported PMIC GPIO inputs. The
613 hardware supports internal pull-up for thermistors and can choose between
614 a 100k, 30k and 400k pull up using the ADC channels.
615
616 To compile this driver as a module, choose M here: the module will
617 be called qcom-spmi-adc5.
618
599config RCAR_GYRO_ADC 619config RCAR_GYRO_ADC
600 tristate "Renesas R-Car GyroADC driver" 620 tristate "Renesas R-Car GyroADC driver"
601 depends on ARCH_RCAR_GEN2 || COMPILE_TEST 621 depends on ARCH_RCAR_GEN2 || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 03db7b578f9c..e478b3065ecd 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
53obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o 53obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
54obj-$(CONFIG_NAU7802) += nau7802.o 54obj-$(CONFIG_NAU7802) += nau7802.o
55obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o 55obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
56obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
56obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o 57obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
57obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o 58obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
58obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o 59obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
new file mode 100644
index 000000000000..a4299417f3de
--- /dev/null
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -0,0 +1,788 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/bitops.h>
7#include <linux/completion.h>
8#include <linux/delay.h>
9#include <linux/err.h>
10#include <linux/iio/iio.h>
11#include <linux/interrupt.h>
12#include <linux/kernel.h>
13#include <linux/log2.h>
14#include <linux/math64.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/platform_device.h>
18#include <linux/regmap.h>
19#include <linux/slab.h>
20
21#include <dt-bindings/iio/qcom,spmi-vadc.h>
22#include "qcom-vadc-common.h"
23
24#define ADC5_USR_REVISION1 0x0
25#define ADC5_USR_STATUS1 0x8
26#define ADC5_USR_STATUS1_REQ_STS BIT(1)
27#define ADC5_USR_STATUS1_EOC BIT(0)
28#define ADC5_USR_STATUS1_REQ_STS_EOC_MASK 0x3
29
30#define ADC5_USR_STATUS2 0x9
31#define ADC5_USR_STATUS2_CONV_SEQ_MASK 0x70
32#define ADC5_USR_STATUS2_CONV_SEQ_MASK_SHIFT 0x5
33
34#define ADC5_USR_IBAT_MEAS 0xf
35#define ADC5_USR_IBAT_MEAS_SUPPORTED BIT(0)
36
37#define ADC5_USR_DIG_PARAM 0x42
38#define ADC5_USR_DIG_PARAM_CAL_VAL BIT(6)
39#define ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT 6
40#define ADC5_USR_DIG_PARAM_CAL_SEL 0x30
41#define ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT 4
42#define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL 0xc
43#define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT 2
44
45#define ADC5_USR_FAST_AVG_CTL 0x43
46#define ADC5_USR_FAST_AVG_CTL_EN BIT(7)
47#define ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK 0x7
48
49#define ADC5_USR_CH_SEL_CTL 0x44
50
51#define ADC5_USR_DELAY_CTL 0x45
52#define ADC5_USR_HW_SETTLE_DELAY_MASK 0xf
53
54#define ADC5_USR_EN_CTL1 0x46
55#define ADC5_USR_EN_CTL1_ADC_EN BIT(7)
56
57#define ADC5_USR_CONV_REQ 0x47
58#define ADC5_USR_CONV_REQ_REQ BIT(7)
59
60#define ADC5_USR_DATA0 0x50
61
62#define ADC5_USR_DATA1 0x51
63
64#define ADC5_USR_IBAT_DATA0 0x52
65
66#define ADC5_USR_IBAT_DATA1 0x53
67
68/*
69 * Conversion time varies based on the decimation, clock rate, fast average
70 * samples and measurements queued across different VADC peripherals.
71 * Set the timeout to a max of 100ms.
72 */
73#define ADC5_CONV_TIME_MIN_US 263
74#define ADC5_CONV_TIME_MAX_US 264
75#define ADC5_CONV_TIME_RETRY 400
76#define ADC5_CONV_TIMEOUT msecs_to_jiffies(100)
77
78/* Digital version >= 5.3 supports hw_settle_2 */
79#define ADC5_HW_SETTLE_DIFF_MINOR 3
80#define ADC5_HW_SETTLE_DIFF_MAJOR 5
81
82enum adc5_cal_method {
83 ADC5_NO_CAL = 0,
84 ADC5_RATIOMETRIC_CAL,
85 ADC5_ABSOLUTE_CAL
86};
87
88enum adc5_cal_val {
89 ADC5_TIMER_CAL = 0,
90 ADC5_NEW_CAL
91};
92
93/**
94 * struct adc5_channel_prop - ADC channel property.
95 * @channel: channel number, refer to the channel list.
96 * @cal_method: calibration method.
97 * @cal_val: calibration value
98 * @decimation: sampling rate supported for the channel.
99 * @prescale: channel scaling performed on the input signal.
100 * @hw_settle_time: the time between AMUX being configured and the
101 * start of conversion.
102 * @avg_samples: ability to provide single result from the ADC
103 * that is an average of multiple measurements.
104 * @scale_fn_type: Represents the scaling function to convert voltage
105 * physical units desired by the client for the channel.
106 * @datasheet_name: Channel name used in device tree.
107 */
108struct adc5_channel_prop {
109 unsigned int channel;
110 enum adc5_cal_method cal_method;
111 enum adc5_cal_val cal_val;
112 unsigned int decimation;
113 unsigned int prescale;
114 unsigned int hw_settle_time;
115 unsigned int avg_samples;
116 enum vadc_scale_fn_type scale_fn_type;
117 const char *datasheet_name;
118};
119
120/**
121 * struct adc5_chip - ADC private structure.
122 * @regmap: SPMI ADC5 peripheral register map field.
123 * @dev: SPMI ADC5 device.
124 * @base: base address for the ADC peripheral.
125 * @nchannels: number of ADC channels.
126 * @chan_props: array of ADC channel properties.
127 * @iio_chans: array of IIO channels specification.
128 * @poll_eoc: use polling instead of interrupt.
129 * @complete: ADC result notification after interrupt is received.
130 * @lock: ADC lock for access to the peripheral.
131 * @data: software configuration data.
132 */
133struct adc5_chip {
134 struct regmap *regmap;
135 struct device *dev;
136 u16 base;
137 unsigned int nchannels;
138 struct adc5_channel_prop *chan_props;
139 struct iio_chan_spec *iio_chans;
140 bool poll_eoc;
141 struct completion complete;
142 struct mutex lock;
143 const struct adc5_data *data;
144};
145
146static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
147 {.num = 1, .den = 1},
148 {.num = 1, .den = 3},
149 {.num = 1, .den = 4},
150 {.num = 1, .den = 6},
151 {.num = 1, .den = 20},
152 {.num = 1, .den = 8},
153 {.num = 10, .den = 81},
154 {.num = 1, .den = 10},
155 {.num = 1, .den = 16}
156};
157
158static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)
159{
160 return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
161}
162
163static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len)
164{
165 return regmap_bulk_write(adc->regmap, adc->base + offset, data, len);
166}
167
168static int adc5_prescaling_from_dt(u32 num, u32 den)
169{
170 unsigned int pre;
171
172 for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++)
173 if (adc5_prescale_ratios[pre].num == num &&
174 adc5_prescale_ratios[pre].den == den)
175 break;
176
177 if (pre == ARRAY_SIZE(adc5_prescale_ratios))
178 return -EINVAL;
179
180 return pre;
181}
182
183static int adc5_hw_settle_time_from_dt(u32 value,
184 const unsigned int *hw_settle)
185{
186 unsigned int i;
187
188 for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
189 if (value == hw_settle[i])
190 return i;
191 }
192
193 return -EINVAL;
194}
195
196static int adc5_avg_samples_from_dt(u32 value)
197{
198 if (!is_power_of_2(value) || value > ADC5_AVG_SAMPLES_MAX)
199 return -EINVAL;
200
201 return __ffs(value);
202}
203
204static int adc5_decimation_from_dt(u32 value,
205 const unsigned int *decimation)
206{
207 unsigned int i;
208
209 for (i = 0; i < ADC5_DECIMATION_SAMPLES_MAX; i++) {
210 if (value == decimation[i])
211 return i;
212 }
213
214 return -EINVAL;
215}
216
217static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
218{
219 int ret;
220 u8 rslt_lsb, rslt_msb;
221
222 ret = adc5_read(adc, ADC5_USR_DATA0, &rslt_lsb, sizeof(rslt_lsb));
223 if (ret)
224 return ret;
225
226 ret = adc5_read(adc, ADC5_USR_DATA1, &rslt_msb, sizeof(rslt_lsb));
227 if (ret)
228 return ret;
229
230 *data = (rslt_msb << 8) | rslt_lsb;
231
232 if (*data == ADC5_USR_DATA_CHECK) {
233 pr_err("Invalid data:0x%x\n", *data);
234 return -EINVAL;
235 }
236
237 pr_debug("voltage raw code:0x%x\n", *data);
238
239 return 0;
240}
241
242static int adc5_poll_wait_eoc(struct adc5_chip *adc)
243{
244 unsigned int count, retry = ADC5_CONV_TIME_RETRY;
245 u8 status1;
246 int ret;
247
248 for (count = 0; count < retry; count++) {
249 ret = adc5_read(adc, ADC5_USR_STATUS1, &status1,
250 sizeof(status1));
251 if (ret)
252 return ret;
253
254 status1 &= ADC5_USR_STATUS1_REQ_STS_EOC_MASK;
255 if (status1 == ADC5_USR_STATUS1_EOC)
256 return 0;
257
258 usleep_range(ADC5_CONV_TIME_MIN_US, ADC5_CONV_TIME_MAX_US);
259 }
260
261 return -ETIMEDOUT;
262}
263
264static void adc5_update_dig_param(struct adc5_chip *adc,
265 struct adc5_channel_prop *prop, u8 *data)
266{
267 /* Update calibration value */
268 *data &= ~ADC5_USR_DIG_PARAM_CAL_VAL;
269 *data |= (prop->cal_val << ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT);
270
271 /* Update calibration select */
272 *data &= ~ADC5_USR_DIG_PARAM_CAL_SEL;
273 *data |= (prop->cal_method << ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT);
274
275 /* Update decimation ratio select */
276 *data &= ~ADC5_USR_DIG_PARAM_DEC_RATIO_SEL;
277 *data |= (prop->decimation << ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT);
278}
279
280static int adc5_configure(struct adc5_chip *adc,
281 struct adc5_channel_prop *prop)
282{
283 int ret;
284 u8 buf[6];
285
286 /* Read registers 0x42 through 0x46 */
287 ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
288 if (ret < 0)
289 return ret;
290
291 /* Digital param selection */
292 adc5_update_dig_param(adc, prop, &buf[0]);
293
294 /* Update fast average sample value */
295 buf[1] &= (u8) ~ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK;
296 buf[1] |= prop->avg_samples;
297
298 /* Select ADC channel */
299 buf[2] = prop->channel;
300
301 /* Select HW settle delay for channel */
302 buf[3] &= (u8) ~ADC5_USR_HW_SETTLE_DELAY_MASK;
303 buf[3] |= prop->hw_settle_time;
304
305 /* Select ADC enable */
306 buf[4] |= ADC5_USR_EN_CTL1_ADC_EN;
307
308 /* Select CONV request */
309 buf[5] |= ADC5_USR_CONV_REQ_REQ;
310
311 if (!adc->poll_eoc)
312 reinit_completion(&adc->complete);
313
314 return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
315}
316
317static int adc5_do_conversion(struct adc5_chip *adc,
318 struct adc5_channel_prop *prop,
319 struct iio_chan_spec const *chan,
320 u16 *data_volt, u16 *data_cur)
321{
322 int ret;
323
324 mutex_lock(&adc->lock);
325
326 ret = adc5_configure(adc, prop);
327 if (ret) {
328 pr_err("ADC configure failed with %d\n", ret);
329 goto unlock;
330 }
331
332 if (adc->poll_eoc) {
333 ret = adc5_poll_wait_eoc(adc);
334 if (ret < 0) {
335 pr_err("EOC bit not set\n");
336 goto unlock;
337 }
338 } else {
339 ret = wait_for_completion_timeout(&adc->complete,
340 ADC5_CONV_TIMEOUT);
341 if (!ret) {
342 pr_debug("Did not get completion timeout.\n");
343 ret = adc5_poll_wait_eoc(adc);
344 if (ret < 0) {
345 pr_err("EOC bit not set\n");
346 goto unlock;
347 }
348 }
349 }
350
351 ret = adc5_read_voltage_data(adc, data_volt);
352unlock:
353 mutex_unlock(&adc->lock);
354
355 return ret;
356}
357
358static irqreturn_t adc5_isr(int irq, void *dev_id)
359{
360 struct adc5_chip *adc = dev_id;
361
362 complete(&adc->complete);
363
364 return IRQ_HANDLED;
365}
366
367static int adc5_of_xlate(struct iio_dev *indio_dev,
368 const struct of_phandle_args *iiospec)
369{
370 struct adc5_chip *adc = iio_priv(indio_dev);
371 int i;
372
373 for (i = 0; i < adc->nchannels; i++)
374 if (adc->chan_props[i].channel == iiospec->args[0])
375 return i;
376
377 return -EINVAL;
378}
379
380static int adc5_read_raw(struct iio_dev *indio_dev,
381 struct iio_chan_spec const *chan, int *val, int *val2,
382 long mask)
383{
384 struct adc5_chip *adc = iio_priv(indio_dev);
385 struct adc5_channel_prop *prop;
386 u16 adc_code_volt, adc_code_cur;
387 int ret;
388
389 prop = &adc->chan_props[chan->address];
390
391 switch (mask) {
392 case IIO_CHAN_INFO_PROCESSED:
393 ret = adc5_do_conversion(adc, prop, chan,
394 &adc_code_volt, &adc_code_cur);
395 if (ret)
396 return ret;
397
398 ret = qcom_adc5_hw_scale(prop->scale_fn_type,
399 &adc5_prescale_ratios[prop->prescale],
400 adc->data,
401 adc_code_volt, val);
402 if (ret)
403 return ret;
404
405 return IIO_VAL_INT;
406 default:
407 return -EINVAL;
408 }
409
410 return 0;
411}
412
413static const struct iio_info adc5_info = {
414 .read_raw = adc5_read_raw,
415 .of_xlate = adc5_of_xlate,
416};
417
418struct adc5_channels {
419 const char *datasheet_name;
420 unsigned int prescale_index;
421 enum iio_chan_type type;
422 long info_mask;
423 enum vadc_scale_fn_type scale_fn_type;
424};
425
426#define ADC5_CHAN(_dname, _type, _mask, _pre, _scale) \
427 { \
428 .datasheet_name = _dname, \
429 .prescale_index = _pre, \
430 .type = _type, \
431 .info_mask = _mask, \
432 .scale_fn_type = _scale, \
433 }, \
434
435#define ADC5_CHAN_TEMP(_dname, _pre, _scale) \
436 ADC5_CHAN(_dname, IIO_TEMP, \
437 BIT(IIO_CHAN_INFO_PROCESSED), \
438 _pre, _scale) \
439
440#define ADC5_CHAN_VOLT(_dname, _pre, _scale) \
441 ADC5_CHAN(_dname, IIO_VOLTAGE, \
442 BIT(IIO_CHAN_INFO_PROCESSED), \
443 _pre, _scale) \
444
445static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = {
446 [ADC5_REF_GND] = ADC5_CHAN_VOLT("ref_gnd", 1,
447 SCALE_HW_CALIB_DEFAULT)
448 [ADC5_1P25VREF] = ADC5_CHAN_VOLT("vref_1p25", 1,
449 SCALE_HW_CALIB_DEFAULT)
450 [ADC5_VPH_PWR] = ADC5_CHAN_VOLT("vph_pwr", 3,
451 SCALE_HW_CALIB_DEFAULT)
452 [ADC5_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 3,
453 SCALE_HW_CALIB_DEFAULT)
454 [ADC5_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 1,
455 SCALE_HW_CALIB_PMIC_THERM)
456 [ADC5_USB_IN_I] = ADC5_CHAN_VOLT("usb_in_i_uv", 1,
457 SCALE_HW_CALIB_DEFAULT)
458 [ADC5_USB_IN_V_16] = ADC5_CHAN_VOLT("usb_in_v_div_16", 16,
459 SCALE_HW_CALIB_DEFAULT)
460 [ADC5_CHG_TEMP] = ADC5_CHAN_TEMP("chg_temp", 1,
461 SCALE_HW_CALIB_PM5_CHG_TEMP)
462 /* Charger prescales SBUx and MID_CHG to fit within 1.8V upper unit */
463 [ADC5_SBUx] = ADC5_CHAN_VOLT("chg_sbux", 3,
464 SCALE_HW_CALIB_DEFAULT)
465 [ADC5_MID_CHG_DIV6] = ADC5_CHAN_VOLT("chg_mid_chg", 6,
466 SCALE_HW_CALIB_DEFAULT)
467 [ADC5_XO_THERM_100K_PU] = ADC5_CHAN_TEMP("xo_therm", 1,
468 SCALE_HW_CALIB_XOTHERM)
469 [ADC5_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_100k_pu", 1,
470 SCALE_HW_CALIB_THERM_100K_PULLUP)
471 [ADC5_AMUX_THM2_100K_PU] = ADC5_CHAN_TEMP("amux_thm2_100k_pu", 1,
472 SCALE_HW_CALIB_THERM_100K_PULLUP)
473 [ADC5_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_100k_pu", 1,
474 SCALE_HW_CALIB_THERM_100K_PULLUP)
475 [ADC5_AMUX_THM2] = ADC5_CHAN_TEMP("amux_thm2", 1,
476 SCALE_HW_CALIB_PM5_SMB_TEMP)
477};
478
479static const struct adc5_channels adc5_chans_rev2[ADC5_MAX_CHANNEL] = {
480 [ADC5_REF_GND] = ADC5_CHAN_VOLT("ref_gnd", 1,
481 SCALE_HW_CALIB_DEFAULT)
482 [ADC5_1P25VREF] = ADC5_CHAN_VOLT("vref_1p25", 1,
483 SCALE_HW_CALIB_DEFAULT)
484 [ADC5_VPH_PWR] = ADC5_CHAN_VOLT("vph_pwr", 3,
485 SCALE_HW_CALIB_DEFAULT)
486 [ADC5_VBAT_SNS] = ADC5_CHAN_VOLT("vbat_sns", 3,
487 SCALE_HW_CALIB_DEFAULT)
488 [ADC5_VCOIN] = ADC5_CHAN_VOLT("vcoin", 3,
489 SCALE_HW_CALIB_DEFAULT)
490 [ADC5_DIE_TEMP] = ADC5_CHAN_TEMP("die_temp", 1,
491 SCALE_HW_CALIB_PMIC_THERM)
492 [ADC5_AMUX_THM1_100K_PU] = ADC5_CHAN_TEMP("amux_thm1_100k_pu", 1,
493 SCALE_HW_CALIB_THERM_100K_PULLUP)
494 [ADC5_AMUX_THM3_100K_PU] = ADC5_CHAN_TEMP("amux_thm3_100k_pu", 1,
495 SCALE_HW_CALIB_THERM_100K_PULLUP)
496 [ADC5_AMUX_THM5_100K_PU] = ADC5_CHAN_TEMP("amux_thm5_100k_pu", 1,
497 SCALE_HW_CALIB_THERM_100K_PULLUP)
498 [ADC5_XO_THERM_100K_PU] = ADC5_CHAN_TEMP("xo_therm_100k_pu", 1,
499 SCALE_HW_CALIB_THERM_100K_PULLUP)
500};
501
502static int adc5_get_dt_channel_data(struct adc5_chip *adc,
503 struct adc5_channel_prop *prop,
504 struct device_node *node,
505 const struct adc5_data *data)
506{
507 const char *name = node->name, *channel_name;
508 u32 chan, value, varr[2];
509 int ret;
510 struct device *dev = adc->dev;
511
512 ret = of_property_read_u32(node, "reg", &chan);
513 if (ret) {
514 dev_err(dev, "invalid channel number %s\n", name);
515 return ret;
516 }
517
518 if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA) {
519 dev_err(dev, "%s invalid channel number %d\n", name, chan);
520 return -EINVAL;
521 }
522
523 /* the channel has DT description */
524 prop->channel = chan;
525
526 channel_name = of_get_property(node,
527 "label", NULL) ? : node->name;
528 if (!channel_name) {
529 pr_err("Invalid channel name\n");
530 return -EINVAL;
531 }
532 prop->datasheet_name = channel_name;
533
534 ret = of_property_read_u32(node, "qcom,decimation", &value);
535 if (!ret) {
536 ret = adc5_decimation_from_dt(value, data->decimation);
537 if (ret < 0) {
538 dev_err(dev, "%02x invalid decimation %d\n",
539 chan, value);
540 return ret;
541 }
542 prop->decimation = ret;
543 } else {
544 prop->decimation = ADC5_DECIMATION_DEFAULT;
545 }
546
547 ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
548 if (!ret) {
549 ret = adc5_prescaling_from_dt(varr[0], varr[1]);
550 if (ret < 0) {
551 dev_err(dev, "%02x invalid pre-scaling <%d %d>\n",
552 chan, varr[0], varr[1]);
553 return ret;
554 }
555 prop->prescale = ret;
556 }
557
558 ret = of_property_read_u32(node, "qcom,hw-settle-time", &value);
559 if (!ret) {
560 u8 dig_version[2];
561
562 ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version,
563 sizeof(dig_version));
564 if (ret < 0) {
565 dev_err(dev, "Invalid dig version read %d\n", ret);
566 return ret;
567 }
568
569 pr_debug("dig_ver:minor:%d, major:%d\n", dig_version[0],
570 dig_version[1]);
571 /* Digital controller >= 5.3 have hw_settle_2 option */
572 if (dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
573 dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR)
574 ret = adc5_hw_settle_time_from_dt(value,
575 data->hw_settle_2);
576 else
577 ret = adc5_hw_settle_time_from_dt(value,
578 data->hw_settle_1);
579
580 if (ret < 0) {
581 dev_err(dev, "%02x invalid hw-settle-time %d us\n",
582 chan, value);
583 return ret;
584 }
585 prop->hw_settle_time = ret;
586 } else {
587 prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME;
588 }
589
590 ret = of_property_read_u32(node, "qcom,avg-samples", &value);
591 if (!ret) {
592 ret = adc5_avg_samples_from_dt(value);
593 if (ret < 0) {
594 dev_err(dev, "%02x invalid avg-samples %d\n",
595 chan, value);
596 return ret;
597 }
598 prop->avg_samples = ret;
599 } else {
600 prop->avg_samples = VADC_DEF_AVG_SAMPLES;
601 }
602
603 if (of_property_read_bool(node, "qcom,ratiometric"))
604 prop->cal_method = ADC5_RATIOMETRIC_CAL;
605 else
606 prop->cal_method = ADC5_ABSOLUTE_CAL;
607
608 /*
609 * Default to using timer calibration. Using a fresh calibration value
610 * for every conversion will increase the overall time for a request.
611 */
612 prop->cal_val = ADC5_TIMER_CAL;
613
614 dev_dbg(dev, "%02x name %s\n", chan, name);
615
616 return 0;
617}
618
619static const struct adc5_data adc5_data_pmic = {
620 .full_scale_code_volt = 0x70e4,
621 .full_scale_code_cur = 0x2710,
622 .adc_chans = adc5_chans_pmic,
623 .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
624 {250, 420, 840},
625 .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
626 {15, 100, 200, 300, 400, 500, 600, 700,
627 800, 900, 1, 2, 4, 6, 8, 10},
628 .hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
629 {15, 100, 200, 300, 400, 500, 600, 700,
630 1, 2, 4, 8, 16, 32, 64, 128},
631};
632
633static const struct adc5_data adc5_data_pmic_rev2 = {
634 .full_scale_code_volt = 0x4000,
635 .full_scale_code_cur = 0x1800,
636 .adc_chans = adc5_chans_rev2,
637 .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
638 {256, 512, 1024},
639 .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
640 {0, 100, 200, 300, 400, 500, 600, 700,
641 800, 900, 1, 2, 4, 6, 8, 10},
642 .hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
643 {15, 100, 200, 300, 400, 500, 600, 700,
644 1, 2, 4, 8, 16, 32, 64, 128},
645};
646
647static const struct of_device_id adc5_match_table[] = {
648 {
649 .compatible = "qcom,spmi-adc5",
650 .data = &adc5_data_pmic,
651 },
652 {
653 .compatible = "qcom,spmi-adc-rev2",
654 .data = &adc5_data_pmic_rev2,
655 },
656 { }
657};
658
659static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
660{
661 const struct adc5_channels *adc_chan;
662 struct iio_chan_spec *iio_chan;
663 struct adc5_channel_prop prop, *chan_props;
664 struct device_node *child;
665 unsigned int index = 0;
666 const struct of_device_id *id;
667 const struct adc5_data *data;
668 int ret;
669
670 adc->nchannels = of_get_available_child_count(node);
671 if (!adc->nchannels)
672 return -EINVAL;
673
674 adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels,
675 sizeof(*adc->iio_chans), GFP_KERNEL);
676 if (!adc->iio_chans)
677 return -ENOMEM;
678
679 adc->chan_props = devm_kcalloc(adc->dev, adc->nchannels,
680 sizeof(*adc->chan_props), GFP_KERNEL);
681 if (!adc->chan_props)
682 return -ENOMEM;
683
684 chan_props = adc->chan_props;
685 iio_chan = adc->iio_chans;
686 id = of_match_node(adc5_match_table, node);
687 if (id)
688 data = id->data;
689 else
690 data = &adc5_data_pmic;
691 adc->data = data;
692
693 for_each_available_child_of_node(node, child) {
694 ret = adc5_get_dt_channel_data(adc, &prop, child, data);
695 if (ret) {
696 of_node_put(child);
697 return ret;
698 }
699
700 prop.scale_fn_type =
701 data->adc_chans[prop.channel].scale_fn_type;
702 *chan_props = prop;
703 adc_chan = &data->adc_chans[prop.channel];
704
705 iio_chan->channel = prop.channel;
706 iio_chan->datasheet_name = prop.datasheet_name;
707 iio_chan->extend_name = prop.datasheet_name;
708 iio_chan->info_mask_separate = adc_chan->info_mask;
709 iio_chan->type = adc_chan->type;
710 iio_chan->address = index;
711 iio_chan++;
712 chan_props++;
713 index++;
714 }
715
716 return 0;
717}
718
719static int adc5_probe(struct platform_device *pdev)
720{
721 struct device_node *node = pdev->dev.of_node;
722 struct device *dev = &pdev->dev;
723 struct iio_dev *indio_dev;
724 struct adc5_chip *adc;
725 struct regmap *regmap;
726 int ret, irq_eoc;
727 u32 reg;
728
729 regmap = dev_get_regmap(dev->parent, NULL);
730 if (!regmap)
731 return -ENODEV;
732
733 ret = of_property_read_u32(node, "reg", &reg);
734 if (ret < 0)
735 return ret;
736
737 indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
738 if (!indio_dev)
739 return -ENOMEM;
740
741 adc = iio_priv(indio_dev);
742 adc->regmap = regmap;
743 adc->dev = dev;
744 adc->base = reg;
745 init_completion(&adc->complete);
746 mutex_init(&adc->lock);
747
748 ret = adc5_get_dt_data(adc, node);
749 if (ret) {
750 pr_err("adc get dt data failed\n");
751 return ret;
752 }
753
754 irq_eoc = platform_get_irq(pdev, 0);
755 if (irq_eoc < 0) {
756 if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL)
757 return irq_eoc;
758 adc->poll_eoc = true;
759 } else {
760 ret = devm_request_irq(dev, irq_eoc, adc5_isr, 0,
761 "pm-adc5", adc);
762 if (ret)
763 return ret;
764 }
765
766 indio_dev->dev.parent = dev;
767 indio_dev->dev.of_node = node;
768 indio_dev->name = pdev->name;
769 indio_dev->modes = INDIO_DIRECT_MODE;
770 indio_dev->info = &adc5_info;
771 indio_dev->channels = adc->iio_chans;
772 indio_dev->num_channels = adc->nchannels;
773
774 return devm_iio_device_register(dev, indio_dev);
775}
776
777static struct platform_driver adc5_driver = {
778 .driver = {
779 .name = "qcom-spmi-adc5.c",
780 .of_match_table = adc5_match_table,
781 },
782 .probe = adc5_probe,
783};
784module_platform_driver(adc5_driver);
785
786MODULE_ALIAS("platform:qcom-spmi-adc5");
787MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC5 ADC driver");
788MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c
index fe3d7826783c..dcd7fb5b9fb2 100644
--- a/drivers/iio/adc/qcom-vadc-common.c
+++ b/drivers/iio/adc/qcom-vadc-common.c
@@ -47,8 +47,79 @@ static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
47 {44, 125} 47 {44, 125}
48}; 48};
49 49
50/*
51 * Voltage to temperature table for 100k pull up for NTCG104EF104 with
52 * 1.875V reference.
53 */
54static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
55 { 1831, -40000 },
56 { 1814, -35000 },
57 { 1791, -30000 },
58 { 1761, -25000 },
59 { 1723, -20000 },
60 { 1675, -15000 },
61 { 1616, -10000 },
62 { 1545, -5000 },
63 { 1463, 0 },
64 { 1370, 5000 },
65 { 1268, 10000 },
66 { 1160, 15000 },
67 { 1049, 20000 },
68 { 937, 25000 },
69 { 828, 30000 },
70 { 726, 35000 },
71 { 630, 40000 },
72 { 544, 45000 },
73 { 467, 50000 },
74 { 399, 55000 },
75 { 340, 60000 },
76 { 290, 65000 },
77 { 247, 70000 },
78 { 209, 75000 },
79 { 179, 80000 },
80 { 153, 85000 },
81 { 130, 90000 },
82 { 112, 95000 },
83 { 96, 100000 },
84 { 82, 105000 },
85 { 71, 110000 },
86 { 62, 115000 },
87 { 53, 120000 },
88 { 46, 125000 },
89};
90
91static int qcom_vadc_scale_hw_calib_volt(
92 const struct vadc_prescale_ratio *prescale,
93 const struct adc5_data *data,
94 u16 adc_code, int *result_uv);
95static int qcom_vadc_scale_hw_calib_therm(
96 const struct vadc_prescale_ratio *prescale,
97 const struct adc5_data *data,
98 u16 adc_code, int *result_mdec);
99static int qcom_vadc_scale_hw_smb_temp(
100 const struct vadc_prescale_ratio *prescale,
101 const struct adc5_data *data,
102 u16 adc_code, int *result_mdec);
103static int qcom_vadc_scale_hw_chg5_temp(
104 const struct vadc_prescale_ratio *prescale,
105 const struct adc5_data *data,
106 u16 adc_code, int *result_mdec);
107static int qcom_vadc_scale_hw_calib_die_temp(
108 const struct vadc_prescale_ratio *prescale,
109 const struct adc5_data *data,
110 u16 adc_code, int *result_mdec);
111
112static struct qcom_adc5_scale_type scale_adc5_fn[] = {
113 [SCALE_HW_CALIB_DEFAULT] = {qcom_vadc_scale_hw_calib_volt},
114 [SCALE_HW_CALIB_THERM_100K_PULLUP] = {qcom_vadc_scale_hw_calib_therm},
115 [SCALE_HW_CALIB_XOTHERM] = {qcom_vadc_scale_hw_calib_therm},
116 [SCALE_HW_CALIB_PMIC_THERM] = {qcom_vadc_scale_hw_calib_die_temp},
117 [SCALE_HW_CALIB_PM5_CHG_TEMP] = {qcom_vadc_scale_hw_chg5_temp},
118 [SCALE_HW_CALIB_PM5_SMB_TEMP] = {qcom_vadc_scale_hw_smb_temp},
119};
120
50static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts, 121static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
51 u32 tablesize, s32 input, s64 *output) 122 u32 tablesize, s32 input, int *output)
52{ 123{
53 bool descending = 1; 124 bool descending = 1;
54 u32 i = 0; 125 u32 i = 0;
@@ -128,7 +199,7 @@ static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
128 bool absolute, u16 adc_code, 199 bool absolute, u16 adc_code,
129 int *result_mdec) 200 int *result_mdec)
130{ 201{
131 s64 voltage = 0, result = 0; 202 s64 voltage = 0;
132 int ret; 203 int ret;
133 204
134 qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage); 205 qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage);
@@ -138,12 +209,11 @@ static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
138 209
139 ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb, 210 ret = qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb,
140 ARRAY_SIZE(adcmap_100k_104ef_104fb), 211 ARRAY_SIZE(adcmap_100k_104ef_104fb),
141 voltage, &result); 212 voltage, result_mdec);
142 if (ret) 213 if (ret)
143 return ret; 214 return ret;
144 215
145 result *= 1000; 216 *result_mdec *= 1000;
146 *result_mdec = result;
147 217
148 return 0; 218 return 0;
149} 219}
@@ -191,6 +261,99 @@ static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph,
191 return 0; 261 return 0;
192} 262}
193 263
264static int qcom_vadc_scale_code_voltage_factor(u16 adc_code,
265 const struct vadc_prescale_ratio *prescale,
266 const struct adc5_data *data,
267 unsigned int factor)
268{
269 s64 voltage, temp, adc_vdd_ref_mv = 1875;
270
271 /*
272 * The normal data range is between 0V to 1.875V. On cases where
273 * we read low voltage values, the ADC code can go beyond the
274 * range and the scale result is incorrect so we clamp the values
275 * for the cases where the code represents a value below 0V
276 */
277 if (adc_code > VADC5_MAX_CODE)
278 adc_code = 0;
279
280 /* (ADC code * vref_vadc (1.875V)) / full_scale_code */
281 voltage = (s64) adc_code * adc_vdd_ref_mv * 1000;
282 voltage = div64_s64(voltage, data->full_scale_code_volt);
283 if (voltage > 0) {
284 voltage *= prescale->den;
285 temp = prescale->num * factor;
286 voltage = div64_s64(voltage, temp);
287 } else {
288 voltage = 0;
289 }
290
291 return (int) voltage;
292}
293
294static int qcom_vadc_scale_hw_calib_volt(
295 const struct vadc_prescale_ratio *prescale,
296 const struct adc5_data *data,
297 u16 adc_code, int *result_uv)
298{
299 *result_uv = qcom_vadc_scale_code_voltage_factor(adc_code,
300 prescale, data, 1);
301
302 return 0;
303}
304
305static int qcom_vadc_scale_hw_calib_therm(
306 const struct vadc_prescale_ratio *prescale,
307 const struct adc5_data *data,
308 u16 adc_code, int *result_mdec)
309{
310 int voltage;
311
312 voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
313 prescale, data, 1000);
314
315 /* Map voltage to temperature from look-up table */
316 return qcom_vadc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref,
317 ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
318 voltage, result_mdec);
319}
320
321static int qcom_vadc_scale_hw_calib_die_temp(
322 const struct vadc_prescale_ratio *prescale,
323 const struct adc5_data *data,
324 u16 adc_code, int *result_mdec)
325{
326 *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code,
327 prescale, data, 2);
328 *result_mdec -= KELVINMIL_CELSIUSMIL;
329
330 return 0;
331}
332
333static int qcom_vadc_scale_hw_smb_temp(
334 const struct vadc_prescale_ratio *prescale,
335 const struct adc5_data *data,
336 u16 adc_code, int *result_mdec)
337{
338 *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code * 100,
339 prescale, data, PMIC5_SMB_TEMP_SCALE_FACTOR);
340 *result_mdec = PMIC5_SMB_TEMP_CONSTANT - *result_mdec;
341
342 return 0;
343}
344
345static int qcom_vadc_scale_hw_chg5_temp(
346 const struct vadc_prescale_ratio *prescale,
347 const struct adc5_data *data,
348 u16 adc_code, int *result_mdec)
349{
350 *result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code,
351 prescale, data, 4);
352 *result_mdec = PMIC5_CHG_TEMP_SCALE_FACTOR - *result_mdec;
353
354 return 0;
355}
356
194int qcom_vadc_scale(enum vadc_scale_fn_type scaletype, 357int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
195 const struct vadc_linear_graph *calib_graph, 358 const struct vadc_linear_graph *calib_graph,
196 const struct vadc_prescale_ratio *prescale, 359 const struct vadc_prescale_ratio *prescale,
@@ -221,6 +384,22 @@ int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
221} 384}
222EXPORT_SYMBOL(qcom_vadc_scale); 385EXPORT_SYMBOL(qcom_vadc_scale);
223 386
387int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
388 const struct vadc_prescale_ratio *prescale,
389 const struct adc5_data *data,
390 u16 adc_code, int *result)
391{
392 if (!(scaletype >= SCALE_HW_CALIB_DEFAULT &&
393 scaletype < SCALE_HW_CALIB_INVALID)) {
394 pr_err("Invalid scale type %d\n", scaletype);
395 return -EINVAL;
396 }
397
398 return scale_adc5_fn[scaletype].scale_fn(prescale, data,
399 adc_code, result);
400}
401EXPORT_SYMBOL(qcom_adc5_hw_scale);
402
224int qcom_vadc_decimation_from_dt(u32 value) 403int qcom_vadc_decimation_from_dt(u32 value)
225{ 404{
226 if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN || 405 if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h
index 1d5354ff5c72..bbb1fa02b382 100644
--- a/drivers/iio/adc/qcom-vadc-common.h
+++ b/drivers/iio/adc/qcom-vadc-common.h
@@ -25,15 +25,31 @@
25 25
26#define VADC_DECIMATION_MIN 512 26#define VADC_DECIMATION_MIN 512
27#define VADC_DECIMATION_MAX 4096 27#define VADC_DECIMATION_MAX 4096
28#define ADC5_DEF_VBAT_PRESCALING 1 /* 1:3 */
29#define ADC5_DECIMATION_SHORT 250
30#define ADC5_DECIMATION_MEDIUM 420
31#define ADC5_DECIMATION_LONG 840
32/* Default decimation - 1024 for rev2, 840 for pmic5 */
33#define ADC5_DECIMATION_DEFAULT 2
34#define ADC5_DECIMATION_SAMPLES_MAX 3
28 35
29#define VADC_HW_SETTLE_DELAY_MAX 10000 36#define VADC_HW_SETTLE_DELAY_MAX 10000
37#define VADC_HW_SETTLE_SAMPLES_MAX 16
30#define VADC_AVG_SAMPLES_MAX 512 38#define VADC_AVG_SAMPLES_MAX 512
39#define ADC5_AVG_SAMPLES_MAX 16
31 40
32#define KELVINMIL_CELSIUSMIL 273150 41#define KELVINMIL_CELSIUSMIL 273150
42#define PMIC5_CHG_TEMP_SCALE_FACTOR 377500
43#define PMIC5_SMB_TEMP_CONSTANT 419400
44#define PMIC5_SMB_TEMP_SCALE_FACTOR 356
33 45
34#define PMI_CHG_SCALE_1 -138890 46#define PMI_CHG_SCALE_1 -138890
35#define PMI_CHG_SCALE_2 391750000000LL 47#define PMI_CHG_SCALE_2 391750000000LL
36 48
49#define VADC5_MAX_CODE 0x7fff
50#define ADC5_FULL_SCALE_CODE 0x70e4
51#define ADC5_USR_DATA_CHECK 0x8000
52
37/** 53/**
38 * struct vadc_map_pt - Map the graph representation for ADC channel 54 * struct vadc_map_pt - Map the graph representation for ADC channel
39 * @x: Represent the ADC digitized code. 55 * @x: Represent the ADC digitized code.
@@ -89,6 +105,18 @@ struct vadc_prescale_ratio {
89 * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade. 105 * SCALE_PMIC_THERM: Returns result in milli degree's Centigrade.
90 * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC. 106 * SCALE_XOTHERM: Returns XO thermistor voltage in millidegC.
91 * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp 107 * SCALE_PMI_CHG_TEMP: Conversion for PMI CHG temp
108 * SCALE_HW_CALIB_DEFAULT: Default scaling to convert raw adc code to
109 * voltage (uV) with hardware applied offset/slope values to adc code.
110 * SCALE_HW_CALIB_THERM_100K_PULLUP: Returns temperature in millidegC using
111 * lookup table. The hardware applies offset/slope to adc code.
112 * SCALE_HW_CALIB_XOTHERM: Returns XO thermistor voltage in millidegC using
113 * 100k pullup. The hardware applies offset/slope to adc code.
114 * SCALE_HW_CALIB_PMIC_THERM: Returns result in milli degree's Centigrade.
115 * The hardware applies offset/slope to adc code.
116 * SCALE_HW_CALIB_PM5_CHG_TEMP: Returns result in millidegrees for PMIC5
117 * charger temperature.
118 * SCALE_HW_CALIB_PM5_SMB_TEMP: Returns result in millidegrees for PMIC5
119 * SMB1390 temperature.
92 */ 120 */
93enum vadc_scale_fn_type { 121enum vadc_scale_fn_type {
94 SCALE_DEFAULT = 0, 122 SCALE_DEFAULT = 0,
@@ -96,6 +124,22 @@ enum vadc_scale_fn_type {
96 SCALE_PMIC_THERM, 124 SCALE_PMIC_THERM,
97 SCALE_XOTHERM, 125 SCALE_XOTHERM,
98 SCALE_PMI_CHG_TEMP, 126 SCALE_PMI_CHG_TEMP,
127 SCALE_HW_CALIB_DEFAULT,
128 SCALE_HW_CALIB_THERM_100K_PULLUP,
129 SCALE_HW_CALIB_XOTHERM,
130 SCALE_HW_CALIB_PMIC_THERM,
131 SCALE_HW_CALIB_PM5_CHG_TEMP,
132 SCALE_HW_CALIB_PM5_SMB_TEMP,
133 SCALE_HW_CALIB_INVALID,
134};
135
136struct adc5_data {
137 const u32 full_scale_code_volt;
138 const u32 full_scale_code_cur;
139 const struct adc5_channels *adc_chans;
140 unsigned int *decimation;
141 unsigned int *hw_settle_1;
142 unsigned int *hw_settle_2;
99}; 143};
100 144
101int qcom_vadc_scale(enum vadc_scale_fn_type scaletype, 145int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
@@ -104,6 +148,16 @@ int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
104 bool absolute, 148 bool absolute,
105 u16 adc_code, int *result_mdec); 149 u16 adc_code, int *result_mdec);
106 150
151struct qcom_adc5_scale_type {
152 int (*scale_fn)(const struct vadc_prescale_ratio *prescale,
153 const struct adc5_data *data, u16 adc_code, int *result);
154};
155
156int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
157 const struct vadc_prescale_ratio *prescale,
158 const struct adc5_data *data,
159 u16 adc_code, int *result_mdec);
160
107int qcom_vadc_decimation_from_dt(u32 value); 161int qcom_vadc_decimation_from_dt(u32 value);
108 162
109#endif /* QCOM_VADC_COMMON_H */ 163#endif /* QCOM_VADC_COMMON_H */