9
9
#include <zephyr/device.h>
10
10
#include <zephyr/drivers/i2c.h>
11
11
#include <zephyr/drivers/sensor.h>
12
+ #include <zephyr/pm/device.h>
12
13
#include <zephyr/drivers/sensor/tmp11x.h>
13
14
#include <zephyr/dt-bindings/sensor/tmp11x.h>
14
15
#include <zephyr/sys/util.h>
25
26
26
27
LOG_MODULE_REGISTER (TMP11X , CONFIG_SENSOR_LOG_LEVEL );
27
28
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 )
30
30
{
31
31
const struct tmp11x_dev_config * cfg = dev -> config ;
32
32
@@ -40,8 +40,7 @@ static int tmp11x_reg_read(const struct device *dev, uint8_t reg,
40
40
return 0 ;
41
41
}
42
42
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 )
45
44
{
46
45
const struct tmp11x_dev_config * cfg = dev -> config ;
47
46
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
71
70
return drv_data -> id == TMP117_DEVICE_ID || drv_data -> id == TMP119_DEVICE_ID ;
72
71
}
73
72
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
+
74
98
static bool check_eeprom_bounds (const struct device * dev , off_t offset ,
75
99
size_t len )
76
100
{
@@ -310,8 +334,7 @@ static int tmp11x_attr_set(const struct device *dev,
310
334
/*
311
335
* The offset is encoded into the temperature register format.
312
336
*/
313
- value = (((val -> val1 ) * 10000000 ) + ((val -> val2 ) * 10 ))
314
- / (int32_t )TMP11X_RESOLUTION ;
337
+ value = tmp11x_sensor_value_to_reg_format (val );
315
338
316
339
return tmp11x_reg_write (dev , TMP117_REG_TEMP_OFFSET , value );
317
340
@@ -347,6 +370,41 @@ static int tmp11x_attr_set(const struct device *dev,
347
370
case SENSOR_ATTR_TMP11X_ONE_SHOT_MODE :
348
371
return tmp11x_write_config (dev , TMP11X_CFGR_MODE , TMP11X_MODE_ONE_SHOT );
349
372
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
+
350
408
default :
351
409
return - ENOTSUP ;
352
410
}
@@ -385,6 +443,25 @@ static int tmp11x_attr_get(const struct device *dev, enum sensor_channel chan,
385
443
}
386
444
387
445
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
+
388
465
default :
389
466
return - ENOTSUP ;
390
467
}
@@ -394,7 +471,10 @@ static DEVICE_API(sensor, tmp11x_driver_api) = {
394
471
.attr_set = tmp11x_attr_set ,
395
472
.attr_get = tmp11x_attr_get ,
396
473
.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
398
478
};
399
479
400
480
static int tmp11x_init (const struct device * dev )
@@ -424,18 +504,68 @@ static int tmp11x_init(const struct device *dev)
424
504
425
505
rc = tmp11x_write_config (dev , TMP11X_CFGR_AVG , cfg -> oversampling );
426
506
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
+
427
522
return rc ;
428
523
}
429
524
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);
440
570
441
571
DT_INST_FOREACH_STATUS_OKAY (DEFINE_TMP11X )
0 commit comments