iio:temperature:Add irq and threshold events support for TI TMP007 sensor
Subsystems (2)
PATCH 1/1 iio:temperature:Add irq and threshold events support for TI TMP007 sensor
This patch adds support for ALERT irq and limit threshold events for TI TMP007 - 16 bit IR thermopile sensor with integrated math engine.
Following threshold events are supported:
1. TObj high limit
2. TObj low limit
3. TDie high limit
4. TDie low limit
--- .../devicetree/bindings/iio/temperature/tmp007.txt | 8 + drivers/iio/temperature/tmp007.c | 334 ++++++++++++++++++--- 2 files changed, 304 insertions(+), 38 deletions(-)
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +8 -0
@@ -18,10 +18,18 @@ Required properties: 1 SDA 0x46 1 SCL 0x47 +Optional properties: + + - interrupt-parent: should be the phandle for the interrupt controller + + - interrupts: interrupt mapping for GPIO IRQ + Example: tmp007@40 { compatible = "ti,tmp007"; reg = <0x40>; + interrupt-parent = <&gpio0>; + interrupts = <5 8>; };
drivers/iio/temperature/tmp007.c +296 -38
427 lines not on this page · raw message
Signature · 1 line
2.7.4
A message that is not in the archive (sent off-list or not yet received): [email protected]
I'd prefer subject "iio:temperature:tmp007: Add irq and threshold events support"
Quoted 8 lines
This patch adds support for ALERT irq and limit threshold events for TI TMP007 - 16 bit IR thermopile sensor with integrated math engine.
Following threshold events are supported:
1. TObj high limit
2. TObj low limit
3. TDie high limit
4. TDie low limit
comments below
I suggest to separate clearup from actually adding events support, so two patches
it would be nice if the driver can operate without irq also (irq is optional in DT...)
Quoted 2 lines
Signed-off-by Manivannan Sadhasivam <[email protected]>---
note: this applies on top of patch...
Quoted 15 lines
.../devicetree/bindings/iio/temperature/tmp007.txt | 8 + drivers/iio/temperature/tmp007.c | 334 ++++++++++++++++++--- 2 files changed, 304 insertions(+), 38 deletions(-)Documentation/devicetree/bindings/iio/temperature/tmp007.txt +3
-0@@ -18,10 +18,18 @@ Required properties: 1 SDA 0x46 1 SCL 0x47 +Optional properties: + + - interrupt-parent: should be the phandle for the interrupt controller
Documentation/devicetree/bindings/iio/temperature/tmp007.txt Required properties: · line 33
Quoted 10 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +5
-0+ + - interrupts: interrupt mapping for GPIO IRQ + Example: tmp007@40 { compatible = "ti,tmp007"; reg = <0x40>; + interrupt-parent = <&gpio0>; + interrupts = <5 8>;
why are there two GPIOs?
Quoted 44 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +0
-0};drivers/iio/temperature/tmp007.c +6
-18@@ -11,9 +11,10 @@* * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins) * -* Note: This driver assumes that the sensor has been calibrated beforehand -* -* TODO: ALERT irq, limit threshold events +* Note: +* 1. This driver assumes that the sensor has been calibrated beforehand +* 2. Limit threshold events are enabled at the start +* 3. Operating mode: INT * */ @@ -24,35 +25,49 @@#include <linux/pm.h> #include <linux/bitops.h> #include <linux/of.h> +#include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> - -#define TMP007_TDIE 0x01 -#define TMP007_CONFIG 0x02 -#define TMP007_TOBJECT 0x03 -#define TMP007_STATUS 0x04 -#define TMP007_STATUS_MASK 0x05 -#define TMP007_MANUFACTURER_ID 0x1e -#define TMP007_DEVICE_ID 0x1f - -#define TMP007_CONFIG_CONV_EN BIT(12) -#define TMP007_CONFIG_COMP_EN BIT(5) -#define TMP007_CONFIG_TC_EN BIT(6) -#define TMP007_CONFIG_CR_MASK GENMASK(11, 9) -#define TMP007_CONFIG_CR_SHIFT 9 -
drivers/iio/temperature/tmp007.c line 35
Quoted 10 lines
drivers/iio/temperature/tmp007.c +3
-7-#define TMP007_STATUS_CONV_READY BIT(14) -#define TMP007_STATUS_DATA_VALID BIT(9) - -#define TMP007_MANUFACTURER_MAGIC 0x5449 -#define TMP007_DEVICE_MAGIC 0x0078 - -#define TMP007_TEMP_SHIFT 2 +#include <linux/iio/events.h> + +#define TMP007_TDIE 0x01
this has a lot of clutter; the patch also reformats the #defines by adding whitespace; don't do this in the same patch
Quoted 39 lines
drivers/iio/temperature/tmp007.c +31
-0+#define TMP007_CONFIG 0x02 +#define TMP007_TOBJECT 0x03 +#define TMP007_STATUS 0x04 +#define TMP007_STATUS_MASK 0x05 +#define TMP007_TOBJ_HIGH_LIMIT 0x06 +#define TMP007_TOBJ_LOW_LIMIT 0x07 +#define TMP007_TDIE_HIGH_LIMIT 0x08 +#define TMP007_TDIE_LOW_LIMIT 0x09 +#define TMP007_MANUFACTURER_ID 0x1e +#define TMP007_DEVICE_ID 0x1f + +#define TMP007_CONFIG_CONV_EN BIT(12) +#define TMP007_CONFIG_TC_EN BIT(6) +#define TMP007_CONFIG_CR_MASK GENMASK(11, 9) +#define TMP007_CONFIG_ALERT_EN BIT(8) +#define TMP007_CONFIG_CR_SHIFT 9 + +/* Status register flags */ +#define TMP007_STATUS_ALERT BIT(15) +#define TMP007_STATUS_CONV_READY BIT(14) +#define TMP007_STATUS_OHF BIT(13) +#define TMP007_STATUS_OLF BIT(12) +#define TMP007_STATUS_LHF BIT(11) +#define TMP007_STATUS_LLF BIT(10) +#define TMP007_STATUS_DATA_VALID BIT(9) + +#define TMP007_MANUFACTURER_MAGIC 0x5449 +#define TMP007_DEVICE_MAGIC 0x0078 + +#define TMP007_TEMP_SHIFT 2struct tmp007_data {struct i2c_client *client;u16 config; +u16 status_mask; };static const int tmp007_avgs[5 ][2 ] = { {4 ,0 }, {2 ,0 }, {1 ,0 },
drivers/iio/temperature/tmp007.c static int tmp007_read_temperature(struct tmp007_data *data, u8 reg) · line 73
Quoted 4 lines
drivers/iio/temperature/tmp007.c +0
-1@@ -70,7 +85,7 @@ static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)return ret;if ((ret &TMP007_STATUS_CONV_READY ) && !(ret &TMP007_STATUS_DATA_VALID )) -break ;
another unrelated cleanup
Quoted 6 lines
drivers/iio/temperature/tmp007.c +1
-0+break ;msleep (100 ); }@@ -156,6 +171,185 @@ static int tmp007_write_raw(struct iio_dev *indio_dev,return -EINVAL ;
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 181
Quoted 10 lines
drivers/iio/temperature/tmp007.c +8
-0} +static irqreturn_t tmp007_interrupt_handler (int irq,void *private) +{ +struct iio_dev *indio_dev = private; +struct tmp007_data *data =iio_priv (indio_dev); +int ret; + + ret =i2c_smbus_read_word_swapped (data->client,TMP007_STATUS ); +if (ret <0 )
|| !(ret & (_STATUSS_OHF | STATUS_OLF | ..))
Quoted 52 lines
drivers/iio/temperature/tmp007.c +52
-0+return IRQ_NONE ; + +if (ret &TMP007_STATUS_OHF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_OBJECT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_OLF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_OBJECT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_LHF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_AMBIENT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_LLF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_AMBIENT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ), +iio_get_time_ns (indio_dev)); + +return IRQ_HANDLED ; +} + +static int tmp007_write_event_config (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,int state) +{ +struct tmp007_data *data =iio_priv (indio_dev); +unsigned int status_mask; +int ret; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + status_mask =TMP007_STATUS_LHF ; +else + status_mask =TMP007_STATUS_LLF ; +break ;
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 243
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+case IIO_MOD_TEMP_OBJECT : +if (dir ==IIO_EV_DIR_RISING ) + status_mask =TMP007_STATUS_OHF ; +else + status_mask =TMP007_STATUS_OLF ; +break ; +default : +return -EINVAL ; + } +
mutex around this?
Quoted 28 lines
drivers/iio/temperature/tmp007.c +28
-0+ ret =i2c_smbus_read_word_swapped (data->client,TMP007_STATUS_MASK ); +if (ret <0 ) +return ret; + +if (state) + ret |= status_mask; +else + ret &= ~status_mask; + +return i2c_smbus_write_word_swapped (data->client,TMP007_STATUS_MASK , + data->status_mask = ret); +} + +static int tmp007_read_event_config (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir) +{ +struct tmp007_data *data =iio_priv (indio_dev); +unsigned int mask; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + mask =TMP007_STATUS_LHF ; +else + mask =TMP007_STATUS_LLF ; +break ; +case IIO_MOD_TEMP_OBJECT :
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 281
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+if (dir ==IIO_EV_DIR_RISING ) + mask =TMP007_STATUS_OHF ; +else + mask =TMP007_STATUS_OLF ; +break ; +default : +return -EINVAL ; + } + +return (bool )(data->status_mask & mask);
return type is int, maybe use !! to force to 0/1
return !!(data->status_mask & mask);
Quoted 54 lines
drivers/iio/temperature/tmp007.c +54
-0+} + +static int tmp007_read_thresh (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,enum iio_event_info info, +int *val,int *val2) +{ +struct tmp007_data *data =iio_priv (indio_dev); +int ret; +u8 reg; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT :/* LSB: 0.5 degree Celsius */ +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TDIE_HIGH_LIMIT ; +else + reg =TMP007_TDIE_LOW_LIMIT ; +break ; +case IIO_MOD_TEMP_OBJECT : +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TOBJ_HIGH_LIMIT ; +else + reg =TMP007_TOBJ_LOW_LIMIT ; +break ; +default : +return -EINVAL ; + } + + ret =i2c_smbus_read_word_swapped (data->client, reg); +if (ret <0 ) +return ret; + +/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ + *val =sign_extend32 (ret,15 ) >>7 ; + +return IIO_VAL_INT ; +} + +static int tmp007_write_thresh (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,enum iio_event_info info, +int val,int val2) +{ +struct tmp007_data *data =iio_priv (indio_dev); +u8 reg; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TDIE_HIGH_LIMIT ; +else + reg =TMP007_TDIE_LOW_LIMIT ; +break ; +case IIO_MOD_TEMP_OBJECT :
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 345
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TOBJ_HIGH_LIMIT ; +else + reg =TMP007_TOBJ_LOW_LIMIT ; +break ; +default : +return -EINVAL ; + } + +/* Full scale value is +/- 256 degree Celsius */
I guess we want to specify milli degree Celsius according to sysfs-bus-iio for in_temp_raw
Quoted 61 lines
drivers/iio/temperature/tmp007.c +39
-1+if (val <-256 || val >255 ) +return -EINVAL ; + +/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ +return i2c_smbus_write_word_swapped (data->client, reg, (val <<7 )); +} + static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");static struct attribute *tmp007_attributes[] = {@@ -167,6 +361,36 @@ static const struct attribute_group tmp007_attribute_group = { .attrs = tmp007_attributes, }; +static const struct iio_event_spec tmp007_obj_event[] = { + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_RISING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_FALLING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, +}; + +static const struct iio_event_spec tmp007_die_event[] = { + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_RISING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_FALLING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, +}; +static const struct iio_chan_spec tmp007_channels[] = { { .type =IIO_TEMP ,@@ -175,6 +399,8 @@ static const struct iio_chan_spec tmp007_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .event_spec = tmp007_die_event, + .num_event_specs = ARRAY_SIZE(tmp007_die_event), }, { .type = IIO_TEMP,@@ -183,12 +409,18 @@ static const struct iio_chan_spec tmp007_channels[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - }
drivers/iio/temperature/tmp007.c static const struct iio_chan_spec tmp007_channels[] = { · line 419
Quoted 10 lines
drivers/iio/temperature/tmp007.c +5
-2+ .event_spec = tmp007_obj_event, + .num_event_specs = ARRAY_SIZE(tmp007_obj_event), + }, };static const struct iio_info tmp007_info = { - .read_raw = tmp007_read_raw, - .write_raw = tmp007_write_raw, + .read_raw = &tmp007_read_raw, + .write_raw = &tmp007_write_raw,
unrelated change, no need for & for a function
Quoted 66 lines
drivers/iio/temperature/tmp007.c +18
-9+ .read_event_config = &tmp007_read_event_config, + .write_event_config = &tmp007_write_event_config, + .read_event_value = &tmp007_read_thresh, + .write_event_value = &tmp007_write_thresh, .attrs = &tmp007_attribute_group, .driver_module = THIS_MODULE, };@@ -214,7 +446,6 @@ static int tmp007_probe(struct i2c_client *client,struct tmp007_data *data;struct iio_dev *indio_dev;int ret; -u16 status;if (!i2c_check_functionality (client->adapter,I2C_FUNC_SMBUS_WORD_DATA ))return -EOPNOTSUPP ;@@ -243,8 +474,8 @@ static int tmp007_probe(struct i2c_client *client,/* * Set Configuration register: * 1. Conversion ON -* 2. Comparator mode -* 3. Transient correction enable +* 2. Transient correction enable +* 3. ALERT enable */ ret =i2c_smbus_read_word_swapped (data->client,TMP007_CONFIG );@@ -252,7 +483,7 @@ static int tmp007_probe(struct i2c_client *client,return ret; data->config = ret; - data->config |= (TMP007_CONFIG_CONV_EN |TMP007_CONFIG_COMP_EN |TMP007_CONFIG_TC_EN ); + data->config |= (TMP007_CONFIG_CONV_EN |TMP007_CONFIG_TC_EN |TMP007_CONFIG_ALERT_EN ); ret =i2c_smbus_write_word_swapped (data->client,TMP007_CONFIG , data->config);@@ -260,22 +491,39 @@ static int tmp007_probe(struct i2c_client *client,return ret;/* +* Only the following flags can activate ALERT pin. Data conversion/validity flags +* flags can still be polled for getting temperature data +* * Set Status Mask register: -* 1. Conversion ready enable -* 2. Data valid enable +* 1. Object temperature high limit enable +* 2. Object temperature low limit enable +* 3. TDIE temperature high limit enable +* 4. TDIE temperature low limit enable */ ret =i2c_smbus_read_word_swapped (data->client,TMP007_STATUS_MASK );if (ret <0 ) goto error_powerdown; - status = ret; - status |= (TMP007_STATUS_CONV_READY |TMP007_STATUS_DATA_VALID ); + data->status_mask = ret; + data->status_mask |= (TMP007_STATUS_OHF |TMP007_STATUS_OLF + |TMP007_STATUS_LHF |TMP007_STATUS_LLF ); - ret =i2c_smbus_write_word_swapped (data->client,TMP007_STATUS_MASK , status); + ret =i2c_smbus_write_word_swapped (data->client,TMP007_STATUS_MASK , data->status_mask);if (ret <0 ) goto error_powerdown;
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client, · line 525
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+if (client->irq) { + ret =devm_request_threaded_irq (&client->dev, client->irq, +NULL , tmp007_interrupt_handler, +IRQF_TRIGGER_FALLING |IRQF_ONESHOT , + tmp007_id->name, indio_dev); +if (ret) { +dev_err (&client->dev,"irq request error %d\n" , -ret); + goto error_powerdown; + } + }
what happens when there is no IRQ? it would be nice to still use the driver (without event capability)
drivers/iio/temperature/tmp007.c static int tmp007_resume(struct device *dev) · line 563
Quoted 9 lines
drivers/iio/temperature/tmp007.c +2
-0+return iio_device_register (indio_dev); error_powerdown:@@ -312,6 +560,16 @@ static int tmp007_resume(struct device *dev)return i2c_smbus_write_word_swapped (data->client,TMP007_CONFIG , data->config | TMP007_CONFIG_CONV_EN); } +#else
this seems to be unrelated to the patch
Quoted 13 lines
drivers/iio/temperature/tmp007.c +9
-0+static int tmp007_suspend (struct device *dev) +{ +return 0 ; +} + +static int tmp007_resume (struct device *dev) +{ +return 0 ; +}#endif static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
Signature · 6 lines
Peter Meerwald-Stadler +43-664-2444418 (mobile) -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): alpine.DEB.2.02.1701221002030.31271-jW+XmwGofnusTnJN9+BGXg@public.gmane.org
Thanks Peter for your suggestions.
Quoted 4 lines · Peter Meerwald-Stadler
I'd prefer subject "iio:temperature:tmp007: Add irq and threshold events support"
ACK
Quoted 10 lines
Quoted 1 line
This patch adds support for ALERT irq and limit threshold events for
TI TMP007 - 16 bit IR thermopile sensor
Quoted 7 lines
with integrated math engine.
Following threshold events are supported:
1. TObj high limit
2. TObj low limit
3. TDie high limit
4. TDie low limit
Quoted 4 lines
comments below
I suggest to separate clearup from actually adding events support, so two
patches
Sure. I'll create a separate patch for cleanup later on.
Quoted 3 lines
it would be nice if the driver can operate without irq also (irq is optional in DT...)
I think the driver can work without interrupt.
Quoted 29 lines
Quoted 2 lines
Signed-off-by Manivannan Sadhasivam <[email protected]>---
note: this applies on top of patch...
Quoted 2 lines
.../devicetree/bindings/iio/temperature/tmp007.txt | 8 + drivers/iio/temperature/tmp007.c | 334++++++++++++++++++---
Quoted 3 lines
2 files changed, 304 insertions(+), 38 deletions(-)diff --git
a/Documentation/devicetree/bindings/iio/temperature/tmp007.txtb/Documentation/devicetree/bindings/iio/temperature/tmp007.txtDocumentation/devicetree/bindings/iio/temperature/tmp007.txt Required properties: · line 23
Quoted 10 lines
index 3b8f41f..07c1658 100644
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +3
-0@@ -18,10 +18,18 @@ Required properties: 1 SDA 0x46 1 SCL 0x47 +Optional properties: + + - interrupt-parent: should be the phandle for the interruptcontroller
Quoted 5 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +3
-0+ + - interrupts: interrupt mapping for GPIO IRQ + Example:
Quoted 8 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt Required properties: · line 33
Quoted 5 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +2
-0tmp007@40 { compatible = "ti,tmp007"; reg = <0x40>; + interrupt-parent = <&gpio0>; + interrupts = <5 8>;why are there two GPIOs?
Ahh. I wanted to specify level triggering there. But not needed as it is being specified in probe itself. Acked.
Quoted 53 lines
Review
Quoted 3 lines
Documentation/devicetree/bindings/iio/temperature/tmp007.txt +0
-0};(quoted diff) +0
-0
b/drivers/iio/temperature/tmp007.cdrivers/iio/temperature/tmp007.c line 14
Quoted 8 lines
index 24c6c16..73b5b8d 100644
drivers/iio/temperature/tmp007.c +0
-1@@ -11,9 +11,10 @@* * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins) * -* Note: This driver assumes that the sensor has been calibrated beforehand
drivers/iio/temperature/tmp007.c
Quoted 4 lines
drivers/iio/temperature/tmp007.c +2
-2-* -* TODO: ALERT irq, limit threshold events +* Note: +* 1. This driver assumes that the sensor has been calibrated beforehand
Quoted 35 lines
drivers/iio/temperature/tmp007.c +4
-21+* 2. Limit threshold events are enabled at the start +* 3. Operating mode: INT * */ @@ -24,35 +25,49 @@#include <linux/pm.h> #include <linux/bitops.h> #include <linux/of.h> +#include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> - -#define TMP007_TDIE 0x01 -#define TMP007_CONFIG 0x02 -#define TMP007_TOBJECT 0x03 -#define TMP007_STATUS 0x04 -#define TMP007_STATUS_MASK 0x05 -#define TMP007_MANUFACTURER_ID 0x1e -#define TMP007_DEVICE_ID 0x1f - -#define TMP007_CONFIG_CONV_EN BIT(12) -#define TMP007_CONFIG_COMP_EN BIT(5) -#define TMP007_CONFIG_TC_EN BIT(6) -#define TMP007_CONFIG_CR_MASK GENMASK(11, 9) -#define TMP007_CONFIG_CR_SHIFT 9 - -#define TMP007_STATUS_CONV_READY BIT(14) -#define TMP007_STATUS_DATA_VALID BIT(9) - -#define TMP007_MANUFACTURER_MAGIC 0x5449 -#define TMP007_DEVICE_MAGIC 0x0078 -
Quoted 9 lines
drivers/iio/temperature/tmp007.c line 35
Quoted 4 lines
drivers/iio/temperature/tmp007.c +3
-1-#define TMP007_TEMP_SHIFT 2 +#include <linux/iio/events.h> + +#define TMP007_TDIE 0x01this has a lot of clutter; the patch also reformats the #defines by adding
whitespace; don't do this in the same patch
Ack
Quoted 40 lines
drivers/iio/temperature/tmp007.c static int tmp007_read_temperature(struct
Quoted 39 lines
drivers/iio/temperature/tmp007.c +31
-0+#define TMP007_CONFIG 0x02 +#define TMP007_TOBJECT 0x03 +#define TMP007_STATUS 0x04 +#define TMP007_STATUS_MASK 0x05 +#define TMP007_TOBJ_HIGH_LIMIT 0x06 +#define TMP007_TOBJ_LOW_LIMIT 0x07 +#define TMP007_TDIE_HIGH_LIMIT 0x08 +#define TMP007_TDIE_LOW_LIMIT 0x09 +#define TMP007_MANUFACTURER_ID 0x1e +#define TMP007_DEVICE_ID 0x1f + +#define TMP007_CONFIG_CONV_EN BIT(12) +#define TMP007_CONFIG_TC_EN BIT(6) +#define TMP007_CONFIG_CR_MASK GENMASK(11, 9) +#define TMP007_CONFIG_ALERT_EN BIT(8) +#define TMP007_CONFIG_CR_SHIFT 9 + +/* Status register flags */ +#define TMP007_STATUS_ALERT BIT(15) +#define TMP007_STATUS_CONV_READY BIT(14) +#define TMP007_STATUS_OHF BIT(13) +#define TMP007_STATUS_OLF BIT(12) +#define TMP007_STATUS_LHF BIT(11) +#define TMP007_STATUS_LLF BIT(10) +#define TMP007_STATUS_DATA_VALID BIT(9) + +#define TMP007_MANUFACTURER_MAGIC 0x5449 +#define TMP007_DEVICE_MAGIC 0x0078 + +#define TMP007_TEMP_SHIFT 2struct tmp007_data {struct i2c_client *client;u16 config; +u16 status_mask; };static const int tmp007_avgs[5 ][2 ] = { {4 ,0 }, {2 ,0 }, {1 ,0 },@@ -70,7 +85,7 @@ static int tmp007_read_temperature(struct
tmp007_data*data, u8 reg)
Quoted 6 lines
drivers/iio/temperature/tmp007.c static int tmp007_read_temperature(struct tmp007_data *data, u8 reg) · line 73
Quoted 4 lines
drivers/iio/temperature/tmp007.c +0
-1return ret;if ((ret &TMP007_STATUS_CONV_READY ) && !(ret &TMP007_STATUS_DATA_VALID )) -break ;another unrelated cleanup
Ack
Quoted 10 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev
Quoted 6 lines
drivers/iio/temperature/tmp007.c +1
-0+break ;msleep (100 ); }@@ -156,6 +171,185 @@ static int tmp007_write_raw(struct iio_dev
*indio_dev,Quoted 3 lines
drivers/iio/temperature/tmp007.c +0
-0return -EINVAL ; }
Quoted 11 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 181
Quoted 8 lines
drivers/iio/temperature/tmp007.c +8
-0+static irqreturn_t tmp007_interrupt_handler (int irq,void *private) +{ +struct iio_dev *indio_dev = private; +struct tmp007_data *data =iio_priv (indio_dev); +int ret; + + ret =i2c_smbus_read_word_swapped (data->client,TMP007_STATUS ); +if (ret <0 )|| !(ret & (
_STATUSS_OHF|STATUS_OLF| ..))
Ack
Quoted 56 lines
Quoted 56 lines
drivers/iio/temperature/tmp007.c +56
-0+return IRQ_NONE ; + +if (ret &TMP007_STATUS_OHF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_OBJECT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_OLF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_OBJECT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_LHF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_AMBIENT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ), +iio_get_time_ns (indio_dev)); + +if (ret &TMP007_STATUS_LLF ) +iio_push_event (indio_dev, +IIO_MOD_EVENT_CODE (IIO_TEMP ,0 , +IIO_MOD_TEMP_AMBIENT , +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ), +iio_get_time_ns (indio_dev)); + +return IRQ_HANDLED ; +} + +static int tmp007_write_event_config (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,int state) +{ +struct tmp007_data *data =iio_priv (indio_dev); +unsigned int status_mask; +int ret; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + status_mask =TMP007_STATUS_LHF ; +else + status_mask =TMP007_STATUS_LLF ; +break ; +case IIO_MOD_TEMP_OBJECT : +if (dir ==IIO_EV_DIR_RISING ) + status_mask =TMP007_STATUS_OHF ; +else
Quoted 8 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 243
Quoted 6 lines
drivers/iio/temperature/tmp007.c +6
-0+ status_mask =TMP007_STATUS_OLF ; +break ; +default : +return -EINVAL ; + } +mutex around this?
Ack
Quoted 44 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev · line 244
Quoted 2 lines
drivers/iio/temperature/tmp007.c +1
-0+ ret = i2c_smbus_read_word_swapped(data->client,
TMP007_STATUS_MASK);drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev,
Quoted 9 lines
drivers/iio/temperature/tmp007.c +9
-0+if (ret <0 ) +return ret; + +if (state) + ret |= status_mask; +else + ret &= ~status_mask; + + return i2c_smbus_write_word_swapped(data->client,
TMP007_STATUS_MASK,Quoted 18 lines
drivers/iio/temperature/tmp007.c +18
-0+ data->status_mask = ret); +} + +static int tmp007_read_event_config (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir) +{ +struct tmp007_data *data =iio_priv (indio_dev); +unsigned int mask; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + mask =TMP007_STATUS_LHF ; +else + mask =TMP007_STATUS_LLF ; +break ; +case IIO_MOD_TEMP_OBJECT :drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 281
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+if (dir ==IIO_EV_DIR_RISING ) + mask =TMP007_STATUS_OHF ; +else + mask =TMP007_STATUS_OLF ; +break ; +default : +return -EINVAL ; + } + +return (bool )(data->status_mask & mask);return type is int, maybe use !! to force to 0/1
Quoted 1 line
return !!(data->status_mask & mask);
Ack
Quoted 61 lines
Quoted 61 lines
drivers/iio/temperature/tmp007.c +60
-0+} + +static int tmp007_read_thresh (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,enum iio_event_info info, +int *val,int *val2) +{ +struct tmp007_data *data =iio_priv (indio_dev); +int ret; +u8 reg; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT :/* LSB: 0.5 degree Celsius */ +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TDIE_HIGH_LIMIT ; +else + reg =TMP007_TDIE_LOW_LIMIT ; +break ; +case IIO_MOD_TEMP_OBJECT : +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TOBJ_HIGH_LIMIT ; +else + reg =TMP007_TOBJ_LOW_LIMIT ; +break ; +default : +return -EINVAL ; + } + + ret =i2c_smbus_read_word_swapped (data->client, reg); +if (ret <0 ) +return ret; + +/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ + *val =sign_extend32 (ret,15 ) >>7 ; + +return IIO_VAL_INT ; +} + +static int tmp007_write_thresh (struct iio_dev *indio_dev, +const struct iio_chan_spec *chan,enum iio_event_type type, +enum iio_event_direction dir,enum iio_event_info info, +int val,int val2) +{ +struct tmp007_data *data =iio_priv (indio_dev); +u8 reg; + +switch (chan->channel2) { +case IIO_MOD_TEMP_AMBIENT : +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TDIE_HIGH_LIMIT ; +else + reg =TMP007_TDIE_LOW_LIMIT ; +break ; +case IIO_MOD_TEMP_OBJECT : +if (dir ==IIO_EV_DIR_RISING ) + reg =TMP007_TOBJ_HIGH_LIMIT ; +else + reg =TMP007_TOBJ_LOW_LIMIT ; +break ; +default :
Quoted 9 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev, · line 345
Quoted 4 lines
drivers/iio/temperature/tmp007.c +4
-0+return -EINVAL ; + } + +/* Full scale value is +/- 256 degree Celsius */ I guess we want to specify milli degree Celsius according to sysfs-bus-iio
forin_temp_raw
I didn't get what your are suggesting. Could you please explain?
Quoted 70 lines
drivers/iio/temperature/tmp007.c static int tmp007_write_raw(struct iio_dev *indio_dev,
Quoted 8 lines
drivers/iio/temperature/tmp007.c +7
-0+if (val <-256 || val >255 ) +return -EINVAL ; + +/* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ +return i2c_smbus_write_word_swapped (data->client, reg, (val <<7 )); +} + static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.50.25");
drivers/iio/temperature/tmp007.c static const struct attribute_group
Quoted 3 lines
drivers/iio/temperature/tmp007.c +0
-0static struct attribute *tmp007_attributes[] = {@@ -167,6 +361,36 @@ static const struct attribute_group
tmp007_attribute_group= {drivers/iio/temperature/tmp007.c static const struct iio_chan_spec
Quoted 37 lines
drivers/iio/temperature/tmp007.c +30
-0.attrs = tmp007_attributes, }; +static const struct iio_event_spec tmp007_obj_event[] = { + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_RISING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_FALLING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, +}; + +static const struct iio_event_spec tmp007_die_event[] = { + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_RISING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, + { + .type =IIO_EV_TYPE_THRESH , + .dir =IIO_EV_DIR_FALLING , + .mask_separate =BIT (IIO_EV_INFO_VALUE ) | +BIT (IIO_EV_INFO_ENABLE ), + }, +}; +static const struct iio_chan_spec tmp007_channels[] = { { .type =IIO_TEMP ,@@ -175,6 +399,8 @@ static const struct iio_chan_spectmp007_channels[] = {
drivers/iio/temperature/tmp007.c static const struct iio_chan_spec
Quoted 9 lines
drivers/iio/temperature/tmp007.c +2
-0.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .event_spec = tmp007_die_event, + .num_event_specs = ARRAY_SIZE(tmp007_die_event), }, { .type = IIO_TEMP,@@ -183,12 +409,18 @@ static const struct iio_chan_spectmp007_channels[] = {
Quoted 9 lines
drivers/iio/temperature/tmp007.c +3
-1.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), - } + .event_spec = tmp007_obj_event, + .num_event_specs = ARRAY_SIZE(tmp007_obj_event), + }, };
Quoted 7 lines
drivers/iio/temperature/tmp007.c static const struct iio_chan_spec tmp007_channels[] = { · line 419
Quoted 5 lines
drivers/iio/temperature/tmp007.c +2
-2static const struct iio_info tmp007_info = { - .read_raw = tmp007_read_raw, - .write_raw = tmp007_write_raw, + .read_raw = &tmp007_read_raw, + .write_raw = &tmp007_write_raw,unrelated change, no need for & for a function
Ack
Quoted 78 lines
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client
Quoted 9 lines
drivers/iio/temperature/tmp007.c +4
-0+ .read_event_config = &tmp007_read_event_config, + .write_event_config = &tmp007_write_event_config, + .read_event_value = &tmp007_read_thresh, + .write_event_value = &tmp007_write_thresh, .attrs = &tmp007_attribute_group, .driver_module = THIS_MODULE, };@@ -214,7 +446,6 @@ static int tmp007_probe(struct i2c_client*client,
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client,
Quoted 6 lines
drivers/iio/temperature/tmp007.c +0
-1struct tmp007_data *data;struct iio_dev *indio_dev;int ret; -u16 status; if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA))drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client
Quoted 2 lines
drivers/iio/temperature/tmp007.c +0
-0return -EOPNOTSUPP ;@@ -243,8 +474,8 @@ static int tmp007_probe(struct i2c_client*client,
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client
Quoted 11 lines
drivers/iio/temperature/tmp007.c +2
-2/* * Set Configuration register: * 1. Conversion ON -* 2. Comparator mode -* 3. Transient correction enable +* 2. Transient correction enable +* 3. ALERT enable */ ret =i2c_smbus_read_word_swapped (data->client,TMP007_CONFIG );@@ -252,7 +483,7 @@ static int tmp007_probe(struct i2c_client*client,
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client,
Quoted 4 lines
drivers/iio/temperature/tmp007.c +0
-1return ret; data->config = ret; - data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_COMP_EN |
TMP007_CONFIG_TC_EN);drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client · line 486
Quoted 1 line
drivers/iio/temperature/tmp007.c +1
-0+ data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_TC_EN |
TMP007_CONFIG_ALERT_EN);drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client
Quoted 4 lines
drivers/iio/temperature/tmp007.c +0
-0ret =i2c_smbus_write_word_swapped (data->client,TMP007_CONFIG , data->config);@@ -260,22 +491,39 @@ static int tmp007_probe(struct i2c_client*client,
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client,
Quoted 4 lines
drivers/iio/temperature/tmp007.c +1
-0return ret;/* +* Only the following flags can activate ALERT pin. Data conversion/validity flags
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client,
Quoted 12 lines
drivers/iio/temperature/tmp007.c +6
-2+* flags can still be polled for getting temperature data +* * Set Status Mask register: -* 1. Conversion ready enable -* 2. Data valid enable +* 1. Object temperature high limit enable +* 2. Object temperature low limit enable +* 3. TDIE temperature high limit enable +* 4. TDIE temperature low limit enable */ ret = i2c_smbus_read_word_swapped(data->client,
TMP007_STATUS_MASK);drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client,
Quoted 10 lines
drivers/iio/temperature/tmp007.c +3
-3if (ret <0 ) goto error_powerdown; - status = ret; - status |= (TMP007_STATUS_CONV_READY |TMP007_STATUS_DATA_VALID ); + data->status_mask = ret; + data->status_mask |= (TMP007_STATUS_OHF |TMP007_STATUS_OLF + |TMP007_STATUS_LHF |TMP007_STATUS_LLF ); - ret = i2c_smbus_write_word_swapped(data->client,
TMP007_STATUS_MASK, status);drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client · line 512
Quoted 1 line
drivers/iio/temperature/tmp007.c +1
-0+ ret = i2c_smbus_write_word_swapped(data->client,
TMP007_STATUS_MASK,data->status_mask);Quoted 3 lines
drivers/iio/temperature/tmp007.c +0
-0if (ret <0 ) goto error_powerdown;
Quoted 14 lines
drivers/iio/temperature/tmp007.c static int tmp007_probe(struct i2c_client *client, · line 525
Quoted 10 lines
drivers/iio/temperature/tmp007.c +10
-0+if (client->irq) { + ret =devm_request_threaded_irq (&client->dev, client->irq, +NULL , tmp007_interrupt_handler, +IRQF_TRIGGER_FALLING |IRQF_ONESHOT , + tmp007_id->name, indio_dev); +if (ret) { +dev_err (&client->dev,"irq request error %d\n" , -ret); + goto error_powerdown; + } + }what happens when there is no IRQ? it would be nice to still use the driver (without event capability)
I guess if (client->irq) checks for it. And believe it works without interrupt as well. Correct me if I'm wrong.
Quoted 12 lines
drivers/iio/temperature/tmp007.c static int tmp007_resume(struct device *dev) · line 563
Quoted 9 lines
drivers/iio/temperature/tmp007.c +2
-0+return iio_device_register (indio_dev); error_powerdown:@@ -312,6 +560,16 @@ static int tmp007_resume(struct device *dev)return i2c_smbus_write_word_swapped (data->client,TMP007_CONFIG , data->config | TMP007_CONFIG_CONV_EN); } +#else this seems to be unrelated to the patch
Ack
Quoted 14 lines
drivers/iio/temperature/tmp007.c static int tmp007_resume(struct device *dev)
Quoted 12 lines
drivers/iio/temperature/tmp007.c +9
-0+static int tmp007_suspend (struct device *dev) +{ +return 0 ; +} + +static int tmp007_resume (struct device *dev) +{ +return 0 ; +}#endif static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend,
tmp007_resume);Quoted 1 line
Signature · 5 lines
Sent from my Android device with K-9 Mail. Please excuse my brevity. -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Rob Herring
Acked-byQuoted 9 lines · Manivannan Sadhasivam
This patch adds support for ALERT irq and limit threshold events for TI TMP007 - 16 bit IR thermopile sensor with integrated math engine.
Following threshold events are supported:
1. TObj high limit
2. TObj low limit
3. TDie high limit
4. TDie low limit
Quoted 3 lines
Signed-off-by Manivannan Sadhasivam <[email protected]>--- .../devicetree/bindings/iio/temperature/tmp007.txt | 8 +
Quoted 2 lines
drivers/iio/temperature/tmp007.c | 334 ++++++++++++++++++--- 2 files changed, 304 insertions(+), 38 deletions(-)