summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/sun4i-gpadc-iio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/sun4i-gpadc-iio.c')
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c98
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);