From e2540da86ef83ed90e3c13e02c52991c515b12e5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 18 Sep 2018 12:08:50 -0500 Subject: iio: adc: ti-ads7950: use SPI_CS_WORD to reduce CPU usage This changes how the SPI message for the triggered buffer is setup in the TI ADS7950 A/DC driver. By using the SPI_CS_WORD flag, we can read multiple samples in a single SPI transfer. If the SPI controller supports DMA transfers, we can see a significant reduction in CPU usage. For example, on an ARM9 system running at 456MHz reading just 4 channels at 100Hz: before this change, top shows the CPU usage of the IRQ thread of this driver to be ~7.7%. After this change, the CPU usage drops to ~3.8%. The use of big-endian for the raw data was cargo culted from another driver when this driver was originally written. It used an SPI word size of 8 bits and big-endian byte ordering to effectively emulate 16 bit words. Now, in order to inject a CS toggle between each word, we need to use the correct word size, otherwise we would get a CS toggle half way through each word 16-bit. The SPI subsystem uses CPU byte ordering for multi-byte words. So, the data we get back from the SPI is going to be CPU endian now no matter what. Converting that to big endian will just add overhead on little endian systems so we opt to change the raw data format from big endian to CPU endian. There is a small risk that this could break some lazy userspace programs that use the raw data without checking the data format. We can address this if/when it actually comes up. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads7950.c | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index a5bd5944bc66..0ad63592cc3c 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -51,7 +51,7 @@ struct ti_ads7950_state { struct spi_device *spi; - struct spi_transfer ring_xfer[TI_ADS7950_MAX_CHAN + 2]; + struct spi_transfer ring_xfer; struct spi_transfer scan_single_xfer[3]; struct spi_message ring_msg; struct spi_message scan_single_msg; @@ -65,11 +65,11 @@ struct ti_ads7950_state { * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. */ - __be16 rx_buf[TI_ADS7950_MAX_CHAN + TI_ADS7950_TIMESTAMP_SIZE] + u16 rx_buf[TI_ADS7950_MAX_CHAN + 2 + TI_ADS7950_TIMESTAMP_SIZE] ____cacheline_aligned; - __be16 tx_buf[TI_ADS7950_MAX_CHAN]; - __be16 single_tx; - __be16 single_rx; + u16 tx_buf[TI_ADS7950_MAX_CHAN + 2]; + u16 single_tx; + u16 single_rx; }; @@ -108,7 +108,7 @@ enum ti_ads7950_id { .realbits = bits, \ .storagebits = 16, \ .shift = 12 - (bits), \ - .endianness = IIO_BE, \ + .endianness = IIO_CPU, \ }, \ } @@ -249,23 +249,14 @@ static int ti_ads7950_update_scan_mode(struct iio_dev *indio_dev, len = 0; for_each_set_bit(i, active_scan_mask, indio_dev->num_channels) { cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(i) | st->settings; - st->tx_buf[len++] = cpu_to_be16(cmd); + st->tx_buf[len++] = cmd; } /* Data for the 1st channel is not returned until the 3rd transfer */ - len += 2; - for (i = 0; i < len; i++) { - if ((i + 2) < len) - st->ring_xfer[i].tx_buf = &st->tx_buf[i]; - if (i >= 2) - st->ring_xfer[i].rx_buf = &st->rx_buf[i - 2]; - st->ring_xfer[i].len = 2; - st->ring_xfer[i].cs_change = 1; - } - /* make sure last transfer's cs_change is not set */ - st->ring_xfer[len - 1].cs_change = 0; + st->tx_buf[len++] = 0; + st->tx_buf[len++] = 0; - spi_message_init_with_transfers(&st->ring_msg, st->ring_xfer, len); + st->ring_xfer.len = len * 2; return 0; } @@ -281,7 +272,7 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p) if (ret < 0) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, + iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf[2], iio_get_time_ns(indio_dev)); out: @@ -298,13 +289,13 @@ static int ti_ads7950_scan_direct(struct iio_dev *indio_dev, unsigned int ch) mutex_lock(&indio_dev->mlock); cmd = TI_ADS7950_CR_WRITE | TI_ADS7950_CR_CHAN(ch) | st->settings; - st->single_tx = cpu_to_be16(cmd); + st->single_tx = cmd; ret = spi_sync(st->spi, &st->scan_single_msg); if (ret) goto out; - ret = be16_to_cpu(st->single_rx); + ret = st->single_rx; out: mutex_unlock(&indio_dev->mlock); @@ -378,6 +369,14 @@ static int ti_ads7950_probe(struct spi_device *spi) const struct ti_ads7950_chip_info *info; int ret; + spi->bits_per_word = 16; + spi->mode |= SPI_CS_WORD; + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "Error in spi setup\n"); + return ret; + } + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -398,6 +397,16 @@ static int ti_ads7950_probe(struct spi_device *spi) indio_dev->num_channels = info->num_channels; indio_dev->info = &ti_ads7950_info; + /* build spi ring message */ + spi_message_init(&st->ring_msg); + + st->ring_xfer.tx_buf = &st->tx_buf[0]; + st->ring_xfer.rx_buf = &st->rx_buf[0]; + /* len will be set later */ + st->ring_xfer.cs_change = true; + + spi_message_add_tail(&st->ring_xfer, &st->ring_msg); + /* * Setup default message. The sample is read at the end of the first * transfer, then it takes one full cycle to convert the sample and one -- cgit From d3fa21c73c391975488818b085b894c2980ea052 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 22 Sep 2018 00:58:02 +0300 Subject: iio: adc: imx25-gcq: Fix leak of device_node in mx25_gcq_setup_cfgs() Leaving for_each_child_of_node loop we should release child device node, if it is not stored for future use. Found by Linux Driver Verification project (linuxtesting.org). JC: I'm not sending this as a quick fix as it's been wrong for years, but good to pick up for stable after the merge window. Signed-off-by: Alexey Khoroshilov Fixes: 6df2e98c3ea56 ("iio: adc: Add imx25-gcq ADC driver") Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/fsl-imx25-gcq.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index ea264fa9e567..929c617db364 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -209,12 +209,14 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, ret = of_property_read_u32(child, "reg", ®); if (ret) { dev_err(dev, "Failed to get reg property\n"); + of_node_put(child); return ret; } if (reg >= MX25_NUM_CFGS) { dev_err(dev, "reg value is greater than the number of available configuration registers\n"); + of_node_put(child); return -EINVAL; } @@ -228,6 +230,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, if (IS_ERR(priv->vref[refp])) { dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.", mx25_gcq_refp_names[refp]); + of_node_put(child); return PTR_ERR(priv->vref[refp]); } priv->channel_vref_mv[reg] = @@ -240,6 +243,7 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, break; default: dev_err(dev, "Invalid positive reference %d\n", refp); + of_node_put(child); return -EINVAL; } @@ -254,10 +258,12 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev, if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) { dev_err(dev, "Invalid fsl,adc-refp property value\n"); + of_node_put(child); return -EINVAL; } if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) { dev_err(dev, "Invalid fsl,adc-refn property value\n"); + of_node_put(child); return -EINVAL; } -- cgit From f9c4c27f1be09b942288925dd689049511ab257f Mon Sep 17 00:00:00 2001 From: Song Qiang Date: Thu, 20 Sep 2018 21:49:46 +0800 Subject: iio: magnetometer: hmc5843: Fixed a comment error. Replace 'hcm5843' with 'hmc5843'. Signed-off-by: Song Qiang Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/hmc5843.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index 76a5d7484d8d..a75224cf99df 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -31,7 +31,7 @@ enum hmc5843_ids { }; /** - * struct hcm5843_data - device specific data + * struct hmc5843_data - device specific data * @dev: actual device * @lock: update and read regmap data * @regmap: hardware access register maps -- cgit From 6eb17c6c8aee233e27339bcefe4bf9bef6d94c6c Mon Sep 17 00:00:00 2001 From: Song Qiang Date: Tue, 18 Sep 2018 16:24:21 +0800 Subject: iio: proximity: Add driver support for ST's VL53L0X ToF ranging sensor. This driver was originally written by ST in 2016 as a misc input device driver, and hasn't been maintained for a long time. I grabbed some code from it's API and reformed it into an iio proximity device driver. This version of driver uses i2c bus to talk to the sensor and polling for measuring completes, so no irq line is needed. It can be tested with reading from /sys/bus/iio/devices/iio:deviceX/in_distance_input Signed-off-by: Song Qiang Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 11 +++ drivers/iio/proximity/Makefile | 2 + drivers/iio/proximity/vl53l0x-i2c.c | 164 ++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 drivers/iio/proximity/vl53l0x-i2c.c (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 388ef70c11d2..b99367a89f81 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -92,4 +92,15 @@ config SRF08 To compile this driver as a module, choose M here: the module will be called srf08. +config VL53L0X_I2C + tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)" + depends on I2C + help + Say Y here to build a driver for STMicroelectronics VL53L0X + ToF ranger sensors with i2c interface. + This driver can be used to measure the distance of objects. + + To compile this driver as a module, choose M here: the + module will be called vl53l0x-i2c. + endmenu diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index cac3d7d3325e..6d031f903c4c 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_RFD77402) += rfd77402.o obj-$(CONFIG_SRF04) += srf04.o obj-$(CONFIG_SRF08) += srf08.o obj-$(CONFIG_SX9500) += sx9500.o +obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o + diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c new file mode 100644 index 000000000000..b48216cc1858 --- /dev/null +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for ST VL53L0X FlightSense ToF Ranging Sensor on a i2c bus. + * + * Copyright (C) 2016 STMicroelectronics Imaging Division. + * Copyright (C) 2018 Song Qiang + * + * Datasheet available at + * + * + * Default 7-bit i2c slave address 0x29. + * + * TODO: FIFO buffer, continuous mode, interrupts, range selection, + * sensor ID check. + */ + +#include +#include +#include + +#include + +#define VL_REG_SYSRANGE_START 0x00 + +#define VL_REG_SYSRANGE_MODE_MASK GENMASK(3, 0) +#define VL_REG_SYSRANGE_MODE_SINGLESHOT 0x00 +#define VL_REG_SYSRANGE_MODE_START_STOP BIT(0) +#define VL_REG_SYSRANGE_MODE_BACKTOBACK BIT(1) +#define VL_REG_SYSRANGE_MODE_TIMED BIT(2) +#define VL_REG_SYSRANGE_MODE_HISTOGRAM BIT(3) + +#define VL_REG_RESULT_INT_STATUS 0x13 +#define VL_REG_RESULT_RANGE_STATUS 0x14 +#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0) + +struct vl53l0x_data { + struct i2c_client *client; +}; + +static int vl53l0x_read_proximity(struct vl53l0x_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + struct i2c_client *client = data->client; + u16 tries = 20; + u8 buffer[12]; + int ret; + + ret = i2c_smbus_write_byte_data(client, VL_REG_SYSRANGE_START, 1); + if (ret < 0) + return ret; + + do { + ret = i2c_smbus_read_byte_data(client, + VL_REG_RESULT_RANGE_STATUS); + if (ret < 0) + return ret; + + if (ret & VL_REG_RESULT_RANGE_STATUS_COMPLETE) + break; + + usleep_range(1000, 5000); + } while (--tries); + if (!tries) + return -ETIMEDOUT; + + ret = i2c_smbus_read_i2c_block_data(client, VL_REG_RESULT_RANGE_STATUS, + 12, buffer); + if (ret < 0) + return ret; + else if (ret != 12) + return -EREMOTEIO; + + /* Values should be between 30~1200 in millimeters. */ + *val = (buffer[10] << 8) + buffer[11]; + + return 0; +} + +static const struct iio_chan_spec vl53l0x_channels[] = { + { + .type = IIO_DISTANCE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static int vl53l0x_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct vl53l0x_data *data = iio_priv(indio_dev); + int ret; + + if (chan->type != IIO_DISTANCE) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = vl53l0x_read_proximity(data, chan, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1000; + + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info vl53l0x_info = { + .read_raw = vl53l0x_read_raw, +}; + +static int vl53l0x_probe(struct i2c_client *client) +{ + struct vl53l0x_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_I2C_BLOCK | + I2C_FUNC_SMBUS_BYTE_DATA)) + return -EOPNOTSUPP; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = "vl53l0x"; + indio_dev->info = &vl53l0x_info; + indio_dev->channels = vl53l0x_channels; + indio_dev->num_channels = ARRAY_SIZE(vl53l0x_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct of_device_id st_vl53l0x_dt_match[] = { + { .compatible = "st,vl53l0x", }, + { } +}; +MODULE_DEVICE_TABLE(of, st_vl53l0x_dt_match); + +static struct i2c_driver vl53l0x_driver = { + .driver = { + .name = "vl53l0x-i2c", + .of_match_table = st_vl53l0x_dt_match, + }, + .probe_new = vl53l0x_probe, +}; +module_i2c_driver(vl53l0x_driver); + +MODULE_AUTHOR("Song Qiang "); +MODULE_DESCRIPTION("ST vl53l0x ToF ranging sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 5851b499de048c9e0ee1ef2e3fbd8d3d89cbdf18 Mon Sep 17 00:00:00 2001 From: ryang Date: Sat, 22 Sep 2018 16:57:54 -0400 Subject: iio: light: bh1750: Add device tree support Add device tree support for ROHM BH1750 series ambient light sensors. Signed-off-by: ryang Signed-off-by: Jonathan Cameron --- drivers/iio/light/bh1750.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index c3a481452b67..28347df78cff 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -307,9 +307,20 @@ static const struct i2c_device_id bh1750_id[] = { }; MODULE_DEVICE_TABLE(i2c, bh1750_id); +static const struct of_device_id bh1750_of_match[] = { + { .compatible = "rohm,bh1710", }, + { .compatible = "rohm,bh1715", }, + { .compatible = "rohm,bh1721", }, + { .compatible = "rohm,bh1750", }, + { .compatible = "rohm,bh1751", }, + { } +}; +MODULE_DEVICE_TABLE(of, bh1750_of_match); + static struct i2c_driver bh1750_driver = { .driver = { .name = "bh1750", + .of_match_table = bh1750_of_match, .pm = &bh1750_pm_ops, }, .probe = bh1750_probe, -- cgit From 3d9bf07a72f9257f081be7d4381cb70cf0d9426e Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 23 Sep 2018 00:21:00 +0200 Subject: iio: adc: meson-saradc: remove #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT This define is of no use because the driver is avoiding shifting bits by itself but using FIELD_GET/FIELD_PREP (which are using bit masks) instead. There is already a MESON_SAR_ADC_DELTA_10_TS_C_MASK bit mask so MESON_SAR_ADC_DELTA_10_TS_C_SHIFT was redundant. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index da2d16dfa63e..b97b06bf7713 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -148,7 +148,6 @@ #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) - #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11 #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) -- cgit From 234c64a290cb6ec79a2b1ac289a1713dc9f7890e Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 23 Sep 2018 00:21:01 +0200 Subject: iio: adc: meson-saradc: use of_device_get_match_data This simplifies our _probe function by using of_device_get_match_data instead of open-coding it. No functional changes. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index b97b06bf7713..9d8f2139debc 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -978,11 +978,11 @@ MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); static int meson_sar_adc_probe(struct platform_device *pdev) { + const struct meson_sar_adc_data *match_data; struct meson_sar_adc_priv *priv; struct iio_dev *indio_dev; struct resource *res; void __iomem *base; - const struct of_device_id *match; int irq, ret; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); @@ -994,13 +994,13 @@ static int meson_sar_adc_probe(struct platform_device *pdev) priv = iio_priv(indio_dev); init_completion(&priv->done); - match = of_match_device(meson_sar_adc_of_match, &pdev->dev); - if (!match) { - dev_err(&pdev->dev, "failed to match device\n"); + match_data = of_device_get_match_data(&pdev->dev); + if (!match_data) { + dev_err(&pdev->dev, "failed to get match data\n"); return -ENODEV; } - priv->data = match->data; + priv->data = match_data; indio_dev->name = priv->data->name; indio_dev->dev.parent = &pdev->dev; -- cgit From 057e5a1109faa01091a989c224833e2df6003b2e Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 23 Sep 2018 00:21:02 +0200 Subject: iio: adc: meson-saradc: simplify access to meson_sar_adc_param Commit 053ffe3c8cfe31 ("iio: adc: meson-saradc: squash and share the common adc platform data") put all the data which is needed at runtime from struct meson_sar_adc_data to a new struct meson_sar_adc_param so we can re-use the platform specific configuration without having to duplicate everything just to change the name. The only place where struct meson_sar_adc_data is now needed is the _probe function which has to pass the name to the iio_dev. All other functions only need access to struct meson_sar_adc_param. This means we can simplify struct meson_sar_adc_priv. The goal of this patch is to make the code a bit easier to read since this removes one level of nesting. No functional changes intended. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 9d8f2139debc..1c4ba83c0725 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -234,7 +234,7 @@ struct meson_sar_adc_data { struct meson_sar_adc_priv { struct regmap *regmap; struct regulator *vref; - const struct meson_sar_adc_data *data; + const struct meson_sar_adc_param *param; struct clk *clkin; struct clk *core_clk; struct clk *adc_sel_clk; @@ -279,7 +279,7 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) /* use val_calib = scale * val_raw + offset calibration function */ tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; - return clamp(tmp, 0, (1 << priv->data->param->resolution) - 1); + return clamp(tmp, 0, (1 << priv->param->resolution) - 1); } static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) @@ -331,7 +331,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, } fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); - fifo_val &= GENMASK(priv->data->param->resolution - 1, 0); + fifo_val &= GENMASK(priv->param->resolution - 1, 0); *val = meson_sar_adc_calib_val(indio_dev, fifo_val); return 0; @@ -450,7 +450,7 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev) mutex_lock(&indio_dev->mlock); - if (priv->data->param->has_bl30_integration) { + if (priv->param->has_bl30_integration) { /* prevent BL30 from using the SAR ADC while we are using it */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, MESON_SAR_ADC_DELAY_KERNEL_BUSY, @@ -478,7 +478,7 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - if (priv->data->param->has_bl30_integration) + if (priv->param->has_bl30_integration) /* allow BL30 to use the SAR ADC again */ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); @@ -562,7 +562,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, } *val = ret / 1000; - *val2 = priv->data->param->resolution; + *val2 = priv->param->resolution; return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_CALIBBIAS: @@ -635,7 +635,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) */ meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); - if (priv->data->param->has_bl30_integration) { + if (priv->param->has_bl30_integration) { /* * leave sampling delay and the input clocks as configured by * BL30 to make sure BL30 gets the values it expects when @@ -715,7 +715,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) return ret; } - ret = clk_set_rate(priv->adc_clk, priv->data->param->clock_rate); + ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); if (ret) { dev_err(indio_dev->dev.parent, "failed to set adc clock rate\n"); @@ -728,7 +728,7 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - const struct meson_sar_adc_param *param = priv->data->param; + const struct meson_sar_adc_param *param = priv->param; u32 enable_mask; if (param->bandgap_reg == MESON_SAR_ADC_REG11) @@ -848,8 +848,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev) int ret, nominal0, nominal1, value0, value1; /* use points 25% and 75% for calibration */ - nominal0 = (1 << priv->data->param->resolution) / 4; - nominal1 = (1 << priv->data->param->resolution) * 3 / 4; + nominal0 = (1 << priv->param->resolution) / 4; + nominal1 = (1 << priv->param->resolution) * 3 / 4; meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); usleep_range(10, 20); @@ -1000,9 +1000,9 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return -ENODEV; } - priv->data = match_data; + priv->param = match_data->param; - indio_dev->name = priv->data->name; + indio_dev->name = match_data->name; indio_dev->dev.parent = &pdev->dev; indio_dev->dev.of_node = pdev->dev.of_node; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1026,7 +1026,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) return ret; priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, - priv->data->param->regmap_config); + priv->param->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); -- cgit From bc1b45326223e7e890053cf6266357adfa61942d Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Mon, 24 Sep 2018 10:51:43 +0300 Subject: iio: adc: at91: fix acking DRDY irq on simple conversions When doing simple conversions, the driver did not acknowledge the DRDY irq. If this irq status is not acked, it will be left pending, and as soon as a trigger is enabled, the irq handler will be called, it doesn't know why this status has occurred because no channel is pending, and then it will go int a irq loop and board will hang. To avoid this situation, read the LCDR after a raw conversion is done. Fixes: 0e589d5fb ("ARM: AT91: IIO: Add AT91 ADC driver.") Cc: Maxime Ripard Signed-off-by: Eugen Hristev Acked-by: Ludovic Desroches Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 44b516863c9d..e3be88e7192c 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -279,6 +279,8 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev) iio_trigger_poll(idev->trig); } else { st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb)); + /* Needed to ACK the DRDY interruption */ + at91_adc_readl(st, AT91_ADC_LCDR); st->done = true; wake_up_interruptible(&st->wq_data_avail); } -- cgit From aea835f2dc8a682942b859179c49ad1841a6c8b9 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Mon, 24 Sep 2018 10:51:44 +0300 Subject: iio: adc: at91: fix wrong channel number in triggered buffer mode When channels are registered, the hardware channel number is not the actual iio channel number. This is because the driver is probed with a certain number of accessible channels. Some pins are routed and some not, depending on the description of the board in the DT. Because of that, channels 0,1,2,3 can correspond to hardware channels 2,3,4,5 for example. In the buffered triggered case, we need to do the translation accordingly. Fixed the channel number to stop reading the wrong channel. Fixes: 0e589d5fb ("ARM: AT91: IIO: Add AT91 ADC driver.") Cc: Maxime Ripard Signed-off-by: Eugen Hristev Acked-by: Ludovic Desroches Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91_adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index e3be88e7192c..75d2f73582a3 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -248,12 +248,14 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *idev = pf->indio_dev; struct at91_adc_state *st = iio_priv(idev); + struct iio_chan_spec const *chan; int i, j = 0; for (i = 0; i < idev->masklength; i++) { if (!test_bit(i, idev->active_scan_mask)) continue; - st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i)); + chan = idev->channels + i; + st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, chan->channel)); j++; } -- cgit From bdd4b07ffa5e5d2d577952a559a87498e7bac0da Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Tue, 25 Sep 2018 00:13:25 +0200 Subject: iio: adc: meson-saradc: do not use meson_sar_adc_iio_channels directly In the future we may support two different channel sets: - one which includes the voltage pads and the temperature sensor output (for Meson8, Meson8b and Meson8m2) - one which only includes the voltage pads (GXBB, GXL, GXM and AXG) Channel 7 has a special function on all of these platforms. However, since we will have different channel array definitions we want our code to always use whatever channels struct iio_dev uses. No functional changes for now. This is the preparation for adding temperature sensor support to this driver. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 1c4ba83c0725..809d1230be34 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -854,7 +854,7 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev) meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); usleep_range(10, 20); ret = meson_sar_adc_get_sample(indio_dev, - &meson_sar_adc_iio_channels[7], + &indio_dev->channels[7], MEAN_AVERAGING, EIGHT_SAMPLES, &value0); if (ret < 0) goto out; @@ -862,7 +862,7 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev) meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); usleep_range(10, 20); ret = meson_sar_adc_get_sample(indio_dev, - &meson_sar_adc_iio_channels[7], + &indio_dev->channels[7], MEAN_AVERAGING, EIGHT_SAMPLES, &value1); if (ret < 0) goto out; -- cgit From 827df0571fb32d308f26c34641c1a88ba500d28e Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Tue, 25 Sep 2018 00:13:26 +0200 Subject: iio: adc: meson-saradc: use the address attribute from iio_chan_spec Until now the "channel" number is identical to how the channel is identified inside the (FIFO) registers. In our case we have eight channels and the hardware also has eight inputs. However, there are two special inputs: - channel 6 can select between the SAR_ADC_CH6 pad and the chip's internal temperature sensor - channel 7 can select between SAR_ADC_CH7 and VSS, VDD / 4, VDD / 2, VDD * 3 / 4 and VDD. When programming the registers to read for example the temperature sensor we have to select FIFO channel 6, set the correct bit which muxes channel 6 to the temperature sensor and then start the ADC measurement for channel 6 as usual. When we add support for the temperature sensor the driver has to know about that it has to use FIFO channel 6 to measure using the chip's internal temperature sensor. However, in that case the iio_chan_spec channel will not be 6 because this is already used for the SAR_ADC_CH6 pad input. Thus we use iio_chan_spec's address field to store the FIFO channel number for each channel. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 809d1230be34..028ccd218f82 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -172,6 +172,7 @@ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _chan, \ + .address = _chan, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ @@ -323,10 +324,10 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); - if (fifo_chan != chan->channel) { + if (fifo_chan != chan->address) { dev_err(&indio_dev->dev, - "ADC FIFO entry belongs to channel %d instead of %d\n", - fifo_chan, chan->channel); + "ADC FIFO entry belongs to channel %d instead of %lu\n", + fifo_chan, chan->address); return -EINVAL; } @@ -343,16 +344,16 @@ static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, enum meson_sar_adc_num_samples samples) { struct meson_sar_adc_priv *priv = iio_priv(indio_dev); - int val, channel = chan->channel; + int val, address = chan->address; - val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel); + val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, - MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel), + MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), val); - val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel); + val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, - MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val); + MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); } static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, @@ -372,23 +373,23 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, /* map channel index 0 to the channel which we want to read */ regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, regval); regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, - chan->channel); + chan->address); regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, regval); - if (chan->channel == 6) + if (chan->address == 6) regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0); } @@ -526,8 +527,8 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, if (ret) { dev_warn(indio_dev->dev.parent, - "failed to read sample for channel %d: %d\n", - chan->channel, ret); + "failed to read sample for channel %lu: %d\n", + chan->address, ret); return ret; } -- cgit From 8911a43bc198877fad9f4b0246a866b26bb547ab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 28 Sep 2018 11:23:40 +0200 Subject: iio: ad5064: Fix regulator handling The correct way to handle errors returned by regualtor_get() and friends is to propagate the error since that means that an regulator was specified, but something went wrong when requesting it. For handling optional regulators, e.g. when the device has an internal vref, regulator_get_optional() should be used to avoid getting the dummy regulator that the regulator core otherwise provides. Signed-off-by: Lars-Peter Clausen Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5064.c | 53 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index bf4fc40ec84d..2f98cb2a3b96 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -808,6 +808,40 @@ static int ad5064_set_config(struct ad5064_state *st, unsigned int val) return ad5064_write(st, cmd, 0, val, 0); } +static int ad5064_request_vref(struct ad5064_state *st, struct device *dev) +{ + unsigned int i; + int ret; + + for (i = 0; i < ad5064_num_vref(st); ++i) + st->vref_reg[i].supply = ad5064_vref_name(st, i); + + if (!st->chip_info->internal_vref) + return devm_regulator_bulk_get(dev, ad5064_num_vref(st), + st->vref_reg); + + /* + * This assumes that when the regulator has an internal VREF + * there is only one external VREF connection, which is + * currently the case for all supported devices. + */ + st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref"); + if (!IS_ERR(st->vref_reg[0].consumer)) + return 0; + + ret = PTR_ERR(st->vref_reg[0].consumer); + if (ret != -ENODEV) + return ret; + + /* If no external regulator was supplied use the internal VREF */ + st->use_internal_vref = true; + ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); + if (ret) + dev_err(dev, "Failed to enable internal vref: %d\n", ret); + + return ret; +} + static int ad5064_probe(struct device *dev, enum ad5064_type type, const char *name, ad5064_write_func write) { @@ -828,22 +862,11 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, st->dev = dev; st->write = write; - for (i = 0; i < ad5064_num_vref(st); ++i) - st->vref_reg[i].supply = ad5064_vref_name(st, i); + ret = ad5064_request_vref(st, dev); + if (ret) + return ret; - ret = devm_regulator_bulk_get(dev, ad5064_num_vref(st), - st->vref_reg); - if (ret) { - if (!st->chip_info->internal_vref) - return ret; - st->use_internal_vref = true; - ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); - if (ret) { - dev_err(dev, "Failed to enable internal vref: %d\n", - ret); - return ret; - } - } else { + if (!st->use_internal_vref) { ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); if (ret) return ret; -- cgit