diff options
Diffstat (limited to 'drivers/iio/adc/sun4i-gpadc-iio.c')
| -rw-r--r-- | drivers/iio/adc/sun4i-gpadc-iio.c | 98 |
1 files changed, 37 insertions, 61 deletions
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 81d4c39e414a..479115ea50bf 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC * * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com> * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - * * The Allwinner SoCs all have an ADC that can also act as a touchscreen * controller and a thermal sensor. * The thermal sensor works only when the ADC acts as a touchscreen controller @@ -27,7 +24,6 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> @@ -118,12 +114,9 @@ struct sun4i_gpadc_iio { .datasheet_name = _name, \ } -static struct iio_map sun4i_gpadc_hwmon_maps[] = { - { - .adc_channel_label = "temp_adc", - .consumer_dev_name = "iio_hwmon.0", - }, - { /* sentinel */ }, +static const struct iio_map sun4i_gpadc_hwmon_maps[] = { + IIO_MAP("temp_adc", "iio_hwmon.0", NULL), + { } }; static const struct iio_chan_spec sun4i_gpadc_channels[] = { @@ -161,7 +154,6 @@ static const struct regmap_config sun4i_gpadc_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, - .fast_io = true, }; static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel, @@ -252,10 +244,10 @@ static int sun4i_gpadc_read(struct iio_dev *indio_dev, int channel, int *val, *val = info->temp_data; ret = 0; - pm_runtime_mark_last_busy(indio_dev->dev.parent); err: pm_runtime_put_autosuspend(indio_dev->dev.parent); + disable_irq(irq); mutex_unlock(&info->mutex); return ret; @@ -278,7 +270,6 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); - pm_runtime_mark_last_busy(indio_dev->dev.parent); pm_runtime_put_autosuspend(indio_dev->dev.parent); return 0; @@ -351,7 +342,6 @@ static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev, static const struct iio_info sun4i_gpadc_iio_info = { .read_raw = sun4i_gpadc_read_raw, - .driver_module = THIS_MODULE, }; static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id) @@ -365,7 +355,6 @@ static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->temp_data_irq); return IRQ_HANDLED; } @@ -380,7 +369,6 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) complete(&info->completion); out: - disable_irq_nosync(info->fifo_data_irq); return IRQ_HANDLED; } @@ -417,9 +405,9 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) return 0; } -static int sun4i_gpadc_get_temp(void *data, int *temp) +static int sun4i_gpadc_get_temp(struct thermal_zone_device *tz, int *temp) { - struct sun4i_gpadc_iio *info = data; + struct sun4i_gpadc_iio *info = thermal_zone_device_priv(tz); int val, scale, offset; if (sun4i_gpadc_temp_read(info->indio_dev, &val)) @@ -433,7 +421,7 @@ static int sun4i_gpadc_get_temp(void *data, int *temp) return 0; } -static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { +static const struct thermal_zone_device_ops sun4i_ts_tz_ops = { .get_temp = &sun4i_gpadc_get_temp, }; @@ -465,10 +453,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, atomic_set(atomic, 1); ret = platform_get_irq_byname(pdev, name); - if (ret < 0) { - dev_err(&pdev->dev, "no %s interrupt registered\n", name); + if (ret < 0) return ret; - } ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret); if (ret < 0) { @@ -477,7 +463,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, } *irq = ret; - ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, 0, + ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, + IRQF_NO_AUTOEN, devname, info); if (ret < 0) { dev_err(&pdev->dev, "could not request %s interrupt: %d\n", @@ -485,7 +472,6 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name, return ret; } - disable_irq(*irq); atomic_set(atomic, 0); return 0; @@ -496,29 +482,25 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { .compatible = "allwinner,sun8i-a33-ths", .data = &sun8i_a33_gpadc_data, }, - { /* sentinel */ } + { } }; static int sun4i_gpadc_probe_dt(struct platform_device *pdev, struct iio_dev *indio_dev) { struct sun4i_gpadc_iio *info = iio_priv(indio_dev); - const struct of_device_id *of_dev; - struct resource *mem; void __iomem *base; int ret; - of_dev = of_match_device(sun4i_gpadc_of_id, &pdev->dev); - if (!of_dev) + info->data = of_device_get_match_data(&pdev->dev); + if (!info->data) return -ENODEV; info->no_irq = true; - info->data = (struct gpadc_data *)of_dev->data; indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels); indio_dev->channels = sun8i_a33_gpadc_channels; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, mem); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -530,17 +512,10 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, return ret; } - if (!IS_ENABLED(CONFIG_THERMAL_OF)) - return 0; + if (IS_ENABLED(CONFIG_THERMAL_OF)) + info->sensor_device = &pdev->dev; - info->sensor_device = &pdev->dev; - info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0, - info, &sun4i_ts_tz_ops); - if (IS_ERR(info->tzd)) - dev_err(&pdev->dev, "could not register thermal sensor: %ld\n", - PTR_ERR(info->tzd)); - - return PTR_ERR_OR_ZERO(info->tzd); + return 0; } static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, @@ -587,15 +562,6 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, * return the temperature. */ info->sensor_device = pdev->dev.parent; - info->tzd = thermal_zone_of_sensor_register(info->sensor_device, - 0, info, - &sun4i_ts_tz_ops); - if (IS_ERR(info->tzd)) { - dev_err(&pdev->dev, - "could not register thermal sensor: %ld\n", - PTR_ERR(info->tzd)); - return PTR_ERR(info->tzd); - } } else { indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels_no_temp); @@ -646,8 +612,6 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) info->indio_dev = indio_dev; init_completion(&info->completion); indio_dev->name = dev_name(&pdev->dev); - indio_dev->dev.parent = &pdev->dev; - indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->info = &sun4i_gpadc_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -665,6 +629,22 @@ static int sun4i_gpadc_probe(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); pm_runtime_enable(&pdev->dev); + if (IS_ENABLED(CONFIG_THERMAL_OF)) { + info->tzd = devm_thermal_of_zone_register(info->sensor_device, + 0, info, + &sun4i_ts_tz_ops); + /* + * Do not fail driver probing when failing to register in + * thermal because no thermal DT node is found. + */ + if (IS_ERR(info->tzd) && PTR_ERR(info->tzd) != -ENODEV) { + dev_err(&pdev->dev, + "could not register thermal sensor: %ld\n", + PTR_ERR(info->tzd)); + return PTR_ERR(info->tzd); + } + } + ret = devm_iio_device_register(&pdev->dev, indio_dev); if (ret < 0) { dev_err(&pdev->dev, "could not register the device\n"); @@ -683,7 +663,7 @@ err_map: return ret; } -static int sun4i_gpadc_remove(struct platform_device *pdev) +static void sun4i_gpadc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct sun4i_gpadc_iio *info = iio_priv(indio_dev); @@ -692,21 +672,17 @@ static int sun4i_gpadc_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!IS_ENABLED(CONFIG_THERMAL_OF)) - return 0; - - thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd); + return; if (!info->no_irq) iio_map_array_unregister(indio_dev); - - return 0; } static const struct platform_device_id sun4i_gpadc_id[] = { { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data }, { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data }, { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id); |
