99#include <zephyr/device.h>
1010#include <zephyr/drivers/i2c.h>
1111#include <zephyr/drivers/sensor.h>
12- #include <zephyr/drivers/sensor/tmp11x .h>
12+ #include <zephyr/pm/device .h>
1313#include <zephyr/dt-bindings/sensor/tmp11x.h>
14+
1415#include <zephyr/sys/util.h>
1516#include <zephyr/sys/byteorder.h>
1617#include <zephyr/sys/__assert.h>
2526
2627LOG_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+
7498static 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
400480static 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
441571DT_INST_FOREACH_STATUS_OKAY (DEFINE_TMP11X )
0 commit comments