summaryrefslogtreecommitdiffstats
path: root/drivers/iio/adc
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-11-24 08:30:08 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-11-24 08:30:08 +0100
commit749c1e1481e1d242ded9dd1bf210ddb7c0d22a4f (patch)
treed3d8ea19491e1be977019ea2ad02441524fa4c26 /drivers/iio/adc
parentf65b243d6ab856d768aa8039da8a2a47603b8847 (diff)
parent16be06aa1a28b3bc967f0f32e7e4668889bd5131 (diff)
Merge tag 'iio-for-5.11a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes: First set of new device support, features and cleanups for IIO in the 5.11 cycle Usual mixed bag of new drivers / device support + cleanups etc with the addition of a fairly big set of yaml conversions. Txt to yaml format conversions. In some cases dropped separate binding and moved to trivial devices (drop). Listed by manufacturer - dht11 temperature(drop) - adi,ad2s90 adi,ad5272 adi,ad5592r adi,ad5758 adi,ad5933 adi,ad7303 adi,adis16480 adi,adf4350 - ams,as3935 - asahi-kasei,ak8974 - atmel,sama5d2-adc - avago,apds9300 avago,apds9960 - bosch,bma180 bosch,bmc150_magn bosch,bme680 bosch,bmg180 - brcm,iproc-static-adc - capella,cm36651 - domintech,dmard06(drop) - fsl,mag3110 fsl,mma8452 fsl,vf610-dac - hoperf,hp03 - honeywell,hmc5843 - kionix,kxcjk1013 - maxim,ds1803(drop) maxim,ds4424 maxim,max30100 maxim,max30102 maxim,max31856 maxim,max31855k maxim,max44009 maxim,max5481 maxim,max5821 - meas,htu21(drop) meas,ms5367(drop) meas,ms5611 meas,tsys01(drop) - mediatek,mt2701-auxadc - melexis,mlx90614 melexis,mlx90632 - memsic,mmc35240(drop) - microchip,mcp41010 microchip,mcp4131 microchip,mcp4725 - murata,zap2326 - nxp,fxas21002c nxp,lpc1850-dac - pni,rm3100 - qcom,pm8018-adc qcom,spmi-iadc - renesas,isl29501 renesas,rcar-gyroadc - samsung,sensorhub-rinato - sensiron,sgp30 - sentech,sx9500 - sharp,gp2ap020a00f - st,hts221 st,lsm6dsx st,st-sensors(many!) st,uvis25 st,vcl53l0x st,vl6180 - ti,adc084s021 ti,ads124s08 ti,dac5571 ti,dac7311 ti,dac7512 ti,dac7612 ti,hdc1000(drop) ti,palmas-gpadc ti,opt3001 ti,tmp07 - upisemi,us51882 - vishay,vcnl4035 - x-powers,axp209 New device support * adi,ad5685 - Add support for AD5338R dual output 10-bit DAC - Add DT-binding doc. * mediatek,mt6360 - New driver for this SoC ADC with bindings and using new channel label support in the IIO core. * st,lsm6dsx - Add support for LSM6DST Core: * Add "label" to device channels, provided via a new core callback. Including DT docs for when that is the source, and ABI docs. * Add devm_iio_triggered_buffer_setup_ext to take extra attributes. * dmaengine, unwrap use of iio_buffer_set_attrs() * Drop iio_buffer_set_attrs() * Centralize ioctl call handling. Later fix to ensure -EINVAL returned if no handler has run. * Fix an issue with IIO_VAL_FRACTIONAL and negative values - doesn't affect any known existing drivers, but will impact a future one. * kernel-doc fix in trigger.h * file-ops ordering cleanup Features * semtech,sx9310 - Add control of hardware gain, proximity thresholds, hysteresis and debounce. - Increase what information on hardware configuration can be provided via DT. Cleanup and minor features * adi,ad5685 - Add of_match_table * adi,ad7292 - Drop pointless spi_set_drvdata() call * adi,ad7298 - Drop platform data and tidy up external reference config. * adi,ad7303 - Drop platform data handling as unused. * adi,ad7768 - Add new label attribute for channels provided from dt. * adi,ad7887 - devm_ usage in probe simplifying remove and error handling. * adi,adis16201 - Drop pointless spi_set_drvdata() call * adi,adis16209 - Drop pointless spi_set_drvdata() call * adi,adis16240 - White space fixup * adi,adxl372 - use new devm_iio_triggered-buffer_setup_ext() * amlogic,meson-saradc - Drop pointless semicolon. * amstaos,tsl2563 - Put back i2c_device_id table as needed for greybus probing. * atmel,at91_adc - Use of_device_get_match_data() instead of open coding it. - Constify some driver data - Add KCONFIG dep on CONFIG_OF and drop of_match_ptr() - Drop platform data as mostly dead code. - Tidy up reference voltage logic * atmel-sama5d2 - Drop a pointless semicolon - Merge buffer and trigger init into a separate function - Use new devm_iio_triggered_buff_setup_ext() * avago,apds9960 - Drop a pointless semicolon * bosch,bmc150 - Drop a pointless semicolon - Use new iio_triggered_buffer_setup_ext() * bosch,bmp280 - Drop a pointless semicolon * fsl,mma8452 - Constification * (google),cros_ec - Use new devm_iio_triggered_buffer_setup_ext() * hid-sensors - Use new iio_triggered_buffer_setup_ext() * ingenic,adc - Drop a pointless semicolon * invensense,icm426xx - Fix MAINTAINERS entry missing : * mediatek,mt6577_audxac - Add binding doc for mt8516 compatible with mt8173 * motorola,cpcap-adc - Fix an implicit fallthrough marking that clang needs to avoid warning. * samsung,exynos-adc - Stop relying on users counter form input device in ISR. * st,lsm6dsx - add vdd and vddio regulator control (including binding update) * st,stm32-adc - Tidy up code for dma transfers. - Adapt clock duty cycle for proper functioning. Note no known problems with existing boards. * st,vl53l0x-i2c - Put back i2c_device_id table as needed for greybus probing. * vishay,vcnl4035 - Put back i2c_device_id table as needed for greybus probing. * tag 'iio-for-5.11a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (126 commits) dt-bindings:iio:adc:x-powers,axp209-adc: txt to yaml conversion dt-bindings:iio:adc:renesas,rcar-gyroadc: txt to yaml conversion. dt-bindings:iio:adc:atmel,sama5d2-adc: txt to yaml conversion dt-bindings:iio:magnetometer:pni,rm3100: txt to yaml conversion. dt-bindings:iio:magnetometer:honeywell,hmc5843: txt to yaml format conversion dt-bindings:iio:magnetometer:bosch,bmc150_magn: txt to yaml conversion. dt-bindings:iio:magnetometer:asahi-kasei,ak8974: txt to yaml format conversion dt-bindings:iio:magnetometer:fsl,mag3110: txt to yaml conversion dt-bindings:iio:light:st,vl6180: txt to yaml format conversion. dt-bindings:iio:light:vishay,vcnl4035: txt to yaml conversion dt-bindings:iio:light:st,uvis25: txt to yaml conversion for this UV sensor dt-bindings:iio:light:upisemi,us51882: txt to yaml conversion. dt-bindings:iio:light:ti,opt3001: txt to yaml conversion dt-bindings:iio:light:maxim,max44009: txt to yaml conversion. dt-bindings:iio:light:sharp,gp2ap020a00f: txt to yaml conversion. dt-bindings:iio:light:capella,cm36651: txt to yaml conversion. dt-bindings:iio:light:avago,apds9960: txt to yaml conversion dt-bindings:iio:light:avago,apds9300: txt to yaml conversion. dt-bindings:iio:imu:st,lsm6dsx: txt to yaml conversion dt-bindings:iio:imu:adi,adis16480: txt to yaml conversion ...
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig13
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad7292.c2
-rw-r--r--drivers/iio/adc/ad7298.c17
-rw-r--r--drivers/iio/adc/ad7768-1.c41
-rw-r--r--drivers/iio/adc/ad7887.c55
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c84
-rw-r--r--drivers/iio/adc/at91_adc.c73
-rw-r--r--drivers/iio/adc/cpcap-adc.c1
-rw-r--r--drivers/iio/adc/exynos_adc.c7
-rw-r--r--drivers/iio/adc/ingenic-adc.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c2
-rw-r--r--drivers/iio/adc/mt6360-adc.c372
-rw-r--r--drivers/iio/adc/stm32-adc-core.c21
-rw-r--r--drivers/iio/adc/stm32-adc.c29
15 files changed, 560 insertions, 160 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 91ae90514aff..15587a1bc80d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -295,7 +295,7 @@ config ASPEED_ADC
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91 || COMPILE_TEST
- depends on INPUT && SYSFS
+ depends on INPUT && SYSFS && OF
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
@@ -703,6 +703,17 @@ config MCP3911
This driver can also be built as a module. If so, the module will be
called mcp3911.
+config MEDIATEK_MT6360_ADC
+ tristate "Mediatek MT6360 ADC driver"
+ depends on MFD_MT6360
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to enable MT6360 ADC support.
+ Integrated for System Monitoring includes
+ is used in smartphones and tablets and supports a 11 channel
+ general purpose ADC.
+
config MEDIATEK_MT6577_AUXADC
tristate "MediaTek AUXADC driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 90f94ada7b30..5fca90ada0ec 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MCP3911) += mcp3911.o
+obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c
index ab204e9199e9..70e33dd1c9f7 100644
--- a/drivers/iio/adc/ad7292.c
+++ b/drivers/iio/adc/ad7292.c
@@ -276,8 +276,6 @@ static int ad7292_probe(struct spi_device *spi)
return -EINVAL;
}
- spi_set_drvdata(spi, indio_dev);
-
st->reg = devm_regulator_get_optional(&spi->dev, "vref");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 48d43cb0f932..fa1047f74a1f 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -23,8 +23,6 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
-#include <linux/platform_data/ad7298.h>
-
#define AD7298_WRITE BIT(15) /* write to the control register */
#define AD7298_REPEAT BIT(14) /* repeated conversion enable */
#define AD7298_CH(x) BIT(13 - (x)) /* channel select */
@@ -283,7 +281,6 @@ static const struct iio_info ad7298_info = {
static int ad7298_probe(struct spi_device *spi)
{
- struct ad7298_platform_data *pdata = spi->dev.platform_data;
struct ad7298_state *st;
struct iio_dev *indio_dev;
int ret;
@@ -294,14 +291,18 @@ static int ad7298_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
- if (pdata && pdata->ext_ref)
+ st->reg = devm_regulator_get_optional(&spi->dev, "vref");
+ if (!IS_ERR(st->reg)) {
st->ext_ref = AD7298_EXTREF;
+ } else {
+ ret = PTR_ERR(st->reg);
+ if (ret != -ENODEV)
+ return ret;
- if (st->ext_ref) {
- st->reg = devm_regulator_get(&spi->dev, "vref");
- if (IS_ERR(st->reg))
- return PTR_ERR(st->reg);
+ st->reg = NULL;
+ }
+ if (st->reg) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index 0e93b0766eb4..5c0cbee03230 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -161,6 +161,7 @@ struct ad7768_state {
struct completion completion;
struct iio_trigger *trig;
struct gpio_desc *gpio_sync_in;
+ const char *labels[ARRAY_SIZE(ad7768_channels)];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
@@ -407,6 +408,14 @@ static int ad7768_write_raw(struct iio_dev *indio_dev,
}
}
+static int ad7768_read_label(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, char *label)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ return sprintf(label, "%s\n", st->labels[chan->channel]);
+}
+
static struct attribute *ad7768_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
NULL
@@ -420,6 +429,7 @@ static const struct iio_info ad7768_info = {
.attrs = &ad7768_group,
.read_raw = &ad7768_read_raw,
.write_raw = &ad7768_write_raw,
+ .read_label = ad7768_read_label,
.debugfs_reg_access = &ad7768_reg_access,
};
@@ -532,6 +542,33 @@ static void ad7768_clk_disable(void *data)
clk_disable_unprepare(st->mclk);
}
+static int ad7768_set_channel_label(struct iio_dev *indio_dev,
+ int num_channels)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ struct device *device = indio_dev->dev.parent;
+ struct fwnode_handle *fwnode;
+ struct fwnode_handle *child;
+ const char *label;
+ int crt_ch = 0;
+
+ fwnode = dev_fwnode(device);
+ fwnode_for_each_child_node(fwnode, child) {
+ if (fwnode_property_read_u32(child, "reg", &crt_ch))
+ continue;
+
+ if (crt_ch >= num_channels)
+ continue;
+
+ if (fwnode_property_read_string(child, "label", &label))
+ continue;
+
+ st->labels[crt_ch] = label;
+ }
+
+ return 0;
+}
+
static int ad7768_probe(struct spi_device *spi)
{
struct ad7768_state *st;
@@ -604,6 +641,10 @@ static int ad7768_probe(struct spi_device *spi)
init_completion(&st->completion);
+ ret = ad7768_set_channel_label(indio_dev, ARRAY_SIZE(ad7768_channels));
+ if (ret)
+ return ret;
+
ret = devm_request_irq(&spi->dev, spi->irq,
&ad7768_interrupt,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 037bcb47693c..4f6f0e0e03ee 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -232,6 +232,13 @@ static const struct iio_info ad7887_info = {
.read_raw = &ad7887_read_raw,
};
+static void ad7887_reg_disable(void *data)
+{
+ struct regulator *reg = data;
+
+ regulator_disable(reg);
+}
+
static int ad7887_probe(struct spi_device *spi)
{
struct ad7887_platform_data *pdata = spi->dev.platform_data;
@@ -246,14 +253,22 @@ static int ad7887_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
- if (!pdata || !pdata->use_onchip_ref) {
- st->reg = devm_regulator_get(&spi->dev, "vref");
- if (IS_ERR(st->reg))
+ st->reg = devm_regulator_get_optional(&spi->dev, "vref");
+ if (IS_ERR(st->reg)) {
+ if (PTR_ERR(st->reg) != -ENODEV)
return PTR_ERR(st->reg);
+ st->reg = NULL;
+ }
+
+ if (st->reg) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, ad7887_reg_disable, st->reg);
+ if (ret)
+ return ret;
}
st->chip_info =
@@ -269,7 +284,7 @@ static int ad7887_probe(struct spi_device *spi)
/* Setup default message */
mode = AD7887_PM_MODE4;
- if (!pdata || !pdata->use_onchip_ref)
+ if (!st->reg)
mode |= AD7887_REF_DIS;
if (pdata && pdata->en_dual)
mode |= AD7887_DUAL;
@@ -312,36 +327,13 @@ static int ad7887_probe(struct spi_device *spi)
indio_dev->num_channels = st->chip_info->num_channels;
}
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
&ad7887_trigger_handler, &ad7887_ring_setup_ops);
if (ret)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_unregister_ring;
-
- return 0;
-error_unregister_ring:
- iio_triggered_buffer_cleanup(indio_dev);
-error_disable_reg:
- if (st->reg)
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static int ad7887_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad7887_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- if (st->reg)
- regulator_disable(st->reg);
+ return ret;
- return 0;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad7887_id[] = {
@@ -355,7 +347,6 @@ static struct spi_driver ad7887_driver = {
.name = "ad7887",
},
.probe = ad7887_probe,
- .remove = ad7887_remove,
.id_table = ad7887_id,
};
module_spi_driver(ad7887_driver);
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index b917a4714a9c..6edcc99009d1 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1013,21 +1013,6 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
return trig;
}
-
-static int at91_adc_trigger_init(struct iio_dev *indio)
-{
- struct at91_adc_state *st = iio_priv(indio);
-
- st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
- if (IS_ERR(st->trig)) {
- dev_err(&indio->dev,
- "could not allocate trigger\n");
- return PTR_ERR(st->trig);
- }
-
- return 0;
-}
-
static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
struct iio_poll_func *pf)
{
@@ -1155,13 +1140,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
-static int at91_adc_buffer_init(struct iio_dev *indio)
-{
- return devm_iio_triggered_buffer_setup(&indio->dev, indio,
- &iio_pollfunc_store_time,
- &at91_adc_trigger_handler, &at91_buffer_setup_ops);
-}
-
static unsigned at91_adc_startup_time(unsigned startup_time_min,
unsigned adc_clk_khz)
{
@@ -1472,7 +1450,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
return 0;
default:
return -EINVAL;
- };
+ }
}
static void at91_adc_dma_init(struct platform_device *pdev)
@@ -1691,6 +1669,44 @@ static const struct iio_info at91_adc_info = {
.hwfifo_set_watermark = &at91_adc_set_watermark,
};
+static int at91_adc_buffer_and_trigger_init(struct device *dev,
+ struct iio_dev *indio)
+{
+ struct at91_adc_state *st = iio_priv(indio);
+ const struct attribute **fifo_attrs;
+ int ret;
+
+ if (st->selected_trig->hw_trig)
+ fifo_attrs = at91_adc_fifo_attributes;
+ else
+ fifo_attrs = NULL;
+
+ ret = devm_iio_triggered_buffer_setup_ext(&indio->dev, indio,
+ &iio_pollfunc_store_time,
+ &at91_adc_trigger_handler, &at91_buffer_setup_ops, fifo_attrs);
+ if (ret < 0) {
+ dev_err(dev, "couldn't initialize the buffer.\n");
+ return ret;
+ }
+
+ if (!st->selected_trig->hw_trig)
+ return 0;
+
+ st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
+ if (IS_ERR(st->trig)) {
+ dev_err(dev, "could not allocate trigger\n");
+ return PTR_ERR(st->trig);
+ }
+
+ /*
+ * Initially the iio buffer has a length of 2 and
+ * a watermark of 1
+ */
+ st->dma_st.watermark = 1;
+
+ return 0;
+}
+
static int at91_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
@@ -1826,27 +1842,9 @@ static int at91_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
- ret = at91_adc_buffer_init(indio_dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
+ ret = at91_adc_buffer_and_trigger_init(&pdev->dev, indio_dev);
+ if (ret < 0)
goto per_clk_disable_unprepare;
- }
-
- if (st->selected_trig->hw_trig) {
- ret = at91_adc_trigger_init(indio_dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "couldn't setup the triggers.\n");
- goto per_clk_disable_unprepare;
- }
- /*
- * Initially the iio buffer has a length of 2 and
- * a watermark of 1
- */
- st->dma_st.watermark = 1;
-
- iio_buffer_set_attrs(indio_dev->buffer,
- at91_adc_fifo_attributes);
- }
if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32)))
dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n");
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 9b2c548fae95..601708168082 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -22,8 +22,6 @@
#include <linux/slab.h>
#include <linux/wait.h>
-#include <linux/platform_data/at91_adc.h>
-
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
@@ -153,6 +151,25 @@
#define TOUCH_SHTIM 0xa
#define TOUCH_SCTIM_US 10 /* 10us for the Touchscreen Switches Closure Time */
+enum atmel_adc_ts_type {
+ ATMEL_ADC_TOUCHSCREEN_NONE = 0,
+ ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
+ ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
+};
+
+/**
+ * struct at91_adc_trigger - description of triggers
+ * @name: name of the trigger advertised to the user
+ * @value: value to set in the ADC's trigger setup register
+ * to enable the trigger
+ * @is_external: Does the trigger rely on an external pin?
+ */
+struct at91_adc_trigger {
+ const char *name;
+ u8 value;
+ bool is_external;
+};
+
/**
* struct at91_adc_reg_desc - Various informations relative to registers
* @channel_base: Base offset for the channel data registers
@@ -202,7 +219,7 @@ struct at91_adc_state {
struct mutex lock;
u8 num_channels;
void __iomem *reg_base;
- struct at91_adc_reg_desc *registers;
+ const struct at91_adc_reg_desc *registers;
u32 startup_time;
u8 sample_hold_time;
bool sleep_mode;
@@ -214,7 +231,7 @@ struct at91_adc_state {
u32 res; /* resolution used for convertions */
bool low_res; /* the resolution corresponds to the lowest one */
wait_queue_head_t wq_data_avail;
- struct at91_adc_caps *caps;
+ const struct at91_adc_caps *caps;
/*
* Following ADC channels are shared by touchscreen:
@@ -550,7 +567,7 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
{
struct iio_dev *idev = iio_trigger_get_drvdata(trig);
struct at91_adc_state *st = iio_priv(idev);
- struct at91_adc_reg_desc *reg = st->registers;
+ const struct at91_adc_reg_desc *reg = st->registers;
u32 status = at91_adc_readl(st, reg->trigger_register);
int value;
u8 bit;
@@ -829,8 +846,6 @@ static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz)
return ticks;
}
-static const struct of_device_id at91_adc_dt_ids[];
-
static int at91_adc_probe_dt_ts(struct device_node *node,
struct at91_adc_state *st, struct device *dev)
{
@@ -875,11 +890,7 @@ static int at91_adc_probe_dt(struct iio_dev *idev,
int i = 0, ret;
u32 prop;
- if (!node)
- return -EINVAL;
-
- st->caps = (struct at91_adc_caps *)
- of_match_device(at91_adc_dt_ids, &pdev->dev)->data;
+ st->caps = of_device_get_match_data(&pdev->dev);
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
@@ -960,30 +971,6 @@ error_ret:
return ret;
}
-static int at91_adc_probe_pdata(struct at91_adc_state *st,
- struct platform_device *pdev)
-{
- struct at91_adc_data *pdata = pdev->dev.platform_data;
-
- if (!pdata)
- return -EINVAL;
-
- st->caps = (struct at91_adc_caps *)
- platform_get_device_id(pdev)->driver_data;
-
- st->use_external = pdata->use_external_triggers;
- st->vref_mv = pdata->vref;
- st->channels_mask = pdata->channels_used;
- st->num_channels = st->caps->num_channels;
- st->startup_time = pdata->startup_time;
- st->trigger_number = pdata->trigger_number;
- st->trigger_list = pdata->trigger_list;
- st->registers = &st->caps->registers;
- st->touchscreen_type = pdata->touchscreen_type;
-
- return 0;
-}
-
static const struct iio_info at91_adc_info = {
.read_raw = &at91_adc_read_raw,
};
@@ -1160,15 +1147,9 @@ static int at91_adc_probe(struct platform_device *pdev)
st = iio_priv(idev);
- if (pdev->dev.of_node)
- ret = at91_adc_probe_dt(idev, pdev);
- else
- ret = at91_adc_probe_pdata(st, pdev);
-
- if (ret) {
- dev_err(&pdev->dev, "No platform data available.\n");
- return -EINVAL;
- }
+ ret = at91_adc_probe_dt(idev, pdev);
+ if (ret)
+ return ret;
platform_set_drvdata(pdev, idev);
@@ -1469,7 +1450,7 @@ static struct platform_driver at91_adc_driver = {
.id_table = at91_adc_ids,
.driver = {
.name = DRIVER_NAME,
- .of_match_table = of_match_ptr(at91_adc_dt_ids),
+ .of_match_table = at91_adc_dt_ids,
.pm = &at91_adc_pm_ops,
},
};
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index 64c3cc382311..f19c9aa93f17 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -557,6 +557,7 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
break;
case CPCAP_ADC_BATTP_PI16 ... CPCAP_ADC_BATTI_PI17:
value1 |= CPCAP_BIT_RAND1;
+ break;
default:
break;
}
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 99f4404e9fd1..784c10deeb1a 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -7,6 +7,7 @@
* Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@samsung.com>
*/
+#include <linux/compiler.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
@@ -135,6 +136,8 @@ struct exynos_adc {
u32 value;
unsigned int version;
+ bool ts_enabled;
+
bool read_ts;
u32 ts_x;
u32 ts_y;
@@ -651,7 +654,7 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
bool pressed;
int ret;
- while (info->input->users) {
+ while (READ_ONCE(info->ts_enabled)) {
ret = exynos_read_s3c64xx_ts(dev, &x, &y);
if (ret == -ETIMEDOUT)
break;
@@ -731,6 +734,7 @@ static int exynos_adc_ts_open(struct input_dev *dev)
{
struct exynos_adc *info = input_get_drvdata(dev);
+ WRITE_ONCE(info->ts_enabled, true);
enable_irq(info->tsirq);
return 0;
@@ -740,6 +744,7 @@ static void exynos_adc_ts_close(struct input_dev *dev)
{
struct exynos_adc *info = input_get_drvdata(dev);
+ WRITE_ONCE(info->ts_enabled, false);
disable_irq(info->tsirq);
}
diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index 1aafbe2cfe67..34c03a264f74 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -562,7 +562,7 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
return IIO_AVAIL_LIST;
default:
return -EINVAL;
- };
+ }
}
static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index e03988698755..66dc452d643a 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -593,13 +593,11 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING,
ONE_SAMPLE, val);
- break;
case IIO_CHAN_INFO_AVERAGE_RAW:
return meson_sar_adc_get_sample(indio_dev, chan,
MEAN_AVERAGING, EIGHT_SAMPLES,
val);
- break;
case IIO_CHAN_INFO_SCALE:
if (chan->type == IIO_VOLTAGE) {
diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
new file mode 100644
index 000000000000..f57db3056fbe
--- /dev/null
+++ b/drivers/iio/adc/mt6360-adc.c
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/unaligned/be_byteshift.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define MT6360_REG_PMUCHGCTRL3 0x313
+#define MT6360_REG_PMUADCCFG 0x356
+#define MT6360_REG_PMUADCIDLET 0x358
+#define MT6360_REG_PMUADCRPT1 0x35A
+
+/* PMUCHGCTRL3 0x313 */
+#define MT6360_AICR_MASK GENMASK(7, 2)
+#define MT6360_AICR_SHFT 2
+#define MT6360_AICR_400MA 0x6
+/* PMUADCCFG 0x356 */
+#define MT6360_ADCEN_MASK BIT(15)
+/* PMUADCRPT1 0x35A */
+#define MT6360_PREFERCH_MASK GENMASK(7, 4)
+#define MT6360_PREFERCH_SHFT 4
+#define MT6360_RPTCH_MASK GENMASK(3, 0)
+#define MT6360_NO_PREFER 15
+
+/* Time in ms */
+#define ADC_WAIT_TIME_MS 25
+#define ADC_CONV_TIMEOUT_MS 100
+#define ADC_LOOP_TIME_US 2000
+
+enum {
+ MT6360_CHAN_USBID = 0,
+ MT6360_CHAN_VBUSDIV5,
+ MT6360_CHAN_VBUSDIV2,
+ MT6360_CHAN_VSYS,
+ MT6360_CHAN_VBAT,
+ MT6360_CHAN_IBUS,
+ MT6360_CHAN_IBAT,
+ MT6360_CHAN_CHG_VDDP,
+ MT6360_CHAN_TEMP_JC,
+ MT6360_CHAN_VREF_TS,
+ MT6360_CHAN_TS,
+ MT6360_CHAN_MAX
+};
+
+struct mt6360_adc_data {
+ struct device *dev;
+ struct regmap *regmap;
+ /* Due to only one set of ADC control, this lock is used to prevent the race condition */
+ struct mutex adc_lock;
+ ktime_t last_off_timestamps[MT6360_CHAN_MAX];
+};
+
+static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int *val)
+{
+ __be16 adc_enable;
+ u8 rpt[3];
+ ktime_t predict_end_t, timeout;
+ unsigned int pre_wait_time;
+ int ret;
+
+ mutex_lock(&mad->adc_lock);
+
+ /* Select the preferred ADC channel */
+ ret = regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
+ channel << MT6360_PREFERCH_SHFT);
+ if (ret)
+ goto out_adc_lock;
+
+ adc_enable = cpu_to_be16(MT6360_ADCEN_MASK | BIT(channel));
+ ret = regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG, &adc_enable, sizeof(adc_enable));
+ if (ret)
+ goto out_adc_lock;
+
+ predict_end_t = ktime_add_ms(mad->last_off_timestamps[channel], 2 * ADC_WAIT_TIME_MS);
+
+ if (ktime_after(ktime_get(), predict_end_t))
+ pre_wait_time = ADC_WAIT_TIME_MS;
+ else
+ pre_wait_time = 3 * ADC_WAIT_TIME_MS;
+
+ if (msleep_interruptible(pre_wait_time)) {
+ ret = -ERESTARTSYS;
+ goto out_adc_conv;
+ }
+
+ timeout = ktime_add_ms(ktime_get(), ADC_CONV_TIMEOUT_MS);
+ while (true) {
+ ret = regmap_raw_read(mad->regmap, MT6360_REG_PMUADCRPT1, rpt, sizeof(rpt));
+ if (ret)
+ goto out_adc_conv;
+
+ /*
+ * There are two functions, ZCV and TypeC OTP, running ADC VBAT and TS in
+ * background, and ADC samples are taken on a fixed frequency no matter read the
+ * previous one or not.
+ * To avoid conflict, We set minimum time threshold after enable ADC and
+ * check report channel is the same.
+ * The worst case is run the same ADC twice and background function is also running,
+ * ADC conversion sequence is desire channel before start ADC, background ADC,
+ * desire channel after start ADC.
+ * So the minimum correct data is three times of typical conversion time.
+ */
+ if ((rpt[0] & MT6360_RPTCH_MASK) == channel)
+ break;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = -ETIMEDOUT;
+ goto out_adc_conv;
+ }
+
+ usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US);
+ }
+
+ *val = rpt[1] << 8 | rpt[2];
+ ret = IIO_VAL_INT;
+
+out_adc_conv:
+ /* Only keep ADC enable */
+ adc_enable = cpu_to_be16(MT6360_ADCEN_MASK);
+ regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG, &adc_enable, sizeof(adc_enable));
+ mad->last_off_timestamps[channel] = ktime_get();
+ /* Config prefer channel to NO_PREFER */
+ regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
+ MT6360_NO_PREFER << MT6360_PREFERCH_SHFT);
+out_adc_lock:
+ mutex_unlock(&mad->adc_lock);
+
+ return ret;
+}
+
+static int mt6360_adc_read_scale(struct mt6360_adc_data *mad, int channel, int *val, int *val2)
+{
+ unsigned int regval;
+ int ret;
+
+ switch (channel) {
+ case MT6360_CHAN_USBID:
+ case MT6360_CHAN_VSYS:
+ case MT6360_CHAN_VBAT:
+ case MT6360_CHAN_CHG_VDDP:
+ case MT6360_CHAN_VREF_TS:
+ case MT6360_CHAN_TS:
+ *val = 1250;
+ return IIO_VAL_INT;
+ case MT6360_CHAN_VBUSDIV5:
+ *val = 6250;
+ return IIO_VAL_INT;
+ case MT6360_CHAN_VBUSDIV2:
+ case MT6360_CHAN_IBUS:
+ case MT6360_CHAN_IBAT:
+ *val = 2500;
+
+ if (channel == MT6360_CHAN_IBUS) {
+ /* IBUS will be affected by input current limit for the different Ron */
+ /* Check whether the config is <400mA or not */
+ ret = regmap_read(mad->regmap, MT6360_REG_PMUCHGCTRL3, &regval);
+ if (ret)
+ return ret;
+
+ regval = (regval & MT6360_AICR_MASK) >> MT6360_AICR_SHFT;
+ if (regval < MT6360_AICR_400MA)
+ *val = 1900;
+ }
+
+ return IIO_VAL_INT;
+ case MT6360_CHAN_TEMP_JC:
+ *val = 105;
+ *val2 = 100;
+ return IIO_VAL_FRACTIONAL;
+ }
+
+ return -EINVAL;
+}
+
+static int mt6360_adc_read_offset(struct mt6360_adc_data *mad, int channel, int *val)
+{
+ *val = (channel == MT6360_CHAN_TEMP_JC) ? -80 : 0;
+ return IIO_VAL_INT;
+}
+
+static int mt6360_adc_read_raw(struct iio_dev *iio_dev, const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct mt6360_adc_data *mad = iio_priv(iio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ return mt6360_adc_read_channel(mad, chan->channel, val);
+ case IIO_CHAN_INFO_SCALE:
+ return mt6360_adc_read_scale(mad, chan->channel, val, val2);
+ case IIO_CHAN_INFO_OFFSET:
+ return mt6360_adc_read_offset(mad, chan->channel, val);
+ }
+
+ return -EINVAL;
+}
+
+static const char *mt6360_channel_labels[MT6360_CHAN_MAX] = {
+ "usbid", "vbusdiv5", "vbusdiv2", "vsys", "vbat", "ibus", "ibat", "chg_vddp",
+ "temp_jc", "vref_ts", "ts",
+};
+<