Skip to content

Commit 26fff11

Browse files
committed
drivers: sensor: tmp11x: add trigger for alert & p,
Allows to configure the alert or therm mode for triggers based on the low/high temperature treshholds Also adding simple PM Signed-off-by: Tobias Meyer <[email protected]>
1 parent 9d0942b commit 26fff11

File tree

11 files changed

+448
-18
lines changed

11 files changed

+448
-18
lines changed

drivers/sensor/ti/tmp11x/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
zephyr_library()
44

55
zephyr_library_sources(tmp11x.c)
6+
zephyr_library_sources_ifdef(CONFIG_TMP11X_TRIGGER tmp11x_trigger.c)

drivers/sensor/ti/tmp11x/Kconfig

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,46 @@ config TMP11X
1010
select I2C
1111
help
1212
Enable driver for TMP116, TMP117 and TMP119 temperature sensors.
13+
14+
choice
15+
prompt "TMP11X Alert Pin Trigger Mode"
16+
default TMP11X_TRIGGER_GLOBAL_THREAD
17+
depends on TMP11X
18+
19+
config TMP11X_TRIGGER_NONE
20+
bool "No trigger"
21+
22+
config TMP11X_TRIGGER_GLOBAL_THREAD
23+
bool "Use global thread"
24+
depends on GPIO
25+
select TMP11X_TRIGGER
26+
27+
config TMP11X_TRIGGER_OWN_THREAD
28+
bool "Use own thread"
29+
depends on GPIO
30+
select TMP11X_TRIGGER
31+
32+
endchoice
33+
34+
config TMP11X_TRIGGER
35+
bool
36+
depends on GPIO
37+
help
38+
Enable support for the TMP11X alert pin functionality.
39+
The alert pin can be configured to trigger when temperature
40+
exceeds configurable high/low thresholds. This is supported
41+
on TMP116, TMP117, and TMP119 devices.
42+
43+
config TMP11X_THREAD_PRIORITY
44+
int "Thread priority"
45+
depends on TMP11X_TRIGGER_OWN_THREAD
46+
default 10
47+
help
48+
Priority of thread used by the driver to handle interrupts.
49+
50+
config TMP11X_THREAD_STACK_SIZE
51+
int "Thread stack size"
52+
depends on TMP11X_TRIGGER_OWN_THREAD
53+
default 1024
54+
help
55+
Stack size of thread used by the driver to handle interrupts.

drivers/sensor/ti/tmp11x/tmp11x.c

Lines changed: 147 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/device.h>
1010
#include <zephyr/drivers/i2c.h>
1111
#include <zephyr/drivers/sensor.h>
12+
#include <zephyr/pm/device.h>
1213
#include <zephyr/drivers/sensor/tmp11x.h>
1314
#include <zephyr/dt-bindings/sensor/tmp11x.h>
1415
#include <zephyr/sys/util.h>
@@ -25,8 +26,7 @@
2526

2627
LOG_MODULE_REGISTER(TMP11X, CONFIG_SENSOR_LOG_LEVEL);
2728

