mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 01:41:39 +00:00
iio: humidity: Add triggered buffer support for AM2315
Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
parent
366a3270c1
commit
0d96d5ead3
1 changed files with 78 additions and 3 deletions
|
@ -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 @@ static int am2315_read_data(struct am2315_data *data,
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue