Lines Matching +full:autosuspend +full:- +full:delay

1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com>
15 * This is also the reason of using autosuspend in pm_runtime. If there was no
16 * autosuspend, the thermal sensor would need X seconds after every
17 * pm_runtime_get_sync to get a value from the ADC. The autosuspend allows the
31 #include <linux/delay.h>
36 #include <linux/mfd/sun4i-gpadc.h>
58 .temp_offset = -1932,
67 .temp_offset = -1447,
76 .temp_offset = -1623,
85 .temp_offset = -1662,
170 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_prepare_for_irq()
172 reinit_completion(&info->completion); in sun4i_prepare_for_irq()
174 ret = regmap_write(info->regmap, SUN4I_GPADC_INT_FIFOC, in sun4i_prepare_for_irq()
180 ret = regmap_read(info->regmap, SUN4I_GPADC_CTRL1, &reg); in sun4i_prepare_for_irq()
184 if (irq == info->fifo_data_irq) { in sun4i_prepare_for_irq()
185 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
186 info->data->tp_mode_en | in sun4i_prepare_for_irq()
187 info->data->tp_adc_select | in sun4i_prepare_for_irq()
188 info->data->adc_chan_select(channel)); in sun4i_prepare_for_irq()
193 if ((reg & info->data->adc_chan_mask) != in sun4i_prepare_for_irq()
194 info->data->adc_chan_select(channel)) in sun4i_prepare_for_irq()
202 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
203 info->data->tp_mode_en); in sun4i_prepare_for_irq()
213 if ((reg & info->data->tp_adc_select) != info->data->tp_adc_select) in sun4i_prepare_for_irq()
225 mutex_lock(&info->mutex); in sun4i_gpadc_read()
235 * set at periods of ~0.6s in sun4i_gpadc_runtime_resume). A 1s delay in sun4i_gpadc_read()
239 if (!wait_for_completion_timeout(&info->completion, in sun4i_gpadc_read()
241 ret = -ETIMEDOUT; in sun4i_gpadc_read()
245 if (irq == info->fifo_data_irq) in sun4i_gpadc_read()
246 *val = info->adc_data; in sun4i_gpadc_read()
248 *val = info->temp_data; in sun4i_gpadc_read()
251 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_read()
254 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_read()
256 mutex_unlock(&info->mutex); in sun4i_gpadc_read()
266 return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq); in sun4i_gpadc_adc_read()
273 if (info->no_irq) { in sun4i_gpadc_temp_read()
274 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
276 regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); in sun4i_gpadc_temp_read()
278 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
279 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
284 return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq); in sun4i_gpadc_temp_read()
291 *val = info->data->temp_offset; in sun4i_gpadc_temp_offset()
300 *val = info->data->temp_scale; in sun4i_gpadc_temp_scale()
319 if (chan->type == IIO_VOLTAGE) in sun4i_gpadc_read_raw()
320 ret = sun4i_gpadc_adc_read(indio_dev, chan->channel, in sun4i_gpadc_read_raw()
330 if (chan->type == IIO_VOLTAGE) { in sun4i_gpadc_read_raw()
343 return -EINVAL; in sun4i_gpadc_read_raw()
346 return -EINVAL; in sun4i_gpadc_read_raw()
357 if (atomic_read(&info->ignore_temp_data_irq)) in sun4i_gpadc_temp_data_irq_handler()
360 if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data)) in sun4i_gpadc_temp_data_irq_handler()
361 complete(&info->completion); in sun4i_gpadc_temp_data_irq_handler()
371 if (atomic_read(&info->ignore_fifo_data_irq)) in sun4i_gpadc_fifo_data_irq_handler()
374 if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data)) in sun4i_gpadc_fifo_data_irq_handler()
375 complete(&info->completion); in sun4i_gpadc_fifo_data_irq_handler()
386 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); in sun4i_gpadc_runtime_suspend()
388 regmap_write(info->regmap, SUN4I_GPADC_TPR, 0); in sun4i_gpadc_runtime_suspend()
398 regmap_write(info->regmap, SUN4I_GPADC_CTRL0, in sun4i_gpadc_runtime_resume()
402 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en); in sun4i_gpadc_runtime_resume()
403 regmap_write(info->regmap, SUN4I_GPADC_CTRL3, in sun4i_gpadc_runtime_resume()
407 regmap_write(info->regmap, SUN4I_GPADC_TPR, in sun4i_gpadc_runtime_resume()
419 if (sun4i_gpadc_temp_read(info->indio_dev, &val)) in sun4i_gpadc_get_temp()
420 return -ETIMEDOUT; in sun4i_gpadc_get_temp()
422 sun4i_gpadc_temp_scale(info->indio_dev, &scale); in sun4i_gpadc_get_temp()
423 sun4i_gpadc_temp_offset(info->indio_dev, &offset); in sun4i_gpadc_get_temp()
444 struct sun4i_gpadc_dev *mfd_dev = dev_get_drvdata(pdev->dev.parent); in sun4i_irq_init()
445 struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(&pdev->dev)); in sun4i_irq_init()
465 ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); in sun4i_irq_init()
467 dev_err(&pdev->dev, "failed to get virq for irq %s\n", name); in sun4i_irq_init()
472 ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, in sun4i_irq_init()
476 dev_err(&pdev->dev, "could not request %s interrupt: %d\n", in sun4i_irq_init()
488 .compatible = "allwinner,sun8i-a33-ths",
501 info->data = of_device_get_match_data(&pdev->dev); in sun4i_gpadc_probe_dt()
502 if (!info->data) in sun4i_gpadc_probe_dt()
503 return -ENODEV; in sun4i_gpadc_probe_dt()
505 info->no_irq = true; in sun4i_gpadc_probe_dt()
506 indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels); in sun4i_gpadc_probe_dt()
507 indio_dev->channels = sun8i_a33_gpadc_channels; in sun4i_gpadc_probe_dt()
513 info->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun4i_gpadc_probe_dt()
515 if (IS_ERR(info->regmap)) { in sun4i_gpadc_probe_dt()
516 ret = PTR_ERR(info->regmap); in sun4i_gpadc_probe_dt()
517 dev_err(&pdev->dev, "failed to init regmap: %d\n", ret); in sun4i_gpadc_probe_dt()
522 info->sensor_device = &pdev->dev; in sun4i_gpadc_probe_dt()
532 dev_get_drvdata(pdev->dev.parent); in sun4i_gpadc_probe_mfd()
535 info->no_irq = false; in sun4i_gpadc_probe_mfd()
536 info->regmap = sun4i_gpadc_dev->regmap; in sun4i_gpadc_probe_mfd()
538 indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels); in sun4i_gpadc_probe_mfd()
539 indio_dev->channels = sun4i_gpadc_channels; in sun4i_gpadc_probe_mfd()
541 info->data = (struct gpadc_data *)platform_get_device_id(pdev)->driver_data; in sun4i_gpadc_probe_mfd()
546 * needs a delay, always registering in the thermal framework will in sun4i_gpadc_probe_mfd()
570 info->sensor_device = pdev->dev.parent; in sun4i_gpadc_probe_mfd()
572 indio_dev->num_channels = in sun4i_gpadc_probe_mfd()
574 indio_dev->channels = sun4i_gpadc_channels_no_temp; in sun4i_gpadc_probe_mfd()
580 "temp_data", &info->temp_data_irq, in sun4i_gpadc_probe_mfd()
581 &info->ignore_temp_data_irq); in sun4i_gpadc_probe_mfd()
588 &info->fifo_data_irq, &info->ignore_fifo_data_irq); in sun4i_gpadc_probe_mfd()
595 dev_err(&pdev->dev, in sun4i_gpadc_probe_mfd()
610 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); in sun4i_gpadc_probe()
612 return -ENOMEM; in sun4i_gpadc_probe()
617 mutex_init(&info->mutex); in sun4i_gpadc_probe()
618 info->indio_dev = indio_dev; in sun4i_gpadc_probe()
619 init_completion(&info->completion); in sun4i_gpadc_probe()
620 indio_dev->name = dev_name(&pdev->dev); in sun4i_gpadc_probe()
621 indio_dev->info = &sun4i_gpadc_iio_info; in sun4i_gpadc_probe()
622 indio_dev->modes = INDIO_DIRECT_MODE; in sun4i_gpadc_probe()
624 if (pdev->dev.of_node) in sun4i_gpadc_probe()
632 pm_runtime_set_autosuspend_delay(&pdev->dev, in sun4i_gpadc_probe()
634 pm_runtime_use_autosuspend(&pdev->dev); in sun4i_gpadc_probe()
635 pm_runtime_set_suspended(&pdev->dev); in sun4i_gpadc_probe()
636 pm_runtime_enable(&pdev->dev); in sun4i_gpadc_probe()
639 info->tzd = devm_thermal_of_zone_register(info->sensor_device, in sun4i_gpadc_probe()
646 if (IS_ERR(info->tzd) && PTR_ERR(info->tzd) != -ENODEV) { in sun4i_gpadc_probe()
647 dev_err(&pdev->dev, in sun4i_gpadc_probe()
649 PTR_ERR(info->tzd)); in sun4i_gpadc_probe()
650 return PTR_ERR(info->tzd); in sun4i_gpadc_probe()
654 ret = devm_iio_device_register(&pdev->dev, indio_dev); in sun4i_gpadc_probe()
656 dev_err(&pdev->dev, "could not register the device\n"); in sun4i_gpadc_probe()
663 if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF)) in sun4i_gpadc_probe()
666 pm_runtime_put(&pdev->dev); in sun4i_gpadc_probe()
667 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_probe()
677 pm_runtime_put(&pdev->dev); in sun4i_gpadc_remove()
678 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_remove()
683 if (!info->no_irq) in sun4i_gpadc_remove()
690 { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data },
691 { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data },
692 { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
699 .name = "sun4i-gpadc-iio",
712 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");