28-
static int tmp11x_reg_read(const struct device *dev, uint8_t reg,
29-
uint16_t *val)
29+
int tmp11x_reg_read(const struct device *dev, uint8_t reg, uint16_t *val)
3030
{
3131
const struct tmp11x_dev_config *cfg = dev->config;
3232

@@ -40,8 +40,7 @@ static int tmp11x_reg_read(const struct device *dev, uint8_t reg,
4040
return 0;
4141
}
4242

43-
static int tmp11x_reg_write(const struct device *dev, uint8_t reg,
44-
uint16_t val)
43+
int tmp11x_reg_write(const struct device *dev, uint8_t reg, uint16_t val)
4544
{
4645
const struct tmp11x_dev_config *cfg = dev->config;
4746
uint8_t tx_buf[3] = {reg, val >> 8, val & 0xFF};
@@ -71,6 +70,31 @@ static inline bool tmp11x_is_offset_supported(const struct tmp11x_data *drv_data
7170
return drv_data->id == TMP117_DEVICE_ID || drv_data->id == TMP119_DEVICE_ID;
7271
}
7372

73+
/**
74+
* @brief Convert sensor_value temperature to TMP11X register format
75+
*
76+
* This function converts a temperature from sensor_value format (val1 in degrees C,
77+
* val2 in micro-degrees C) to the TMP11X register format. It uses 64-bit arithmetic
78+
* to prevent overflow and clamps the result to the valid int16_t range.
79+
*
80+
* @param val Pointer to sensor_value containing temperature
81+
* @return Temperature value in TMP11X register format (int16_t)
82+
*/
83+
static inline int16_t tmp11x_sensor_value_to_reg_format(const struct sensor_value *val)
84+
{
85+
int64_t temp_micro = ((int64_t)val->val1 * 1000000) + val->val2;
86+
int64_t temp_scaled = (temp_micro * 10) / TMP11X_RESOLUTION;
87+
88+
/* Clamp to int16_t range */
89+
if (temp_scaled > INT16_MAX) {
90+
return INT16_MAX;
91+
} else if (temp_scaled < INT16_MIN) {
92+
return INT16_MIN;
93+
} else {
94+
return (int16_t)temp_scaled;
95+
}
96+
}
97+
7498
static bool check_eeprom_bounds(const struct device *dev, off_t offset,
7599
size_t len)
76100
{
@@ -310,8 +334,7 @@ static int tmp11x_attr_set(const struct device *dev,
310334
/*
311335
* The offset is encoded into the temperature register format.
312336
*/
313-
value = (((val->val1) * 10000000) + ((val->val2) * 10))
314-
/ (int32_t)TMP11X_RESOLUTION;
337+
value = tmp11x_sensor_value_to_reg_format(val);
315338

316339
return tmp11x_reg_write(dev, TMP117_REG_TEMP_OFFSET, value);
317340

@@ -347,6 +370,41 @@ static int tmp11x_attr_set(const struct device *dev,
347370
case SENSOR_ATTR_TMP11X_ONE_SHOT_MODE:
348371
return tmp11x_write_config(dev, TMP11X_CFGR_MODE, TMP11X_MODE_ONE_SHOT);
349372

373+
#ifdef CONFIG_TMP11X_TRIGGER
374+
case SENSOR_ATTR_TMP11X_ALERT_PIN_POLARITY:
375+
if (val->val1 == TMP11X_ALERT_PIN_ACTIVE_HIGH) {
376+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_POL,
377+
TMP11X_CFGR_ALERT_PIN_POL);
378+
} else {
379+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_POL, 0);
380+
}
381+
382+
case SENSOR_ATTR_TMP11X_ALERT_MODE:
383+
if (val->val1 == TMP11X_ALERT_THERM_MODE) {
384+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_MODE,
385+
TMP11X_CFGR_ALERT_MODE);
386+
} else {
387+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_MODE, 0);
388+
}
389+
390+
case SENSOR_ATTR_UPPER_THRESH:
391+
/* Convert temperature to register format */
392+
value = tmp11x_sensor_value_to_reg_format(val);
393+
return tmp11x_reg_write(dev, TMP11X_REG_HIGH_LIM, value);
394+
395+
case SENSOR_ATTR_LOWER_THRESH:
396+
/* Convert temperature to register format */
397+
value = tmp11x_sensor_value_to_reg_format(val);
398+
return tmp11x_reg_write(dev, TMP11X_REG_LOW_LIM, value);
399+
case SENSOR_ATTR_TMP11X_ALERT_PIN_SELECT:
400+
if (val->val1 == TMP11X_ALERT_PIN_ALERT_SEL) {
401+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_DR_SEL, 0);
402+
} else {
403+
return tmp11x_write_config(dev, TMP11X_CFGR_ALERT_DR_SEL,
404+
TMP11X_CFGR_ALERT_DR_SEL);
405+
}
406+
#endif /* CONFIG_TMP11X_TRIGGER */
407+
350408
default:
351409
return -ENOTSUP;
352410
}
@@ -385,6 +443,25 @@ static int tmp11x_attr_get(const struct device *dev, enum sensor_channel chan,
385443
}
386444

387445
return rc;
446+
447+
#ifdef CONFIG_TMP11X_TRIGGER
448+
case SENSOR_ATTR_UPPER_THRESH:
449+
rc = tmp11x_reg_read(dev, TMP11X_REG_HIGH_LIM, &data);
450+
if (rc == 0) {
451+
tmp11x_temperature_to_sensor_value(data, val);
452+
}
453+
454+
return rc;
455+
456+
case SENSOR_ATTR_LOWER_THRESH:
457+
rc = tmp11x_reg_read(dev, TMP11X_REG_LOW_LIM, &data);
458+
if (rc == 0) {
459+
tmp11x_temperature_to_sensor_value(data, val);
460+
}
461+
462+
return rc;
463+
#endif /* CONFIG_TMP11X_TRIGGER */
464+
388465
default:
389466
return -ENOTSUP;
390467
}
@@ -394,7 +471,10 @@ static DEVICE_API(sensor, tmp11x_driver_api) = {
394471
.attr_set = tmp11x_attr_set,
395472
.attr_get = tmp11x_attr_get,
396473
.sample_fetch = tmp11x_sample_fetch,
397-
.channel_get = tmp11x_channel_get
474+
.channel_get = tmp11x_channel_get,
475+
#ifdef CONFIG_TMP11X_TRIGGER
476+
.trigger_set = tmp11x_trigger_set,
477+
#endif
398478
};
399479

400480
static int tmp11x_init(const struct device *dev)
@@ -424,18 +504,68 @@ static int tmp11x_init(const struct device *dev)
424504

425505
rc = tmp11x_write_config(dev, TMP11X_CFGR_AVG, cfg->oversampling);
426506

507+
rc = tmp11x_write_config(dev, TMP11X_CFGR_ALERT_PIN_POL, cfg->alert_pin_polarity);
508+
509+
rc = tmp11x_write_config(dev, TMP11X_CFGR_ALERT_MODE, cfg->alert_mode);
510+
511+
rc = tmp11x_write_config(dev, TMP11X_CFGR_ALERT_DR_SEL, cfg->alert_dr_sel);
512+
513+
#ifdef CONFIG_TMP11X_TRIGGER
514+
drv_data->dev = dev;
515+
rc = tmp11x_init_interrupt(dev);
516+
if (rc < 0) {
517+
LOG_ERR("%s: Failed to initialize alert pin", dev->name);
518+
return rc;
519+
}
520+
#endif /* CONFIG_TMP11X_TRIGGER */
521+
427522
return rc;
428523
}
429524

430-
#define DEFINE_TMP11X(_num) \
431-
static struct tmp11x_data tmp11x_data_##_num; \
432-
static const struct tmp11x_dev_config tmp11x_config_##_num = { \
433-
.bus = I2C_DT_SPEC_INST_GET(_num), \
434-
.odr = DT_INST_PROP(_num, odr), \
435-
.oversampling = DT_INST_PROP(_num, oversampling), \
436-
}; \
437-
SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp11x_init, NULL, \
438-
&tmp11x_data_##_num, &tmp11x_config_##_num, POST_KERNEL, \
439-
CONFIG_SENSOR_INIT_PRIORITY, &tmp11x_driver_api);
525+
#ifdef CONFIG_PM_DEVICE
526+
static int tmp11x_pm_control(const struct device *dev, enum pm_device_action action)
527+
{
528+
int ret = 0;
529+
530+
switch (action) {
531+
case PM_DEVICE_ACTION_RESUME:
532+
const struct tmp11x_dev_config *cfg = dev->config;
533+
534+
ret = tmp11x_write_config(dev, TMP11X_CFGR_CONV, cfg->odr);
535+
if (ret < 0) {
536+
LOG_ERR("Failed to resume TMP11X");
537+
}
538+
break;
539+
540+
case PM_DEVICE_ACTION_SUSPEND:
541+
ret = tmp11x_write_config(dev, TMP11X_CFGR_MODE, TMP11X_MODE_SHUTDOWN);
542+
if (ret < 0) {
543+
LOG_ERR("Failed to suspend TMP11X");
544+
}
545+
break;
546+
547+
default:
548+
ret = -ENOTSUP;
549+
}
550+
551+
return ret;
552+
}
553+
#endif /* CONFIG_PM_DEVICE */
554+
555+
#define DEFINE_TMP11X(_num) \
556+
static struct tmp11x_data tmp11x_data_##_num; \
557+
static const struct tmp11x_dev_config tmp11x_config_##_num = { \
558+
.bus = I2C_DT_SPEC_INST_GET(_num), \
559+
.odr = DT_INST_PROP(_num, odr), \
560+
.oversampling = DT_INST_PROP(_num, oversampling), \
561+
.alert_pin_polarity = DT_INST_PROP(_num, alert_polarity), \
562+
.alert_mode = DT_INST_PROP(_num, alert_mode), \
563+
.alert_dr_sel = DT_INST_PROP(_num, alert_dr_sel), \
564+
IF_ENABLED(CONFIG_TMP11X_TRIGGER, \
565+
(.alert_gpio = GPIO_DT_SPEC_INST_GET_OR(_num, alert_gpios, {}),)) }; \
566+
PM_DEVICE_DT_INST_DEFINE(_num, tmp11x_pm_control); \
567+
SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp11x_init, PM_DEVICE_DT_INST_GET(_num), \
568+
&tmp11x_data_##_num, &tmp11x_config_##_num, POST_KERNEL, \
569+
CONFIG_SENSOR_INIT_PRIORITY, &tmp11x_driver_api);
440570

