Lines Matching +full:adc +full:- +full:chan

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
6 * connected to the imx25 ADC.
9 #include <dt-bindings/iio/adc/fsl-imx25-gcq.h>
13 #include <linux/mfd/imx25-tsadc.h>
22 static const char * const driver_name = "mx25-gcq";
54 #define MX25_CQG_CHAN(chan, id) {\ argument
57 .channel = chan,\
86 regmap_read(priv->regs, MX25_ADCQ_SR, &stats); in mx25_gcq_irq()
89 regmap_update_bits(priv->regs, MX25_ADCQ_MR, in mx25_gcq_irq()
91 complete(&priv->completed); in mx25_gcq_irq()
95 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0); in mx25_gcq_irq()
98 regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR | in mx25_gcq_irq()
106 struct iio_chan_spec const *chan, in mx25_gcq_get_raw_value() argument
114 regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0, in mx25_gcq_get_raw_value()
115 MX25_ADCQ_ITEM(0, chan->channel)); in mx25_gcq_get_raw_value()
117 regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0); in mx25_gcq_get_raw_value()
120 regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, in mx25_gcq_get_raw_value()
124 &priv->completed, MX25_GCQ_TIMEOUT); in mx25_gcq_get_raw_value()
126 dev_err(dev, "ADC wait for measurement failed\n"); in mx25_gcq_get_raw_value()
129 dev_err(dev, "ADC timed out\n"); in mx25_gcq_get_raw_value()
130 return -ETIMEDOUT; in mx25_gcq_get_raw_value()
133 regmap_read(priv->regs, MX25_ADCQ_FIFO, &data); in mx25_gcq_get_raw_value()
141 struct iio_chan_spec const *chan, int *val, in mx25_gcq_read_raw() argument
149 mutex_lock(&priv->lock); in mx25_gcq_read_raw()
150 ret = mx25_gcq_get_raw_value(&indio_dev->dev, chan, priv, val); in mx25_gcq_read_raw()
151 mutex_unlock(&priv->lock); in mx25_gcq_read_raw()
155 *val = priv->channel_vref_mv[chan->channel]; in mx25_gcq_read_raw()
160 return -EINVAL; in mx25_gcq_read_raw()
178 struct device_node *np = pdev->dev.of_node; in mx25_gcq_setup_cfgs()
180 struct device *dev = &pdev->dev; in mx25_gcq_setup_cfgs()
189 regmap_write(priv->regs, MX25_ADCQ_CFG(i), in mx25_gcq_setup_cfgs()
202 priv->vref[MX25_ADC_REFP_INT] = NULL; in mx25_gcq_setup_cfgs()
203 priv->vref[MX25_ADC_REFP_EXT] = in mx25_gcq_setup_cfgs()
204 devm_regulator_get_optional(&pdev->dev, "vref-ext"); in mx25_gcq_setup_cfgs()
205 priv->vref[MX25_ADC_REFP_XP] = in mx25_gcq_setup_cfgs()
206 devm_regulator_get_optional(&pdev->dev, "vref-xp"); in mx25_gcq_setup_cfgs()
207 priv->vref[MX25_ADC_REFP_YP] = in mx25_gcq_setup_cfgs()
208 devm_regulator_get_optional(&pdev->dev, "vref-yp"); in mx25_gcq_setup_cfgs()
226 return -EINVAL; in mx25_gcq_setup_cfgs()
229 of_property_read_u32(child, "fsl,adc-refp", &refp); in mx25_gcq_setup_cfgs()
230 of_property_read_u32(child, "fsl,adc-refn", &refn); in mx25_gcq_setup_cfgs()
236 if (IS_ERR(priv->vref[refp])) { in mx25_gcq_setup_cfgs()
237 dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.", in mx25_gcq_setup_cfgs()
240 return PTR_ERR(priv->vref[refp]); in mx25_gcq_setup_cfgs()
242 priv->channel_vref_mv[reg] = in mx25_gcq_setup_cfgs()
243 regulator_get_voltage(priv->vref[refp]); in mx25_gcq_setup_cfgs()
245 priv->channel_vref_mv[reg] /= 1000; in mx25_gcq_setup_cfgs()
248 priv->channel_vref_mv[reg] = 2500; in mx25_gcq_setup_cfgs()
253 return -EINVAL; in mx25_gcq_setup_cfgs()
266 dev_err(dev, "Invalid fsl,adc-refp property value\n"); in mx25_gcq_setup_cfgs()
268 return -EINVAL; in mx25_gcq_setup_cfgs()
271 dev_err(dev, "Invalid fsl,adc-refn property value\n"); in mx25_gcq_setup_cfgs()
273 return -EINVAL; in mx25_gcq_setup_cfgs()
276 regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg), in mx25_gcq_setup_cfgs()
281 regmap_update_bits(priv->regs, MX25_ADCQ_CR, in mx25_gcq_setup_cfgs()
285 regmap_write(priv->regs, MX25_ADCQ_CR, in mx25_gcq_setup_cfgs()
291 if (!IS_ERR_OR_NULL(priv->vref[i])) in mx25_gcq_setup_cfgs()
292 devm_regulator_put(priv->vref[i]); in mx25_gcq_setup_cfgs()
293 priv->vref[i] = NULL; in mx25_gcq_setup_cfgs()
304 struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent); in mx25_gcq_probe()
305 struct device *dev = &pdev->dev; in mx25_gcq_probe()
310 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); in mx25_gcq_probe()
312 return -ENOMEM; in mx25_gcq_probe()
320 priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig); in mx25_gcq_probe()
321 if (IS_ERR(priv->regs)) { in mx25_gcq_probe()
323 return PTR_ERR(priv->regs); in mx25_gcq_probe()
326 mutex_init(&priv->lock); in mx25_gcq_probe()
328 init_completion(&priv->completed); in mx25_gcq_probe()
335 if (!priv->vref[i]) in mx25_gcq_probe()
338 ret = regulator_enable(priv->vref[i]); in mx25_gcq_probe()
343 priv->clk = tsadc->clk; in mx25_gcq_probe()
344 ret = clk_prepare_enable(priv->clk); in mx25_gcq_probe()
350 priv->irq = platform_get_irq(pdev, 0); in mx25_gcq_probe()
351 if (priv->irq <= 0) { in mx25_gcq_probe()
352 ret = priv->irq; in mx25_gcq_probe()
354 ret = -ENXIO; in mx25_gcq_probe()
358 ret = request_irq(priv->irq, mx25_gcq_irq, 0, pdev->name, priv); in mx25_gcq_probe()
364 indio_dev->channels = mx25_gcq_channels; in mx25_gcq_probe()
365 indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels); in mx25_gcq_probe()
366 indio_dev->info = &mx25_gcq_iio_info; in mx25_gcq_probe()
367 indio_dev->name = driver_name; in mx25_gcq_probe()
380 free_irq(priv->irq, priv); in mx25_gcq_probe()
382 clk_disable_unprepare(priv->clk); in mx25_gcq_probe()
386 for (; i-- > 0;) { in mx25_gcq_probe()
387 if (priv->vref[i]) in mx25_gcq_probe()
388 regulator_disable(priv->vref[i]); in mx25_gcq_probe()
400 free_irq(priv->irq, priv); in mx25_gcq_remove()
401 clk_disable_unprepare(priv->clk); in mx25_gcq_remove()
402 for (i = 4; i-- > 0;) { in mx25_gcq_remove()
403 if (priv->vref[i]) in mx25_gcq_remove()
404 regulator_disable(priv->vref[i]); in mx25_gcq_remove()
411 { .compatible = "fsl,imx25-gcq", },
418 .name = "mx25-gcq",
426 MODULE_DESCRIPTION("ADC driver for Freescale mx25");