Lines Matching +full:adc +full:- +full:chan
1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/iio/adc/qcom-vadc-common.h>
23 #include <dt-bindings/iio/qcom,spmi-vadc.h>
104 * struct adc5_channel_prop - ADC channel property.
113 * @avg_samples: ability to provide single result from the ADC
133 * struct adc5_chip - ADC private structure.
136 * @base: base address for the ADC peripheral.
137 * @nchannels: number of ADC channels.
138 * @chan_props: array of ADC channel properties.
141 * @complete: ADC result notification after interrupt is received.
142 * @lock: ADC lock for access to the peripheral.
158 static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len) in adc5_read() argument
160 return regmap_bulk_read(adc->regmap, adc->base + offset, data, len); in adc5_read()
163 static int adc5_write(struct adc5_chip *adc, u16 offset, u8 *data, int len) in adc5_write() argument
165 return regmap_bulk_write(adc->regmap, adc->base + offset, data, len); in adc5_write()
168 static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val) in adc5_masked_write() argument
170 return regmap_update_bits(adc->regmap, adc->base + offset, mask, val); in adc5_masked_write()
173 static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data) in adc5_read_voltage_data() argument
178 ret = adc5_read(adc, ADC5_USR_DATA0, &rslt_lsb, sizeof(rslt_lsb)); in adc5_read_voltage_data()
182 ret = adc5_read(adc, ADC5_USR_DATA1, &rslt_msb, sizeof(rslt_lsb)); in adc5_read_voltage_data()
189 dev_err(adc->dev, "Invalid data:0x%x\n", *data); in adc5_read_voltage_data()
190 return -EINVAL; in adc5_read_voltage_data()
193 dev_dbg(adc->dev, "voltage raw code:0x%x\n", *data); in adc5_read_voltage_data()
198 static int adc5_poll_wait_eoc(struct adc5_chip *adc) in adc5_poll_wait_eoc() argument
205 ret = adc5_read(adc, ADC5_USR_STATUS1, &status1, in adc5_poll_wait_eoc()
217 return -ETIMEDOUT; in adc5_poll_wait_eoc()
220 static void adc5_update_dig_param(struct adc5_chip *adc, in adc5_update_dig_param() argument
225 *data |= (prop->cal_val << ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT); in adc5_update_dig_param()
229 *data |= (prop->cal_method << ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT); in adc5_update_dig_param()
233 *data |= (prop->decimation << ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT); in adc5_update_dig_param()
236 static int adc5_configure(struct adc5_chip *adc, in adc5_configure() argument
243 ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); in adc5_configure()
248 adc5_update_dig_param(adc, prop, &buf[0]); in adc5_configure()
252 buf[1] |= prop->avg_samples; in adc5_configure()
254 /* Select ADC channel */ in adc5_configure()
255 buf[2] = prop->channel; in adc5_configure()
259 buf[3] |= prop->hw_settle_time; in adc5_configure()
261 /* Select ADC enable */ in adc5_configure()
267 if (!adc->poll_eoc) in adc5_configure()
268 reinit_completion(&adc->complete); in adc5_configure()
270 return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); in adc5_configure()
273 static int adc7_configure(struct adc5_chip *adc, in adc7_configure() argument
279 ret = adc5_masked_write(adc, ADC_APP_SID, ADC_APP_SID_MASK, prop->sid); in adc7_configure()
283 ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); in adc7_configure()
288 adc5_update_dig_param(adc, prop, &buf[0]); in adc7_configure()
292 buf[1] |= prop->avg_samples; in adc7_configure()
294 /* Select ADC channel */ in adc7_configure()
295 buf[2] = prop->channel; in adc7_configure()
299 buf[3] |= prop->hw_settle_time; in adc7_configure()
304 if (!adc->poll_eoc) in adc7_configure()
305 reinit_completion(&adc->complete); in adc7_configure()
307 ret = adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf)); in adc7_configure()
311 return adc5_write(adc, ADC5_USR_CONV_REQ, &conv_req, 1); in adc7_configure()
314 static int adc5_do_conversion(struct adc5_chip *adc, in adc5_do_conversion() argument
316 struct iio_chan_spec const *chan, in adc5_do_conversion() argument
321 mutex_lock(&adc->lock); in adc5_do_conversion()
323 ret = adc5_configure(adc, prop); in adc5_do_conversion()
325 dev_err(adc->dev, "ADC configure failed with %d\n", ret); in adc5_do_conversion()
329 if (adc->poll_eoc) { in adc5_do_conversion()
330 ret = adc5_poll_wait_eoc(adc); in adc5_do_conversion()
332 dev_err(adc->dev, "EOC bit not set\n"); in adc5_do_conversion()
336 ret = wait_for_completion_timeout(&adc->complete, in adc5_do_conversion()
339 dev_dbg(adc->dev, "Did not get completion timeout.\n"); in adc5_do_conversion()
340 ret = adc5_poll_wait_eoc(adc); in adc5_do_conversion()
342 dev_err(adc->dev, "EOC bit not set\n"); in adc5_do_conversion()
348 ret = adc5_read_voltage_data(adc, data_volt); in adc5_do_conversion()
350 mutex_unlock(&adc->lock); in adc5_do_conversion()
355 static int adc7_do_conversion(struct adc5_chip *adc, in adc7_do_conversion() argument
357 struct iio_chan_spec const *chan, in adc7_do_conversion() argument
363 mutex_lock(&adc->lock); in adc7_do_conversion()
365 ret = adc7_configure(adc, prop); in adc7_do_conversion()
367 dev_err(adc->dev, "ADC configure failed with %d\n", ret); in adc7_do_conversion()
372 wait_for_completion_timeout(&adc->complete, ADC7_CONV_TIMEOUT); in adc7_do_conversion()
374 ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1); in adc7_do_conversion()
379 dev_err(adc->dev, "Unexpected conversion fault\n"); in adc7_do_conversion()
380 ret = -EIO; in adc7_do_conversion()
384 ret = adc5_read_voltage_data(adc, data_volt); in adc7_do_conversion()
387 mutex_unlock(&adc->lock); in adc7_do_conversion()
392 typedef int (*adc_do_conversion)(struct adc5_chip *adc,
394 struct iio_chan_spec const *chan,
399 struct adc5_chip *adc = dev_id; in adc5_isr() local
401 complete(&adc->complete); in adc5_isr()
409 struct adc5_chip *adc = iio_priv(indio_dev); in adc5_of_xlate() local
412 for (i = 0; i < adc->nchannels; i++) in adc5_of_xlate()
413 if (adc->chan_props[i].channel == iiospec->args[0]) in adc5_of_xlate()
416 return -EINVAL; in adc5_of_xlate()
422 struct adc5_chip *adc = iio_priv(indio_dev); in adc7_of_xlate() local
425 for (i = 0; i < adc->nchannels; i++) { in adc7_of_xlate()
426 v_channel = (adc->chan_props[i].sid << ADC_CHANNEL_OFFSET) | in adc7_of_xlate()
427 adc->chan_props[i].channel; in adc7_of_xlate()
428 if (v_channel == iiospec->args[0]) in adc7_of_xlate()
432 return -EINVAL; in adc7_of_xlate()
436 struct iio_chan_spec const *chan, int *val, int *val2, in adc_read_raw_common() argument
439 struct adc5_chip *adc = iio_priv(indio_dev); in adc_read_raw_common() local
444 prop = &adc->chan_props[chan->address]; in adc_read_raw_common()
448 ret = do_conv(adc, prop, chan, in adc_read_raw_common()
453 ret = qcom_adc5_hw_scale(prop->scale_fn_type, in adc_read_raw_common()
454 prop->prescale, in adc_read_raw_common()
455 adc->data, in adc_read_raw_common()
462 return -EINVAL; in adc_read_raw_common()
467 struct iio_chan_spec const *chan, int *val, int *val2, in adc5_read_raw() argument
470 return adc_read_raw_common(indio_dev, chan, val, val2, in adc5_read_raw()
475 struct iio_chan_spec const *chan, int *val, int *val2, in adc7_read_raw() argument
478 return adc_read_raw_common(indio_dev, chan, val, val2, in adc7_read_raw()
614 static int adc5_get_dt_channel_data(struct adc5_chip *adc, in adc5_get_dt_channel_data() argument
619 const char *name = node->name, *channel_name; in adc5_get_dt_channel_data()
620 u32 chan, value, varr[2]; in adc5_get_dt_channel_data() local
623 struct device *dev = adc->dev; in adc5_get_dt_channel_data()
625 ret = of_property_read_u32(node, "reg", &chan); in adc5_get_dt_channel_data()
635 if (adc->data->info == &adc7_info) { in adc5_get_dt_channel_data()
636 sid = chan >> ADC_CHANNEL_OFFSET; in adc5_get_dt_channel_data()
637 chan = chan & ADC_CHANNEL_MASK; in adc5_get_dt_channel_data()
640 if (chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA || in adc5_get_dt_channel_data()
641 !data->adc_chans[chan].datasheet_name) { in adc5_get_dt_channel_data()
642 dev_err(dev, "%s invalid channel number %d\n", name, chan); in adc5_get_dt_channel_data()
643 return -EINVAL; in adc5_get_dt_channel_data()
647 prop->channel = chan; in adc5_get_dt_channel_data()
648 prop->sid = sid; in adc5_get_dt_channel_data()
651 "label", NULL) ? : node->name; in adc5_get_dt_channel_data()
654 return -EINVAL; in adc5_get_dt_channel_data()
656 prop->datasheet_name = channel_name; in adc5_get_dt_channel_data()
660 ret = qcom_adc5_decimation_from_dt(value, data->decimation); in adc5_get_dt_channel_data()
663 chan, value); in adc5_get_dt_channel_data()
666 prop->decimation = ret; in adc5_get_dt_channel_data()
668 prop->decimation = ADC5_DECIMATION_DEFAULT; in adc5_get_dt_channel_data()
671 ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2); in adc5_get_dt_channel_data()
675 dev_err(dev, "%02x invalid pre-scaling <%d %d>\n", in adc5_get_dt_channel_data()
676 chan, varr[0], varr[1]); in adc5_get_dt_channel_data()
679 prop->prescale = ret; in adc5_get_dt_channel_data()
681 prop->prescale = in adc5_get_dt_channel_data()
682 adc->data->adc_chans[prop->channel].prescale_index; in adc5_get_dt_channel_data()
685 ret = of_property_read_u32(node, "qcom,hw-settle-time", &value); in adc5_get_dt_channel_data()
689 ret = adc5_read(adc, ADC5_USR_REVISION1, dig_version, in adc5_get_dt_channel_data()
701 adc->data->info == &adc7_info) in adc5_get_dt_channel_data()
702 ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_2); in adc5_get_dt_channel_data()
704 ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_1); in adc5_get_dt_channel_data()
707 dev_err(dev, "%02x invalid hw-settle-time %d us\n", in adc5_get_dt_channel_data()
708 chan, value); in adc5_get_dt_channel_data()
711 prop->hw_settle_time = ret; in adc5_get_dt_channel_data()
713 prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME; in adc5_get_dt_channel_data()
716 ret = of_property_read_u32(node, "qcom,avg-samples", &value); in adc5_get_dt_channel_data()
720 dev_err(dev, "%02x invalid avg-samples %d\n", in adc5_get_dt_channel_data()
721 chan, value); in adc5_get_dt_channel_data()
724 prop->avg_samples = ret; in adc5_get_dt_channel_data()
726 prop->avg_samples = VADC_DEF_AVG_SAMPLES; in adc5_get_dt_channel_data()
730 prop->cal_method = ADC5_RATIOMETRIC_CAL; in adc5_get_dt_channel_data()
732 prop->cal_method = ADC5_ABSOLUTE_CAL; in adc5_get_dt_channel_data()
738 prop->cal_val = ADC5_TIMER_CAL; in adc5_get_dt_channel_data()
740 dev_dbg(dev, "%02x name %s\n", chan, name); in adc5_get_dt_channel_data()
789 .compatible = "qcom,spmi-adc5",
793 .compatible = "qcom,spmi-adc7",
797 .compatible = "qcom,spmi-adc-rev2",
804 static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node) in adc5_get_dt_data() argument
813 adc->nchannels = of_get_available_child_count(node); in adc5_get_dt_data()
814 if (!adc->nchannels) in adc5_get_dt_data()
815 return -EINVAL; in adc5_get_dt_data()
817 adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels, in adc5_get_dt_data()
818 sizeof(*adc->iio_chans), GFP_KERNEL); in adc5_get_dt_data()
819 if (!adc->iio_chans) in adc5_get_dt_data()
820 return -ENOMEM; in adc5_get_dt_data()
822 adc->chan_props = devm_kcalloc(adc->dev, adc->nchannels, in adc5_get_dt_data()
823 sizeof(*adc->chan_props), GFP_KERNEL); in adc5_get_dt_data()
824 if (!adc->chan_props) in adc5_get_dt_data()
825 return -ENOMEM; in adc5_get_dt_data()
827 chan_props = adc->chan_props; in adc5_get_dt_data()
828 iio_chan = adc->iio_chans; in adc5_get_dt_data()
829 adc->data = of_device_get_match_data(adc->dev); in adc5_get_dt_data()
830 if (!adc->data) in adc5_get_dt_data()
831 adc->data = &adc5_data_pmic; in adc5_get_dt_data()
834 ret = adc5_get_dt_channel_data(adc, &prop, child, adc->data); in adc5_get_dt_data()
841 adc->data->adc_chans[prop.channel].scale_fn_type; in adc5_get_dt_data()
843 adc_chan = &adc->data->adc_chans[prop.channel]; in adc5_get_dt_data()
845 iio_chan->channel = prop.channel; in adc5_get_dt_data()
846 iio_chan->datasheet_name = prop.datasheet_name; in adc5_get_dt_data()
847 iio_chan->extend_name = prop.datasheet_name; in adc5_get_dt_data()
848 iio_chan->info_mask_separate = adc_chan->info_mask; in adc5_get_dt_data()
849 iio_chan->type = adc_chan->type; in adc5_get_dt_data()
850 iio_chan->address = index; in adc5_get_dt_data()
861 struct device_node *node = pdev->dev.of_node; in adc5_probe()
862 struct device *dev = &pdev->dev; in adc5_probe()
864 struct adc5_chip *adc; in adc5_probe() local
869 regmap = dev_get_regmap(dev->parent, NULL); in adc5_probe()
871 return -ENODEV; in adc5_probe()
877 indio_dev = devm_iio_device_alloc(dev, sizeof(*adc)); in adc5_probe()
879 return -ENOMEM; in adc5_probe()
881 adc = iio_priv(indio_dev); in adc5_probe()
882 adc->regmap = regmap; in adc5_probe()
883 adc->dev = dev; in adc5_probe()
884 adc->base = reg; in adc5_probe()
886 init_completion(&adc->complete); in adc5_probe()
887 mutex_init(&adc->lock); in adc5_probe()
889 ret = adc5_get_dt_data(adc, node); in adc5_probe()
891 dev_err(dev, "adc get dt data failed\n"); in adc5_probe()
897 if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL) in adc5_probe()
899 adc->poll_eoc = true; in adc5_probe()
902 "pm-adc5", adc); in adc5_probe()
907 indio_dev->name = pdev->name; in adc5_probe()
908 indio_dev->modes = INDIO_DIRECT_MODE; in adc5_probe()
909 indio_dev->info = adc->data->info; in adc5_probe()
910 indio_dev->channels = adc->iio_chans; in adc5_probe()
911 indio_dev->num_channels = adc->nchannels; in adc5_probe()
918 .name = "qcom-spmi-adc5",
925 MODULE_ALIAS("platform:qcom-spmi-adc5");
926 MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC5 ADC driver");