Lines Matching +full:adc +full:- +full:channels
1 // SPDX-License-Identifier: GPL-2.0-only
6 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
12 #include <linux/iio/adc/qcom-vadc-common.h>
26 * Thermal monitoring block consists of 8 (ADC_TM5_NUM_CHANNELS) channels. Each
27 * channel is programmed to use one of ADC channels for voltage comparison.
28 * Voltages are programmed using ADC codes, so we have to convert temp to
29 * voltage and then to ADC code value.
31 * Configuration of TM channels must match configuration of corresponding ADC
32 * channels.
178 * struct adc_tm5_channel - ADC Thermal Monitoring channel data.
180 * @adc_channel: corresponding ADC channel number.
186 * @avg_samples: ability to provide single result from the ADC
192 * @chip: ADC TM chip instance.
212 * struct adc_tm5_chip - ADC Thermal Monitoring properties
216 * @channels: array of ADC TM channel data.
217 * @nchannels: amount of channels defined/allocated
219 * Applies to all channels, used only on Gen1 ADC_TM.
220 * @avg_samples: ability to provide single result from the ADC
222 * channels, used only on Gen1 ADC_TM.
225 * It is used to ensure only one ADC channel configuration
233 struct adc_tm5_channel *channels; member
243 return regmap_bulk_read(adc_tm->regmap, adc_tm->base + offset, data, len); in adc_tm5_read()
248 return regmap_bulk_write(adc_tm->regmap, adc_tm->base + offset, data, len); in adc_tm5_write()
253 return regmap_write_bits(adc_tm->regmap, adc_tm->base + offset, mask, val); in adc_tm5_reg_update()
264 dev_err(chip->dev, "read status low failed: %d\n", ret); in adc_tm5_isr()
270 dev_err(chip->dev, "read status high failed: %d\n", ret); in adc_tm5_isr()
274 for (i = 0; i < chip->nchannels; i++) { in adc_tm5_isr()
276 unsigned int ch = chip->channels[i].channel; in adc_tm5_isr()
279 if (!chip->channels[i].tzd) in adc_tm5_isr()
284 dev_err(chip->dev, "ctl read failed: %d, channel %d\n", ret, i); in adc_tm5_isr()
298 thermal_zone_device_update(chip->channels[i].tzd, in adc_tm5_isr()
313 dev_err(chip->dev, "read status_low failed: %d\n", ret); in adc_tm5_gen2_isr()
319 dev_err(chip->dev, "read status_high failed: %d\n", ret); in adc_tm5_gen2_isr()
325 dev_err(chip->dev, "clear status low failed with %d\n", ret); in adc_tm5_gen2_isr()
331 dev_err(chip->dev, "clear status high failed with %d\n", ret); in adc_tm5_gen2_isr()
335 for (i = 0; i < chip->nchannels; i++) { in adc_tm5_gen2_isr()
337 unsigned int ch = chip->channels[i].channel; in adc_tm5_gen2_isr()
340 if (!chip->channels[i].tzd) in adc_tm5_gen2_isr()
343 if (!chip->channels[i].meas_en) in adc_tm5_gen2_isr()
347 (chip->channels[i].low_thr_en); in adc_tm5_gen2_isr()
350 (chip->channels[i].high_thr_en); in adc_tm5_gen2_isr()
353 thermal_zone_device_update(chip->channels[i].tzd, in adc_tm5_gen2_isr()
365 if (!channel || !channel->iio) in adc_tm5_get_temp()
366 return -EINVAL; in adc_tm5_get_temp()
368 ret = iio_read_channel_processed(channel->iio, temp); in adc_tm5_get_temp()
373 return -EINVAL; in adc_tm5_get_temp()
380 struct adc_tm5_chip *chip = channel->chip; in adc_tm5_disable_channel()
381 unsigned int reg = ADC_TM5_M_EN(channel->channel); in adc_tm5_disable_channel()
403 dev_err(chip->dev, "adc-tm enable failed with %d\n", ret); in adc_tm5_gen2_conv_req()
410 dev_err(chip->dev, "adc-tm handshake failed with %d\n", ret); in adc_tm5_gen2_conv_req()
417 dev_err(chip->dev, "adc-tm request conversion failed with %d\n", ret); in adc_tm5_gen2_conv_req()
429 dev_err(chip->dev, "adc-tm read failed with %d\n", ret); in adc_tm5_gen2_conv_req()
439 dev_err(chip->dev, "adc-tm conversion request handshake timed out\n"); in adc_tm5_gen2_conv_req()
441 return -ETIMEDOUT; in adc_tm5_gen2_conv_req()
446 struct adc_tm5_chip *chip = channel->chip; in adc_tm5_gen2_disable_channel()
450 mutex_lock(&chip->adc_mutex_lock); in adc_tm5_gen2_disable_channel()
452 channel->meas_en = false; in adc_tm5_gen2_disable_channel()
453 channel->high_thr_en = false; in adc_tm5_gen2_disable_channel()
454 channel->low_thr_en = false; in adc_tm5_gen2_disable_channel()
458 dev_err(chip->dev, "adc-tm block read failed with %d\n", ret); in adc_tm5_gen2_disable_channel()
463 val |= FIELD_PREP(ADC_TM_GEN2_TM_CH_SEL, channel->channel); in adc_tm5_gen2_disable_channel()
467 dev_err(chip->dev, "adc-tm channel disable failed with %d\n", ret); in adc_tm5_gen2_disable_channel()
474 dev_err(chip->dev, "adc-tm interrupt disable failed with %d\n", ret); in adc_tm5_gen2_disable_channel()
479 ret = adc_tm5_gen2_conv_req(channel->chip); in adc_tm5_gen2_disable_channel()
481 dev_err(chip->dev, "adc-tm channel configure failed with %d\n", ret); in adc_tm5_gen2_disable_channel()
484 mutex_unlock(&chip->adc_mutex_lock); in adc_tm5_gen2_disable_channel()
496 dev_err(chip->dev, "adc-tm enable failed\n"); in adc_tm5_enable()
503 dev_err(chip->dev, "adc-tm request conversion failed\n"); in adc_tm5_enable()
512 struct adc_tm5_chip *chip = channel->chip; in adc_tm5_configure()
514 u16 reg = ADC_TM5_M_ADC_CH_SEL_CTL(channel->channel); in adc_tm5_configure()
519 dev_err(chip->dev, "channel %d params read failed: %d\n", channel->channel, ret); in adc_tm5_configure()
523 buf[0] = channel->adc_channel; in adc_tm5_configure()
527 u16 adc_code = qcom_adc_tm5_temp_volt_scale(channel->prescale, in adc_tm5_configure()
528 chip->data->full_scale_code_volt, high); in adc_tm5_configure()
537 if (low != -INT_MAX) { in adc_tm5_configure()
538 u16 adc_code = qcom_adc_tm5_temp_volt_scale(channel->prescale, in adc_tm5_configure()
539 chip->data->full_scale_code_volt, low); in adc_tm5_configure()
551 buf[6] |= FIELD_PREP(ADC_TM5_M_CTL_HW_SETTLE_DELAY_MASK, channel->hw_settle_time); in adc_tm5_configure()
553 buf[6] |= FIELD_PREP(ADC_TM5_M_CTL_CAL_SEL_MASK, channel->cal_method); in adc_tm5_configure()
559 dev_err(chip->dev, "channel %d params write failed: %d\n", channel->channel, ret); in adc_tm5_configure()
568 struct adc_tm5_chip *chip = channel->chip; in adc_tm5_gen2_configure()
573 mutex_lock(&chip->adc_mutex_lock); in adc_tm5_gen2_configure()
575 channel->meas_en = true; in adc_tm5_gen2_configure()
579 dev_err(chip->dev, "adc-tm block read failed with %d\n", ret); in adc_tm5_gen2_configure()
584 buf[0] = channel->adc_channel >> 8; in adc_tm5_gen2_configure()
588 buf[1] |= FIELD_PREP(ADC_TM_GEN2_TM_CH_SEL, channel->channel); in adc_tm5_gen2_configure()
593 buf[2] |= FIELD_PREP(ADC_TM_GEN2_CTL_DEC_RATIO_MASK, channel->decimation); in adc_tm5_gen2_configure()
595 buf[2] |= FIELD_PREP(ADC_TM_GEN2_CTL_CAL_SEL, channel->cal_method); in adc_tm5_gen2_configure()
597 buf[3] = channel->avg_samples | ADC_TM_GEN2_FAST_AVG_EN; in adc_tm5_gen2_configure()
599 buf[4] = channel->adc_channel & 0xff; in adc_tm5_gen2_configure()
601 buf[5] = channel->hw_settle_time & ADC_TM_GEN2_HW_SETTLE_DELAY; in adc_tm5_gen2_configure()
605 channel->low_thr_en = true; in adc_tm5_gen2_configure()
609 channel->low_thr_en = false; in adc_tm5_gen2_configure()
613 if (low != -INT_MAX) { in adc_tm5_gen2_configure()
614 channel->high_thr_en = true; in adc_tm5_gen2_configure()
618 channel->high_thr_en = false; in adc_tm5_gen2_configure()
622 if (channel->high_thr_en) in adc_tm5_gen2_configure()
624 if (channel->low_thr_en) in adc_tm5_gen2_configure()
629 dev_err(chip->dev, "channel %d params write failed: %d\n", channel->channel, ret); in adc_tm5_gen2_configure()
633 ret = adc_tm5_gen2_conv_req(channel->chip); in adc_tm5_gen2_configure()
635 dev_err(chip->dev, "adc-tm channel configure failed with %d\n", ret); in adc_tm5_gen2_configure()
638 mutex_unlock(&chip->adc_mutex_lock); in adc_tm5_gen2_configure()
649 return -EINVAL; in adc_tm5_set_trips()
651 chip = channel->chip; in adc_tm5_set_trips()
652 dev_dbg(chip->dev, "%d:low(mdegC):%d, high(mdegC):%d\n", in adc_tm5_set_trips()
653 channel->channel, low, high); in adc_tm5_set_trips()
655 if (high == INT_MAX && low <= -INT_MAX) in adc_tm5_set_trips()
656 ret = chip->data->disable_channel(channel); in adc_tm5_set_trips()
658 ret = chip->data->configure(channel, low, high); in adc_tm5_set_trips()
673 for (i = 0; i < adc_tm->nchannels; i++) { in adc_tm5_register_tzd()
674 adc_tm->channels[i].chip = adc_tm; in adc_tm5_register_tzd()
675 tzd = devm_thermal_of_zone_register(adc_tm->dev, in adc_tm5_register_tzd()
676 adc_tm->channels[i].channel, in adc_tm5_register_tzd()
677 &adc_tm->channels[i], in adc_tm5_register_tzd()
680 if (PTR_ERR(tzd) == -ENODEV) { in adc_tm5_register_tzd()
681 dev_dbg(adc_tm->dev, "thermal sensor on channel %d is not used\n", in adc_tm5_register_tzd()
682 adc_tm->channels[i].channel); in adc_tm5_register_tzd()
686 dev_err(adc_tm->dev, "Error registering TZ zone for channel %d: %ld\n", in adc_tm5_register_tzd()
687 adc_tm->channels[i].channel, PTR_ERR(tzd)); in adc_tm5_register_tzd()
690 adc_tm->channels[i].tzd = tzd; in adc_tm5_register_tzd()
691 devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd); in adc_tm5_register_tzd()
703 for (i = 0; i < chip->nchannels; i++) { in adc_tm_hc_init()
704 if (chip->channels[i].channel >= ADC_TM5_NUM_CHANNELS) { in adc_tm_hc_init()
705 dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel); in adc_tm_hc_init()
706 return -EINVAL; in adc_tm_hc_init()
710 buf[0] = chip->decimation; in adc_tm_hc_init()
711 buf[1] = chip->avg_samples | ADC_TM5_FAST_AVG_EN; in adc_tm_hc_init()
715 dev_err(chip->dev, "block write failed: %d\n", ret); in adc_tm_hc_init()
729 dev_err(chip->dev, "read failed for BTM channels\n"); in adc_tm5_init()
733 for (i = 0; i < chip->nchannels; i++) { in adc_tm5_init()
734 if (chip->channels[i].channel >= channels_available) { in adc_tm5_init()
735 dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel); in adc_tm5_init()
736 return -EINVAL; in adc_tm5_init()
740 buf[0] = chip->decimation; in adc_tm5_init()
741 buf[1] = chip->avg_samples | ADC_TM5_FAST_AVG_EN; in adc_tm5_init()
748 dev_err(chip->dev, "block write failed: %d\n", ret); in adc_tm5_init()
764 dev_err(chip->dev, "read failed for BTM channels\n"); in adc_tm5_gen2_init()
768 for (i = 0; i < chip->nchannels; i++) { in adc_tm5_gen2_init()
769 if (chip->channels[i].channel >= channels_available) { in adc_tm5_gen2_init()
770 dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel); in adc_tm5_gen2_init()
771 return -EINVAL; in adc_tm5_gen2_init()
775 mutex_init(&chip->adc_mutex_lock); in adc_tm5_gen2_init()
784 const char *name = node->name; in adc_tm5_get_dt_channel_data()
787 struct device *dev = adc_tm->dev; in adc_tm5_get_dt_channel_data()
798 return -EINVAL; in adc_tm5_get_dt_channel_data()
801 channel->channel = chan; in adc_tm5_get_dt_channel_data()
804 * We are tied to PMIC's ADC controller, which always use single in adc_tm5_get_dt_channel_data()
806 * #io-channel-cells, just enforce cell_count = 1. in adc_tm5_get_dt_channel_data()
808 ret = of_parse_phandle_with_fixed_args(node, "io-channels", 1, 0, &args); in adc_tm5_get_dt_channel_data()
810 dev_err(dev, "%s: error parsing ADC channel number %d: %d\n", name, chan, ret); in adc_tm5_get_dt_channel_data()
816 dev_err(dev, "%s: invalid args count for ADC channel %d\n", name, chan); in adc_tm5_get_dt_channel_data()
817 return -EINVAL; in adc_tm5_get_dt_channel_data()
821 if (adc_tm->data->gen == ADC_TM5_GEN2) in adc_tm5_get_dt_channel_data()
825 dev_err(dev, "%s: invalid ADC channel number %d\n", name, chan); in adc_tm5_get_dt_channel_data()
826 return -EINVAL; in adc_tm5_get_dt_channel_data()
828 channel->adc_channel = args.args[0]; in adc_tm5_get_dt_channel_data()
830 channel->iio = devm_fwnode_iio_channel_get_by_name(adc_tm->dev, in adc_tm5_get_dt_channel_data()
832 if (IS_ERR(channel->iio)) in adc_tm5_get_dt_channel_data()
833 return dev_err_probe(dev, PTR_ERR(channel->iio), "%s: error getting channel\n", in adc_tm5_get_dt_channel_data()
836 ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2); in adc_tm5_get_dt_channel_data()
840 dev_err(dev, "%s: invalid pre-scaling <%d %d>\n", in adc_tm5_get_dt_channel_data()
844 channel->prescale = ret; in adc_tm5_get_dt_channel_data()
847 channel->prescale = 0; in adc_tm5_get_dt_channel_data()
850 ret = of_property_read_u32(node, "qcom,hw-settle-time-us", &value); in adc_tm5_get_dt_channel_data()
852 ret = qcom_adc5_hw_settle_time_from_dt(value, adc_tm->data->hw_settle); in adc_tm5_get_dt_channel_data()
854 dev_err(dev, "%s invalid hw-settle-time-us %d us\n", in adc_tm5_get_dt_channel_data()
858 channel->hw_settle_time = ret; in adc_tm5_get_dt_channel_data()
860 channel->hw_settle_time = VADC_DEF_HW_SETTLE_TIME; in adc_tm5_get_dt_channel_data()
864 channel->cal_method = ADC_TM5_RATIOMETRIC_CAL; in adc_tm5_get_dt_channel_data()
866 channel->cal_method = ADC_TM5_ABSOLUTE_CAL; in adc_tm5_get_dt_channel_data()
868 if (adc_tm->data->gen == ADC_TM5_GEN2) { in adc_tm5_get_dt_channel_data()
871 ret = qcom_adc5_decimation_from_dt(value, adc_tm->data->decimation); in adc_tm5_get_dt_channel_data()
876 channel->decimation = ret; in adc_tm5_get_dt_channel_data()
878 channel->decimation = ADC5_DECIMATION_DEFAULT; in adc_tm5_get_dt_channel_data()
881 ret = of_property_read_u32(node, "qcom,avg-samples", &value); in adc_tm5_get_dt_channel_data()
885 dev_err(dev, "invalid avg-samples %d\n", value); in adc_tm5_get_dt_channel_data()
888 channel->avg_samples = ret; in adc_tm5_get_dt_channel_data()
890 channel->avg_samples = VADC_DEF_AVG_SAMPLES; in adc_tm5_get_dt_channel_data()
907 .irq_name = "pm-adc-tm5",
920 .irq_name = "pm-adc-tm5",
934 .irq_name = "pm-adc-tm5-gen2",
940 struct adc_tm5_channel *channels; in adc_tm5_get_dt_data() local
944 struct device *dev = adc_tm->dev; in adc_tm5_get_dt_data()
946 adc_tm->nchannels = of_get_available_child_count(node); in adc_tm5_get_dt_data()
947 if (!adc_tm->nchannels) in adc_tm5_get_dt_data()
948 return -EINVAL; in adc_tm5_get_dt_data()
950 adc_tm->channels = devm_kcalloc(dev, adc_tm->nchannels, in adc_tm5_get_dt_data()
951 sizeof(*adc_tm->channels), GFP_KERNEL); in adc_tm5_get_dt_data()
952 if (!adc_tm->channels) in adc_tm5_get_dt_data()
953 return -ENOMEM; in adc_tm5_get_dt_data()
955 channels = adc_tm->channels; in adc_tm5_get_dt_data()
957 adc_tm->data = of_device_get_match_data(dev); in adc_tm5_get_dt_data()
958 if (!adc_tm->data) in adc_tm5_get_dt_data()
959 adc_tm->data = &adc_tm5_data_pmic; in adc_tm5_get_dt_data()
963 ret = qcom_adc5_decimation_from_dt(value, adc_tm->data->decimation); in adc_tm5_get_dt_data()
968 adc_tm->decimation = ret; in adc_tm5_get_dt_data()
970 adc_tm->decimation = ADC5_DECIMATION_DEFAULT; in adc_tm5_get_dt_data()
973 ret = of_property_read_u32(node, "qcom,avg-samples", &value); in adc_tm5_get_dt_data()
977 dev_err(dev, "invalid avg-samples %d\n", value); in adc_tm5_get_dt_data()
980 adc_tm->avg_samples = ret; in adc_tm5_get_dt_data()
982 adc_tm->avg_samples = VADC_DEF_AVG_SAMPLES; in adc_tm5_get_dt_data()
986 ret = adc_tm5_get_dt_channel_data(adc_tm, channels, child); in adc_tm5_get_dt_data()
992 channels++; in adc_tm5_get_dt_data()
1000 struct device_node *node = pdev->dev.of_node; in adc_tm5_probe()
1001 struct device *dev = &pdev->dev; in adc_tm5_probe()
1007 regmap = dev_get_regmap(dev->parent, NULL); in adc_tm5_probe()
1009 return -ENODEV; in adc_tm5_probe()
1015 adc_tm = devm_kzalloc(&pdev->dev, sizeof(*adc_tm), GFP_KERNEL); in adc_tm5_probe()
1017 return -ENOMEM; in adc_tm5_probe()
1019 adc_tm->regmap = regmap; in adc_tm5_probe()
1020 adc_tm->dev = dev; in adc_tm5_probe()
1021 adc_tm->base = reg; in adc_tm5_probe()
1031 ret = adc_tm->data->init(adc_tm); in adc_tm5_probe()
1033 dev_err(dev, "adc-tm init failed\n"); in adc_tm5_probe()
1043 return devm_request_threaded_irq(dev, irq, NULL, adc_tm->data->isr, in adc_tm5_probe()
1044 IRQF_ONESHOT, adc_tm->data->irq_name, adc_tm); in adc_tm5_probe()
1049 .compatible = "qcom,spmi-adc-tm5",
1053 .compatible = "qcom,spmi-adc-tm-hc",
1057 .compatible = "qcom,spmi-adc-tm5-gen2",
1066 .name = "qcom-spmi-adc-tm5",
1073 MODULE_DESCRIPTION("SPMI PMIC Thermal Monitor ADC driver");