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