From a9fbbbd7d2668232babc60ef77539dd82a33a89c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:38:00 +0000 Subject: [PATCH 01/30] iio: adis16400: Remove unused variable 'rx' is not used in this function. Remove it. Signed-off-by: Sachin Kamat Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16400_buffer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c index f2cf829e5df1..6e727ffe5262 100644 --- a/drivers/iio/imu/adis16400_buffer.c +++ b/drivers/iio/imu/adis16400_buffer.c @@ -18,7 +18,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, { struct adis16400_state *st = iio_priv(indio_dev); struct adis *adis = &st->adis; - uint16_t *tx, *rx; + uint16_t *tx; if (st->variant->flags & ADIS16400_NO_BURST) return adis_update_scan_mode(indio_dev, scan_mask); @@ -35,7 +35,6 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, if (!adis->buffer) return -ENOMEM; - rx = adis->buffer; tx = adis->buffer + indio_dev->scan_bytes; tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); From 15255c6b4de66b8d282d0b62398d90ff7b24f4a5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:38:00 +0000 Subject: [PATCH 02/30] iio: ad5624r_spi: Remove redundant variable By re-arranging the code, 'ret' can be removed from this function. Signed-off-by: Sachin Kamat Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5624r_spi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index e8199cce2aea..61bb9d4239ea 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -67,7 +67,6 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev, long mask) { struct ad5624r_state *st = iio_priv(indio_dev); - int ret; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -79,10 +78,8 @@ static int ad5624r_write_raw(struct iio_dev *indio_dev, chan->address, val, chan->scan_type.shift); default: - ret = -EINVAL; + return -EINVAL; } - - return -EINVAL; } static const char * const ad5624r_powerdown_modes[] = { From 0d3a9b2daddc1ebb6db66d5f913bcd93f449f8e5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:38:00 +0000 Subject: [PATCH 03/30] iio: ad5504: Remove redundant variable By re-arranging the code, 'ret' can be removed from this function. Signed-off-by: Sachin Kamat Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5504.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index c917dd24090a..581ec141de3d 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -125,7 +125,6 @@ static int ad5504_write_raw(struct iio_dev *indio_dev, long mask) { struct ad5504_state *st = iio_priv(indio_dev); - int ret; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -134,10 +133,8 @@ static int ad5504_write_raw(struct iio_dev *indio_dev, return ad5504_spi_write(st, chan->address, val); default: - ret = -EINVAL; + return -EINVAL; } - - return -EINVAL; } static const char * const ad5504_powerdown_modes[] = { From 10215d8689b605ce30ef9327a98337ce056b1c3d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:38:00 +0000 Subject: [PATCH 04/30] iio: ad5686: Remove redundant variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘regdone’ is not used in the function. Remove it. Signed-off-by: Sachin Kamat Cc: Michael Hennerich Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5686.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 17aca4d9bd06..f57562aa396f 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -313,7 +313,7 @@ static int ad5686_probe(struct spi_device *spi) { struct ad5686_state *st; struct iio_dev *indio_dev; - int ret, regdone = 0, voltage_uv = 0; + int ret, voltage_uv = 0; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) @@ -355,7 +355,6 @@ static int ad5686_probe(struct spi_device *spi) indio_dev->channels = st->chip_info->channel; indio_dev->num_channels = AD5686_DAC_CHANNELS; - regdone = 1; ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0, !!voltage_uv, 0); if (ret) From fc96d25ad0dc8cf512d233abdc6a8e097d357d95 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:38:00 +0000 Subject: [PATCH 05/30] iio: xilinx-xadc: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'offset’ is not used in the function. Remove it. Signed-off-by: Sachin Kamat Acked-by: Lars-Peter Clausen Cc: Michal Simek Signed-off-by: Jonathan Cameron --- drivers/iio/adc/xilinx-xadc-events.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c index 3e7f0d7a80c3..edcf3aabd70d 100644 --- a/drivers/iio/adc/xilinx-xadc-events.c +++ b/drivers/iio/adc/xilinx-xadc-events.c @@ -31,17 +31,11 @@ static const struct iio_chan_spec *xadc_event_to_channel( static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event) { const struct iio_chan_spec *chan; - unsigned int offset; /* Temperature threshold error, we don't handle this yet */ if (event == 0) return; - if (event < 4) - offset = event; - else - offset = event + 4; - chan = xadc_event_to_channel(indio_dev, event); if (chan->type == IIO_TEMP) { From a034234277d2f51104deadd559dd9584ba00a8cc Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 07:44:00 +0000 Subject: [PATCH 06/30] iio: hid-sensors: Fix compilation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the 'static' keyword to beginning of definition to silence the following compilation warning: drivers/iio/common/hid-sensors/hid-sensor-attributes.c:34:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] Signed-off-by: Sachin Kamat Cc: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 403dd3d8986e..1614340e5733 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -26,12 +26,12 @@ #include #include -struct { +static struct { u32 usage_id; int unit; /* 0 for default others from HID sensor spec */ int scale_val0; /* scale, whole number */ int scale_val1; /* scale, fraction in micros */ -} static unit_conversion[] = { +} unit_conversion[] = { {HID_USAGE_SENSOR_ACCEL_3D, 0, 9, 806650}, {HID_USAGE_SENSOR_ACCEL_3D, HID_USAGE_SENSOR_UNITS_METERS_PER_SEC_SQRD, 1, 0}, From 6c25539cbc460f7f594e30ac6db88d5e61e8baff Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 7 May 2014 13:38:00 +0100 Subject: [PATCH 07/30] iio: Add Intersil isl29125 digital color light sensor driver datasheet: http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29125.pdf Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 12 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/isl29125.c | 347 +++++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) create mode 100644 drivers/iio/light/isl29125.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index c89740d4748f..7d83dca6d080 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -62,6 +62,18 @@ config GP2AP020A00F To compile this driver as a module, choose M here: the module will be called gp2ap020a00f. +config ISL29125 + tristate "Intersil ISL29125 digital color light sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here if you want to build a driver for the Intersil ISL29125 + RGB light sensor for I2C. + + To compile this driver as a module, choose M here: the module will be + called isl29125. + config HID_SENSOR_ALS depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 3eb36e5151fa..f3d1857b2083 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_CM36651) += cm36651.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o +obj-$(CONFIG_ISL29125) += isl29125.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c new file mode 100644 index 000000000000..c82f4a6f8464 --- /dev/null +++ b/drivers/iio/light/isl29125.c @@ -0,0 +1,347 @@ +/* + * isl29125.c - Support for Intersil ISL29125 RGB light sensor + * + * Copyright (c) 2014 Peter Meerwald + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * RGB light sensor with 16-bit channels for red, green, blue); + * 7-bit I2C slave address 0x44 + * + * TODO: interrupt support, IR compensation, thresholds, 12bit + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ISL29125_DRV_NAME "isl29125" + +#define ISL29125_DEVICE_ID 0x00 +#define ISL29125_CONF1 0x01 +#define ISL29125_CONF2 0x02 +#define ISL29125_CONF3 0x03 +#define ISL29125_STATUS 0x08 +#define ISL29125_GREEN_DATA 0x09 +#define ISL29125_RED_DATA 0x0b +#define ISL29125_BLUE_DATA 0x0d + +#define ISL29125_ID 0x7d + +#define ISL29125_MODE_MASK GENMASK(2, 0) +#define ISL29125_MODE_PD 0x0 +#define ISL29125_MODE_G 0x1 +#define ISL29125_MODE_R 0x2 +#define ISL29125_MODE_B 0x3 +#define ISL29125_MODE_RGB 0x5 + +#define ISL29125_MODE_RANGE BIT(3) + +#define ISL29125_STATUS_CONV BIT(1) + +struct isl29125_data { + struct i2c_client *client; + struct mutex lock; + u8 conf1; + u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */ +}; + +#define ISL29125_CHANNEL(_color, _si) { \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .channel2 = IIO_MOD_LIGHT_##_color, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +static const struct iio_chan_spec isl29125_channels[] = { + ISL29125_CHANNEL(GREEN, 0), + ISL29125_CHANNEL(RED, 1), + ISL29125_CHANNEL(BLUE, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + +static const struct { + u8 mode, data; +} isl29125_regs[] = { + {ISL29125_MODE_G, ISL29125_GREEN_DATA}, + {ISL29125_MODE_R, ISL29125_RED_DATA}, + {ISL29125_MODE_B, ISL29125_BLUE_DATA}, +}; + +static int isl29125_read_data(struct isl29125_data *data, int si) +{ + int tries = 5; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1 | isl29125_regs[si].mode); + if (ret < 0) + return ret; + + msleep(101); + + while (tries--) { + ret = i2c_smbus_read_byte_data(data->client, ISL29125_STATUS); + if (ret < 0) + goto fail; + if (ret & ISL29125_STATUS_CONV) + break; + msleep(20); + } + + if (tries < 0) { + dev_err(&data->client->dev, "data not ready\n"); + ret = -EIO; + goto fail; + } + + ret = i2c_smbus_read_word_data(data->client, isl29125_regs[si].data); + +fail: + i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, data->conf1); + return ret; +} + +static int isl29125_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct isl29125_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + mutex_lock(&data->lock); + ret = isl29125_read_data(data, chan->scan_index); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + if (data->conf1 & ISL29125_MODE_RANGE) + *val2 = 152590; /* 10k lux full range */ + else + *val2 = 5722; /* 375 lux full range */ + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int isl29125_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct isl29125_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + if (val != 0) + return -EINVAL; + if (val2 == 152590) + data->conf1 |= ISL29125_MODE_RANGE; + else if (val2 == 5722) + data->conf1 &= ~ISL29125_MODE_RANGE; + else + return -EINVAL; + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1); + default: + return -EINVAL; + } +} + +static irqreturn_t isl29125_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct isl29125_data *data = iio_priv(indio_dev); + int i, j = 0; + + for_each_set_bit(i, indio_dev->active_scan_mask, + indio_dev->masklength) { + int ret = i2c_smbus_read_word_data(data->client, + isl29125_regs[i].data); + if (ret < 0) + goto done; + + data->buffer[j++] = ret; + } + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_info isl29125_info = { + .read_raw = isl29125_read_raw, + .write_raw = isl29125_write_raw, + .driver_module = THIS_MODULE, +}; + +static int isl29125_buffer_preenable(struct iio_dev *indio_dev) +{ + struct isl29125_data *data = iio_priv(indio_dev); + + data->conf1 |= ISL29125_MODE_RGB; + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1); +} + +static int isl29125_buffer_predisable(struct iio_dev *indio_dev) +{ + struct isl29125_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret < 0) + return ret; + + data->conf1 &= ~ISL29125_MODE_MASK; + data->conf1 |= ISL29125_MODE_PD; + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1); +} + +static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = { + .preenable = isl29125_buffer_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = isl29125_buffer_predisable, +}; + +static int isl29125_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct isl29125_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &isl29125_info; + indio_dev->name = ISL29125_DRV_NAME; + indio_dev->channels = isl29125_channels; + indio_dev->num_channels = ARRAY_SIZE(isl29125_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = i2c_smbus_read_byte_data(data->client, ISL29125_DEVICE_ID); + if (ret < 0) + return ret; + if (ret != ISL29125_ID) + return -ENODEV; + + data->conf1 = ISL29125_MODE_PD | ISL29125_MODE_RANGE; + ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(data->client, ISL29125_STATUS, 0); + if (ret < 0) + return ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + isl29125_trigger_handler, &isl29125_buffer_setup_ops); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + + return 0; + +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; +} + +static int isl29125_powerdown(struct isl29125_data *data) +{ + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + (data->conf1 & ~ISL29125_MODE_MASK) | ISL29125_MODE_PD); +} + +static int isl29125_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + isl29125_powerdown(iio_priv(indio_dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int isl29125_suspend(struct device *dev) +{ + struct isl29125_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + return isl29125_powerdown(data); +} + +static int isl29125_resume(struct device *dev) +{ + struct isl29125_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1, + data->conf1); +} +#endif + +static SIMPLE_DEV_PM_OPS(isl29125_pm_ops, isl29125_suspend, isl29125_resume); + +static const struct i2c_device_id isl29125_id[] = { + { "isl29125", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isl29125_id); + +static struct i2c_driver isl29125_driver = { + .driver = { + .name = ISL29125_DRV_NAME, + .pm = &isl29125_pm_ops, + .owner = THIS_MODULE, + }, + .probe = isl29125_probe, + .remove = isl29125_remove, + .id_table = isl29125_id, +}; +module_i2c_driver(isl29125_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("ISL29125 RGB light sensor driver"); +MODULE_LICENSE("GPL"); From a244e7b57f0fb778bd333b10fffbeb362b94ffc3 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Wed, 7 May 2014 13:38:00 +0100 Subject: [PATCH 08/30] iio: Add driver for AMS/TAOS tcs3414 digital color sensor 16-bit digital color sensor with red, green, blue and clear channel datasheet: http://ams.com/eng/content/download/250258/975997/TCS3414_Datasheet_EN_v1.pdf Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 12 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/tcs3414.c | 405 ++++++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+) create mode 100644 drivers/iio/light/tcs3414.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 7d83dca6d080..bf05ca5b0a57 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -128,6 +128,18 @@ config LTR501 This driver can also be built as a module. If so, the module will be called ltr501. +config TCS3414 + tristate "TAOS TCS3414 digital color sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for the TAOS TCS3414 + family of digital color sensors. + + This driver can also be built as a module. If so, the module + will be called tcs3414. + config TCS3472 tristate "TAOS TCS3472 color light-to-digital converter" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index f3d1857b2083..8b8c09f9c1f8 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ISL29125) += isl29125.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o +obj-$(CONFIG_TCS3414) += tcs3414.o obj-$(CONFIG_TCS3472) += tcs3472.o obj-$(CONFIG_TSL4531) += tsl4531.o obj-$(CONFIG_VCNL4000) += vcnl4000.o diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c new file mode 100644 index 000000000000..a9e449b0be0c --- /dev/null +++ b/drivers/iio/light/tcs3414.c @@ -0,0 +1,405 @@ +/* + * tcs3414.c - Support for TAOS TCS3414 digital color sensor + * + * Copyright (c) 2014 Peter Meerwald + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * Digital color sensor with 16-bit channels for red, green, blue, clear); + * 7-bit I2C slave address 0x39 (TCS3414) or 0x29, 0x49, 0x59 (TCS3413, + * TCS3415, TCS3416, resp.) + * + * TODO: sync, interrupt support, thresholds, prescaler + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TCS3414_DRV_NAME "tcs3414" + +#define TCS3414_COMMAND BIT(7) +#define TCS3414_COMMAND_WORD (TCS3414_COMMAND | BIT(5)) + +#define TCS3414_CONTROL (TCS3414_COMMAND | 0x00) +#define TCS3414_TIMING (TCS3414_COMMAND | 0x01) +#define TCS3414_ID (TCS3414_COMMAND | 0x04) +#define TCS3414_GAIN (TCS3414_COMMAND | 0x07) +#define TCS3414_DATA_GREEN (TCS3414_COMMAND_WORD | 0x10) +#define TCS3414_DATA_RED (TCS3414_COMMAND_WORD | 0x12) +#define TCS3414_DATA_BLUE (TCS3414_COMMAND_WORD | 0x14) +#define TCS3414_DATA_CLEAR (TCS3414_COMMAND_WORD | 0x16) + +#define TCS3414_CONTROL_ADC_VALID BIT(4) +#define TCS3414_CONTROL_ADC_EN BIT(1) +#define TCS3414_CONTROL_POWER BIT(0) + +#define TCS3414_INTEG_MASK GENMASK(1, 0) +#define TCS3414_INTEG_12MS 0x0 +#define TCS3414_INTEG_100MS 0x1 +#define TCS3414_INTEG_400MS 0x2 + +#define TCS3414_GAIN_MASK GENMASK(5, 4) +#define TCS3414_GAIN_SHIFT 4 + +struct tcs3414_data { + struct i2c_client *client; + struct mutex lock; + u8 control; + u8 gain; + u8 timing; + u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */ +}; + +#define TCS3414_CHANNEL(_color, _si, _addr) { \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ + .channel2 = IIO_MOD_LIGHT_##_color, \ + .address = _addr, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +/* scale factors: 1/gain */ +static const int tcs3414_scales[][2] = { + {1, 0}, {0, 250000}, {0, 62500}, {0, 15625} +}; + +/* integration time in ms */ +static const int tcs3414_times[] = { 12, 100, 400 }; + +static const struct iio_chan_spec tcs3414_channels[] = { + TCS3414_CHANNEL(GREEN, 0, TCS3414_DATA_GREEN), + TCS3414_CHANNEL(RED, 1, TCS3414_DATA_RED), + TCS3414_CHANNEL(BLUE, 2, TCS3414_DATA_BLUE), + TCS3414_CHANNEL(CLEAR, 3, TCS3414_DATA_CLEAR), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static int tcs3414_req_data(struct tcs3414_data *data) +{ + int tries = 25; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control | TCS3414_CONTROL_ADC_EN); + if (ret < 0) + return ret; + + while (tries--) { + ret = i2c_smbus_read_byte_data(data->client, TCS3414_CONTROL); + if (ret < 0) + return ret; + if (ret & TCS3414_CONTROL_ADC_VALID) + break; + msleep(20); + } + + ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control); + if (ret < 0) + return ret; + + if (tries < 0) { + dev_err(&data->client->dev, "data not ready\n"); + return -EIO; + } + + return 0; +} + +static int tcs3414_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct tcs3414_data *data = iio_priv(indio_dev); + int i, ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + mutex_lock(&data->lock); + ret = tcs3414_req_data(data); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + ret = i2c_smbus_read_word_data(data->client, chan->address); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT; + *val = tcs3414_scales[i][0]; + *val2 = tcs3414_scales[i][1]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_INT_TIME: + *val = 0; + *val2 = tcs3414_times[data->timing & TCS3414_INTEG_MASK] * 1000; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int tcs3414_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct tcs3414_data *data = iio_priv(indio_dev); + int i; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + for (i = 0; i < ARRAY_SIZE(tcs3414_scales); i++) { + if (val == tcs3414_scales[i][0] && + val2 == tcs3414_scales[i][1]) { + data->gain &= ~TCS3414_GAIN_MASK; + data->gain |= i << TCS3414_GAIN_SHIFT; + return i2c_smbus_write_byte_data( + data->client, TCS3414_GAIN, + data->gain); + } + } + return -EINVAL; + case IIO_CHAN_INFO_INT_TIME: + if (val != 0) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(tcs3414_times); i++) { + if (val == tcs3414_times[i] * 1000) { + data->timing &= ~TCS3414_INTEG_MASK; + data->timing |= i; + return i2c_smbus_write_byte_data( + data->client, TCS3414_TIMING, + data->timing); + } + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static irqreturn_t tcs3414_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct tcs3414_data *data = iio_priv(indio_dev); + int i, j = 0; + + for_each_set_bit(i, indio_dev->active_scan_mask, + indio_dev->masklength) { + int ret = i2c_smbus_read_word_data(data->client, + TCS3414_DATA_GREEN + 2*i); + if (ret < 0) + goto done; + + data->buffer[j++] = ret; + } + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static IIO_CONST_ATTR(scale_available, "1 0.25 0.0625 0.015625"); +static IIO_CONST_ATTR_INT_TIME_AVAIL("0.012 0.1 0.4"); + +static struct attribute *tcs3414_attributes[] = { + &iio_const_attr_scale_available.dev_attr.attr, + &iio_const_attr_integration_time_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group tcs3414_attribute_group = { + .attrs = tcs3414_attributes, +}; + +static const struct iio_info tcs3414_info = { + .read_raw = tcs3414_read_raw, + .write_raw = tcs3414_write_raw, + .attrs = &tcs3414_attribute_group, + .driver_module = THIS_MODULE, +}; + +static int tcs3414_buffer_preenable(struct iio_dev *indio_dev) +{ + struct tcs3414_data *data = iio_priv(indio_dev); + + data->control |= TCS3414_CONTROL_ADC_EN; + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control); +} + +static int tcs3414_buffer_predisable(struct iio_dev *indio_dev) +{ + struct tcs3414_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret < 0) + return ret; + + data->control &= ~TCS3414_CONTROL_ADC_EN; + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control); +} + +static const struct iio_buffer_setup_ops tcs3414_buffer_setup_ops = { + .preenable = tcs3414_buffer_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = tcs3414_buffer_predisable, +}; + +static int tcs3414_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tcs3414_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &tcs3414_info; + indio_dev->name = TCS3414_DRV_NAME; + indio_dev->channels = tcs3414_channels; + indio_dev->num_channels = ARRAY_SIZE(tcs3414_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = i2c_smbus_read_byte_data(data->client, TCS3414_ID); + if (ret < 0) + return ret; + + switch (ret & 0xf0) { + case 0x00: + dev_info(&client->dev, "TCS3404 found\n"); + break; + case 0x10: + dev_info(&client->dev, "TCS3413/14/15/16 found\n"); + break; + default: + return -ENODEV; + } + + data->control = TCS3414_CONTROL_POWER; + ret = i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control); + if (ret < 0) + return ret; + + data->timing = TCS3414_INTEG_12MS; /* free running */ + ret = i2c_smbus_write_byte_data(data->client, TCS3414_TIMING, + data->timing); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, TCS3414_GAIN); + if (ret < 0) + return ret; + data->gain = ret; + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + tcs3414_trigger_handler, &tcs3414_buffer_setup_ops); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto buffer_cleanup; + + return 0; + +buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; +} + +static int tcs3414_powerdown(struct tcs3414_data *data) +{ + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control & ~(TCS3414_CONTROL_POWER | + TCS3414_CONTROL_ADC_EN)); +} + +static int tcs3414_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + tcs3414_powerdown(iio_priv(indio_dev)); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tcs3414_suspend(struct device *dev) +{ + struct tcs3414_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + return tcs3414_powerdown(data); +} + +static int tcs3414_resume(struct device *dev) +{ + struct tcs3414_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + return i2c_smbus_write_byte_data(data->client, TCS3414_CONTROL, + data->control); +} +#endif + +static SIMPLE_DEV_PM_OPS(tcs3414_pm_ops, tcs3414_suspend, tcs3414_resume); + +static const struct i2c_device_id tcs3414_id[] = { + { "tcs3414", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tcs3414_id); + +static struct i2c_driver tcs3414_driver = { + .driver = { + .name = TCS3414_DRV_NAME, + .pm = &tcs3414_pm_ops, + .owner = THIS_MODULE, + }, + .probe = tcs3414_probe, + .remove = tcs3414_remove, + .id_table = tcs3414_id, +}; +module_i2c_driver(tcs3414_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("TCS3414 digital color sensors driver"); +MODULE_LICENSE("GPL"); From 2d239c9e92087d5f4f667371ae350db9f76e3191 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 22 Jun 2014 20:59:00 +0100 Subject: [PATCH 09/30] iio:st sensors: remove custom sampling frequence attribute in favour of core support. This allows in kernel client drivers to access this Signed-off-by: Jonathan Cameron Cc: Denis Ciocca Reviewed-by: Hartmut Knaack --- drivers/iio/accel/st_accel_core.c | 12 ++++++-- .../iio/common/st_sensors/st_sensors_core.c | 29 ------------------- drivers/iio/gyro/st_gyro_core.c | 12 ++++++-- drivers/iio/magnetometer/st_magn_core.c | 12 ++++++-- drivers/iio/pressure/st_pressure_core.c | 27 +++++++++++++++-- include/linux/iio/common/st_sensors.h | 12 +------- 6 files changed, 56 insertions(+), 48 deletions(-) diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index a2abf7c2ce3b..087864854c61 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -393,6 +393,9 @@ static int st_accel_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = adata->current_fullscale->gain; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = adata->odr; + return IIO_VAL_INT; default: return -EINVAL; } @@ -410,6 +413,13 @@ static int st_accel_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: err = st_sensors_set_fullscale_by_gain(indio_dev, val2); break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&indio_dev->mlock); + err = st_sensors_set_odr(indio_dev, val); + mutex_unlock(&indio_dev->mlock); + return err; default: return -EINVAL; } @@ -417,14 +427,12 @@ static int st_accel_write_raw(struct iio_dev *indio_dev, return err; } -static ST_SENSOR_DEV_ATTR_SAMP_FREQ(); static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available); static struct attribute *st_accel_attributes[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_in_accel_scale_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index e8b932fed70e..30fb6407fad0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -463,35 +463,6 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_check_device_support); -ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev)); - - return sprintf(buf, "%d\n", adata->odr); -} -EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency); - -ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - int err; - unsigned int odr; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - - err = kstrtoint(buf, 10, &odr); - if (err < 0) - goto conversion_error; - - mutex_lock(&indio_dev->mlock); - err = st_sensors_set_odr(indio_dev, odr); - mutex_unlock(&indio_dev->mlock); - -conversion_error: - return err < 0 ? err : size; -} -EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency); - ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index ed74a9069989..f156fc6c5c6c 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -245,6 +245,9 @@ static int st_gyro_read_raw(struct iio_dev *indio_dev, *val = 0; *val2 = gdata->current_fullscale->gain; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = gdata->odr; + return IIO_VAL_INT; default: return -EINVAL; } @@ -262,6 +265,13 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: err = st_sensors_set_fullscale_by_gain(indio_dev, val2); break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&indio_dev->mlock); + err = st_sensors_set_odr(indio_dev, val); + mutex_unlock(&indio_dev->mlock); + return err; default: err = -EINVAL; } @@ -269,14 +279,12 @@ static int st_gyro_write_raw(struct iio_dev *indio_dev, return err; } -static ST_SENSOR_DEV_ATTR_SAMP_FREQ(); static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available); static struct attribute *st_gyro_attributes[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index 240a21dd0c61..a4b64130ac2f 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -299,6 +299,9 @@ static int st_magn_read_raw(struct iio_dev *indio_dev, else *val2 = mdata->current_fullscale->gain; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = mdata->odr; + return IIO_VAL_INT; default: return -EINVAL; } @@ -316,6 +319,13 @@ static int st_magn_write_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: err = st_sensors_set_fullscale_by_gain(indio_dev, val2); break; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&indio_dev->mlock); + err = st_sensors_set_odr(indio_dev, val); + mutex_unlock(&indio_dev->mlock); + return err; default: err = -EINVAL; } @@ -323,14 +333,12 @@ static int st_magn_write_raw(struct iio_dev *indio_dev, return err; } -static ST_SENSOR_DEV_ATTR_SAMP_FREQ(); static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available); static struct attribute *st_magn_attributes[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_in_magn_scale_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index cd7e01f3a93b..473d914ef470 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -307,6 +307,27 @@ static const struct st_sensors st_press_sensors[] = { }, }; +static int st_press_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *ch, + int val, + int val2, + long mask) +{ + int err; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + mutex_lock(&indio_dev->mlock); + err = st_sensors_set_odr(indio_dev, val); + mutex_unlock(&indio_dev->mlock); + return err; + default: + return -EINVAL; + } +} + static int st_press_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, int *val, int *val2, long mask) @@ -349,6 +370,9 @@ static int st_press_read_raw(struct iio_dev *indio_dev, } return IIO_VAL_FRACTIONAL; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = pdata->odr; + return IIO_VAL_INT; default: return -EINVAL; } @@ -357,12 +381,10 @@ static int st_press_read_raw(struct iio_dev *indio_dev, return err; } -static ST_SENSOR_DEV_ATTR_SAMP_FREQ(); static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL(); static struct attribute *st_press_attributes[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, NULL, }; @@ -374,6 +396,7 @@ static const struct iio_info press_info = { .driver_module = THIS_MODULE, .attrs = &st_press_attribute_group, .read_raw = &st_press_read_raw, + .write_raw = &st_press_write_raw, }; #ifdef CONFIG_IIO_TRIGGER diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 96f51f0e0096..d8257ab60bac 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -47,6 +47,7 @@ .type = device_type, \ .modified = mod, \ .info_mask_separate = mask, \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = index, \ .channel2 = ch2, \ .address = addr, \ @@ -59,11 +60,6 @@ }, \ } -#define ST_SENSOR_DEV_ATTR_SAMP_FREQ() \ - IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, \ - st_sensors_sysfs_get_sampling_frequency, \ - st_sensors_sysfs_set_sampling_frequency) - #define ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL() \ IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \ st_sensors_sysfs_sampling_frequency_avail) @@ -285,12 +281,6 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev, int st_sensors_check_device_support(struct iio_dev *indio_dev, int num_sensors_list, const struct st_sensors *sensors); -ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev, - struct device_attribute *attr, char *buf); - -ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size); - ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, struct device_attribute *attr, char *buf); From 95bb8918f9bc87a69cb7a795b568e01afecff9cb Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 22 Jun 2014 20:59:00 +0100 Subject: [PATCH 10/30] iio: gyro: itg3200 switch sampling frequency attr to core support. By using the info_mask_shared_by_all element of the channel spec, access to the sampling frequency becomes available to in kernel users of the driver. It also shortens and simplifies the code a little. Signed-off-by: Jonathan Cameron Reviewed-by: Hartmut Knaack Cc: Manuel Stahl Cc: Thorsten Nowak Cc: Christian Strobel --- drivers/iio/gyro/itg3200_core.c | 105 ++++++++++++++------------------ 1 file changed, 45 insertions(+), 60 deletions(-) diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index 8295e318399f..6a8020d48140 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -90,6 +90,7 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, { int ret = 0; u8 reg; + u8 regval; switch (info) { case IIO_CHAN_INFO_RAW: @@ -107,65 +108,60 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, /* Only the temperature channel has an offset */ *val = 23000; return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, ®val); + if (ret) + return ret; + + *val = (regval & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000; + + ret = itg3200_read_reg_8(indio_dev, + ITG3200_REG_SAMPLE_RATE_DIV, + ®val); + if (ret) + return ret; + + *val /= regval + 1; + return IIO_VAL_INT; + default: return -EINVAL; } } -static ssize_t itg3200_read_frequency(struct device *dev, - struct device_attribute *attr, char *buf) +static int itg3200_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - int ret, sps; - u8 val; - - ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &val); - if (ret) - return ret; - - sps = (val & ITG3200_DLPF_CFG_MASK) ? 1000 : 8000; - - ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, &val); - if (ret) - return ret; - - sps /= val + 1; - - return sprintf(buf, "%d\n", sps); -} - -static ssize_t itg3200_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - unsigned val; int ret; u8 t; - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val == 0 || val2 != 0) + return -EINVAL; - mutex_lock(&indio_dev->mlock); + mutex_lock(&indio_dev->mlock); - ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t); - if (ret) - goto err_ret; + ret = itg3200_read_reg_8(indio_dev, ITG3200_REG_DLPF, &t); + if (ret) { + mutex_unlock(&indio_dev->mlock); + return ret; + } + t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1; - if (val == 0) { - ret = -EINVAL; - goto err_ret; + ret = itg3200_write_reg_8(indio_dev, + ITG3200_REG_SAMPLE_RATE_DIV, + t); + + mutex_unlock(&indio_dev->mlock); + return ret; + + default: + return -EINVAL; } - t = ((t & ITG3200_DLPF_CFG_MASK) ? 1000u : 8000u) / val - 1; - - ret = itg3200_write_reg_8(indio_dev, ITG3200_REG_SAMPLE_RATE_DIV, t); - -err_ret: - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; } /* @@ -255,6 +251,7 @@ static int itg3200_initial_setup(struct iio_dev *indio_dev) .channel2 = IIO_MOD_ ## _mod, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = ITG3200_REG_GYRO_ ## _mod ## OUT_H, \ .scan_index = ITG3200_SCAN_GYRO_ ## _mod, \ .scan_type = ITG3200_ST, \ @@ -267,6 +264,7 @@ static const struct iio_chan_spec itg3200_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = ITG3200_REG_TEMP_OUT_H, .scan_index = ITG3200_SCAN_TEMP, .scan_type = ITG3200_ST, @@ -277,22 +275,9 @@ static const struct iio_chan_spec itg3200_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ITG3200_SCAN_ELEMENTS), }; -/* IIO device attributes */ -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, itg3200_read_frequency, - itg3200_write_frequency); - -static struct attribute *itg3200_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - NULL -}; - -static const struct attribute_group itg3200_attribute_group = { - .attrs = itg3200_attributes, -}; - static const struct iio_info itg3200_info = { - .attrs = &itg3200_attribute_group, .read_raw = &itg3200_read_raw, + .write_raw = &itg3200_write_raw, .driver_module = THIS_MODULE, }; From 82695ef549b5299d3d9e088d6648289bda8ef3d8 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 22 Jun 2014 20:59:00 +0100 Subject: [PATCH 11/30] iio: adis: Switch sampling frequency attr to core support. By using the info_mask_shared_by_all element of the channel spec, acce to the sampling frequency becomes available to in kernel users of the driver. It also shortens and simplifies the code. This particular conversion was made more complicated by the shared library and the fact that a number of the drivers do not actually have support for setting or reading the sampling frequency. The hardware, in those cases investigated supports it. It's just never been implemented. Signed-off-by: Jonathan Cameron Reviewed-by: Hartmut Knaack Acked-by: Lars-Peter Clausen --- drivers/iio/gyro/adis16260.c | 124 ++++++++------------- drivers/staging/iio/accel/adis16201_core.c | 14 +-- drivers/staging/iio/accel/adis16203_core.c | 11 +- drivers/staging/iio/accel/adis16204_core.c | 12 +- drivers/staging/iio/accel/adis16209_core.c | 18 +-- drivers/staging/iio/accel/adis16240_core.c | 12 +- include/linux/iio/imu/adis.h | 33 +++--- 7 files changed, 99 insertions(+), 125 deletions(-) diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 22b6fb80fa1a..75fe0edd3d0f 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -101,65 +101,6 @@ #define ADIS16260_SCAN_TEMP 3 #define ADIS16260_SCAN_ANGL 4 -static ssize_t adis16260_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis *adis = iio_priv(indio_dev); - int ret, len = 0; - u16 t; - int sps; - ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &t); - if (ret) - return ret; - - if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */ - sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256; - else - sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048; - sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1; - len = sprintf(buf, "%d\n", sps); - return len; -} - -static ssize_t adis16260_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis *adis = iio_priv(indio_dev); - unsigned int val; - int ret; - u8 t; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - if (spi_get_device_id(adis->spi)->driver_data) - t = 256 / val; - else - t = 2048 / val; - - if (t > ADIS16260_SMPL_PRD_DIV_MASK) - t = ADIS16260_SMPL_PRD_DIV_MASK; - else if (t > 0) - t--; - - if (t >= 0x0A) - adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; - else - adis->spi->max_speed_hz = ADIS16260_SPI_FAST; - ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); - - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - /* Power down the device */ static int adis16260_stop_device(struct iio_dev *indio_dev) { @@ -174,18 +115,19 @@ static int adis16260_stop_device(struct iio_dev *indio_dev) return ret; } -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16260_read_frequency, - adis16260_write_frequency); - static const struct iio_chan_spec adis16260_channels[] = { ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO, BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_CALIBSCALE), 14), - ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, 14), - ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, 12), - ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, 12), - ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, 12), + BIT(IIO_CHAN_INFO_CALIBSCALE), + BIT(IIO_CHAN_INFO_SAMP_FREQ), 14), + ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0, + BIT(IIO_CHAN_INFO_SAMP_FREQ), 14), + ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP, + BIT(IIO_CHAN_INFO_SAMP_FREQ), 12), + ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY, + BIT(IIO_CHAN_INFO_SAMP_FREQ), 12), + ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC, + BIT(IIO_CHAN_INFO_SAMP_FREQ), 12), IIO_CHAN_SOFT_TIMESTAMP(5), }; @@ -258,6 +200,20 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, *val = val16; return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16); + if (ret) + return ret; + + if (spi_get_device_id(adis->spi)->driver_data) + /* If an adis16251 */ + *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ? + 8 : 256; + else + *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ? + 66 : 2048; + *val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1; + return IIO_VAL_INT; } return -EINVAL; } @@ -269,7 +225,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, long mask) { struct adis *adis = iio_priv(indio_dev); + int ret; u8 addr; + u8 t; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: @@ -284,21 +242,31 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, addr = adis16260_addresses[chan->scan_index][1]; return adis_write_reg_16(adis, addr, val); + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&indio_dev->mlock); + if (spi_get_device_id(adis->spi)->driver_data) + t = 256 / val; + else + t = 2048 / val; + + if (t > ADIS16260_SMPL_PRD_DIV_MASK) + t = ADIS16260_SMPL_PRD_DIV_MASK; + else if (t > 0) + t--; + + if (t >= 0x0A) + adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; + else + adis->spi->max_speed_hz = ADIS16260_SPI_FAST; + ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); + + mutex_unlock(&indio_dev->mlock); + return ret; } return -EINVAL; } -static struct attribute *adis16260_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16260_attribute_group = { - .attrs = adis16260_attributes, -}; - static const struct iio_info adis16260_info = { - .attrs = &adis16260_attribute_group, .read_raw = &adis16260_read_raw, .write_raw = &adis16260_write_raw, .update_scan_mode = adis_update_scan_mode, diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 2105576fa77c..50ba1fa7f98a 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -131,17 +131,17 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16201_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 12), - ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT, ADIS16201_SCAN_SUPPLY, 0, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT, ADIS16201_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT, ADIS16201_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT, ADIS16201_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), - ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 12), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC, ADIS16201_SCAN_AUX_ADC, 0, 12), ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT, ADIS16201_SCAN_INCLI_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT, ADIS16201_SCAN_INCLI_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), IIO_CHAN_SOFT_TIMESTAMP(7) }; diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 409a28ed9043..f472137b0069 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -99,13 +99,14 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16203_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 12), - ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 12), + ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12), + ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12), ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), /* Fixme: Not what it appears to be - see data sheet */ - ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 0, 14), - ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 12), + ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, + 0, 0, 14), + ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12), IIO_CHAN_SOFT_TIMESTAMP(5), }; diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index b8ea76857cd6..19eaebc77d7a 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -136,15 +136,15 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16204_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 12), - ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 12), - ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12), + ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12), + ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 14), ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT, - ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 14), + ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14), IIO_CHAN_SOFT_TIMESTAMP(5), }; diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 4492e51d8886..374dc6edbcf5 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -130,16 +130,18 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16209_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 14), - ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 12), + ADIS_SUPPLY_CHAN(ADIS16209_SUPPLY_OUT, ADIS16209_SCAN_SUPPLY, 0, 14), + ADIS_TEMP_CHAN(ADIS16209_TEMP_OUT, ADIS16209_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16209_XACCL_OUT, ADIS16209_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16209_YACCL_OUT, ADIS16209_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS), 14), - ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 12), - ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, 0, 14), - ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, 0, 14), - ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 14), + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), + ADIS_AUX_ADC_CHAN(ADIS16209_AUX_ADC, ADIS16209_SCAN_AUX_ADC, 0, 12), + ADIS_INCLI_CHAN(X, ADIS16209_XINCL_OUT, ADIS16209_SCAN_INCLI_X, + 0, 0, 14), + ADIS_INCLI_CHAN(Y, ADIS16209_YINCL_OUT, ADIS16209_SCAN_INCLI_Y, + 0, 0, 14), + ADIS_ROT_CHAN(X, ADIS16209_ROT_OUT, ADIS16209_SCAN_ROT, 0, 0, 14), IIO_CHAN_SOFT_TIMESTAMP(8) }; diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 3a303a03d028..74ace2a8769d 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -173,15 +173,15 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, } static const struct iio_chan_spec adis16240_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 10), - ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 10), + ADIS_SUPPLY_CHAN(ADIS16240_SUPPLY_OUT, ADIS16240_SCAN_SUPPLY, 0, 10), + ADIS_AUX_ADC_CHAN(ADIS16240_AUX_ADC, ADIS16240_SCAN_AUX_ADC, 0, 10), ADIS_ACCEL_CHAN(X, ADIS16240_XACCL_OUT, ADIS16240_SCAN_ACC_X, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), ADIS_ACCEL_CHAN(Y, ADIS16240_YACCL_OUT, ADIS16240_SCAN_ACC_Y, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), ADIS_ACCEL_CHAN(Z, ADIS16240_ZACCL_OUT, ADIS16240_SCAN_ACC_Z, - BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 10), - ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 10), + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK), 0, 10), + ADIS_TEMP_CHAN(ADIS16240_TEMP_OUT, ADIS16240_SCAN_TEMP, 0, 10), IIO_CHAN_SOFT_TIMESTAMP(6) }; diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index b665dc7f017b..fa2d01ef8f55 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -157,13 +157,14 @@ int adis_single_conversion(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, unsigned int error_mask, int *val); -#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, bits) { \ +#define ADIS_VOLTAGE_CHAN(addr, si, chan, name, info_all, bits) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = (chan), \ .extend_name = name, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = info_all, \ .address = (addr), \ .scan_index = (si), \ .scan_type = { \ @@ -174,19 +175,20 @@ int adis_single_conversion(struct iio_dev *indio_dev, }, \ } -#define ADIS_SUPPLY_CHAN(addr, si, bits) \ - ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", bits) +#define ADIS_SUPPLY_CHAN(addr, si, info_all, bits) \ + ADIS_VOLTAGE_CHAN(addr, si, 0, "supply", info_all, bits) -#define ADIS_AUX_ADC_CHAN(addr, si, bits) \ - ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, bits) +#define ADIS_AUX_ADC_CHAN(addr, si, info_all, bits) \ + ADIS_VOLTAGE_CHAN(addr, si, 1, NULL, info_all, bits) -#define ADIS_TEMP_CHAN(addr, si, bits) { \ +#define ADIS_TEMP_CHAN(addr, si, info_all, bits) { \ .type = IIO_TEMP, \ .indexed = 1, \ .channel = 0, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = info_all, \ .address = (addr), \ .scan_index = (si), \ .scan_type = { \ @@ -197,13 +199,14 @@ int adis_single_conversion(struct iio_dev *indio_dev, }, \ } -#define ADIS_MOD_CHAN(_type, mod, addr, si, info_sep, bits) { \ +#define ADIS_MOD_CHAN(_type, mod, addr, si, info_sep, info_all, bits) { \ .type = (_type), \ .modified = 1, \ .channel2 = IIO_MOD_ ## mod, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ info_sep, \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = info_all, \ .address = (addr), \ .scan_index = (si), \ .scan_type = { \ @@ -214,17 +217,17 @@ int adis_single_conversion(struct iio_dev *indio_dev, }, \ } -#define ADIS_ACCEL_CHAN(mod, addr, si, info_sep, bits) \ - ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info_sep, bits) +#define ADIS_ACCEL_CHAN(mod, addr, si, info_sep, info_all, bits) \ + ADIS_MOD_CHAN(IIO_ACCEL, mod, addr, si, info_sep, info_all, bits) -#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, bits) \ - ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info_sep, bits) +#define ADIS_GYRO_CHAN(mod, addr, si, info_sep, info_all, bits) \ + ADIS_MOD_CHAN(IIO_ANGL_VEL, mod, addr, si, info_sep, info_all, bits) -#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, bits) \ - ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info_sep, bits) +#define ADIS_INCLI_CHAN(mod, addr, si, info_sep, info_all, bits) \ + ADIS_MOD_CHAN(IIO_INCLI, mod, addr, si, info_sep, info_all, bits) -#define ADIS_ROT_CHAN(mod, addr, si, info_sep, bits) \ - ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, bits) +#define ADIS_ROT_CHAN(mod, addr, si, info_sep, info_all, bits) \ + ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, info_all, bits) #ifdef CONFIG_IIO_ADIS_LIB_BUFFER From a07a97d0493446566b25d4a966b5e4792c1ba8a3 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 22 Jun 2014 20:59:00 +0100 Subject: [PATCH 12/30] iio: imu: adis16400 switch sampling frequency attr to core support. By using the info_mask_shared_by_all element of the channel spec, access to the sampling frequency becomes available to in kernel users of the driver. It also shortens and simplifies the code. Signed-off-by: Jonathan Cameron Reviewed-by: Hartmut Knaack Acked-by: Lars-Peter Clausen --- drivers/iio/imu/adis16400_core.c | 78 ++++++++++---------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c index 433583b6f800..b70873de04ea 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400_core.c @@ -214,21 +214,6 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); } -static ssize_t adis16400_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis16400_state *st = iio_priv(indio_dev); - int ret; - - ret = st->variant->get_freq(st); - if (ret < 0) - return ret; - - return sprintf(buf, "%d.%.3d\n", ret / 1000, ret % 1000); -} - static const unsigned adis16400_3db_divisors[] = { [0] = 2, /* Special case */ [1] = 6, @@ -260,30 +245,6 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) return ret; } -static ssize_t adis16400_write_frequency(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis16400_state *st = iio_priv(indio_dev); - int i, f, val; - int ret; - - ret = iio_str_to_fixpoint(buf, 100, &i, &f); - if (ret) - return ret; - - val = i * 1000 + f; - - if (val <= 0) - return -EINVAL; - - mutex_lock(&indio_dev->mlock); - st->variant->set_freq(st, val); - mutex_unlock(&indio_dev->mlock); - - return len; -} - /* Power down the device */ static int adis16400_stop_device(struct iio_dev *indio_dev) { @@ -350,10 +311,6 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) return ret; } -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16400_read_frequency, - adis16400_write_frequency); - static const uint8_t adis16400_addresses[] = { [ADIS16400_SCAN_GYRO_X] = ADIS16400_XGYRO_OFF, [ADIS16400_SCAN_GYRO_Y] = ADIS16400_YGYRO_OFF, @@ -394,6 +351,16 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, val * 1000 + val2 / 1000); mutex_unlock(&indio_dev->mlock); return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + sps = val * 1000 + val2 / 1000; + + if (sps <= 0) + return -EINVAL; + + mutex_lock(&indio_dev->mlock); + ret = st->variant->set_freq(st, sps); + mutex_unlock(&indio_dev->mlock); + return ret; default: return -EINVAL; } @@ -474,6 +441,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = st->variant->get_freq(st); + if (ret < 0) + return ret; + *val = ret / 1000; + *val2 = (ret % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -486,6 +460,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, .extend_name = name, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = (si), \ .scan_type = { \ @@ -511,6 +486,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = addr, \ .scan_index = ADIS16400_SCAN_GYRO_ ## mod, \ .scan_type = { \ @@ -530,6 +506,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = ADIS16400_SCAN_ACC_ ## mod, \ .scan_type = { \ @@ -548,6 +525,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = ADIS16400_SCAN_MAGN_ ## mod, \ .scan_type = { \ @@ -573,6 +551,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = ADIS16350_SCAN_TEMP_ ## mod, \ .scan_type = { \ @@ -591,6 +570,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_OFFSET) | \ BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = ADIS16350_SCAN_TEMP_X, \ .scan_type = { \ @@ -608,6 +588,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, .channel2 = IIO_MOD_ ## mod, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (addr), \ .scan_index = ADIS16300_SCAN_INCLI_ ## mod, \ .scan_type = { \ @@ -649,6 +630,7 @@ static const struct iio_chan_spec adis16448_channels[] = { .type = IIO_PRESSURE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = ADIS16448_BARO_OUT, .scan_index = ADIS16400_SCAN_BARO, .scan_type = { @@ -704,15 +686,6 @@ static const struct iio_chan_spec adis16334_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; -static struct attribute *adis16400_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16400_attribute_group = { - .attrs = adis16400_attributes, -}; - static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, @@ -813,7 +786,6 @@ static const struct iio_info adis16400_info = { .driver_module = THIS_MODULE, .read_raw = &adis16400_read_raw, .write_raw = &adis16400_write_raw, - .attrs = &adis16400_attribute_group, .update_scan_mode = adis16400_update_scan_mode, .debugfs_reg_access = adis_debugfs_reg_access, }; From e4f959390178987f3ad73ff89c6918e564172359 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 22 Jun 2014 20:59:00 +0100 Subject: [PATCH 13/30] iio: imu: adis16480 switch sampling frequency attr to core support By using the info_mask_shared_by_all element of the channel spec, access to the sampling frequency becomes available to in kernel users of the driver. It also shortens and simplifies the code. Signed-off-by: Jonathan Cameron Reviewed-by: Hartmut Knaack Acked-by: Lars-Peter Clausen --- drivers/iio/imu/adis16480.c | 82 ++++++++++--------------------------- 1 file changed, 22 insertions(+), 60 deletions(-) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index dd4206cac62d..989605dd6f78 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -257,11 +257,16 @@ static int adis16480_debugfs_init(struct iio_dev *indio_dev) #endif -static int adis16480_set_freq(struct adis16480 *st, unsigned int freq) +static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2) { + struct adis16480 *st = iio_priv(indio_dev); unsigned int t; - t = 2460000 / freq; + t = val * 1000 + val2 / 1000; + if (t <= 0) + return -EINVAL; + + t = 2460000 / t; if (t > 2048) t = 2048; @@ -271,65 +276,24 @@ static int adis16480_set_freq(struct adis16480 *st, unsigned int freq) return adis_write_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, t); } -static int adis16480_get_freq(struct adis16480 *st, unsigned int *freq) +static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2) { + struct adis16480 *st = iio_priv(indio_dev); uint16_t t; int ret; + unsigned freq; ret = adis_read_reg_16(&st->adis, ADIS16480_REG_DEC_RATE, &t); if (ret < 0) return ret; - *freq = 2460000 / (t + 1); + freq = 2460000 / (t + 1); + *val = freq / 1000; + *val2 = (freq % 1000) * 1000; - return 0; + return IIO_VAL_INT_PLUS_MICRO; } -static ssize_t adis16480_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis16480 *st = iio_priv(indio_dev); - unsigned int freq; - int ret; - - ret = adis16480_get_freq(st, &freq); - if (ret < 0) - return ret; - - return sprintf(buf, "%d.%.3d\n", freq / 1000, freq % 1000); -} - -static ssize_t adis16480_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adis16480 *st = iio_priv(indio_dev); - int freq_int, freq_fract; - long val; - int ret; - - ret = iio_str_to_fixpoint(buf, 100, &freq_int, &freq_fract); - if (ret) - return ret; - - val = freq_int * 1000 + freq_fract; - - if (val <= 0) - return -EINVAL; - - ret = adis16480_set_freq(st, val); - - return ret ? ret : len; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16480_read_frequency, - adis16480_write_frequency); - enum { ADIS16480_SCAN_GYRO_X, ADIS16480_SCAN_GYRO_Y, @@ -571,6 +535,8 @@ static int adis16480_read_raw(struct iio_dev *indio_dev, return adis16480_get_calibscale(indio_dev, chan, val); case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: return adis16480_get_filter_freq(indio_dev, chan, val); + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16480_get_freq(indio_dev, val, val2); default: return -EINVAL; } @@ -586,6 +552,9 @@ static int adis16480_write_raw(struct iio_dev *indio_dev, return adis16480_set_calibscale(indio_dev, chan, val); case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: return adis16480_set_filter_freq(indio_dev, chan, val); + case IIO_CHAN_INFO_SAMP_FREQ: + return adis16480_set_freq(indio_dev, val, val2); + default: return -EINVAL; } @@ -600,6 +569,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_CALIBBIAS) | \ _info_sep, \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = (_address), \ .scan_index = (_si), \ .scan_type = { \ @@ -638,6 +608,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_CALIBBIAS) | \ BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = ADIS16480_REG_BAROM_OUT, \ .scan_index = ADIS16480_SCAN_BARO, \ .scan_type = { \ @@ -655,6 +626,7 @@ static int adis16480_write_raw(struct iio_dev *indio_dev, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .address = ADIS16480_REG_TEMP_OUT, \ .scan_index = ADIS16480_SCAN_TEMP, \ .scan_type = { \ @@ -717,17 +689,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { }, }; -static struct attribute *adis16480_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16480_attribute_group = { - .attrs = adis16480_attributes, -}; - static const struct iio_info adis16480_info = { - .attrs = &adis16480_attribute_group, .read_raw = &adis16480_read_raw, .write_raw = &adis16480_write_raw, .update_scan_mode = adis_update_scan_mode, From 3ce85cc4fbb71739f98806b9c9d63950a60cd8ae Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 7 Jul 2014 10:47:00 +0100 Subject: [PATCH 14/30] iio: st_sensors: get platform data from device tree Currently the STMicroelectronics sensors only support one single platform data item: configuration of the DRDY (data ready) pin for a particular design. Augment the core to prioritize and take this information from the device tree if the parent device has an assigned device node, else fall back to passed in platform data (usually the default data). Cc: Lee Jones Cc: Denis CIOCCA Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../iio/common/st_sensors/st_sensors_core.c | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 30fb6407fad0..8a4ec00a91a0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -14,8 +14,8 @@ #include #include #include +#include #include - #include @@ -265,14 +265,47 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, return 0; } +#ifdef CONFIG_OF +static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, + struct st_sensors_platform_data *defdata) +{ + struct st_sensors_platform_data *pdata; + struct device_node *np = dev->of_node; + u32 val; + + if (!np) + return NULL; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) + pdata->drdy_int_pin = (u8) val; + else + pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 1; + + return pdata; +} +#else +static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, + struct st_sensors_platform_data *defdata) +{ + return NULL; +} +#endif + int st_sensors_init_sensor(struct iio_dev *indio_dev, struct st_sensors_platform_data *pdata) { struct st_sensor_data *sdata = iio_priv(indio_dev); + struct st_sensors_platform_data *of_pdata; int err = 0; mutex_init(&sdata->tb.buf_lock); + /* If OF/DT pdata exists, it will take precedence of anything else */ + of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata); + if (of_pdata) + pdata = of_pdata; + if (pdata) err = st_sensors_set_drdy_int_pin(indio_dev, pdata); From 0599173e38fe59b64963b9c39d0727c45e6ebefc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 7 Jul 2014 10:48:00 +0100 Subject: [PATCH 15/30] iio: st_sensors: add device tree bindings This adds some basic, simple device tree bindings to the STMicro MEMS sensor drivers. Cc: devicetree@vger.kernel.org Cc: Lee Jones Cc: Denis CIOCCA Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/st-sensors.txt | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/st-sensors.txt diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt new file mode 100644 index 000000000000..a7a0a15913ad --- /dev/null +++ b/Documentation/devicetree/bindings/iio/st-sensors.txt @@ -0,0 +1,54 @@ +STMicroelectronics MEMS sensors + +The STMicroelectronics sensor devices are pretty straight-forward I2C or +SPI devices, all sharing the same device tree descriptions no matter what +type of sensor it is. + +Required properties: +- compatible: see the list of valid compatible strings below +- reg: the I2C or SPI address the device will respond to + +Optional properties: +- vdd-supply: an optional regulator that needs to be on to provide VDD + power to the sensor. +- vddio-supply: an optional regulator that needs to be on to provide the + VDD IO power to the sensor. +- st,drdy-int-pin: the pin on the package that will be used to signal + "data ready" (valid values: 1 or 2). This property is not configurable + on all sensors. + +Sensors may also have applicable pin control settings, those use the +standard bindings from pinctrl/pinctrl-bindings.txt. + +Valid compatible strings: + +Accelerometers: +- st,lsm303dlh-accel +- st,lsm303dlhc-accel +- st,lis3dh-accel +- st,lsm330d-accel +- st,lsm330dl-accel +- st,lsm330dlc-accel +- st,lis331dlh-accel +- st,lsm303dl-accel +- st,lsm303dlm-accel +- st,lsm330-accel + +Gyroscopes: +- st,l3g4200d-gyro +- st,lsm330d-gyro +- st,lsm330dl-gyro +- st,lsm330dlc-gyro +- st,l3gd20-gyro +- st,l3g4is-gyro +- st,lsm330-gyro + +Magnetometers: +- st,lsm303dlhc-magn +- st,lsm303dlm-magn +- st,lis3mdl-magn + +Pressure sensors: +- st,lps001wp-press +- st,lps25h-press +- st,lps331ap-press From fb123a6b6b893e8461c17a6d068fd6e1671cf0de Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 30 Jun 2014 10:29:00 +0100 Subject: [PATCH 16/30] iio: hid-sensors: make hid_sensor_get_reporting_interval static This fixes the following sparse warning: CHECK drivers/iio/common/hid-sensors/hid-sensor-attributes.c drivers/iio/common/hid-sensors/hid-sensor-attributes.c:346:5: warning: symbol 'hid_sensor_get_reporting_interval' was not declared. Should it be static? Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/common/hid-sensors/hid-sensor-attributes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index 1614340e5733..25b01e156d82 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -343,6 +343,7 @@ int hid_sensor_format_scale(u32 usage_id, } EXPORT_SYMBOL(hid_sensor_format_scale); +static int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev, u32 usage_id, struct hid_sensor_common *st) From 260974704ea4c01fb21166182e8b0cf266cbd77a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 7 Mar 2014 12:56:00 +0000 Subject: [PATCH 17/30] staging: iio: ad9832: Remove redundant check 'val' is unsigned and cannot be negative. Signed-off-by: Sachin Kamat Cc: Michael Hennerich Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9832.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c index b7c8351ce2ff..cf68159a5848 100644 --- a/drivers/staging/iio/frequency/ad9832.c +++ b/drivers/staging/iio/frequency/ad9832.c @@ -120,7 +120,7 @@ static ssize_t ad9832_write(struct device *dev, struct device_attribute *attr, ret = spi_sync(st->spi, &st->msg); break; case AD9832_PHASE_SYM: - if (val < 0 || val > 3) { + if (val > 3) { ret = -EINVAL; break; } From 49f681fab6a1e8e9d354bba692ba17cdcaa1fb1e Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 7 Jul 2014 15:12:00 +0100 Subject: [PATCH 18/30] staging: iio: remove duplicate case labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, compiling iio_event_monitor program fails: io_event_monitor.c: In function ‘event_is_known’: iio_event_monitor.c:125:2: error: duplicate case value case IIO_MOD_LIGHT_BOTH: ^ iio_event_monitor.c:121:2: error: previously used here case IIO_MOD_LIGHT_BOTH: Fixes: da4db94 (iio staging: add recently added modifiers to iio_event_monitor) Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/staging/iio/Documentation/iio_event_monitor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index cb35a97f00c3..569d6f8face5 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -122,8 +122,6 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_LIGHT_IR: case IIO_MOD_ROOT_SUM_SQUARED_X_Y: case IIO_MOD_SUM_SQUARED_X_Y_Z: - case IIO_MOD_LIGHT_BOTH: - case IIO_MOD_LIGHT_IR: case IIO_MOD_LIGHT_CLEAR: case IIO_MOD_LIGHT_RED: case IIO_MOD_LIGHT_GREEN: From 744966d6dc7d9945d8b9cc511d98a0ec5aeee9ed Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Tue, 7 Jan 2014 19:44:00 +0000 Subject: [PATCH 19/30] staging: iio: Introduce the use of devm_ioremap_resource This patch introduces the use of devm_ioremap_resource. It does away with call to request_mem_region and the error checking on platform_get_resource. Also, the calls to free the allocated resources like release_mem_region and iounmap are done away with. The ret variable in the probe function is also eliminated. Also, a bug is fixed as the goto in the error handling of request_mem_region should not have called release_mem_region which releases a resource that has not been allocated. Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_par.c | 37 +++++----------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 8a48d18de788..7511839ba94e 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -53,7 +53,7 @@ static int ad7606_par_probe(struct platform_device *pdev) struct iio_dev *indio_dev; void __iomem *addr; resource_size_t remap_size; - int ret, irq; + int irq; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -62,56 +62,31 @@ static int ad7606_par_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return PTR_ERR(addr); remap_size = resource_size(res); - /* Request the regions */ - if (!request_mem_region(res->start, remap_size, "iio-ad7606")) { - ret = -EBUSY; - goto out1; - } - addr = ioremap(res->start, remap_size); - if (!addr) { - ret = -ENOMEM; - goto out1; - } - indio_dev = ad7606_probe(&pdev->dev, irq, addr, platform_get_device_id(pdev)->driver_data, remap_size > 1 ? &ad7606_par16_bops : &ad7606_par8_bops); - if (IS_ERR(indio_dev)) { - ret = PTR_ERR(indio_dev); - goto out2; - } + if (IS_ERR(indio_dev)) + return PTR_ERR(indio_dev); platform_set_drvdata(pdev, indio_dev); return 0; - -out2: - iounmap(addr); -out1: - release_mem_region(res->start, remap_size); - - return ret; } static int ad7606_par_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct resource *res; - struct ad7606_state *st = iio_priv(indio_dev); ad7606_remove(indio_dev, platform_get_irq(pdev, 0)); - iounmap(st->base_address); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - return 0; } From f64c3052b62ca6684f43f923dcc19fefcc8606c2 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Tue, 7 Jan 2014 22:19:00 +0000 Subject: [PATCH 20/30] iio:trigger: Introduce the use of devm_kzalloc This patch introduces the use of the managed version of kzalloc and removes the kfrees in the probe and remove functions. More return paths are added and the labels are renamed to order them. Signed-off-by: Himangi Saraogi Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- .../staging/iio/trigger/iio-trig-bfin-timer.c | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c index 16f1a06bcd89..a21b7c514776 100644 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c @@ -182,45 +182,40 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) unsigned int config; int ret; - st = kzalloc(sizeof(*st), GFP_KERNEL); - if (st == NULL) { - ret = -ENOMEM; - goto out; - } + st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); + if (st == NULL) + return -ENOMEM; st->irq = platform_get_irq(pdev, 0); if (!st->irq) { dev_err(&pdev->dev, "No IRQs specified"); - ret = -ENODEV; - goto out1; + return -ENODEV; } ret = iio_bfin_tmr_get_number(st->irq); if (ret < 0) - goto out1; + return ret; st->timer_num = ret; st->t = &iio_bfin_timer_code[st->timer_num]; st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); - if (!st->trig) { - ret = -ENOMEM; - goto out1; - } + if (!st->trig) + return -ENOMEM; st->trig->ops = &iio_bfin_tmr_trigger_ops; st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; iio_trigger_set_drvdata(st->trig, st); ret = iio_trigger_register(st->trig); if (ret) - goto out2; + goto out; ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr, 0, st->trig->name, st); if (ret) { dev_err(&pdev->dev, "request IRQ-%d failed", st->irq); - goto out4; + goto out1; } config = PWM_OUT | PERIOD_CNT | IRQ_ENA; @@ -260,13 +255,10 @@ static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) return 0; out_free_irq: free_irq(st->irq, st); -out4: - iio_trigger_unregister(st->trig); -out2: - iio_trigger_put(st->trig); out1: - kfree(st); + iio_trigger_unregister(st->trig); out: + iio_trigger_put(st->trig); return ret; } @@ -280,7 +272,6 @@ static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) free_irq(st->irq, st); iio_trigger_unregister(st->trig); iio_trigger_put(st->trig); - kfree(st); return 0; } From 48d58a58dc37fd7d53745738512ebee30b5f7f41 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 7 Aug 2014 12:06:00 +0100 Subject: [PATCH 21/30] staging:iio:ad7291 remove double define Remove second instance of definition of AD7291_BITS. Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 357cef2a6f4c..e6ef35c24061 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -73,8 +73,6 @@ #define AD7291_T_VALUE_FLOAT_OFFSET 2 #define AD7291_T_VALUE_FLOAT_MASK 0x2 -#define AD7291_BITS 12 - struct ad7291_chip_info { struct i2c_client *client; struct regulator *reg; From 975d98cef83043d3aad3ec3f4554494071a01531 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 7 Aug 2014 12:06:00 +0100 Subject: [PATCH 22/30] staging:iio:ad7291 fix coding style Fix indention and comment style. Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index e6ef35c24061..0de28d81490e 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -31,7 +31,6 @@ * is in the read mask. * * The noise-delayed bit as per datasheet suggestion is always enabled. - * */ /* @@ -163,7 +162,8 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) } static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan, - enum iio_event_direction dir, enum iio_event_info info) + enum iio_event_direction dir, + enum iio_event_info info) { unsigned int offset; @@ -180,14 +180,14 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan, switch (info) { case IIO_EV_INFO_VALUE: - if (dir == IIO_EV_DIR_FALLING) - return AD7291_DATA_HIGH(offset); - else - return AD7291_DATA_LOW(offset); + if (dir == IIO_EV_DIR_FALLING) + return AD7291_DATA_HIGH(offset); + else + return AD7291_DATA_LOW(offset); case IIO_EV_INFO_HYSTERESIS: - return AD7291_HYST(offset); + return AD7291_HYST(offset); default: - break; + break; } return 0; } @@ -204,7 +204,7 @@ static int ad7291_read_event_value(struct iio_dev *indio_dev, u16 uval; ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info), - &uval); + &uval); if (ret < 0) return ret; @@ -235,7 +235,7 @@ static int ad7291_write_event_value(struct iio_dev *indio_dev, } return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info), - val); + val); } static int ad7291_read_event_config(struct iio_dev *indio_dev, @@ -244,8 +244,10 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct ad7291_chip_info *chip = iio_priv(indio_dev); - /* To be enabled the channel must simply be on. If any are enabled - we are in continuous sampling mode */ + /* + * To be enabled the channel must simply be on. If any are enabled + * we are in continuous sampling mode + */ switch (chan->type) { case IIO_VOLTAGE: @@ -342,7 +344,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, } /* Read voltage */ ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_VOLTAGE); + AD7291_VOLTAGE); if (ret < 0) { mutex_unlock(&chip->state_lock); return ret; @@ -353,7 +355,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, case IIO_TEMP: /* Assumes tsense bit of command register always set */ ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_T_SENSE); + AD7291_T_SENSE); if (ret < 0) return ret; *val = sign_extend32(ret, 11); @@ -363,7 +365,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, } case IIO_CHAN_INFO_AVERAGE_RAW: ret = i2c_smbus_read_word_swapped(chip->client, - AD7291_T_AVERAGE); + AD7291_T_AVERAGE); if (ret < 0) return ret; *val = sign_extend32(ret, 11); @@ -458,7 +460,7 @@ static const struct iio_info ad7291_info = { }; static int ad7291_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct ad7291_platform_data *pdata = client->dev.platform_data; struct ad7291_chip_info *chip; From 5714d0c13a34e04436974b61a3bc805fd055459a Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 7 Aug 2014 12:06:00 +0100 Subject: [PATCH 23/30] staging:iio:ad7291 cleanup defines Use BIT and GENMASK, remove unused defines, use AD7291_VOLTAGE_OFFSET definition and move AD7291_BITS. Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 0de28d81490e..0ec6454b33a1 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -46,31 +46,27 @@ #define AD7291_VOLTAGE_ALERT_STATUS 0x1F #define AD7291_T_ALERT_STATUS 0x20 +#define AD7291_BITS 12 #define AD7291_VOLTAGE_LIMIT_COUNT 8 /* * AD7291 command */ -#define AD7291_AUTOCYCLE (1 << 0) -#define AD7291_RESET (1 << 1) -#define AD7291_ALERT_CLEAR (1 << 2) -#define AD7291_ALERT_POLARITY (1 << 3) -#define AD7291_EXT_REF (1 << 4) -#define AD7291_NOISE_DELAY (1 << 5) -#define AD7291_T_SENSE_MASK (1 << 7) -#define AD7291_VOLTAGE_MASK 0xFF00 -#define AD7291_VOLTAGE_OFFSET 0x8 +#define AD7291_AUTOCYCLE BIT(0) +#define AD7291_RESET BIT(1) +#define AD7291_ALERT_CLEAR BIT(2) +#define AD7291_ALERT_POLARITY BIT(3) +#define AD7291_EXT_REF BIT(4) +#define AD7291_NOISE_DELAY BIT(5) +#define AD7291_T_SENSE_MASK BIT(7) +#define AD7291_VOLTAGE_MASK GENMASK(15, 8) +#define AD7291_VOLTAGE_OFFSET 8 /* * AD7291 value masks */ -#define AD7291_CHANNEL_MASK 0xF000 -#define AD7291_BITS 12 -#define AD7291_VALUE_MASK 0xFFF -#define AD7291_T_VALUE_SIGN 0x400 -#define AD7291_T_VALUE_FLOAT_OFFSET 2 -#define AD7291_T_VALUE_FLOAT_MASK 0x2 +#define AD7291_VALUE_MASK GENMASK(11, 0) struct ad7291_chip_info { struct i2c_client *client; @@ -172,7 +168,7 @@ static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan, offset = chan->channel; break; case IIO_TEMP: - offset = 8; + offset = AD7291_VOLTAGE_OFFSET; break; default: return 0; @@ -251,7 +247,7 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev, switch (chan->type) { case IIO_VOLTAGE: - if (chip->c_mask & (1 << (15 - chan->channel))) + if (chip->c_mask & BIT(15 - chan->channel)) return 1; else return 0; @@ -336,7 +332,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, } /* Enable this channel alone */ regval = chip->command & (~AD7291_VOLTAGE_MASK); - regval |= 1 << (15 - chan->channel); + regval |= BIT(15 - chan->channel); ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval); if (ret < 0) { mutex_unlock(&chip->state_lock); From 8a32f65f389396267ae50a78d3416bcac5d4d959 Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 7 Aug 2014 12:06:00 +0100 Subject: [PATCH 24/30] staging:iio:ad7291 faciliate ad7291_read_event_config() Save some lines in returning a voltage event. Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 0ec6454b33a1..40f1cea25e1f 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -247,10 +247,7 @@ static int ad7291_read_event_config(struct iio_dev *indio_dev, switch (chan->type) { case IIO_VOLTAGE: - if (chip->c_mask & BIT(15 - chan->channel)) - return 1; - else - return 0; + return !!(chip->c_mask & BIT(15 - chan->channel)); case IIO_TEMP: /* always on */ return 1; From cfa71bf35c87c79ad9a03a29a7426b495446b2bf Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Thu, 7 Aug 2014 12:06:00 +0100 Subject: [PATCH 25/30] staging:iio:ad7291 define alert register bits Define some names for alert register bits and apply them to ad7291_event_handler(). Signed-off-by: Hartmut Knaack Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 40f1cea25e1f..9139958da787 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -68,6 +68,17 @@ */ #define AD7291_VALUE_MASK GENMASK(11, 0) +/* + * AD7291 alert register bits + */ +#define AD7291_T_LOW BIT(0) +#define AD7291_T_HIGH BIT(1) +#define AD7291_T_AVG_LOW BIT(2) +#define AD7291_T_AVG_HIGH BIT(3) +#define AD7291_V_LOW(x) BIT((x) * 2) +#define AD7291_V_HIGH(x) BIT((x) * 2 + 1) + + struct ad7291_chip_info { struct i2c_client *client; struct regulator *reg; @@ -122,14 +133,14 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) ad7291_i2c_write(chip, AD7291_COMMAND, command); /* For now treat t_sense and t_sense_average the same */ - if ((t_status & (1 << 0)) || (t_status & (1 << 2))) + if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW)) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); - if ((t_status & (1 << 1)) || (t_status & (1 << 3))) + if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH)) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, @@ -137,18 +148,18 @@ static irqreturn_t ad7291_event_handler(int irq, void *private) IIO_EV_DIR_RISING), timestamp); - for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT*2; i += 2) { - if (v_status & (1 << i)) + for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) { + if (v_status & AD7291_V_LOW(i)) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - i/2, + i, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), timestamp); - if (v_status & (1 << (i + 1))) + if (v_status & AD7291_V_HIGH(i)) iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, - i/2, + i, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), timestamp); From 3b1cae7c2c2b801b8530db07a02587bc1a41b3fe Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 30 Jun 2014 09:50:00 +0100 Subject: [PATCH 26/30] staging:iio:ad7291: Move out of staging The ad7291 driver is in a reasonable shape. It does not use non-standard API/ABI and there are no major style issues with the driver. So this patch moves it out of staging. There is one small warning from checkpatch which is also fixed in this patch. The patch also sorts the #include directives in alphabetical order. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 10 ++++++++++ drivers/iio/adc/Makefile | 1 + drivers/{staging => }/iio/adc/ad7291.c | 13 +++++++------ drivers/staging/iio/adc/Kconfig | 7 ------- drivers/staging/iio/adc/Makefile | 1 - .../adc => include/linux/platform_data}/ad7291.h | 0 6 files changed, 18 insertions(+), 14 deletions(-) rename drivers/{staging => }/iio/adc/ad7291.c (99%) rename {drivers/staging/iio/adc => include/linux/platform_data}/ad7291.h (100%) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 20a7073f1dd6..11b048a59fde 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -20,6 +20,16 @@ config AD7266 Say yes here to build support for Analog Devices AD7265 and AD7266 ADCs. +config AD7291 + tristate "Analog Devices AD7291 ADC driver" + depends on I2C + help + Say yes here to build support for Analog Devices AD7291 + 8 Channel ADC with temperature sensor. + + To compile this driver as a module, choose M here: the + module will be called ad7291. + config AD7298 tristate "Analog Devices AD7298 ADC driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 38cf5c3f5631..ad81b512aa3d 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -5,6 +5,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD7266) += ad7266.o +obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7923) += ad7923.o obj-$(CONFIG_AD7476) += ad7476.o diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c similarity index 99% rename from drivers/staging/iio/adc/ad7291.c rename to drivers/iio/adc/ad7291.c index 9139958da787..4ed78b94afd8 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -6,22 +6,22 @@ * Licensed under the GPL-2 or later. */ -#include #include -#include -#include -#include +#include #include +#include +#include #include #include #include -#include +#include +#include #include #include #include -#include "ad7291.h" +#include /* * Simplified handling @@ -379,6 +379,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: if (chip->reg) { int vref; + vref = regulator_get_voltage(chip->reg); if (vref < 0) return vref; diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index b87e382ad768..75d2d1bf93d1 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -3,13 +3,6 @@ # menu "Analog to digital converters" -config AD7291 - tristate "Analog Devices AD7291 ADC driver" - depends on I2C - help - Say yes here to build support for Analog Devices AD7291 - 8 Channel ADC with temperature sensor. - config AD7606 tristate "Analog Devices AD7606 ADC driver" depends on GPIOLIB diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index afdcd1ff08ff..1c4277dbd318 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o obj-$(CONFIG_AD7606) += ad7606.o -obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7192) += ad7192.o diff --git a/drivers/staging/iio/adc/ad7291.h b/include/linux/platform_data/ad7291.h similarity index 100% rename from drivers/staging/iio/adc/ad7291.h rename to include/linux/platform_data/ad7291.h From 2d7768a872b73a7105d6355948dae0acff72f061 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 7 Aug 2014 08:16:00 +0100 Subject: [PATCH 27/30] iio: st_sensors: add devicetree probing support The I2C devices that make up the STMicroelectronics MEMS sensors may be sneakily enabled by cleverly giving the device node the same name as a string match from the platform device ID table. However the right method is to use the compatible string. On detection, the ST sensors use the ID string to probe and instatiate the right sensor driver, so pass the kernel-internal ID string in the .data field of the OF match table, and set the I2C client name to this name when a compatible match is used. This avoids having misc Linux-specific strings floating around in the device tree. Cc: Lee Jones Cc: Denis CIOCCA Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 51 +++++++++++++++++++ .../iio/common/st_sensors/st_sensors_i2c.c | 30 +++++++++++ drivers/iio/gyro/st_gyro_i2c.c | 39 ++++++++++++++ drivers/iio/magnetometer/st_magn_i2c.c | 23 +++++++++ drivers/iio/pressure/st_pressure_i2c.c | 23 +++++++++ include/linux/iio/common/st_sensors_i2c.h | 11 ++++ 6 files changed, 177 insertions(+) diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index d7bedbdfc81d..7164aeff3ab1 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -18,6 +18,55 @@ #include #include "st_accel.h" +#ifdef CONFIG_OF +static const struct of_device_id st_accel_of_match[] = { + { + .compatible = "st,lsm303dlh-accel", + .data = LSM303DLH_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm303dlhc-accel", + .data = LSM303DLHC_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis3dh-accel", + .data = LIS3DH_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330d-accel", + .data = LSM330D_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330dl-accel", + .data = LSM330DL_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330dlc-accel", + .data = LSM330DLC_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lis331dlh-accel", + .data = LIS331DLH_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm303dl-accel", + .data = LSM303DL_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm303dlm-accel", + .data = LSM303DLM_ACCEL_DEV_NAME, + }, + { + .compatible = "st,lsm330-accel", + .data = LSM330_ACCEL_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_accel_of_match); +#else +#define st_accel_of_match NULL +#endif + static int st_accel_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -31,6 +80,7 @@ static int st_accel_i2c_probe(struct i2c_client *client, adata = iio_priv(indio_dev); adata->dev = &client->dev; + st_sensors_of_i2c_probe(client, st_accel_of_match); st_sensors_i2c_configure(indio_dev, client, adata); @@ -67,6 +117,7 @@ static struct i2c_driver st_accel_driver = { .driver = { .owner = THIS_MODULE, .name = "st-accel-i2c", + .of_match_table = of_match_ptr(st_accel_of_match), }, .probe = st_accel_i2c_probe, .remove = st_accel_i2c_remove, diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index 38af9440c103..bb6f3085f57b 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -76,6 +77,35 @@ void st_sensors_i2c_configure(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_i2c_configure); +#ifdef CONFIG_OF +/** + * st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors + * @client: the I2C client device for the sensor + * @match: the OF match table for the device, containing compatible strings + * but also a .data field with the corresponding internal kernel name + * used by this sensor. + * + * In effect this function matches a compatible string to an internal kernel + * name for a certain sensor device, so that the rest of the autodetection can + * rely on that name from this point on. I2C client devices will be renamed + * to match the internal kernel convention. + */ +void st_sensors_of_i2c_probe(struct i2c_client *client, + const struct of_device_id *match) +{ + const struct of_device_id *of_id; + + of_id = of_match_device(match, &client->dev); + if (!of_id) + return; + + /* The name from the OF match takes precedence if present */ + strncpy(client->name, of_id->data, sizeof(client->name)); + client->name[sizeof(client->name) - 1] = '\0'; +} +EXPORT_SYMBOL(st_sensors_of_i2c_probe); +#endif + MODULE_AUTHOR("Denis Ciocca "); MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 23c12f361b05..8fa0ad2ef4ef 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -18,6 +18,43 @@ #include #include "st_gyro.h" +#ifdef CONFIG_OF +static const struct of_device_id st_gyro_of_match[] = { + { + .compatible = "st,l3g4200d-gyro", + .data = L3G4200D_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330d-gyro", + .data = LSM330D_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330dl-gyro", + .data = LSM330DL_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330dlc-gyro", + .data = LSM330DLC_GYRO_DEV_NAME, + }, + { + .compatible = "st,l3gd20-gyro", + .data = L3GD20_GYRO_DEV_NAME, + }, + { + .compatible = "st,l3g4is-gyro", + .data = L3G4IS_GYRO_DEV_NAME, + }, + { + .compatible = "st,lsm330-gyro", + .data = LSM330_GYRO_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_gyro_of_match); +#else +#define st_gyro_of_match NULL +#endif + static int st_gyro_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -31,6 +68,7 @@ static int st_gyro_i2c_probe(struct i2c_client *client, gdata = iio_priv(indio_dev); gdata->dev = &client->dev; + st_sensors_of_i2c_probe(client, st_gyro_of_match); st_sensors_i2c_configure(indio_dev, client, gdata); @@ -65,6 +103,7 @@ static struct i2c_driver st_gyro_driver = { .driver = { .owner = THIS_MODULE, .name = "st-gyro-i2c", + .of_match_table = of_match_ptr(st_gyro_of_match), }, .probe = st_gyro_i2c_probe, .remove = st_gyro_i2c_remove, diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 892e0feeb5c1..689250058442 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -18,6 +18,27 @@ #include #include "st_magn.h" +#ifdef CONFIG_OF +static const struct of_device_id st_magn_of_match[] = { + { + .compatible = "st,lsm303dlhc-magn", + .data = LSM303DLHC_MAGN_DEV_NAME, + }, + { + .compatible = "st,lsm303dlm-magn", + .data = LSM303DLM_MAGN_DEV_NAME, + }, + { + .compatible = "st,lis3mdl-magn", + .data = LIS3MDL_MAGN_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_magn_of_match); +#else +#define st_magn_of_match NULL +#endif + static int st_magn_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -31,6 +52,7 @@ static int st_magn_i2c_probe(struct i2c_client *client, mdata = iio_priv(indio_dev); mdata->dev = &client->dev; + st_sensors_of_i2c_probe(client, st_magn_of_match); st_sensors_i2c_configure(indio_dev, client, mdata); @@ -61,6 +83,7 @@ static struct i2c_driver st_magn_driver = { .driver = { .owner = THIS_MODULE, .name = "st-magn-i2c", + .of_match_table = of_match_ptr(st_magn_of_match), }, .probe = st_magn_i2c_probe, .remove = st_magn_i2c_remove, diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 3cd73e39b840..acaf165260bb 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -18,6 +18,27 @@ #include #include "st_pressure.h" +#ifdef CONFIG_OF +static const struct of_device_id st_press_of_match[] = { + { + .compatible = "st,lps001wp-press", + .data = LPS001WP_PRESS_DEV_NAME, + }, + { + .compatible = "st,lps25h-press", + .data = LPS25H_PRESS_DEV_NAME, + }, + { + .compatible = "st,lps331ap-press", + .data = LPS331AP_PRESS_DEV_NAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_press_of_match); +#else +#define st_press_of_match NULL +#endif + static int st_press_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -31,6 +52,7 @@ static int st_press_i2c_probe(struct i2c_client *client, pdata = iio_priv(indio_dev); pdata->dev = &client->dev; + st_sensors_of_i2c_probe(client, st_press_of_match); st_sensors_i2c_configure(indio_dev, client, pdata); @@ -60,6 +82,7 @@ static struct i2c_driver st_press_driver = { .driver = { .owner = THIS_MODULE, .name = "st-press-i2c", + .of_match_table = of_match_ptr(st_press_of_match), }, .probe = st_press_i2c_probe, .remove = st_press_i2c_remove, diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 67d845385ae2..1796af093368 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -13,8 +13,19 @@ #include #include +#include void st_sensors_i2c_configure(struct iio_dev *indio_dev, struct i2c_client *client, struct st_sensor_data *sdata); +#ifdef CONFIG_OF +void st_sensors_of_i2c_probe(struct i2c_client *client, + const struct of_device_id *match); +#else +static inline void st_sensors_of_i2c_probe(struct i2c_client *client, + const struct of_device_id *match) +{ +} +#endif + #endif /* ST_SENSORS_I2C_H */ From 77a533c73f032050be8b447828358a228a0a5736 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Thu, 7 Aug 2014 23:29:00 +0100 Subject: [PATCH 28/30] iio: core : events ABI for specifying period The iio sysfs ABI defines a way to specify period for roc and thresholds. What: /sys/.../events/in_accel_x_thresh_rising_period What: /sys/.../events/in_accel_x_thresh_falling_period what: /sys/.../events/in_accel_x_roc_rising_period What: /sys/.../events/in_accel_x_roc_falling_period But there is no way to add period with the current event info enum. Added IIO_EV_INFO_PERIOD and corresponding string. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 1 + include/linux/iio/types.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 258a973a1fb8..35a5b0311dae 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -209,6 +209,7 @@ static const char * const iio_ev_info_text[] = { [IIO_EV_INFO_ENABLE] = "en", [IIO_EV_INFO_VALUE] = "value", [IIO_EV_INFO_HYSTERESIS] = "hysteresis", + [IIO_EV_INFO_PERIOD] = "period", }; static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr) diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index d480631eabc2..4a848d6be3bf 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -70,6 +70,7 @@ enum iio_event_info { IIO_EV_INFO_ENABLE, IIO_EV_INFO_VALUE, IIO_EV_INFO_HYSTERESIS, + IIO_EV_INFO_PERIOD, }; enum iio_event_direction { From a3fb96a8c02ae4fa19d9f68f6f3e6bd53c70cd86 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Fri, 7 Nov 2014 14:06:00 +0000 Subject: [PATCH 29/30] iio: mma8452: add DT support Allow the mma8452 to be described in the device tree. Since no device specific binding attributes exist the trivial I2C binding is sufficient to describe the compatible string. Signed-off-by: Martin Fuzzey Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/i2c/trivial-devices.txt | 1 + drivers/iio/accel/mma8452.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index bef86e57c388..1a794213f7d1 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -50,6 +50,7 @@ epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer +fsl,mma8452 MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 17aeea170566..9231f8a65e79 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -423,9 +423,15 @@ static const struct i2c_device_id mma8452_id[] = { }; MODULE_DEVICE_TABLE(i2c, mma8452_id); +static const struct of_device_id mma8452_dt_ids[] = { + { .compatible = "fsl,mma8452" }, + { } +}; + static struct i2c_driver mma8452_driver = { .driver = { .name = "mma8452", + .of_match_table = of_match_ptr(mma8452_dt_ids), .pm = MMA8452_PM_OPS, }, .probe = mma8452_probe, From 90c5f2d1b8212dde11a3dcc9e87ba3593beeb3ac Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 13 Jul 2014 12:44:00 +0100 Subject: [PATCH 30/30] staging:iio:adc:Kconfig: Let MXS_LRADC depend on HAS_IOMEM MXS_LRADC need HAS_IOMEM, so let it depend on HAS_IOMEM The related error (with allmodconfig under score): MODPOST 1365 modules ERROR: "devm_ioremap_resource" [drivers/staging/iio/adc/mxs-lradc.ko] undefined! Signed-off-by: Chen Gang Acked-by: Marek Vasut Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 75d2d1bf93d1..d01c7076a342 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -87,7 +87,7 @@ config LPC32XX_ADC config MXS_LRADC tristate "Freescale i.MX23/i.MX28 LRADC" - depends on ARCH_MXS || COMPILE_TEST + depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM depends on INPUT select STMP_DEVICE select IIO_BUFFER