Commit | Line | Data |
---|---|---|
97fb5e8d | 1 | // SPDX-License-Identifier: GPL-2.0-only |
0917de94 | 2 | /* |
ba71704a | 3 | * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. |
0917de94 SV |
4 | */ |
5 | ||
6 | #include <linux/bitops.h> | |
7 | #include <linux/completion.h> | |
8 | #include <linux/delay.h> | |
9 | #include <linux/err.h> | |
ec82edb2 | 10 | #include <linux/iio/adc/qcom-vadc-common.h> |
0917de94 SV |
11 | #include <linux/iio/iio.h> |
12 | #include <linux/interrupt.h> | |
13 | #include <linux/kernel.h> | |
937125ac | 14 | #include <linux/math64.h> |
0917de94 | 15 | #include <linux/module.h> |
e7c672d0 | 16 | #include <linux/mod_devicetable.h> |
0917de94 | 17 | #include <linux/platform_device.h> |
e7c672d0 | 18 | #include <linux/property.h> |
0917de94 SV |
19 | #include <linux/regmap.h> |
20 | #include <linux/slab.h> | |
21 | #include <linux/log2.h> | |
22 | ||
23 | #include <dt-bindings/iio/qcom,spmi-vadc.h> | |
24 | ||
25 | /* VADC register and bit definitions */ | |
26 | #define VADC_REVISION2 0x1 | |
27 | #define VADC_REVISION2_SUPPORTED_VADC 1 | |
28 | ||
29 | #define VADC_PERPH_TYPE 0x4 | |
30 | #define VADC_PERPH_TYPE_ADC 8 | |
31 | ||
32 | #define VADC_PERPH_SUBTYPE 0x5 | |
33 | #define VADC_PERPH_SUBTYPE_VADC 1 | |
34 | ||
35 | #define VADC_STATUS1 0x8 | |
36 | #define VADC_STATUS1_OP_MODE 4 | |
37 | #define VADC_STATUS1_REQ_STS BIT(1) | |
38 | #define VADC_STATUS1_EOC BIT(0) | |
39 | #define VADC_STATUS1_REQ_STS_EOC_MASK 0x3 | |
40 | ||
41 | #define VADC_MODE_CTL 0x40 | |
42 | #define VADC_OP_MODE_SHIFT 3 | |
43 | #define VADC_OP_MODE_NORMAL 0 | |
44 | #define VADC_AMUX_TRIM_EN BIT(1) | |
45 | #define VADC_ADC_TRIM_EN BIT(0) | |
46 | ||
47 | #define VADC_EN_CTL1 0x46 | |
48 | #define VADC_EN_CTL1_SET BIT(7) | |
49 | ||
50 | #define VADC_ADC_CH_SEL_CTL 0x48 | |
51 | ||
52 | #define VADC_ADC_DIG_PARAM 0x50 | |
53 | #define VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT 2 | |
54 | ||
55 | #define VADC_HW_SETTLE_DELAY 0x51 | |
56 | ||
57 | #define VADC_CONV_REQ 0x52 | |
58 | #define VADC_CONV_REQ_SET BIT(7) | |
59 | ||
60 | #define VADC_FAST_AVG_CTL 0x5a | |
61 | #define VADC_FAST_AVG_EN 0x5b | |
62 | #define VADC_FAST_AVG_EN_SET BIT(7) | |
63 | ||
64 | #define VADC_ACCESS 0xd0 | |
65 | #define VADC_ACCESS_DATA 0xa5 | |
66 | ||
67 | #define VADC_PERH_RESET_CTL3 0xda | |
68 | #define VADC_FOLLOW_WARM_RB BIT(2) | |
69 | ||
70 | #define VADC_DATA 0x60 /* 16 bits */ | |
71 | ||
0917de94 SV |
72 | #define VADC_CHAN_MIN VADC_USBIN |
73 | #define VADC_CHAN_MAX VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM | |
74 | ||
0917de94 SV |
75 | /** |
76 | * struct vadc_channel_prop - VADC channel property. | |
77 | * @channel: channel number, refer to the channel list. | |
78 | * @calibration: calibration type. | |
79 | * @decimation: sampling rate supported for the channel. | |
80 | * @prescale: channel scaling performed on the input signal. | |
81 | * @hw_settle_time: the time between AMUX being configured and the | |
82 | * start of conversion. | |
83 | * @avg_samples: ability to provide single result from the ADC | |
84 | * that is an average of multiple measurements. | |
e932d4f0 | 85 | * @scale_fn_type: Represents the scaling function to convert voltage |
7c271eea | 86 | * physical units desired by the client for the channel. |
0917de94 SV |
87 | */ |
88 | struct vadc_channel_prop { | |
89 | unsigned int channel; | |
90 | enum vadc_calibration calibration; | |
91 | unsigned int decimation; | |
92 | unsigned int prescale; | |
93 | unsigned int hw_settle_time; | |
94 | unsigned int avg_samples; | |
e932d4f0 | 95 | enum vadc_scale_fn_type scale_fn_type; |
0917de94 SV |
96 | }; |
97 | ||
98 | /** | |
99 | * struct vadc_priv - VADC private structure. | |
100 | * @regmap: pointer to struct regmap. | |
101 | * @dev: pointer to struct device. | |
102 | * @base: base address for the ADC peripheral. | |
103 | * @nchannels: number of VADC channels. | |
104 | * @chan_props: array of VADC channel properties. | |
105 | * @iio_chans: array of IIO channels specification. | |
106 | * @are_ref_measured: are reference points measured. | |
107 | * @poll_eoc: use polling instead of interrupt. | |
108 | * @complete: VADC result notification after interrupt is received. | |
109 | * @graph: store parameters for calibration. | |
110 | * @lock: ADC lock for access to the peripheral. | |
111 | */ | |
112 | struct vadc_priv { | |
113 | struct regmap *regmap; | |
114 | struct device *dev; | |
115 | u16 base; | |
116 | unsigned int nchannels; | |
117 | struct vadc_channel_prop *chan_props; | |
118 | struct iio_chan_spec *iio_chans; | |
119 | bool are_ref_measured; | |
120 | bool poll_eoc; | |
121 | struct completion complete; | |
122 | struct vadc_linear_graph graph[2]; | |
123 | struct mutex lock; | |
124 | }; | |
125 | ||
a5e9b2dd AS |
126 | static const struct u32_fract vadc_prescale_ratios[] = { |
127 | { .numerator = 1, .denominator = 1 }, | |
128 | { .numerator = 1, .denominator = 3 }, | |
129 | { .numerator = 1, .denominator = 4 }, | |
130 | { .numerator = 1, .denominator = 6 }, | |
131 | { .numerator = 1, .denominator = 20 }, | |
132 | { .numerator = 1, .denominator = 8 }, | |
133 | { .numerator = 10, .denominator = 81 }, | |
134 | { .numerator = 1, .denominator = 10 }, | |
0917de94 SV |
135 | }; |
136 | ||
137 | static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data) | |
138 | { | |
139 | return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1); | |
140 | } | |
141 | ||
142 | static int vadc_write(struct vadc_priv *vadc, u16 offset, u8 data) | |
143 | { | |
144 | return regmap_write(vadc->regmap, vadc->base + offset, data); | |
145 | } | |
146 | ||
147 | static int vadc_reset(struct vadc_priv *vadc) | |
148 | { | |
149 | u8 data; | |
150 | int ret; | |
151 | ||
152 | ret = vadc_write(vadc, VADC_ACCESS, VADC_ACCESS_DATA); | |
153 | if (ret) | |
154 | return ret; | |
155 | ||
156 | ret = vadc_read(vadc, VADC_PERH_RESET_CTL3, &data); | |
157 | if (ret) | |
158 | return ret; | |
159 | ||
160 | ret = vadc_write(vadc, VADC_ACCESS, VADC_ACCESS_DATA); | |
161 | if (ret) | |
162 | return ret; | |
163 | ||
164 | data |= VADC_FOLLOW_WARM_RB; | |
165 | ||
166 | return vadc_write(vadc, VADC_PERH_RESET_CTL3, data); | |
167 | } | |
168 | ||
169 | static int vadc_set_state(struct vadc_priv *vadc, bool state) | |
170 | { | |
171 | return vadc_write(vadc, VADC_EN_CTL1, state ? VADC_EN_CTL1_SET : 0); | |
172 | } | |
173 | ||
174 | static void vadc_show_status(struct vadc_priv *vadc) | |
175 | { | |
176 | u8 mode, sta1, chan, dig, en, req; | |
177 | int ret; | |
178 | ||
179 | ret = vadc_read(vadc, VADC_MODE_CTL, &mode); | |
180 | if (ret) | |
181 | return; | |
182 | ||
183 | ret = vadc_read(vadc, VADC_ADC_DIG_PARAM, &dig); | |
184 | if (ret) | |
185 | return; | |
186 | ||
187 | ret = vadc_read(vadc, VADC_ADC_CH_SEL_CTL, &chan); | |
188 | if (ret) | |
189 | return; | |
190 | ||
191 | ret = vadc_read(vadc, VADC_CONV_REQ, &req); | |
192 | if (ret) | |
193 | return; | |
194 | ||
195 | ret = vadc_read(vadc, VADC_STATUS1, &sta1); | |
196 | if (ret) | |
197 | return; | |
198 | ||
199 | ret = vadc_read(vadc, VADC_EN_CTL1, &en); | |
200 | if (ret) | |
201 | return; | |
202 | ||
203 | dev_err(vadc->dev, | |
204 | "mode:%02x en:%02x chan:%02x dig:%02x req:%02x sta1:%02x\n", | |
205 | mode, en, chan, dig, req, sta1); | |
206 | } | |
207 | ||
208 | static int vadc_configure(struct vadc_priv *vadc, | |
209 | struct vadc_channel_prop *prop) | |
210 | { | |
211 | u8 decimation, mode_ctrl; | |
212 | int ret; | |
213 | ||
214 | /* Mode selection */ | |
215 | mode_ctrl = (VADC_OP_MODE_NORMAL << VADC_OP_MODE_SHIFT) | | |
216 | VADC_ADC_TRIM_EN | VADC_AMUX_TRIM_EN; | |
217 | ret = vadc_write(vadc, VADC_MODE_CTL, mode_ctrl); | |
218 | if (ret) | |
219 | return ret; | |
220 | ||
221 | /* Channel selection */ | |
222 | ret = vadc_write(vadc, VADC_ADC_CH_SEL_CTL, prop->channel); | |
223 | if (ret) | |
224 | return ret; | |
225 | ||
226 | /* Digital parameter setup */ | |
227 | decimation = prop->decimation << VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT; | |
228 | ret = vadc_write(vadc, VADC_ADC_DIG_PARAM, decimation); | |
229 | if (ret) | |
230 | return ret; | |
231 | ||
232 | /* HW settle time delay */ | |
233 | ret = vadc_write(vadc, VADC_HW_SETTLE_DELAY, prop->hw_settle_time); | |
234 | if (ret) | |
235 | return ret; | |
236 | ||
237 | ret = vadc_write(vadc, VADC_FAST_AVG_CTL, prop->avg_samples); | |
238 | if (ret) | |
239 | return ret; | |
240 | ||
241 | if (prop->avg_samples) | |
242 | ret = vadc_write(vadc, VADC_FAST_AVG_EN, VADC_FAST_AVG_EN_SET); | |
243 | else | |
244 | ret = vadc_write(vadc, VADC_FAST_AVG_EN, 0); | |
245 | ||
246 | return ret; | |
247 | } | |
248 | ||
249 | static int vadc_poll_wait_eoc(struct vadc_priv *vadc, unsigned int interval_us) | |
250 | { | |
251 | unsigned int count, retry; | |
252 | u8 sta1; | |
253 | int ret; | |
254 | ||
255 | retry = interval_us / VADC_CONV_TIME_MIN_US; | |
256 | ||
257 | for (count = 0; count < retry; count++) { | |
258 | ret = vadc_read(vadc, VADC_STATUS1, &sta1); | |
259 | if (ret) | |
260 | return ret; | |
261 | ||
262 | sta1 &= VADC_STATUS1_REQ_STS_EOC_MASK; | |
263 | if (sta1 == VADC_STATUS1_EOC) | |
264 | return 0; | |
265 | ||
266 | usleep_range(VADC_CONV_TIME_MIN_US, VADC_CONV_TIME_MAX_US); | |
267 | } | |
268 | ||
269 | vadc_show_status(vadc); | |
270 | ||
271 | return -ETIMEDOUT; | |
272 | } | |
273 | ||
274 | static int vadc_read_result(struct vadc_priv *vadc, u16 *data) | |
275 | { | |
276 | int ret; | |
277 | ||
278 | ret = regmap_bulk_read(vadc->regmap, vadc->base + VADC_DATA, data, 2); | |
279 | if (ret) | |
280 | return ret; | |
281 | ||
282 | *data = clamp_t(u16, *data, VADC_MIN_ADC_CODE, VADC_MAX_ADC_CODE); | |
283 | ||
284 | return 0; | |
285 | } | |
286 | ||
287 | static struct vadc_channel_prop *vadc_get_channel(struct vadc_priv *vadc, | |
288 | unsigned int num) | |
289 | { | |
290 | unsigned int i; | |
291 | ||
292 | for (i = 0; i < vadc->nchannels; i++) | |
293 | if (vadc->chan_props[i].channel == num) | |
294 | return &vadc->chan_props[i]; | |
295 | ||
296 | dev_dbg(vadc->dev, "no such channel %02x\n", num); | |
297 | ||
298 | return NULL; | |
299 | } | |
300 | ||
301 | static int vadc_do_conversion(struct vadc_priv *vadc, | |
302 | struct vadc_channel_prop *prop, u16 *data) | |
303 | { | |
304 | unsigned int timeout; | |
305 | int ret; | |
306 | ||
307 | mutex_lock(&vadc->lock); | |
308 | ||
309 | ret = vadc_configure(vadc, prop); | |
310 | if (ret) | |
311 | goto unlock; | |
312 | ||
313 | if (!vadc->poll_eoc) | |
314 | reinit_completion(&vadc->complete); | |
315 | ||
316 | ret = vadc_set_state(vadc, true); | |
317 | if (ret) | |
318 | goto unlock; | |
319 | ||
320 | ret = vadc_write(vadc, VADC_CONV_REQ, VADC_CONV_REQ_SET); | |
321 | if (ret) | |
322 | goto err_disable; | |
323 | ||
324 | timeout = BIT(prop->avg_samples) * VADC_CONV_TIME_MIN_US * 2; | |
325 | ||
326 | if (vadc->poll_eoc) { | |
327 | ret = vadc_poll_wait_eoc(vadc, timeout); | |
328 | } else { | |
329 | ret = wait_for_completion_timeout(&vadc->complete, timeout); | |
330 | if (!ret) { | |
331 | ret = -ETIMEDOUT; | |
332 | goto err_disable; | |
333 | } | |
334 | ||
335 | /* Double check conversion status */ | |
336 | ret = vadc_poll_wait_eoc(vadc, VADC_CONV_TIME_MIN_US); | |
337 | if (ret) | |
338 | goto err_disable; | |
339 | } | |
340 | ||
341 | ret = vadc_read_result(vadc, data); | |
342 | ||
343 | err_disable: | |
344 | vadc_set_state(vadc, false); | |
345 | if (ret) | |
346 | dev_err(vadc->dev, "conversion failed\n"); | |
347 | unlock: | |
348 | mutex_unlock(&vadc->lock); | |
349 | return ret; | |
350 | } | |
351 | ||
352 | static int vadc_measure_ref_points(struct vadc_priv *vadc) | |
353 | { | |
354 | struct vadc_channel_prop *prop; | |
355 | u16 read_1, read_2; | |
356 | int ret; | |
357 | ||
7c271eea | 358 | vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE; |
0917de94 SV |
359 | vadc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV; |
360 | ||
361 | prop = vadc_get_channel(vadc, VADC_REF_1250MV); | |
362 | ret = vadc_do_conversion(vadc, prop, &read_1); | |
363 | if (ret) | |
364 | goto err; | |
365 | ||
366 | /* Try with buffered 625mV channel first */ | |
367 | prop = vadc_get_channel(vadc, VADC_SPARE1); | |
368 | if (!prop) | |
369 | prop = vadc_get_channel(vadc, VADC_REF_625MV); | |
370 | ||
371 | ret = vadc_do_conversion(vadc, prop, &read_2); | |
372 | if (ret) | |
373 | goto err; | |
374 | ||
375 | if (read_1 == read_2) { | |
376 | ret = -EINVAL; | |
377 | goto err; | |
378 | } | |
379 | ||
380 | vadc->graph[VADC_CALIB_ABSOLUTE].dy = read_1 - read_2; | |
381 | vadc->graph[VADC_CALIB_ABSOLUTE].gnd = read_2; | |
382 | ||
383 | /* Ratiometric calibration */ | |
384 | prop = vadc_get_channel(vadc, VADC_VDD_VADC); | |
385 | ret = vadc_do_conversion(vadc, prop, &read_1); | |
386 | if (ret) | |
387 | goto err; | |
388 | ||
389 | prop = vadc_get_channel(vadc, VADC_GND_REF); | |
390 | ret = vadc_do_conversion(vadc, prop, &read_2); | |
391 | if (ret) | |
392 | goto err; | |
393 | ||
394 | if (read_1 == read_2) { | |
395 | ret = -EINVAL; | |
396 | goto err; | |
397 | } | |
398 | ||
399 | vadc->graph[VADC_CALIB_RATIOMETRIC].dy = read_1 - read_2; | |
400 | vadc->graph[VADC_CALIB_RATIOMETRIC].gnd = read_2; | |
401 | err: | |
402 | if (ret) | |
403 | dev_err(vadc->dev, "measure reference points failed\n"); | |
404 | ||
405 | return ret; | |
406 | } | |
407 | ||
a5e9b2dd | 408 | static int vadc_prescaling_from_dt(u32 numerator, u32 denominator) |
0917de94 SV |
409 | { |
410 | unsigned int pre; | |
411 | ||
412 | for (pre = 0; pre < ARRAY_SIZE(vadc_prescale_ratios); pre++) | |
a5e9b2dd AS |
413 | if (vadc_prescale_ratios[pre].numerator == numerator && |
414 | vadc_prescale_ratios[pre].denominator == denominator) | |
0917de94 SV |
415 | break; |
416 | ||
417 | if (pre == ARRAY_SIZE(vadc_prescale_ratios)) | |
418 | return -EINVAL; | |
419 | ||
420 | return pre; | |
421 | } | |
422 | ||
423 | static int vadc_hw_settle_time_from_dt(u32 value) | |
424 | { | |
425 | if ((value <= 1000 && value % 100) || (value > 1000 && value % 2000)) | |
426 | return -EINVAL; | |
427 | ||
428 | if (value <= 1000) | |
429 | value /= 100; | |
430 | else | |
431 | value = value / 2000 + 10; | |
432 | ||
433 | return value; | |
434 | } | |
435 | ||
436 | static int vadc_avg_samples_from_dt(u32 value) | |
437 | { | |
438 | if (!is_power_of_2(value) || value > VADC_AVG_SAMPLES_MAX) | |
439 | return -EINVAL; | |
440 | ||
441 | return __ffs64(value); | |
442 | } | |
443 | ||
444 | static int vadc_read_raw(struct iio_dev *indio_dev, | |
445 | struct iio_chan_spec const *chan, int *val, int *val2, | |
446 | long mask) | |
447 | { | |
448 | struct vadc_priv *vadc = iio_priv(indio_dev); | |
449 | struct vadc_channel_prop *prop; | |
450 | u16 adc_code; | |
451 | int ret; | |
452 | ||
453 | switch (mask) { | |
454 | case IIO_CHAN_INFO_PROCESSED: | |
455 | prop = &vadc->chan_props[chan->address]; | |
456 | ret = vadc_do_conversion(vadc, prop, &adc_code); | |
457 | if (ret) | |
458 | break; | |
459 | ||
e932d4f0 LW |
460 | ret = qcom_vadc_scale(prop->scale_fn_type, |
461 | &vadc->graph[prop->calibration], | |
462 | &vadc_prescale_ratios[prop->prescale], | |
463 | (prop->calibration == VADC_CALIB_ABSOLUTE), | |
464 | adc_code, val); | |
465 | if (ret) | |
466 | break; | |
0917de94 | 467 | |
0917de94 SV |
468 | return IIO_VAL_INT; |
469 | case IIO_CHAN_INFO_RAW: | |
470 | prop = &vadc->chan_props[chan->address]; | |
471 | ret = vadc_do_conversion(vadc, prop, &adc_code); | |
472 | if (ret) | |
473 | break; | |
474 | ||
ba71704a | 475 | *val = (int)adc_code; |
0917de94 | 476 | return IIO_VAL_INT; |
0917de94 SV |
477 | default: |
478 | ret = -EINVAL; | |
479 | break; | |
480 | } | |
481 | ||
482 | return ret; | |
483 | } | |
484 | ||
e7c672d0 NS |
485 | static int vadc_fwnode_xlate(struct iio_dev *indio_dev, |
486 | const struct fwnode_reference_args *iiospec) | |
0917de94 SV |
487 | { |
488 | struct vadc_priv *vadc = iio_priv(indio_dev); | |
489 | unsigned int i; | |
490 | ||
491 | for (i = 0; i < vadc->nchannels; i++) | |
492 | if (vadc->iio_chans[i].channel == iiospec->args[0]) | |
493 | return i; | |
494 | ||
495 | return -EINVAL; | |
496 | } | |
497 | ||
498 | static const struct iio_info vadc_info = { | |
499 | .read_raw = vadc_read_raw, | |
e7c672d0 | 500 | .fwnode_xlate = vadc_fwnode_xlate, |
0917de94 SV |
501 | }; |
502 | ||
503 | struct vadc_channels { | |
504 | const char *datasheet_name; | |
505 | unsigned int prescale_index; | |
506 | enum iio_chan_type type; | |
507 | long info_mask; | |
e932d4f0 | 508 | enum vadc_scale_fn_type scale_fn_type; |
0917de94 SV |
509 | }; |
510 | ||
7c271eea | 511 | #define VADC_CHAN(_dname, _type, _mask, _pre, _scale) \ |
0917de94 SV |
512 | [VADC_##_dname] = { \ |
513 | .datasheet_name = __stringify(_dname), \ | |
514 | .prescale_index = _pre, \ | |
515 | .type = _type, \ | |
7c271eea | 516 | .info_mask = _mask, \ |
e932d4f0 | 517 | .scale_fn_type = _scale \ |
0917de94 SV |
518 | }, \ |
519 | ||
7c271eea RKP |
520 | #define VADC_NO_CHAN(_dname, _type, _mask, _pre) \ |
521 | [VADC_##_dname] = { \ | |
522 | .datasheet_name = __stringify(_dname), \ | |
523 | .prescale_index = _pre, \ | |
524 | .type = _type, \ | |
525 | .info_mask = _mask \ | |
526 | }, | |
0917de94 | 527 | |
7c271eea RKP |
528 | #define VADC_CHAN_TEMP(_dname, _pre, _scale) \ |
529 | VADC_CHAN(_dname, IIO_TEMP, \ | |
530 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED), \ | |
531 | _pre, _scale) \ | |
532 | ||
533 | #define VADC_CHAN_VOLT(_dname, _pre, _scale) \ | |
0917de94 | 534 | VADC_CHAN(_dname, IIO_VOLTAGE, \ |
ba71704a | 535 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\ |
7c271eea RKP |
536 | _pre, _scale) \ |
537 | ||
538 | #define VADC_CHAN_NO_SCALE(_dname, _pre) \ | |
539 | VADC_NO_CHAN(_dname, IIO_VOLTAGE, \ | |
540 | BIT(IIO_CHAN_INFO_RAW), \ | |
0917de94 SV |
541 | _pre) \ |
542 | ||
543 | /* | |
544 | * The array represents all possible ADC channels found in the supported PMICs. | |
545 | * Every index in the array is equal to the channel number per datasheet. The | |
546 | * gaps in the array should be treated as reserved channels. | |
547 | */ | |
548 | static const struct vadc_channels vadc_chans[] = { | |
7c271eea RKP |
549 | VADC_CHAN_VOLT(USBIN, 4, SCALE_DEFAULT) |
550 | VADC_CHAN_VOLT(DCIN, 4, SCALE_DEFAULT) | |
551 | VADC_CHAN_NO_SCALE(VCHG_SNS, 3) | |
552 | VADC_CHAN_NO_SCALE(SPARE1_03, 1) | |
553 | VADC_CHAN_NO_SCALE(USB_ID_MV, 1) | |
554 | VADC_CHAN_VOLT(VCOIN, 1, SCALE_DEFAULT) | |
555 | VADC_CHAN_NO_SCALE(VBAT_SNS, 1) | |
556 | VADC_CHAN_VOLT(VSYS, 1, SCALE_DEFAULT) | |
557 | VADC_CHAN_TEMP(DIE_TEMP, 0, SCALE_PMIC_THERM) | |
558 | VADC_CHAN_VOLT(REF_625MV, 0, SCALE_DEFAULT) | |
559 | VADC_CHAN_VOLT(REF_1250MV, 0, SCALE_DEFAULT) | |
560 | VADC_CHAN_NO_SCALE(CHG_TEMP, 0) | |
561 | VADC_CHAN_NO_SCALE(SPARE1, 0) | |
562 | VADC_CHAN_TEMP(SPARE2, 0, SCALE_PMI_CHG_TEMP) | |
563 | VADC_CHAN_VOLT(GND_REF, 0, SCALE_DEFAULT) | |
564 | VADC_CHAN_VOLT(VDD_VADC, 0, SCALE_DEFAULT) | |
565 | ||
566 | VADC_CHAN_NO_SCALE(P_MUX1_1_1, 0) | |
567 | VADC_CHAN_NO_SCALE(P_MUX2_1_1, 0) | |
568 | VADC_CHAN_NO_SCALE(P_MUX3_1_1, 0) | |
569 | VADC_CHAN_NO_SCALE(P_MUX4_1_1, 0) | |
570 | VADC_CHAN_NO_SCALE(P_MUX5_1_1, 0) | |
571 | VADC_CHAN_NO_SCALE(P_MUX6_1_1, 0) | |
572 | VADC_CHAN_NO_SCALE(P_MUX7_1_1, 0) | |
573 | VADC_CHAN_NO_SCALE(P_MUX8_1_1, 0) | |
574 | VADC_CHAN_NO_SCALE(P_MUX9_1_1, 0) | |
575 | VADC_CHAN_NO_SCALE(P_MUX10_1_1, 0) | |
576 | VADC_CHAN_NO_SCALE(P_MUX11_1_1, 0) | |
577 | VADC_CHAN_NO_SCALE(P_MUX12_1_1, 0) | |
578 | VADC_CHAN_NO_SCALE(P_MUX13_1_1, 0) | |
579 | VADC_CHAN_NO_SCALE(P_MUX14_1_1, 0) | |
580 | VADC_CHAN_NO_SCALE(P_MUX15_1_1, 0) | |
581 | VADC_CHAN_NO_SCALE(P_MUX16_1_1, 0) | |
582 | ||
583 | VADC_CHAN_NO_SCALE(P_MUX1_1_3, 1) | |
584 | VADC_CHAN_NO_SCALE(P_MUX2_1_3, 1) | |
585 | VADC_CHAN_NO_SCALE(P_MUX3_1_3, 1) | |
586 | VADC_CHAN_NO_SCALE(P_MUX4_1_3, 1) | |
587 | VADC_CHAN_NO_SCALE(P_MUX5_1_3, 1) | |
588 | VADC_CHAN_NO_SCALE(P_MUX6_1_3, 1) | |
589 | VADC_CHAN_NO_SCALE(P_MUX7_1_3, 1) | |
590 | VADC_CHAN_NO_SCALE(P_MUX8_1_3, 1) | |
591 | VADC_CHAN_NO_SCALE(P_MUX9_1_3, 1) | |
592 | VADC_CHAN_NO_SCALE(P_MUX10_1_3, 1) | |
593 | VADC_CHAN_NO_SCALE(P_MUX11_1_3, 1) | |
594 | VADC_CHAN_NO_SCALE(P_MUX12_1_3, 1) | |
595 | VADC_CHAN_NO_SCALE(P_MUX13_1_3, 1) | |
596 | VADC_CHAN_NO_SCALE(P_MUX14_1_3, 1) | |
597 | VADC_CHAN_NO_SCALE(P_MUX15_1_3, 1) | |
598 | VADC_CHAN_NO_SCALE(P_MUX16_1_3, 1) | |
599 | ||
600 | VADC_CHAN_NO_SCALE(LR_MUX1_BAT_THERM, 0) | |
7d200b28 | 601 | VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_DEFAULT) |
7c271eea RKP |
602 | VADC_CHAN_NO_SCALE(LR_MUX3_XO_THERM, 0) |
603 | VADC_CHAN_NO_SCALE(LR_MUX4_AMUX_THM1, 0) | |
604 | VADC_CHAN_NO_SCALE(LR_MUX5_AMUX_THM2, 0) | |
605 | VADC_CHAN_NO_SCALE(LR_MUX6_AMUX_THM3, 0) | |
606 | VADC_CHAN_NO_SCALE(LR_MUX7_HW_ID, 0) | |
607 | VADC_CHAN_NO_SCALE(LR_MUX8_AMUX_THM4, 0) | |
608 | VADC_CHAN_NO_SCALE(LR_MUX9_AMUX_THM5, 0) | |
609 | VADC_CHAN_NO_SCALE(LR_MUX10_USB_ID, 0) | |
610 | VADC_CHAN_NO_SCALE(AMUX_PU1, 0) | |
611 | VADC_CHAN_NO_SCALE(AMUX_PU2, 0) | |
612 | VADC_CHAN_NO_SCALE(LR_MUX3_BUF_XO_THERM, 0) | |
613 | ||
614 | VADC_CHAN_NO_SCALE(LR_MUX1_PU1_BAT_THERM, 0) | |
615 | VADC_CHAN_NO_SCALE(LR_MUX2_PU1_BAT_ID, 0) | |
616 | VADC_CHAN_NO_SCALE(LR_MUX3_PU1_XO_THERM, 0) | |
617 | VADC_CHAN_TEMP(LR_MUX4_PU1_AMUX_THM1, 0, SCALE_THERM_100K_PULLUP) | |
618 | VADC_CHAN_TEMP(LR_MUX5_PU1_AMUX_THM2, 0, SCALE_THERM_100K_PULLUP) | |
619 | VADC_CHAN_TEMP(LR_MUX6_PU1_AMUX_THM3, 0, SCALE_THERM_100K_PULLUP) | |
620 | VADC_CHAN_NO_SCALE(LR_MUX7_PU1_AMUX_HW_ID, 0) | |
621 | VADC_CHAN_TEMP(LR_MUX8_PU1_AMUX_THM4, 0, SCALE_THERM_100K_PULLUP) | |
622 | VADC_CHAN_TEMP(LR_MUX9_PU1_AMUX_THM5, 0, SCALE_THERM_100K_PULLUP) | |
623 | VADC_CHAN_NO_SCALE(LR_MUX10_PU1_AMUX_USB_ID, 0) | |
624 | VADC_CHAN_TEMP(LR_MUX3_BUF_PU1_XO_THERM, 0, SCALE_XOTHERM) | |
625 | ||
626 | VADC_CHAN_NO_SCALE(LR_MUX1_PU2_BAT_THERM, 0) | |
627 | VADC_CHAN_NO_SCALE(LR_MUX2_PU2_BAT_ID, 0) | |
628 | VADC_CHAN_NO_SCALE(LR_MUX3_PU2_XO_THERM, 0) | |
629 | VADC_CHAN_NO_SCALE(LR_MUX4_PU2_AMUX_THM1, 0) | |
630 | VADC_CHAN_NO_SCALE(LR_MUX5_PU2_AMUX_THM2, 0) | |
631 | VADC_CHAN_NO_SCALE(LR_MUX6_PU2_AMUX_THM3, 0) | |
632 | VADC_CHAN_NO_SCALE(LR_MUX7_PU2_AMUX_HW_ID, 0) | |
633 | VADC_CHAN_NO_SCALE(LR_MUX8_PU2_AMUX_THM4, 0) | |
634 | VADC_CHAN_NO_SCALE(LR_MUX9_PU2_AMUX_THM5, 0) | |
635 | VADC_CHAN_NO_SCALE(LR_MUX10_PU2_AMUX_USB_ID, 0) | |
636 | VADC_CHAN_NO_SCALE(LR_MUX3_BUF_PU2_XO_THERM, 0) | |
637 | ||
638 | VADC_CHAN_NO_SCALE(LR_MUX1_PU1_PU2_BAT_THERM, 0) | |
639 | VADC_CHAN_NO_SCALE(LR_MUX2_PU1_PU2_BAT_ID, 0) | |
640 | VADC_CHAN_NO_SCALE(LR_MUX3_PU1_PU2_XO_THERM, 0) | |
641 | VADC_CHAN_NO_SCALE(LR_MUX4_PU1_PU2_AMUX_THM1, 0) | |
642 | VADC_CHAN_NO_SCALE(LR_MUX5_PU1_PU2_AMUX_THM2, 0) | |
643 | VADC_CHAN_NO_SCALE(LR_MUX6_PU1_PU2_AMUX_THM3, 0) | |
644 | VADC_CHAN_NO_SCALE(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0) | |
645 | VADC_CHAN_NO_SCALE(LR_MUX8_PU1_PU2_AMUX_THM4, 0) | |
646 | VADC_CHAN_NO_SCALE(LR_MUX9_PU1_PU2_AMUX_THM5, 0) | |
647 | VADC_CHAN_NO_SCALE(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0) | |
648 | VADC_CHAN_NO_SCALE(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0) | |
0917de94 SV |
649 | }; |
650 | ||
e7c672d0 | 651 | static int vadc_get_fw_channel_data(struct device *dev, |
0917de94 | 652 | struct vadc_channel_prop *prop, |
e7c672d0 | 653 | struct fwnode_handle *fwnode) |
0917de94 | 654 | { |
e7c672d0 | 655 | const char *name = fwnode_get_name(fwnode); |
0917de94 SV |
656 | u32 chan, value, varr[2]; |
657 | int ret; | |
658 | ||
e7c672d0 | 659 | ret = fwnode_property_read_u32(fwnode, "reg", &chan); |
0917de94 SV |
660 | if (ret) { |
661 | dev_err(dev, "invalid channel number %s\n", name); | |
662 | return ret; | |
663 | } | |
664 | ||
665 | if (chan > VADC_CHAN_MAX || chan < VADC_CHAN_MIN) { | |
666 | dev_err(dev, "%s invalid channel number %d\n", name, chan); | |
667 | return -EINVAL; | |
668 | } | |
669 | ||
670 | /* the channel has DT description */ | |
671 | prop->channel = chan; | |
672 | ||
e7c672d0 | 673 | ret = fwnode_property_read_u32(fwnode, "qcom,decimation", &value); |
0917de94 | 674 | if (!ret) { |
e932d4f0 | 675 | ret = qcom_vadc_decimation_from_dt(value); |
0917de94 SV |
676 | if (ret < 0) { |
677 | dev_err(dev, "%02x invalid decimation %d\n", | |
678 | chan, value); | |
679 | return ret; | |
680 | } | |
681 | prop->decimation = ret; | |
682 | } else { | |
683 | prop->decimation = VADC_DEF_DECIMATION; | |
684 | } | |
685 | ||
e7c672d0 | 686 | ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2); |
0917de94 SV |
687 | if (!ret) { |
688 | ret = vadc_prescaling_from_dt(varr[0], varr[1]); | |
689 | if (ret < 0) { | |
690 | dev_err(dev, "%02x invalid pre-scaling <%d %d>\n", | |
691 | chan, varr[0], varr[1]); | |
692 | return ret; | |
693 | } | |
694 | prop->prescale = ret; | |
695 | } else { | |
696 | prop->prescale = vadc_chans[prop->channel].prescale_index; | |
697 | } | |
698 | ||
e7c672d0 | 699 | ret = fwnode_property_read_u32(fwnode, "qcom,hw-settle-time", &value); |
0917de94 SV |
700 | if (!ret) { |
701 | ret = vadc_hw_settle_time_from_dt(value); | |
702 | if (ret < 0) { | |
703 | dev_err(dev, "%02x invalid hw-settle-time %d us\n", | |
704 | chan, value); | |
705 | return ret; | |
706 | } | |
707 | prop->hw_settle_time = ret; | |
708 | } else { | |
709 | prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME; | |
710 | } | |
711 | ||
e7c672d0 | 712 | ret = fwnode_property_read_u32(fwnode, "qcom,avg-samples", &value); |
0917de94 SV |
713 | if (!ret) { |
714 | ret = vadc_avg_samples_from_dt(value); | |
715 | if (ret < 0) { | |
716 | dev_err(dev, "%02x invalid avg-samples %d\n", | |
717 | chan, value); | |
718 | return ret; | |
719 | } | |
720 | prop->avg_samples = ret; | |
721 | } else { | |
722 | prop->avg_samples = VADC_DEF_AVG_SAMPLES; | |
723 | } | |
724 | ||
e7c672d0 | 725 | if (fwnode_property_read_bool(fwnode, "qcom,ratiometric")) |
0917de94 SV |
726 | prop->calibration = VADC_CALIB_RATIOMETRIC; |
727 | else | |
728 | prop->calibration = VADC_CALIB_ABSOLUTE; | |
729 | ||
730 | dev_dbg(dev, "%02x name %s\n", chan, name); | |
731 | ||
732 | return 0; | |
733 | } | |
734 | ||
e7c672d0 | 735 | static int vadc_get_fw_data(struct vadc_priv *vadc) |
0917de94 SV |
736 | { |
737 | const struct vadc_channels *vadc_chan; | |
738 | struct iio_chan_spec *iio_chan; | |
739 | struct vadc_channel_prop prop; | |
e7c672d0 | 740 | struct fwnode_handle *child; |
0917de94 SV |
741 | unsigned int index = 0; |
742 | int ret; | |
743 | ||
e7c672d0 | 744 | vadc->nchannels = device_get_child_node_count(vadc->dev); |
0917de94 SV |
745 | if (!vadc->nchannels) |
746 | return -EINVAL; | |
747 | ||
748 | vadc->iio_chans = devm_kcalloc(vadc->dev, vadc->nchannels, | |
749 | sizeof(*vadc->iio_chans), GFP_KERNEL); | |
750 | if (!vadc->iio_chans) | |
751 | return -ENOMEM; | |
752 | ||
753 | vadc->chan_props = devm_kcalloc(vadc->dev, vadc->nchannels, | |
754 | sizeof(*vadc->chan_props), GFP_KERNEL); | |
755 | if (!vadc->chan_props) | |
756 | return -ENOMEM; | |
757 | ||
758 | iio_chan = vadc->iio_chans; | |
759 | ||
e7c672d0 NS |
760 | device_for_each_child_node(vadc->dev, child) { |
761 | ret = vadc_get_fw_channel_data(vadc->dev, &prop, child); | |
d4c65fe4 | 762 | if (ret) { |
e7c672d0 | 763 | fwnode_handle_put(child); |
0917de94 | 764 | return ret; |
d4c65fe4 | 765 | } |
0917de94 | 766 | |
e932d4f0 | 767 | prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type; |
0917de94 SV |
768 | vadc->chan_props[index] = prop; |
769 | ||
770 | vadc_chan = &vadc_chans[prop.channel]; | |
771 | ||
772 | iio_chan->channel = prop.channel; | |
773 | iio_chan->datasheet_name = vadc_chan->datasheet_name; | |
774 | iio_chan->info_mask_separate = vadc_chan->info_mask; | |
775 | iio_chan->type = vadc_chan->type; | |
776 | iio_chan->indexed = 1; | |
777 | iio_chan->address = index++; | |
778 | ||
779 | iio_chan++; | |
780 | } | |
781 | ||
782 | /* These channels are mandatory, they are used as reference points */ | |
783 | if (!vadc_get_channel(vadc, VADC_REF_1250MV)) { | |
784 | dev_err(vadc->dev, "Please define 1.25V channel\n"); | |
785 | return -ENODEV; | |
786 | } | |
787 | ||
788 | if (!vadc_get_channel(vadc, VADC_REF_625MV)) { | |
789 | dev_err(vadc->dev, "Please define 0.625V channel\n"); | |
790 | return -ENODEV; | |
791 | } | |
792 | ||
793 | if (!vadc_get_channel(vadc, VADC_VDD_VADC)) { | |
794 | dev_err(vadc->dev, "Please define VDD channel\n"); | |
795 | return -ENODEV; | |
796 | } | |
797 | ||
798 | if (!vadc_get_channel(vadc, VADC_GND_REF)) { | |
799 | dev_err(vadc->dev, "Please define GND channel\n"); | |
800 | return -ENODEV; | |
801 | } | |
802 | ||
803 | return 0; | |
804 | } | |
805 | ||
806 | static irqreturn_t vadc_isr(int irq, void *dev_id) | |
807 | { | |
808 | struct vadc_priv *vadc = dev_id; | |
809 | ||
810 | complete(&vadc->complete); | |
811 | ||
812 | return IRQ_HANDLED; | |
813 | } | |
814 | ||
815 | static int vadc_check_revision(struct vadc_priv *vadc) | |
816 | { | |
817 | u8 val; | |
818 | int ret; | |
819 | ||
820 | ret = vadc_read(vadc, VADC_PERPH_TYPE, &val); | |
821 | if (ret) | |
822 | return ret; | |
823 | ||
824 | if (val < VADC_PERPH_TYPE_ADC) { | |
825 | dev_err(vadc->dev, "%d is not ADC\n", val); | |
826 | return -ENODEV; | |
827 | } | |
828 | ||
829 | ret = vadc_read(vadc, VADC_PERPH_SUBTYPE, &val); | |
830 | if (ret) | |
831 | return ret; | |
832 | ||
833 | if (val < VADC_PERPH_SUBTYPE_VADC) { | |
834 | dev_err(vadc->dev, "%d is not VADC\n", val); | |
835 | return -ENODEV; | |
836 | } | |
837 | ||
838 | ret = vadc_read(vadc, VADC_REVISION2, &val); | |
839 | if (ret) | |
840 | return ret; | |
841 | ||
842 | if (val < VADC_REVISION2_SUPPORTED_VADC) { | |
843 | dev_err(vadc->dev, "revision %d not supported\n", val); | |
844 | return -ENODEV; | |
845 | } | |
846 | ||
847 | return 0; | |
848 | } | |
849 | ||
850 | static int vadc_probe(struct platform_device *pdev) | |
851 | { | |
0917de94 SV |
852 | struct device *dev = &pdev->dev; |
853 | struct iio_dev *indio_dev; | |
854 | struct vadc_priv *vadc; | |
855 | struct regmap *regmap; | |
856 | int ret, irq_eoc; | |
857 | u32 reg; | |
858 | ||
859 | regmap = dev_get_regmap(dev->parent, NULL); | |
860 | if (!regmap) | |
861 | return -ENODEV; | |
862 | ||
e7c672d0 | 863 | ret = device_property_read_u32(dev, "reg", ®); |
0917de94 SV |
864 | if (ret < 0) |
865 | return ret; | |
866 | ||
867 | indio_dev = devm_iio_device_alloc(dev, sizeof(*vadc)); | |
868 | if (!indio_dev) | |
869 | return -ENOMEM; | |
870 | ||
871 | vadc = iio_priv(indio_dev); | |
872 | vadc->regmap = regmap; | |
873 | vadc->dev = dev; | |
874 | vadc->base = reg; | |
875 | vadc->are_ref_measured = false; | |
876 | init_completion(&vadc->complete); | |
877 | mutex_init(&vadc->lock); | |
878 | ||
879 | ret = vadc_check_revision(vadc); | |
880 | if (ret) | |
881 | return ret; | |
882 | ||
e7c672d0 | 883 | ret = vadc_get_fw_data(vadc); |
0917de94 SV |
884 | if (ret) |
885 | return ret; | |
886 | ||
887 | irq_eoc = platform_get_irq(pdev, 0); | |
888 | if (irq_eoc < 0) { | |
889 | if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL) | |
890 | return irq_eoc; | |
891 | vadc->poll_eoc = true; | |
892 | } else { | |
893 | ret = devm_request_irq(dev, irq_eoc, vadc_isr, 0, | |
894 | "spmi-vadc", vadc); | |
895 | if (ret) | |
896 | return ret; | |
897 | } | |
898 | ||
899 | ret = vadc_reset(vadc); | |
900 | if (ret) { | |
901 | dev_err(dev, "reset failed\n"); | |
902 | return ret; | |
903 | } | |
904 | ||
905 | ret = vadc_measure_ref_points(vadc); | |
906 | if (ret) | |
907 | return ret; | |
908 | ||
0917de94 SV |
909 | indio_dev->name = pdev->name; |
910 | indio_dev->modes = INDIO_DIRECT_MODE; | |
911 | indio_dev->info = &vadc_info; | |
912 | indio_dev->channels = vadc->iio_chans; | |
913 | indio_dev->num_channels = vadc->nchannels; | |
914 | ||
915 | return devm_iio_device_register(dev, indio_dev); | |
916 | } | |
917 | ||
918 | static const struct of_device_id vadc_match_table[] = { | |
919 | { .compatible = "qcom,spmi-vadc" }, | |
920 | { } | |
921 | }; | |
922 | MODULE_DEVICE_TABLE(of, vadc_match_table); | |
923 | ||
924 | static struct platform_driver vadc_driver = { | |
925 | .driver = { | |
926 | .name = "qcom-spmi-vadc", | |
927 | .of_match_table = vadc_match_table, | |
928 | }, | |
929 | .probe = vadc_probe, | |
930 | }; | |
931 | module_platform_driver(vadc_driver); | |
932 | ||
933 | MODULE_ALIAS("platform:qcom-spmi-vadc"); | |
934 | MODULE_DESCRIPTION("Qualcomm SPMI PMIC voltage ADC driver"); | |
935 | MODULE_LICENSE("GPL v2"); | |
936 | MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); | |
937 | MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>"); |