Lines Matching +full:hw +full:- +full:settle +full:- +full:time +full:- +full:us
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
10 #include <linux/iio/adc/qcom-vadc-common.h>
23 #include <dt-bindings/iio/qcom,spmi-vadc.h>
76 * struct vadc_channel_prop - VADC channel property.
81 * @hw_settle_time: the time between AMUX being configured and the
101 * struct vadc_priv - VADC private structure.
141 return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1); in vadc_read()
146 return regmap_write(vadc->regmap, vadc->base + offset, data); in vadc_write()
205 dev_err(vadc->dev, in vadc_show_status()
224 ret = vadc_write(vadc, VADC_ADC_CH_SEL_CTL, prop->channel); in vadc_configure()
229 decimation = prop->decimation << VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT; in vadc_configure()
234 /* HW settle time delay */ in vadc_configure()
235 ret = vadc_write(vadc, VADC_HW_SETTLE_DELAY, prop->hw_settle_time); in vadc_configure()
239 ret = vadc_write(vadc, VADC_FAST_AVG_CTL, prop->avg_samples); in vadc_configure()
243 if (prop->avg_samples) in vadc_configure()
273 return -ETIMEDOUT; in vadc_poll_wait_eoc()
280 ret = regmap_bulk_read(vadc->regmap, vadc->base + VADC_DATA, data, 2); in vadc_read_result()
294 for (i = 0; i < vadc->nchannels; i++) in vadc_get_channel()
295 if (vadc->chan_props[i].channel == num) in vadc_get_channel()
296 return &vadc->chan_props[i]; in vadc_get_channel()
298 dev_dbg(vadc->dev, "no such channel %02x\n", num); in vadc_get_channel()
309 mutex_lock(&vadc->lock); in vadc_do_conversion()
315 if (!vadc->poll_eoc) in vadc_do_conversion()
316 reinit_completion(&vadc->complete); in vadc_do_conversion()
326 timeout = BIT(prop->avg_samples) * VADC_CONV_TIME_MIN_US * 2; in vadc_do_conversion()
328 if (vadc->poll_eoc) { in vadc_do_conversion()
331 ret = wait_for_completion_timeout(&vadc->complete, timeout); in vadc_do_conversion()
333 ret = -ETIMEDOUT; in vadc_do_conversion()
348 dev_err(vadc->dev, "conversion failed\n"); in vadc_do_conversion()
350 mutex_unlock(&vadc->lock); in vadc_do_conversion()
360 vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE; in vadc_measure_ref_points()
361 vadc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV; in vadc_measure_ref_points()
378 ret = -EINVAL; in vadc_measure_ref_points()
382 vadc->graph[VADC_CALIB_ABSOLUTE].dy = read_1 - read_2; in vadc_measure_ref_points()
383 vadc->graph[VADC_CALIB_ABSOLUTE].gnd = read_2; in vadc_measure_ref_points()
397 ret = -EINVAL; in vadc_measure_ref_points()
401 vadc->graph[VADC_CALIB_RATIOMETRIC].dy = read_1 - read_2; in vadc_measure_ref_points()
402 vadc->graph[VADC_CALIB_RATIOMETRIC].gnd = read_2; in vadc_measure_ref_points()
405 dev_err(vadc->dev, "measure reference points failed\n"); in vadc_measure_ref_points()
420 return -EINVAL; in vadc_prescaling_from_dt()
428 return -EINVAL; in vadc_hw_settle_time_from_dt()
441 return -EINVAL; in vadc_avg_samples_from_dt()
457 prop = &vadc->chan_props[chan->address]; in vadc_read_raw()
462 ret = qcom_vadc_scale(prop->scale_fn_type, in vadc_read_raw()
463 &vadc->graph[prop->calibration], in vadc_read_raw()
464 &vadc_prescale_ratios[prop->prescale], in vadc_read_raw()
465 (prop->calibration == VADC_CALIB_ABSOLUTE), in vadc_read_raw()
472 prop = &vadc->chan_props[chan->address]; in vadc_read_raw()
480 ret = -EINVAL; in vadc_read_raw()
493 for (i = 0; i < vadc->nchannels; i++) in vadc_fwnode_xlate()
494 if (vadc->iio_chans[i].channel == iiospec->args[0]) in vadc_fwnode_xlate()
497 return -EINVAL; in vadc_fwnode_xlate()
504 const char *name = vadc->chan_props[chan->address].channel_name; in vadc_read_label()
679 return -EINVAL; in vadc_get_fw_channel_data()
685 prop->channel_name = label; in vadc_get_fw_channel_data()
688 prop->channel = chan; in vadc_get_fw_channel_data()
698 prop->decimation = ret; in vadc_get_fw_channel_data()
700 prop->decimation = VADC_DEF_DECIMATION; in vadc_get_fw_channel_data()
703 ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2); in vadc_get_fw_channel_data()
707 dev_err(dev, "%02x invalid pre-scaling <%d %d>\n", in vadc_get_fw_channel_data()
711 prop->prescale = ret; in vadc_get_fw_channel_data()
713 prop->prescale = vadc_chans[prop->channel].prescale_index; in vadc_get_fw_channel_data()
716 ret = fwnode_property_read_u32(fwnode, "qcom,hw-settle-time", &value); in vadc_get_fw_channel_data()
720 dev_err(dev, "%02x invalid hw-settle-time %d us\n", in vadc_get_fw_channel_data()
724 prop->hw_settle_time = ret; in vadc_get_fw_channel_data()
726 prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME; in vadc_get_fw_channel_data()
729 ret = fwnode_property_read_u32(fwnode, "qcom,avg-samples", &value); in vadc_get_fw_channel_data()
733 dev_err(dev, "%02x invalid avg-samples %d\n", in vadc_get_fw_channel_data()
737 prop->avg_samples = ret; in vadc_get_fw_channel_data()
739 prop->avg_samples = VADC_DEF_AVG_SAMPLES; in vadc_get_fw_channel_data()
743 prop->calibration = VADC_CALIB_RATIOMETRIC; in vadc_get_fw_channel_data()
745 prop->calibration = VADC_CALIB_ABSOLUTE; in vadc_get_fw_channel_data()
761 vadc->nchannels = device_get_child_node_count(vadc->dev); in vadc_get_fw_data()
762 if (!vadc->nchannels) in vadc_get_fw_data()
763 return -EINVAL; in vadc_get_fw_data()
765 vadc->iio_chans = devm_kcalloc(vadc->dev, vadc->nchannels, in vadc_get_fw_data()
766 sizeof(*vadc->iio_chans), GFP_KERNEL); in vadc_get_fw_data()
767 if (!vadc->iio_chans) in vadc_get_fw_data()
768 return -ENOMEM; in vadc_get_fw_data()
770 vadc->chan_props = devm_kcalloc(vadc->dev, vadc->nchannels, in vadc_get_fw_data()
771 sizeof(*vadc->chan_props), GFP_KERNEL); in vadc_get_fw_data()
772 if (!vadc->chan_props) in vadc_get_fw_data()
773 return -ENOMEM; in vadc_get_fw_data()
775 iio_chan = vadc->iio_chans; in vadc_get_fw_data()
777 device_for_each_child_node(vadc->dev, child) { in vadc_get_fw_data()
778 ret = vadc_get_fw_channel_data(vadc->dev, &prop, child); in vadc_get_fw_data()
785 vadc->chan_props[index] = prop; in vadc_get_fw_data()
789 iio_chan->channel = prop.channel; in vadc_get_fw_data()
790 iio_chan->datasheet_name = vadc_chan->datasheet_name; in vadc_get_fw_data()
791 iio_chan->info_mask_separate = vadc_chan->info_mask; in vadc_get_fw_data()
792 iio_chan->type = vadc_chan->type; in vadc_get_fw_data()
793 iio_chan->indexed = 1; in vadc_get_fw_data()
794 iio_chan->address = index++; in vadc_get_fw_data()
801 dev_err(vadc->dev, "Please define 1.25V channel\n"); in vadc_get_fw_data()
802 return -ENODEV; in vadc_get_fw_data()
806 dev_err(vadc->dev, "Please define 0.625V channel\n"); in vadc_get_fw_data()
807 return -ENODEV; in vadc_get_fw_data()
811 dev_err(vadc->dev, "Please define VDD channel\n"); in vadc_get_fw_data()
812 return -ENODEV; in vadc_get_fw_data()
816 dev_err(vadc->dev, "Please define GND channel\n"); in vadc_get_fw_data()
817 return -ENODEV; in vadc_get_fw_data()
827 complete(&vadc->complete); in vadc_isr()
842 dev_err(vadc->dev, "%d is not ADC\n", val); in vadc_check_revision()
843 return -ENODEV; in vadc_check_revision()
851 dev_err(vadc->dev, "%d is not VADC\n", val); in vadc_check_revision()
852 return -ENODEV; in vadc_check_revision()
860 dev_err(vadc->dev, "revision %d not supported\n", val); in vadc_check_revision()
861 return -ENODEV; in vadc_check_revision()
869 struct device *dev = &pdev->dev; in vadc_probe()
876 regmap = dev_get_regmap(dev->parent, NULL); in vadc_probe()
878 return -ENODEV; in vadc_probe()
886 return -ENOMEM; in vadc_probe()
889 vadc->regmap = regmap; in vadc_probe()
890 vadc->dev = dev; in vadc_probe()
891 vadc->base = reg; in vadc_probe()
892 vadc->are_ref_measured = false; in vadc_probe()
893 init_completion(&vadc->complete); in vadc_probe()
894 mutex_init(&vadc->lock); in vadc_probe()
906 if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL) in vadc_probe()
908 vadc->poll_eoc = true; in vadc_probe()
911 "spmi-vadc", vadc); in vadc_probe()
926 indio_dev->name = pdev->name; in vadc_probe()
927 indio_dev->modes = INDIO_DIRECT_MODE; in vadc_probe()
928 indio_dev->info = &vadc_info; in vadc_probe()
929 indio_dev->channels = vadc->iio_chans; in vadc_probe()
930 indio_dev->num_channels = vadc->nchannels; in vadc_probe()
936 { .compatible = "qcom,spmi-vadc" },
943 .name = "qcom-spmi-vadc",
950 MODULE_ALIAS("platform:qcom-spmi-vadc");
953 MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>");
954 MODULE_AUTHOR("Ivan T. Ivanov <iivanov@mm-sol.com>");