Lines Matching +full:vref +full:- +full:buffered
1 // SPDX-License-Identifier: GPL-2.0-or-later
18 #include <linux/mfd/mxs-lradc.h>
32 * Make this runtime configurable if necessary. Currently, if the buffered mode
43 "mxs-lradc-channel0",
44 "mxs-lradc-channel1",
45 "mxs-lradc-channel2",
46 "mxs-lradc-channel3",
47 "mxs-lradc-channel4",
48 "mxs-lradc-channel5",
52 "mxs-lradc-thresh0",
53 "mxs-lradc-thresh1",
54 "mxs-lradc-channel0",
55 "mxs-lradc-channel1",
56 "mxs-lradc-channel2",
57 "mxs-lradc-channel3",
58 "mxs-lradc-channel4",
59 "mxs-lradc-channel5",
60 "mxs-lradc-button0",
61 "mxs-lradc-button1",
135 struct mxs_lradc *lradc = adc->lradc; in mxs_lradc_adc_read_single()
139 * See if there is no buffered operation in progress. If there is simply in mxs_lradc_adc_read_single()
140 * bail out. This can be improved to support both buffered and raw IO at in mxs_lradc_adc_read_single()
148 reinit_completion(&adc->completion); in mxs_lradc_adc_read_single()
151 * No buffered operation in progress, map the channel and trigger it. in mxs_lradc_adc_read_single()
155 if (lradc->soc == IMX28_LRADC) in mxs_lradc_adc_read_single()
157 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_read_single()
158 writel(0x1, adc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_read_single()
161 if (test_bit(chan, &adc->is_divided)) in mxs_lradc_adc_read_single()
163 adc->base + LRADC_CTRL2 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_read_single()
166 adc->base + LRADC_CTRL2 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_read_single()
170 adc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_read_single()
171 writel(chan, adc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_read_single()
173 writel(0, adc->base + LRADC_CH(0)); in mxs_lradc_adc_read_single()
177 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_read_single()
178 writel(BIT(0), adc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_read_single()
181 ret = wait_for_completion_killable_timeout(&adc->completion, HZ); in mxs_lradc_adc_read_single()
183 ret = -ETIMEDOUT; in mxs_lradc_adc_read_single()
188 *val = readl(adc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK; in mxs_lradc_adc_read_single()
193 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_read_single()
212 *val = max - min; in mxs_lradc_adc_read_temp()
225 if (chan->type == IIO_TEMP) in mxs_lradc_adc_read_raw()
228 return mxs_lradc_adc_read_single(iio_dev, chan->channel, val); in mxs_lradc_adc_read_raw()
231 if (chan->type == IIO_TEMP) { in mxs_lradc_adc_read_raw()
241 *val = adc->vref_mv[chan->channel]; in mxs_lradc_adc_read_raw()
242 *val2 = chan->scan_type.realbits - in mxs_lradc_adc_read_raw()
243 test_bit(chan->channel, &adc->is_divided); in mxs_lradc_adc_read_raw()
247 if (chan->type == IIO_TEMP) { in mxs_lradc_adc_read_raw()
250 * want Celsius for hwmon so the offset is -273.15 in mxs_lradc_adc_read_raw()
252 * actually -213.15 * 4 / 1.012 = -1079.644268 in mxs_lradc_adc_read_raw()
254 *val = -1079; in mxs_lradc_adc_read_raw()
260 return -EINVAL; in mxs_lradc_adc_read_raw()
266 return -EINVAL; in mxs_lradc_adc_read_raw()
275 adc->scale_avail[chan->channel]; in mxs_lradc_adc_write_raw()
284 ret = -EINVAL; in mxs_lradc_adc_write_raw()
288 clear_bit(chan->channel, &adc->is_divided); in mxs_lradc_adc_write_raw()
293 set_bit(chan->channel, &adc->is_divided); in mxs_lradc_adc_write_raw()
299 ret = -EINVAL; in mxs_lradc_adc_write_raw()
324 ch = iio_attr->address; in mxs_lradc_adc_show_scale_avail()
325 for (i = 0; i < ARRAY_SIZE(adc->scale_avail[ch]); i++) in mxs_lradc_adc_show_scale_avail()
327 adc->scale_avail[ch][i].integer, in mxs_lradc_adc_show_scale_avail()
328 adc->scale_avail[ch][i].nano); in mxs_lradc_adc_show_scale_avail()
388 struct mxs_lradc *lradc = adc->lradc; in mxs_lradc_adc_handle_irq()
389 unsigned long reg = readl(adc->base + LRADC_CTRL1); in mxs_lradc_adc_handle_irq()
396 if (reg & lradc->buffer_vchans) { in mxs_lradc_adc_handle_irq()
397 spin_lock_irqsave(&adc->lock, flags); in mxs_lradc_adc_handle_irq()
398 iio_trigger_poll(iio->trig); in mxs_lradc_adc_handle_irq()
399 spin_unlock_irqrestore(&adc->lock, flags); in mxs_lradc_adc_handle_irq()
402 complete(&adc->completion); in mxs_lradc_adc_handle_irq()
406 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_handle_irq()
416 struct iio_dev *iio = pf->indio_dev; in mxs_lradc_adc_trigger_handler()
419 ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); in mxs_lradc_adc_trigger_handler()
422 for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { in mxs_lradc_adc_trigger_handler()
423 adc->buffer[j] = readl(adc->base + LRADC_CH(j)); in mxs_lradc_adc_trigger_handler()
424 writel(chan_value, adc->base + LRADC_CH(j)); in mxs_lradc_adc_trigger_handler()
425 adc->buffer[j] &= LRADC_CH_VALUE_MASK; in mxs_lradc_adc_trigger_handler()
426 adc->buffer[j] /= LRADC_DELAY_TIMER_LOOP; in mxs_lradc_adc_trigger_handler()
430 iio_push_to_buffers_with_timestamp(iio, adc->buffer, pf->timestamp); in mxs_lradc_adc_trigger_handler()
432 iio_trigger_notify_done(iio->trig); in mxs_lradc_adc_trigger_handler()
443 writel(LRADC_DELAY_KICK, adc->base + (LRADC_DELAY(0) + st)); in mxs_lradc_adc_configure_trigger()
458 trig = devm_iio_trigger_alloc(&iio->dev, "%s-dev%i", iio->name, in mxs_lradc_adc_trigger_init()
461 return -ENOMEM; in mxs_lradc_adc_trigger_init()
463 trig->dev.parent = adc->dev; in mxs_lradc_adc_trigger_init()
465 trig->ops = &mxs_lradc_adc_trigger_ops; in mxs_lradc_adc_trigger_init()
471 adc->trig = trig; in mxs_lradc_adc_trigger_init()
480 iio_trigger_unregister(adc->trig); in mxs_lradc_adc_trigger_remove()
486 struct mxs_lradc *lradc = adc->lradc; in mxs_lradc_adc_buffer_preenable()
493 ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); in mxs_lradc_adc_buffer_preenable()
495 if (lradc->soc == IMX28_LRADC) in mxs_lradc_adc_buffer_preenable()
496 writel(lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, in mxs_lradc_adc_buffer_preenable()
497 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_preenable()
498 writel(lradc->buffer_vchans, in mxs_lradc_adc_buffer_preenable()
499 adc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_preenable()
501 for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { in mxs_lradc_adc_buffer_preenable()
505 writel(chan_value, adc->base + LRADC_CH(ofs)); in mxs_lradc_adc_buffer_preenable()
511 adc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_preenable()
512 writel(ctrl4_clr, adc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_preenable()
513 writel(ctrl4_set, adc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_buffer_preenable()
514 writel(ctrl1_irq, adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET); in mxs_lradc_adc_buffer_preenable()
516 adc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET); in mxs_lradc_adc_buffer_preenable()
524 struct mxs_lradc *lradc = adc->lradc; in mxs_lradc_adc_buffer_postdisable()
527 adc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_postdisable()
529 writel(lradc->buffer_vchans, in mxs_lradc_adc_buffer_postdisable()
530 adc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_postdisable()
531 if (lradc->soc == IMX28_LRADC) in mxs_lradc_adc_buffer_postdisable()
532 writel(lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, in mxs_lradc_adc_buffer_postdisable()
533 adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); in mxs_lradc_adc_buffer_postdisable()
542 struct mxs_lradc *lradc = adc->lradc; in mxs_lradc_adc_validate_scan_mask()
547 if (lradc->use_touchbutton) in mxs_lradc_adc_validate_scan_mask()
549 if (lradc->touchscreen_wire == MXS_LRADC_TOUCHSCREEN_4WIRE) in mxs_lradc_adc_validate_scan_mask()
551 if (lradc->touchscreen_wire == MXS_LRADC_TOUCHSCREEN_5WIRE) in mxs_lradc_adc_validate_scan_mask()
554 if (lradc->use_touchbutton) in mxs_lradc_adc_validate_scan_mask()
556 if (lradc->touchscreen_wire) in mxs_lradc_adc_validate_scan_mask()
618 .scan_index = -1,
654 .scan_index = -1,
673 writel(adc_cfg, adc->base + LRADC_DELAY(0)); in mxs_lradc_adc_hw_init()
680 writel(0, adc->base + LRADC_CTRL2); in mxs_lradc_adc_hw_init()
685 writel(0, adc->base + LRADC_DELAY(0)); in mxs_lradc_adc_hw_stop()
690 struct device *dev = &pdev->dev; in mxs_lradc_adc_probe()
691 struct mxs_lradc *lradc = dev_get_drvdata(dev->parent); in mxs_lradc_adc_probe()
703 return -ENOMEM; in mxs_lradc_adc_probe()
707 adc->lradc = lradc; in mxs_lradc_adc_probe()
708 adc->dev = dev; in mxs_lradc_adc_probe()
712 return -EINVAL; in mxs_lradc_adc_probe()
714 adc->base = devm_ioremap(dev, iores->start, resource_size(iores)); in mxs_lradc_adc_probe()
715 if (!adc->base) in mxs_lradc_adc_probe()
716 return -ENOMEM; in mxs_lradc_adc_probe()
718 init_completion(&adc->completion); in mxs_lradc_adc_probe()
719 spin_lock_init(&adc->lock); in mxs_lradc_adc_probe()
723 iio->name = pdev->name; in mxs_lradc_adc_probe()
724 iio->dev.of_node = dev->parent->of_node; in mxs_lradc_adc_probe()
725 iio->info = &mxs_lradc_adc_iio_info; in mxs_lradc_adc_probe()
726 iio->modes = INDIO_DIRECT_MODE; in mxs_lradc_adc_probe()
728 if (lradc->soc == IMX23_LRADC) { in mxs_lradc_adc_probe()
729 iio->channels = mx23_lradc_chan_spec; in mxs_lradc_adc_probe()
730 iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec); in mxs_lradc_adc_probe()
734 iio->channels = mx28_lradc_chan_spec; in mxs_lradc_adc_probe()
735 iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec); in mxs_lradc_adc_probe()
740 ret = stmp_reset_block(adc->base); in mxs_lradc_adc_probe()
749 virq = irq_of_parse_and_map(dev->parent->of_node, irq); in mxs_lradc_adc_probe()
767 adc->vref_mv = mxs_lradc_adc_vref_mv[lradc->soc]; in mxs_lradc_adc_probe()
771 for (s = 0; s < ARRAY_SIZE(adc->scale_avail[i]); s++) { in mxs_lradc_adc_probe()
777 * Vref >> (realbits - s) in mxs_lradc_adc_probe()
781 scale_uv = ((u64)adc->vref_mv[i] * 100000000) >> in mxs_lradc_adc_probe()
782 (LRADC_RESOLUTION - s); in mxs_lradc_adc_probe()
783 adc->scale_avail[i][s].nano = in mxs_lradc_adc_probe()
785 adc->scale_avail[i][s].integer = scale_uv; in mxs_lradc_adc_probe()
822 .name = "mxs-lradc-adc",
832 MODULE_ALIAS("platform:mxs-lradc-adc");