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,
167 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_prepare_for_irq()
169 reinit_completion(&info->completion); in sun4i_prepare_for_irq()
171 ret = regmap_write(info->regmap, SUN4I_GPADC_INT_FIFOC, in sun4i_prepare_for_irq()
177 ret = regmap_read(info->regmap, SUN4I_GPADC_CTRL1, &reg); in sun4i_prepare_for_irq()
181 if (irq == info->fifo_data_irq) { in sun4i_prepare_for_irq()
182 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
183 info->data->tp_mode_en | in sun4i_prepare_for_irq()
184 info->data->tp_adc_select | in sun4i_prepare_for_irq()
185 info->data->adc_chan_select(channel)); in sun4i_prepare_for_irq()
190 if ((reg & info->data->adc_chan_mask) != in sun4i_prepare_for_irq()
191 info->data->adc_chan_select(channel)) in sun4i_prepare_for_irq()
199 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
200 info->data->tp_mode_en); in sun4i_prepare_for_irq()
210 if ((reg & info->data->tp_adc_select) != info->data->tp_adc_select) in sun4i_prepare_for_irq()
222 mutex_lock(&info->mutex); in sun4i_gpadc_read()
232 * set at periods of ~0.6s in sun4i_gpadc_runtime_resume). A 1s delay in sun4i_gpadc_read()
236 if (!wait_for_completion_timeout(&info->completion, in sun4i_gpadc_read()
238 ret = -ETIMEDOUT; in sun4i_gpadc_read()
242 if (irq == info->fifo_data_irq) in sun4i_gpadc_read()
243 *val = info->adc_data; in sun4i_gpadc_read()
245 *val = info->temp_data; in sun4i_gpadc_read()
248 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_read()
251 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_read()
253 mutex_unlock(&info->mutex); in sun4i_gpadc_read()
263 return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq); in sun4i_gpadc_adc_read()
270 if (info->no_irq) { in sun4i_gpadc_temp_read()
271 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
273 regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); in sun4i_gpadc_temp_read()
275 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
276 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
281 return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq); in sun4i_gpadc_temp_read()
288 *val = info->data->temp_offset; in sun4i_gpadc_temp_offset()
297 *val = info->data->temp_scale; in sun4i_gpadc_temp_scale()
316 if (chan->type == IIO_VOLTAGE) in sun4i_gpadc_read_raw()
317 ret = sun4i_gpadc_adc_read(indio_dev, chan->channel, in sun4i_gpadc_read_raw()
327 if (chan->type == IIO_VOLTAGE) { in sun4i_gpadc_read_raw()
340 return -EINVAL; in sun4i_gpadc_read_raw()
343 return -EINVAL; in sun4i_gpadc_read_raw()
354 if (atomic_read(&info->ignore_temp_data_irq)) in sun4i_gpadc_temp_data_irq_handler()
357 if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data)) in sun4i_gpadc_temp_data_irq_handler()
358 complete(&info->completion); in sun4i_gpadc_temp_data_irq_handler()
368 if (atomic_read(&info->ignore_fifo_data_irq)) in sun4i_gpadc_fifo_data_irq_handler()
371 if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data)) in sun4i_gpadc_fifo_data_irq_handler()
372 complete(&info->completion); in sun4i_gpadc_fifo_data_irq_handler()
383 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); in sun4i_gpadc_runtime_suspend()
385 regmap_write(info->regmap, SUN4I_GPADC_TPR, 0); in sun4i_gpadc_runtime_suspend()
395 regmap_write(info->regmap, SUN4I_GPADC_CTRL0, in sun4i_gpadc_runtime_resume()
399 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en); in sun4i_gpadc_runtime_resume()
400 regmap_write(info->regmap, SUN4I_GPADC_CTRL3, in sun4i_gpadc_runtime_resume()
404 regmap_write(info->regmap, SUN4I_GPADC_TPR, in sun4i_gpadc_runtime_resume()
416 if (sun4i_gpadc_temp_read(info->indio_dev, &val)) in sun4i_gpadc_get_temp()
417 return -ETIMEDOUT; in sun4i_gpadc_get_temp()
419 sun4i_gpadc_temp_scale(info->indio_dev, &scale); in sun4i_gpadc_get_temp()
420 sun4i_gpadc_temp_offset(info->indio_dev, &offset); in sun4i_gpadc_get_temp()
441 struct sun4i_gpadc_dev *mfd_dev = dev_get_drvdata(pdev->dev.parent); in sun4i_irq_init()
442 struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(&pdev->dev)); in sun4i_irq_init()
462 ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); in sun4i_irq_init()
464 dev_err(&pdev->dev, "failed to get virq for irq %s\n", name); in sun4i_irq_init()
469 ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, in sun4i_irq_init()
473 dev_err(&pdev->dev, "could not request %s interrupt: %d\n", in sun4i_irq_init()
485 .compatible = "allwinner,sun8i-a33-ths",
498 info->data = of_device_get_match_data(&pdev->dev); in sun4i_gpadc_probe_dt()
499 if (!info->data) in sun4i_gpadc_probe_dt()
500 return -ENODEV; in sun4i_gpadc_probe_dt()
502 info->no_irq = true; in sun4i_gpadc_probe_dt()
503 indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels); in sun4i_gpadc_probe_dt()
504 indio_dev->channels = sun8i_a33_gpadc_channels; in sun4i_gpadc_probe_dt()
510 info->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun4i_gpadc_probe_dt()
512 if (IS_ERR(info->regmap)) { in sun4i_gpadc_probe_dt()
513 ret = PTR_ERR(info->regmap); in sun4i_gpadc_probe_dt()
514 dev_err(&pdev->dev, "failed to init regmap: %d\n", ret); in sun4i_gpadc_probe_dt()
519 info->sensor_device = &pdev->dev; in sun4i_gpadc_probe_dt()
529 dev_get_drvdata(pdev->dev.parent); in sun4i_gpadc_probe_mfd()
532 info->no_irq = false; in sun4i_gpadc_probe_mfd()
533 info->regmap = sun4i_gpadc_dev->regmap; in sun4i_gpadc_probe_mfd()
535 indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels); in sun4i_gpadc_probe_mfd()
536 indio_dev->channels = sun4i_gpadc_channels; in sun4i_gpadc_probe_mfd()
538 info->data = (struct gpadc_data *)platform_get_device_id(pdev)->driver_data; in sun4i_gpadc_probe_mfd()
543 * needs a delay, always registering in the thermal framework will in sun4i_gpadc_probe_mfd()
567 info->sensor_device = pdev->dev.parent; in sun4i_gpadc_probe_mfd()
569 indio_dev->num_channels = in sun4i_gpadc_probe_mfd()
571 indio_dev->channels = sun4i_gpadc_channels_no_temp; in sun4i_gpadc_probe_mfd()
577 "temp_data", &info->temp_data_irq, in sun4i_gpadc_probe_mfd()
578 &info->ignore_temp_data_irq); in sun4i_gpadc_probe_mfd()
585 &info->fifo_data_irq, &info->ignore_fifo_data_irq); in sun4i_gpadc_probe_mfd()
592 dev_err(&pdev->dev, in sun4i_gpadc_probe_mfd()
607 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); in sun4i_gpadc_probe()
609 return -ENOMEM; in sun4i_gpadc_probe()
614 mutex_init(&info->mutex); in sun4i_gpadc_probe()
615 info->indio_dev = indio_dev; in sun4i_gpadc_probe()
616 init_completion(&info->completion); in sun4i_gpadc_probe()
617 indio_dev->name = dev_name(&pdev->dev); in sun4i_gpadc_probe()
618 indio_dev->info = &sun4i_gpadc_iio_info; in sun4i_gpadc_probe()
619 indio_dev->modes = INDIO_DIRECT_MODE; in sun4i_gpadc_probe()
621 if (pdev->dev.of_node) in sun4i_gpadc_probe()
629 pm_runtime_set_autosuspend_delay(&pdev->dev, in sun4i_gpadc_probe()
631 pm_runtime_use_autosuspend(&pdev->dev); in sun4i_gpadc_probe()
632 pm_runtime_set_suspended(&pdev->dev); in sun4i_gpadc_probe()
633 pm_runtime_enable(&pdev->dev); in sun4i_gpadc_probe()
636 info->tzd = devm_thermal_of_zone_register(info->sensor_device, in sun4i_gpadc_probe()
643 if (IS_ERR(info->tzd) && PTR_ERR(info->tzd) != -ENODEV) { in sun4i_gpadc_probe()
644 dev_err(&pdev->dev, in sun4i_gpadc_probe()
646 PTR_ERR(info->tzd)); in sun4i_gpadc_probe()
647 return PTR_ERR(info->tzd); in sun4i_gpadc_probe()
651 ret = devm_iio_device_register(&pdev->dev, indio_dev); in sun4i_gpadc_probe()
653 dev_err(&pdev->dev, "could not register the device\n"); in sun4i_gpadc_probe()
660 if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF)) in sun4i_gpadc_probe()
663 pm_runtime_put(&pdev->dev); in sun4i_gpadc_probe()
664 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_probe()
674 pm_runtime_put(&pdev->dev); in sun4i_gpadc_remove()
675 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_remove()
680 if (!info->no_irq) in sun4i_gpadc_remove()
685 { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data },
686 { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data },
687 { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
694 .name = "sun4i-gpadc-iio",
707 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");