* [PATCH v3 0/2] Add support for Aosong AM2315 relative humidity and ambient temperature sensor @ 2016-04-18 14:50 Tiberiu Breana 2016-04-18 14:50 ` [PATCH v3 1/2] iio: humidity: Add support for AM2315 Tiberiu Breana 2016-04-18 14:50 ` [PATCH v3 2/2] iio: humidity: Add triggered buffer " Tiberiu Breana 0 siblings, 2 replies; 5+ messages in thread From: Tiberiu Breana @ 2016-04-18 14:50 UTC (permalink / raw) To: linux-iio; +Cc: Jonathan Cameron, Peter Meerwald-Stadler This patch set adds basic support for the Aosong AM2315 relative humidity and ambient temperature sensor. Patch 1 adds basic support, raw readings and ACPI detection. Patch 2 adds triggered buffer support. --- v3 change log: patch 1/2: - addressed Peter's comments - added a mutex for the read_data sequence - added the am2315_sensor_data struct to better abstract data acquisition patch 2/2: no changes --- v2 change log: patch 1/2: - moved driver from iio/temperature to iio/humidity - addressed Jonathan's comments - fixed scale to export values in millipercent (humidity) and millidegrees (temperature) patch 2/2: no changes --- Tiberiu Breana (2): iio: humidity: Add support for AM2315 iio: humidity: Add triggered buffer support for AM2315 drivers/iio/humidity/Kconfig | 10 ++ drivers/iio/humidity/Makefile | 1 + drivers/iio/humidity/am2315.c | 303 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 drivers/iio/humidity/am2315.c -- 1.9.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 1/2] iio: humidity: Add support for AM2315 2016-04-18 14:50 [PATCH v3 0/2] Add support for Aosong AM2315 relative humidity and ambient temperature sensor Tiberiu Breana @ 2016-04-18 14:50 ` Tiberiu Breana 2016-04-24 8:59 ` Jonathan Cameron 2016-04-18 14:50 ` [PATCH v3 2/2] iio: humidity: Add triggered buffer " Tiberiu Breana 1 sibling, 1 reply; 5+ messages in thread From: Tiberiu Breana @ 2016-04-18 14:50 UTC (permalink / raw) To: linux-iio; +Cc: Jonathan Cameron, Peter Meerwald-Stadler Add basic support for the Aosong AM2315 relative humidity and ambient temperature sensor. Includes support for raw readings and ACPI detection. Datasheet: http://www.aosong.com/asp_bin/Products/en/AM2315.pdf Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> --- drivers/iio/humidity/Kconfig | 10 ++ drivers/iio/humidity/Makefile | 1 + drivers/iio/humidity/am2315.c | 228 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/iio/humidity/am2315.c diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 866dda1..738a86d 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -3,6 +3,16 @@ # menu "Humidity sensors" +config AM2315 + tristate "Aosong AM2315 relative humidity and temperature sensor" + depends on I2C + help + If you say yes here you get support for the Aosong AM2315 + relative humidity and ambient temperature sensor. + + This driver can also be built as a module. If so, the module will + be called am2315. + config DHT11 tristate "DHT11 (and compatible sensors) driver" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile index c9f089a..4a73442 100644 --- a/drivers/iio/humidity/Makefile +++ b/drivers/iio/humidity/Makefile @@ -2,6 +2,7 @@ # Makefile for IIO humidity sensor drivers # +obj-$(CONFIG_AM2315) += am2315.o obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_HDC100X) += hdc100x.o obj-$(CONFIG_HTU21) += htu21.o diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c new file mode 100644 index 0000000..d392fc8 --- /dev/null +++ b/drivers/iio/humidity/am2315.c @@ -0,0 +1,228 @@ +/** + * Aosong AM2315 relative humidity and temperature + * + * Copyright (c) 2016, Intel Corporation. + * + * 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. + * + * 7-bit I2C address: 0x5C. + */ + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> + +#define AM2315_REG_HUM_MSB 0x00 +#define AM2315_REG_HUM_LSB 0x01 +#define AM2315_REG_TEMP_MSB 0x02 +#define AM2315_REG_TEMP_LSB 0x03 + +#define AM2315_FUNCTION_READ 0x03 +#define AM2315_HUM_OFFSET 2 +#define AM2315_TEMP_OFFSET 4 + +#define AM2315_DRIVER_NAME "am2315" + +struct am2315_data { + struct i2c_client *client; + struct mutex lock; +}; + +struct am2315_sensor_data { + s16 hum_data; + s16 temp_data; +}; + +static const struct iio_chan_spec am2315_channels[] = { + { + .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) + }, + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) + }, +}; + +/* CRC calculation algorithm, as specified in the datasheet (page 13). */ +static u16 am2315_crc(u8 *data, u8 nr_bytes) +{ + int i; + u16 crc = 0xffff; + + while (nr_bytes--) { + crc ^= *data++; + for (i = 0; i < 8; i++) { + if (crc & 0x01) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + + return crc; +} + +/* Simple function that sends a few bytes to the device to wake it up. */ +static void am2315_ping(struct i2c_client *client) +{ + i2c_smbus_read_byte_data(client, AM2315_REG_HUM_MSB); +} + +static int am2315_read_data(struct am2315_data *data, + struct am2315_sensor_data *sensor_data) +{ + int ret; + /* tx_buf format: <function code> <start addr> <nr of regs to read> */ + u8 tx_buf[3] = { AM2315_FUNCTION_READ, AM2315_REG_HUM_MSB, 4 }; + /* + * rx_buf format: + * <function code> <number of registers read> + * <humidity MSB> <humidity LSB> <temp MSB> <temp LSB> + * <CRC LSB> <CRC MSB> + */ + u8 rx_buf[8]; + u16 crc; + + /* First wake up the device. */ + am2315_ping(data->client); + + mutex_lock(&data->lock); + ret = i2c_master_send(data->client, tx_buf, sizeof(tx_buf)); + if (ret < 0) { + dev_err(&data->client->dev, "failed to send read request\n"); + goto exit_unlock; + } + /* Wait 2-3 ms, then read back the data sent by the device. */ + usleep_range(2000, 3000); + /* Do a bulk data read, then pick out what we need. */ + ret = i2c_master_recv(data->client, rx_buf, sizeof(rx_buf)); + if (ret < 0) { + dev_err(&data->client->dev, "failed to read sensor data\n"); + goto exit_unlock; + } + mutex_unlock(&data->lock); + /* + * Do a CRC check on the data and compare it to the value + * calculated by the device. + */ + crc = am2315_crc(rx_buf, sizeof(rx_buf) - 2); + if ((crc & 0xff) != rx_buf[6] || (crc >> 8) != rx_buf[7]) { + dev_err(&data->client->dev, "failed to verify sensor data\n"); + return -EIO; + } + + sensor_data->hum_data = (rx_buf[AM2315_HUM_OFFSET] << 8) | + rx_buf[AM2315_HUM_OFFSET + 1]; + sensor_data->temp_data = (rx_buf[AM2315_TEMP_OFFSET] << 8) | + rx_buf[AM2315_TEMP_OFFSET + 1]; + + return ret; + +exit_unlock: + mutex_unlock(&data->lock); + return ret; +} + +static int am2315_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + struct am2315_sensor_data sensor_data; + struct am2315_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = am2315_read_data(data, &sensor_data); + if (ret < 0) + return ret; + *val = (chan->type == IIO_HUMIDITYRELATIVE) ? + sensor_data.hum_data : sensor_data.temp_data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 100; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static const struct iio_info am2315_info = { + .driver_module = THIS_MODULE, + .read_raw = am2315_read_raw, +}; + +static int am2315_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct am2315_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio allocation failed!\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->client = client; + i2c_set_clientdata(client, indio_dev); + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &am2315_info; + indio_dev->name = AM2315_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = am2315_channels; + indio_dev->num_channels = ARRAY_SIZE(am2315_channels); + + return iio_device_register(indio_dev); +} + +static int am2315_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + iio_device_unregister(indio_dev); + + return 0; +} + +static const struct i2c_device_id am2315_i2c_id[] = { + {"am2315", 0}, + {} +}; + +static const struct acpi_device_id am2315_acpi_id[] = { + {"AOS2315", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, am2315_acpi_id); + +static struct i2c_driver am2315_driver = { + .driver = { + .name = "am2315", + .acpi_match_table = ACPI_PTR(am2315_acpi_id), + }, + .probe = am2315_probe, + .remove = am2315_remove, + .id_table = am2315_i2c_id, +}; + +module_i2c_driver(am2315_driver); + +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); +MODULE_DESCRIPTION("Aosong AM2315 relative humidity and temperature"); +MODULE_LICENSE("GPL v2"); -- 1.9.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 1/2] iio: humidity: Add support for AM2315 2016-04-18 14:50 ` [PATCH v3 1/2] iio: humidity: Add support for AM2315 Tiberiu Breana @ 2016-04-24 8:59 ` Jonathan Cameron 0 siblings, 0 replies; 5+ messages in thread From: Jonathan Cameron @ 2016-04-24 8:59 UTC (permalink / raw) To: Tiberiu Breana, linux-iio; +Cc: Peter Meerwald-Stadler On 18/04/16 15:50, Tiberiu Breana wrote: > Add basic support for the Aosong AM2315 relative humidity > and ambient temperature sensor. > Includes support for raw readings and ACPI detection. > > Datasheet: > http://www.aosong.com/asp_bin/Products/en/AM2315.pdf > > Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> Looks good. Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to play with it. Thanks, Jonathan > --- > drivers/iio/humidity/Kconfig | 10 ++ > drivers/iio/humidity/Makefile | 1 + > drivers/iio/humidity/am2315.c | 228 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 239 insertions(+) > create mode 100644 drivers/iio/humidity/am2315.c > > diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig > index 866dda1..738a86d 100644 > --- a/drivers/iio/humidity/Kconfig > +++ b/drivers/iio/humidity/Kconfig > @@ -3,6 +3,16 @@ > # > menu "Humidity sensors" > > +config AM2315 > + tristate "Aosong AM2315 relative humidity and temperature sensor" > + depends on I2C > + help > + If you say yes here you get support for the Aosong AM2315 > + relative humidity and ambient temperature sensor. > + > + This driver can also be built as a module. If so, the module will > + be called am2315. > + > config DHT11 > tristate "DHT11 (and compatible sensors) driver" > depends on GPIOLIB || COMPILE_TEST > diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile > index c9f089a..4a73442 100644 > --- a/drivers/iio/humidity/Makefile > +++ b/drivers/iio/humidity/Makefile > @@ -2,6 +2,7 @@ > # Makefile for IIO humidity sensor drivers > # > > +obj-$(CONFIG_AM2315) += am2315.o > obj-$(CONFIG_DHT11) += dht11.o > obj-$(CONFIG_HDC100X) += hdc100x.o > obj-$(CONFIG_HTU21) += htu21.o > diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c > new file mode 100644 > index 0000000..d392fc8 > --- /dev/null > +++ b/drivers/iio/humidity/am2315.c > @@ -0,0 +1,228 @@ > +/** > + * Aosong AM2315 relative humidity and temperature > + * > + * Copyright (c) 2016, Intel Corporation. > + * > + * 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. > + * > + * 7-bit I2C address: 0x5C. > + */ > + > +#include <linux/acpi.h> > +#include <linux/delay.h> > +#include <linux/i2c.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > + > +#define AM2315_REG_HUM_MSB 0x00 > +#define AM2315_REG_HUM_LSB 0x01 > +#define AM2315_REG_TEMP_MSB 0x02 > +#define AM2315_REG_TEMP_LSB 0x03 > + > +#define AM2315_FUNCTION_READ 0x03 > +#define AM2315_HUM_OFFSET 2 > +#define AM2315_TEMP_OFFSET 4 > + > +#define AM2315_DRIVER_NAME "am2315" > + > +struct am2315_data { > + struct i2c_client *client; > + struct mutex lock; > +}; > + > +struct am2315_sensor_data { > + s16 hum_data; > + s16 temp_data; > +}; > + > +static const struct iio_chan_spec am2315_channels[] = { > + { > + .type = IIO_HUMIDITYRELATIVE, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > + BIT(IIO_CHAN_INFO_SCALE) > + }, > + { > + .type = IIO_TEMP, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > + BIT(IIO_CHAN_INFO_SCALE) > + }, > +}; > + > +/* CRC calculation algorithm, as specified in the datasheet (page 13). */ > +static u16 am2315_crc(u8 *data, u8 nr_bytes) > +{ > + int i; > + u16 crc = 0xffff; > + > + while (nr_bytes--) { > + crc ^= *data++; > + for (i = 0; i < 8; i++) { > + if (crc & 0x01) { > + crc >>= 1; > + crc ^= 0xA001; > + } else { > + crc >>= 1; > + } > + } > + } > + > + return crc; > +} > + > +/* Simple function that sends a few bytes to the device to wake it up. */ > +static void am2315_ping(struct i2c_client *client) > +{ > + i2c_smbus_read_byte_data(client, AM2315_REG_HUM_MSB); > +} > + > +static int am2315_read_data(struct am2315_data *data, > + struct am2315_sensor_data *sensor_data) > +{ > + int ret; > + /* tx_buf format: <function code> <start addr> <nr of regs to read> */ > + u8 tx_buf[3] = { AM2315_FUNCTION_READ, AM2315_REG_HUM_MSB, 4 }; > + /* > + * rx_buf format: > + * <function code> <number of registers read> > + * <humidity MSB> <humidity LSB> <temp MSB> <temp LSB> > + * <CRC LSB> <CRC MSB> > + */ > + u8 rx_buf[8]; > + u16 crc; > + > + /* First wake up the device. */ > + am2315_ping(data->client); > + > + mutex_lock(&data->lock); > + ret = i2c_master_send(data->client, tx_buf, sizeof(tx_buf)); > + if (ret < 0) { > + dev_err(&data->client->dev, "failed to send read request\n"); > + goto exit_unlock; > + } > + /* Wait 2-3 ms, then read back the data sent by the device. */ > + usleep_range(2000, 3000); > + /* Do a bulk data read, then pick out what we need. */ > + ret = i2c_master_recv(data->client, rx_buf, sizeof(rx_buf)); > + if (ret < 0) { > + dev_err(&data->client->dev, "failed to read sensor data\n"); > + goto exit_unlock; > + } > + mutex_unlock(&data->lock); > + /* > + * Do a CRC check on the data and compare it to the value > + * calculated by the device. > + */ > + crc = am2315_crc(rx_buf, sizeof(rx_buf) - 2); > + if ((crc & 0xff) != rx_buf[6] || (crc >> 8) != rx_buf[7]) { > + dev_err(&data->client->dev, "failed to verify sensor data\n"); > + return -EIO; > + } > + > + sensor_data->hum_data = (rx_buf[AM2315_HUM_OFFSET] << 8) | > + rx_buf[AM2315_HUM_OFFSET + 1]; > + sensor_data->temp_data = (rx_buf[AM2315_TEMP_OFFSET] << 8) | > + rx_buf[AM2315_TEMP_OFFSET + 1]; > + > + return ret; > + > +exit_unlock: > + mutex_unlock(&data->lock); > + return ret; > +} > + > +static int am2315_read_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int *val, int *val2, long mask) > +{ > + int ret; > + struct am2315_sensor_data sensor_data; > + struct am2315_data *data = iio_priv(indio_dev); > + > + switch (mask) { > + case IIO_CHAN_INFO_RAW: > + ret = am2315_read_data(data, &sensor_data); > + if (ret < 0) > + return ret; > + *val = (chan->type == IIO_HUMIDITYRELATIVE) ? > + sensor_data.hum_data : sensor_data.temp_data; > + return IIO_VAL_INT; > + case IIO_CHAN_INFO_SCALE: > + *val = 100; > + return IIO_VAL_INT; > + } > + > + return -EINVAL; > +} > + > +static const struct iio_info am2315_info = { > + .driver_module = THIS_MODULE, > + .read_raw = am2315_read_raw, > +}; > + > +static int am2315_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct iio_dev *indio_dev; > + struct am2315_data *data; > + > + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); > + if (!indio_dev) { > + dev_err(&client->dev, "iio allocation failed!\n"); > + return -ENOMEM; > + } > + > + data = iio_priv(indio_dev); > + data->client = client; > + i2c_set_clientdata(client, indio_dev); > + mutex_init(&data->lock); > + > + indio_dev->dev.parent = &client->dev; > + indio_dev->info = &am2315_info; > + indio_dev->name = AM2315_DRIVER_NAME; > + indio_dev->modes = INDIO_DIRECT_MODE; > + indio_dev->channels = am2315_channels; > + indio_dev->num_channels = ARRAY_SIZE(am2315_channels); > + > + return iio_device_register(indio_dev); > +} > + > +static int am2315_remove(struct i2c_client *client) > +{ > + struct iio_dev *indio_dev = i2c_get_clientdata(client); > + > + iio_device_unregister(indio_dev); > + > + return 0; > +} > + > +static const struct i2c_device_id am2315_i2c_id[] = { > + {"am2315", 0}, > + {} > +}; > + > +static const struct acpi_device_id am2315_acpi_id[] = { > + {"AOS2315", 0}, > + {} > +}; > + > +MODULE_DEVICE_TABLE(acpi, am2315_acpi_id); > + > +static struct i2c_driver am2315_driver = { > + .driver = { > + .name = "am2315", > + .acpi_match_table = ACPI_PTR(am2315_acpi_id), > + }, > + .probe = am2315_probe, > + .remove = am2315_remove, > + .id_table = am2315_i2c_id, > +}; > + > +module_i2c_driver(am2315_driver); > + > +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); > +MODULE_DESCRIPTION("Aosong AM2315 relative humidity and temperature"); > +MODULE_LICENSE("GPL v2"); > ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] iio: humidity: Add triggered buffer support for AM2315 2016-04-18 14:50 [PATCH v3 0/2] Add support for Aosong AM2315 relative humidity and ambient temperature sensor Tiberiu Breana 2016-04-18 14:50 ` [PATCH v3 1/2] iio: humidity: Add support for AM2315 Tiberiu Breana @ 2016-04-18 14:50 ` Tiberiu Breana 2016-04-24 9:00 ` Jonathan Cameron 1 sibling, 1 reply; 5+ messages in thread From: Tiberiu Breana @ 2016-04-18 14:50 UTC (permalink / raw) To: linux-iio; +Cc: Jonathan Cameron, Peter Meerwald-Stadler Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> --- drivers/iio/humidity/am2315.c | 81 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index d392fc8..3be6d20 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -15,8 +15,11 @@ #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/iio/buffer.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> +#include <linux/iio/trigger_consumer.h> +#include <linux/iio/triggered_buffer.h> #define AM2315_REG_HUM_MSB 0x00 #define AM2315_REG_HUM_LSB 0x01 @@ -26,12 +29,14 @@ #define AM2315_FUNCTION_READ 0x03 #define AM2315_HUM_OFFSET 2 #define AM2315_TEMP_OFFSET 4 +#define AM2315_ALL_CHANNEL_MASK GENMASK(1, 0) #define AM2315_DRIVER_NAME "am2315" struct am2315_data { struct i2c_client *client; struct mutex lock; + s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ }; struct am2315_sensor_data { @@ -43,13 +48,28 @@ static const struct iio_chan_spec am2315_channels[] = { { .type = IIO_HUMIDITYRELATIVE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE) + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, }, { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_SCALE) + BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, }, + IIO_CHAN_SOFT_TIMESTAMP(2), }; /* CRC calculation algorithm, as specified in the datasheet (page 13). */ @@ -134,6 +154,44 @@ exit_unlock: return ret; } +static irqreturn_t am2315_trigger_handler(int irq, void *p) +{ + int i; + int ret; + int bit; + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct am2315_data *data = iio_priv(indio_dev); + struct am2315_sensor_data sensor_data; + + ret = am2315_read_data(data, &sensor_data); + if (ret < 0) { + mutex_unlock(&data->lock); + goto err; + } + + mutex_lock(&data->lock); + if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { + data->buffer[0] = sensor_data.hum_data; + data->buffer[1] = sensor_data.temp_data; + } else { + i = 0; + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + data->buffer[i] = (bit ? sensor_data.temp_data : + sensor_data.hum_data); + i++; + } + } + mutex_unlock(&data->lock); + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + static int am2315_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -166,6 +224,7 @@ static const struct iio_info am2315_info = { static int am2315_probe(struct i2c_client *client, const struct i2c_device_id *id) { + int ret; struct iio_dev *indio_dev; struct am2315_data *data; @@ -187,7 +246,22 @@ static int am2315_probe(struct i2c_client *client, indio_dev->channels = am2315_channels; indio_dev->num_channels = ARRAY_SIZE(am2315_channels); - return iio_device_register(indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + am2315_trigger_handler, NULL); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_buffer_cleanup; + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + return ret; } static int am2315_remove(struct i2c_client *client) @@ -195,6 +269,7 @@ static int am2315_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); return 0; } -- 1.9.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 2/2] iio: humidity: Add triggered buffer support for AM2315 2016-04-18 14:50 ` [PATCH v3 2/2] iio: humidity: Add triggered buffer " Tiberiu Breana @ 2016-04-24 9:00 ` Jonathan Cameron 0 siblings, 0 replies; 5+ messages in thread From: Jonathan Cameron @ 2016-04-24 9:00 UTC (permalink / raw) To: Tiberiu Breana, linux-iio; +Cc: Peter Meerwald-Stadler On 18/04/16 15:50, Tiberiu Breana wrote: > Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> Applied, thanks, Jonathan > --- > drivers/iio/humidity/am2315.c | 81 +++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 78 insertions(+), 3 deletions(-) > > diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c > index d392fc8..3be6d20 100644 > --- a/drivers/iio/humidity/am2315.c > +++ b/drivers/iio/humidity/am2315.c > @@ -15,8 +15,11 @@ > #include <linux/i2c.h> > #include <linux/kernel.h> > #include <linux/module.h> > +#include <linux/iio/buffer.h> > #include <linux/iio/iio.h> > #include <linux/iio/sysfs.h> > +#include <linux/iio/trigger_consumer.h> > +#include <linux/iio/triggered_buffer.h> > > #define AM2315_REG_HUM_MSB 0x00 > #define AM2315_REG_HUM_LSB 0x01 > @@ -26,12 +29,14 @@ > #define AM2315_FUNCTION_READ 0x03 > #define AM2315_HUM_OFFSET 2 > #define AM2315_TEMP_OFFSET 4 > +#define AM2315_ALL_CHANNEL_MASK GENMASK(1, 0) > > #define AM2315_DRIVER_NAME "am2315" > > struct am2315_data { > struct i2c_client *client; > struct mutex lock; > + s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ > }; > > struct am2315_sensor_data { > @@ -43,13 +48,28 @@ static const struct iio_chan_spec am2315_channels[] = { > { > .type = IIO_HUMIDITYRELATIVE, > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > - BIT(IIO_CHAN_INFO_SCALE) > + BIT(IIO_CHAN_INFO_SCALE), > + .scan_index = 0, > + .scan_type = { > + .sign = 's', > + .realbits = 16, > + .storagebits = 16, > + .endianness = IIO_CPU, > + }, > }, > { > .type = IIO_TEMP, > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > - BIT(IIO_CHAN_INFO_SCALE) > + BIT(IIO_CHAN_INFO_SCALE), > + .scan_index = 1, > + .scan_type = { > + .sign = 's', > + .realbits = 16, > + .storagebits = 16, > + .endianness = IIO_CPU, > + }, > }, > + IIO_CHAN_SOFT_TIMESTAMP(2), > }; > > /* CRC calculation algorithm, as specified in the datasheet (page 13). */ > @@ -134,6 +154,44 @@ exit_unlock: > return ret; > } > > +static irqreturn_t am2315_trigger_handler(int irq, void *p) > +{ > + int i; > + int ret; > + int bit; > + struct iio_poll_func *pf = p; > + struct iio_dev *indio_dev = pf->indio_dev; > + struct am2315_data *data = iio_priv(indio_dev); > + struct am2315_sensor_data sensor_data; > + > + ret = am2315_read_data(data, &sensor_data); > + if (ret < 0) { > + mutex_unlock(&data->lock); > + goto err; > + } > + > + mutex_lock(&data->lock); > + if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { > + data->buffer[0] = sensor_data.hum_data; > + data->buffer[1] = sensor_data.temp_data; > + } else { > + i = 0; > + for_each_set_bit(bit, indio_dev->active_scan_mask, > + indio_dev->masklength) { > + data->buffer[i] = (bit ? sensor_data.temp_data : > + sensor_data.hum_data); > + i++; > + } > + } > + mutex_unlock(&data->lock); > + > + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, > + pf->timestamp); > +err: > + iio_trigger_notify_done(indio_dev->trig); > + return IRQ_HANDLED; > +} > + > static int am2315_read_raw(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, > int *val, int *val2, long mask) > @@ -166,6 +224,7 @@ static const struct iio_info am2315_info = { > static int am2315_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > + int ret; > struct iio_dev *indio_dev; > struct am2315_data *data; > > @@ -187,7 +246,22 @@ static int am2315_probe(struct i2c_client *client, > indio_dev->channels = am2315_channels; > indio_dev->num_channels = ARRAY_SIZE(am2315_channels); > > - return iio_device_register(indio_dev); > + ret = iio_triggered_buffer_setup(indio_dev, NULL, > + am2315_trigger_handler, NULL); > + if (ret < 0) { > + dev_err(&client->dev, "iio triggered buffer setup failed\n"); > + return ret; > + } > + > + ret = iio_device_register(indio_dev); > + if (ret < 0) > + goto err_buffer_cleanup; > + > + return 0; > + > +err_buffer_cleanup: > + iio_triggered_buffer_cleanup(indio_dev); > + return ret; > } > > static int am2315_remove(struct i2c_client *client) > @@ -195,6 +269,7 @@ static int am2315_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); > > return 0; > } > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-04-24 9:00 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-04-18 14:50 [PATCH v3 0/2] Add support for Aosong AM2315 relative humidity and ambient temperature sensor Tiberiu Breana 2016-04-18 14:50 ` [PATCH v3 1/2] iio: humidity: Add support for AM2315 Tiberiu Breana 2016-04-24 8:59 ` Jonathan Cameron 2016-04-18 14:50 ` [PATCH v3 2/2] iio: humidity: Add triggered buffer " Tiberiu Breana 2016-04-24 9:00 ` Jonathan Cameron
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).