441571
DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMP11X)

drivers/sensor/ti/tmp11x/tmp11x.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#define ZEPHYR_DRIVERS_SENSOR_TMP11X_TMP11X_H_
99

1010
#include <zephyr/sys/util_macro.h>
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/drivers/i2c.h>
1113

1214
#define TMP11X_REG_TEMP 0x0
1315
#define TMP11X_REG_CFGR 0x1
@@ -35,6 +37,12 @@
3537
#define TMP11X_EEPROM_UL_UNLOCK BIT(15)
3638
#define TMP11X_EEPROM_UL_BUSY BIT(14)
3739

40+
/* Alert pin configuration bits */
41+
/* Alert pin configuration bits */
42+
#define TMP11X_CFGR_ALERT_DR_SEL BIT(2) /* ALERT pin select (1=Data ready) (0=alert) */
43+
#define TMP11X_CFGR_ALERT_PIN_POL BIT(3) /* Alert pin polarity */
44+
#define TMP11X_CFGR_ALERT_MODE BIT(4) /* Alert pin mode (1=therm, 0=alert) */
45+
3846
#define TMP11X_AVG_1_SAMPLE 0
3947
#define TMP11X_AVG_8_SAMPLES BIT(5)
4048
#define TMP11X_AVG_32_SAMPLES BIT(6)
@@ -46,12 +54,42 @@
4654
struct tmp11x_data {
4755
uint16_t sample;
4856
uint16_t id;
57+
#ifdef CONFIG_TMP11X_TRIGGER
58+
const struct device *dev;
59+
struct gpio_callback alert_cb;
60+
sensor_trigger_handler_t alert_handler;
61+
const struct sensor_trigger *alert_trigger;
62+
63+
#if defined(CONFIG_TMP11X_TRIGGER_OWN_THREAD)
64+
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TMP11X_THREAD_STACK_SIZE);
65+
struct k_thread thread;
66+
struct k_sem gpio_sem;
67+
#elif defined(CONFIG_TMP11X_TRIGGER_GLOBAL_THREAD)
68+
struct k_work work;
69+
#endif /* CONFIG_TMP11X_TRIGGER_OWN_THREAD */
70+
#endif /* CONFIG_TMP11X_TRIGGER */
4971
};
5072

5173
struct tmp11x_dev_config {
5274
struct i2c_dt_spec bus;
5375
uint16_t odr;
5476
uint16_t oversampling;
77+
bool alert_pin_polarity;
78+
bool alert_mode;
79+
bool alert_dr_sel;
80+
#ifdef CONFIG_TMP11X_TRIGGER
81+
struct gpio_dt_spec alert_gpio;
82+
#endif
5583
};
5684

85+
/* Function declarations */
86+
int tmp11x_write_config(const struct device *dev, uint16_t mask, uint16_t conf);
87+
int tmp11x_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
88+
89+
#ifdef CONFIG_TMP11X_TRIGGER
90+
int tmp11x_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
91+
sensor_trigger_handler_t handler);
92+
int tmp11x_init_interrupt(const struct device *dev);
93+
#endif
94+
5795
#endif /* ZEPHYR_DRIVERS_SENSOR_TMP11X_TMP11X_H_ */

0 commit comments

Comments
 (0)