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
32 #include <linux/delay.h>
37 #include <linux/mfd/sun4i-gpadc.h>
59 .temp_offset = -1932,
68 .temp_offset = -1447,
77 .temp_offset = -1623,
86 .temp_offset = -1662,
171 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_prepare_for_irq()
173 reinit_completion(&info->completion); in sun4i_prepare_for_irq()
175 ret = regmap_write(info->regmap, SUN4I_GPADC_INT_FIFOC, in sun4i_prepare_for_irq()
181 ret = regmap_read(info->regmap, SUN4I_GPADC_CTRL1, ®); in sun4i_prepare_for_irq()
185 if (irq == info->fifo_data_irq) { in sun4i_prepare_for_irq()
186 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
187 info->data->tp_mode_en | in sun4i_prepare_for_irq()
188 info->data->tp_adc_select | in sun4i_prepare_for_irq()
189 info->data->adc_chan_select(channel)); in sun4i_prepare_for_irq()
194 if ((reg & info->data->adc_chan_mask) != in sun4i_prepare_for_irq()
195 info->data->adc_chan_select(channel)) in sun4i_prepare_for_irq()
203 ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1, in sun4i_prepare_for_irq()
204 info->data->tp_mode_en); in sun4i_prepare_for_irq()
214 if ((reg & info->data->tp_adc_select) != info->data->tp_adc_select) in sun4i_prepare_for_irq()
226 mutex_lock(&info->mutex); in sun4i_gpadc_read()
236 * set at periods of ~0.6s in sun4i_gpadc_runtime_resume). A 1s delay in sun4i_gpadc_read()
240 if (!wait_for_completion_timeout(&info->completion, in sun4i_gpadc_read()
242 ret = -ETIMEDOUT; in sun4i_gpadc_read()
246 if (irq == info->fifo_data_irq) in sun4i_gpadc_read()
247 *val = info->adc_data; in sun4i_gpadc_read()
249 *val = info->temp_data; in sun4i_gpadc_read()
252 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_read()
255 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_read()
257 mutex_unlock(&info->mutex); in sun4i_gpadc_read()
267 return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq); in sun4i_gpadc_adc_read()
274 if (info->no_irq) { in sun4i_gpadc_temp_read()
275 pm_runtime_get_sync(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
277 regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); in sun4i_gpadc_temp_read()
279 pm_runtime_mark_last_busy(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
280 pm_runtime_put_autosuspend(indio_dev->dev.parent); in sun4i_gpadc_temp_read()
285 return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq); in sun4i_gpadc_temp_read()
292 *val = info->data->temp_offset; in sun4i_gpadc_temp_offset()
301 *val = info->data->temp_scale; in sun4i_gpadc_temp_scale()
320 if (chan->type == IIO_VOLTAGE) in sun4i_gpadc_read_raw()
321 ret = sun4i_gpadc_adc_read(indio_dev, chan->channel, in sun4i_gpadc_read_raw()
331 if (chan->type == IIO_VOLTAGE) { in sun4i_gpadc_read_raw()
344 return -EINVAL; in sun4i_gpadc_read_raw()
347 return -EINVAL; in sun4i_gpadc_read_raw()
358 if (atomic_read(&info->ignore_temp_data_irq)) in sun4i_gpadc_temp_data_irq_handler()
361 if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data)) in sun4i_gpadc_temp_data_irq_handler()
362 complete(&info->completion); in sun4i_gpadc_temp_data_irq_handler()
372 if (atomic_read(&info->ignore_fifo_data_irq)) in sun4i_gpadc_fifo_data_irq_handler()
375 if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data)) in sun4i_gpadc_fifo_data_irq_handler()
376 complete(&info->completion); in sun4i_gpadc_fifo_data_irq_handler()
387 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); in sun4i_gpadc_runtime_suspend()
389 regmap_write(info->regmap, SUN4I_GPADC_TPR, 0); in sun4i_gpadc_runtime_suspend()
399 regmap_write(info->regmap, SUN4I_GPADC_CTRL0, in sun4i_gpadc_runtime_resume()
403 regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en); in sun4i_gpadc_runtime_resume()
404 regmap_write(info->regmap, SUN4I_GPADC_CTRL3, in sun4i_gpadc_runtime_resume()
408 regmap_write(info->regmap, SUN4I_GPADC_TPR, in sun4i_gpadc_runtime_resume()
420 if (sun4i_gpadc_temp_read(info->indio_dev, &val)) in sun4i_gpadc_get_temp()
421 return -ETIMEDOUT; in sun4i_gpadc_get_temp()
423 sun4i_gpadc_temp_scale(info->indio_dev, &scale); in sun4i_gpadc_get_temp()
424 sun4i_gpadc_temp_offset(info->indio_dev, &offset); in sun4i_gpadc_get_temp()
445 struct sun4i_gpadc_dev *mfd_dev = dev_get_drvdata(pdev->dev.parent); in sun4i_irq_init()
446 struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(&pdev->dev)); in sun4i_irq_init()
466 ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); in sun4i_irq_init()
468 dev_err(&pdev->dev, "failed to get virq for irq %s\n", name); in sun4i_irq_init()
473 ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, 0, in sun4i_irq_init()
476 dev_err(&pdev->dev, "could not request %s interrupt: %d\n", in sun4i_irq_init()
489 .compatible = "allwinner,sun8i-a33-ths",
502 info->data = of_device_get_match_data(&pdev->dev); in sun4i_gpadc_probe_dt()
503 if (!info->data) in sun4i_gpadc_probe_dt()
504 return -ENODEV; in sun4i_gpadc_probe_dt()
506 info->no_irq = true; in sun4i_gpadc_probe_dt()
507 indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels); in sun4i_gpadc_probe_dt()
508 indio_dev->channels = sun8i_a33_gpadc_channels; in sun4i_gpadc_probe_dt()
514 info->regmap = devm_regmap_init_mmio(&pdev->dev, base, in sun4i_gpadc_probe_dt()
516 if (IS_ERR(info->regmap)) { in sun4i_gpadc_probe_dt()
517 ret = PTR_ERR(info->regmap); in sun4i_gpadc_probe_dt()
518 dev_err(&pdev->dev, "failed to init regmap: %d\n", ret); in sun4i_gpadc_probe_dt()
523 info->sensor_device = &pdev->dev; in sun4i_gpadc_probe_dt()
533 dev_get_drvdata(pdev->dev.parent); in sun4i_gpadc_probe_mfd()
536 info->no_irq = false; in sun4i_gpadc_probe_mfd()
537 info->regmap = sun4i_gpadc_dev->regmap; in sun4i_gpadc_probe_mfd()
539 indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels); in sun4i_gpadc_probe_mfd()
540 indio_dev->channels = sun4i_gpadc_channels; in sun4i_gpadc_probe_mfd()
542 info->data = (struct gpadc_data *)platform_get_device_id(pdev)->driver_data; in sun4i_gpadc_probe_mfd()
547 * needs a delay, always registering in the thermal framework will in sun4i_gpadc_probe_mfd()
571 info->sensor_device = pdev->dev.parent; in sun4i_gpadc_probe_mfd()
573 indio_dev->num_channels = in sun4i_gpadc_probe_mfd()
575 indio_dev->channels = sun4i_gpadc_channels_no_temp; in sun4i_gpadc_probe_mfd()
581 "temp_data", &info->temp_data_irq, in sun4i_gpadc_probe_mfd()
582 &info->ignore_temp_data_irq); in sun4i_gpadc_probe_mfd()
589 &info->fifo_data_irq, &info->ignore_fifo_data_irq); in sun4i_gpadc_probe_mfd()
596 dev_err(&pdev->dev, in sun4i_gpadc_probe_mfd()
611 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); in sun4i_gpadc_probe()
613 return -ENOMEM; in sun4i_gpadc_probe()
618 mutex_init(&info->mutex); in sun4i_gpadc_probe()
619 info->indio_dev = indio_dev; in sun4i_gpadc_probe()
620 init_completion(&info->completion); in sun4i_gpadc_probe()
621 indio_dev->name = dev_name(&pdev->dev); in sun4i_gpadc_probe()
622 indio_dev->info = &sun4i_gpadc_iio_info; in sun4i_gpadc_probe()
623 indio_dev->modes = INDIO_DIRECT_MODE; in sun4i_gpadc_probe()
625 if (pdev->dev.of_node) in sun4i_gpadc_probe()
633 pm_runtime_set_autosuspend_delay(&pdev->dev, in sun4i_gpadc_probe()
635 pm_runtime_use_autosuspend(&pdev->dev); in sun4i_gpadc_probe()
636 pm_runtime_set_suspended(&pdev->dev); in sun4i_gpadc_probe()
637 pm_runtime_enable(&pdev->dev); in sun4i_gpadc_probe()
640 info->tzd = thermal_zone_of_sensor_register(info->sensor_device, in sun4i_gpadc_probe()
647 if (IS_ERR(info->tzd) && PTR_ERR(info->tzd) != -ENODEV) { in sun4i_gpadc_probe()
648 dev_err(&pdev->dev, in sun4i_gpadc_probe()
650 PTR_ERR(info->tzd)); in sun4i_gpadc_probe()
651 return PTR_ERR(info->tzd); in sun4i_gpadc_probe()
655 ret = devm_iio_device_register(&pdev->dev, indio_dev); in sun4i_gpadc_probe()
657 dev_err(&pdev->dev, "could not register the device\n"); in sun4i_gpadc_probe()
664 if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF)) in sun4i_gpadc_probe()
667 pm_runtime_put(&pdev->dev); in sun4i_gpadc_probe()
668 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_probe()
678 pm_runtime_put(&pdev->dev); in sun4i_gpadc_remove()
679 pm_runtime_disable(&pdev->dev); in sun4i_gpadc_remove()
684 thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd); in sun4i_gpadc_remove()
686 if (!info->no_irq) in sun4i_gpadc_remove()
693 { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data },
694 { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data },
695 { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
702 .name = "sun4i-gpadc-iio",
715 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");