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 )
@@ -423,19 +503,85 @@ static int tmp11x_init(const struct device *dev)
423
503
}
424
504
425
505
rc = tmp11x_write_config (dev , TMP11X_CFGR_AVG , cfg -> oversampling );
506
+ if (rc < 0 ) {
507
+ return rc ;
508
+ }
509
+
510
+ int8_t value = cfg -> alert_pin_polarity ? TMP11X_CFGR_ALERT_PIN_POL : 0 ;
511
+ rc = tmp11x_write_config (dev , TMP11X_CFGR_ALERT_PIN_POL , value );
512
+ if (rc < 0 ) {
513
+ return rc ;
514
+ }
515
+
516
+ value = cfg -> alert_mode ? TMP11X_CFGR_ALERT_MODE : 0 ;
517
+ rc = tmp11x_write_config (dev , TMP11X_CFGR_ALERT_MODE , value );
518
+ if (rc < 0 ) {
519
+ return rc ;
520
+ }
521
+
522
+ value = cfg -> alert_dr_sel ? TMP11X_CFGR_ALERT_DR_SEL : 0 ;
523
+ rc = tmp11x_write_config (dev , TMP11X_CFGR_ALERT_DR_SEL , value );
524
+ if (rc < 0 ) {
525
+ return rc ;
526
+ }
527
+
528
+ #ifdef CONFIG_TMP11X_TRIGGER
529
+ drv_data -> dev = dev ;
530
+ rc = tmp11x_init_interrupt (dev );
531
+ if (rc < 0 ) {
532
+ LOG_ERR ("%s: Failed to initialize alert pin" , dev -> name );
533
+ return rc ;
534
+ }
535
+ #endif /* CONFIG_TMP11X_TRIGGER */
426
536
427
537
return rc ;
428
538
}
429
539
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);
540
+ #ifdef CONFIG_PM_DEVICE
541
+ BUILD_ASSERT (!DT_INST_NODE_HAS_PROP (_num , power_domains ), "Driver does not support power domain" );
542
+ static int tmp11x_pm_control (const struct device * dev , enum pm_device_action action )
543
+ {
544
+ int ret = 0 ;
545
+
546
+ switch (action ) {
547
+ case PM_DEVICE_ACTION_RESUME : {
548
+ const struct tmp11x_dev_config * cfg = dev -> config ;
549
+
550
+ ret = tmp11x_write_config (dev , TMP11X_CFGR_CONV , cfg -> odr );
551
+ if (ret < 0 ) {
552
+ LOG_ERR ("Failed to resume TMP11X" );
553
+ }
554
+ break ;
555
+ }
556
+ case PM_DEVICE_ACTION_SUSPEND : {
557
+ ret = tmp11x_write_config (dev , TMP11X_CFGR_MODE , TMP11X_MODE_SHUTDOWN );
558
+ if (ret < 0 ) {
559
+ LOG_ERR ("Failed to suspend TMP11X" );
560
+ }
561
+ break ;
562
+ }
563
+ default :
564
+ ret = - ENOTSUP ;
565
+ }
566
+
567
+ return ret ;
568
+ }
569
+ #endif /* CONFIG_PM_DEVICE */
570
+
571
+ #define DEFINE_TMP11X (_num ) \
572
+ static struct tmp11x_data tmp11x_data_##_num; \
573
+ static const struct tmp11x_dev_config tmp11x_config_##_num = { \
574
+ .bus = I2C_DT_SPEC_INST_GET(_num), \
575
+ .odr = DT_INST_PROP(_num, odr), \
576
+ .oversampling = DT_INST_PROP(_num, oversampling), \
577
+ .alert_pin_polarity = DT_INST_PROP(_num, alert_polarity), \
578
+ .alert_mode = DT_INST_PROP(_num, alert_mode), \
579
+ .alert_dr_sel = DT_INST_PROP(_num, alert_dr_sel), \
580
+ IF_ENABLED(CONFIG_TMP11X_TRIGGER, \
581
+ (.alert_gpio = GPIO_DT_SPEC_INST_GET_OR(_num, alert_gpios, {}),)) }; \
582
+ PM_DEVICE_DT_INST_DEFINE(_num, tmp11x_pm_control); \
583
+ SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp11x_init, PM_DEVICE_DT_INST_GET(_num), \
584
+ &tmp11x_data_##_num, &tmp11x_config_##_num, POST_KERNEL, \
585
+ CONFIG_SENSOR_INIT_PRIORITY, &tmp11x_driver_api);
440
586
441
587
DT_INST_FOREACH_STATUS_OKAY (DEFINE_TMP11X )
0 commit comments