1010#include <zephyr/drivers/sensor.h>
1111#include <zephyr/drivers/adc.h>
1212#include <zephyr/logging/log.h>
13+ #include <zephyr/sys/util.h>
1314
1415LOG_MODULE_REGISTER (nxp_pmc_tmpsns , CONFIG_SENSOR_LOG_LEVEL );
1516
1617#define DT_DRV_COMPAT nxp_pmc_tmpsns
1718
19+ #if !CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
20+ /* Scale factor for 3 decimal places */
21+ #define NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR 1000
22+ /* For intermediate calculations */
23+ #define NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR_LARGE 1000000
24+
25+ #define NXP_PMC_TMPSNS_TEMP_KELVIN_TO_CELSIUS_SCALED 273150 /* 273.15 * 1000 */
26+ #define NXP_PMC_TMPSNS_TEMP_COEFFICIENT_SCALED 370980 /* 370.98 * 1000 */
27+ #define NXP_PMC_TMPSNS_VREF_BASE_OFFSET_SCALED 953360 /* 953.36 * 1000 */
28+ #define NXP_PMC_TMPSNS_VREF_SCALE_FACTOR 2048 /* Already an integer */
29+ #define NXP_PMC_TMPSNS_CALIBRATION_MASK 0xFF
30+ #endif
31+
1832struct nxp_pmc_tmpsns_config {
1933 const struct device * adc ;
2034 struct adc_sequence adc_seq ;
@@ -27,14 +41,80 @@ struct nxp_pmc_tmpsns_data {
2741 float pmc_tmpsns_value ;
2842};
2943
44+ #if !CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
45+ /**
46+ * Calculate weighted average for CTAT using integer arithmetic
47+ * Result is scaled by 1000 for precision.
48+ */
49+ static inline int32_t calculate_cm_ctat_int (const int16_t * values )
50+ {
51+ int32_t sum = (2 * values [1 ] - values [2 ] +
52+ 2 * values [13 ] - values [12 ] +
53+ 2 * values [6 ] - values [5 ] +
54+ 2 * values [8 ] - values [9 ]);
55+
56+ return (sum * 250 );
57+ }
58+
59+ /**
60+ * Calculate weighted average for temperature using integer arithmetic
61+ * Result is scaled by 1000 for precision.
62+ */
63+ static inline int32_t calculate_cm_temp_int (const int16_t * values )
64+ {
65+ int32_t sum = (2 * values [0 ] - values [3 ] +
66+ 2 * values [14 ] - values [11 ] +
67+ 4 * values [7 ] - values [4 ] - values [10 ]);
68+
69+ return (sum * 250 );
70+ }
71+
72+ /**
73+ * Calculate temperature in millidegrees Celsius using integer arithmetic.
74+ */
75+ static int32_t get_temperature_millidegrees (struct nxp_pmc_tmpsns_data * data ,
76+ const int16_t * pmc_tmpsns_value )
77+ {
78+ if (!data || !pmc_tmpsns_value ) {
79+ return - EINVAL ;
80+ }
81+
82+ /* Calculate temperature sensor components (scaled by 1000) */
83+ int32_t cm_ctat_scaled = calculate_cm_ctat_int (pmc_tmpsns_value );
84+ int32_t cm_temp_scaled = calculate_cm_temp_int (pmc_tmpsns_value );
85+
86+ /* Extract calibration value */
87+ int32_t calibration = (int8_t )(data -> pmc_tmpsns_calibration &
88+ NXP_PMC_TMPSNS_CALIBRATION_MASK );
89+
90+ /* Calculate reference voltage with calibration */
91+ int64_t vref_numerator = (int64_t )(NXP_PMC_TMPSNS_VREF_BASE_OFFSET_SCALED +
92+ calibration * NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR ) * cm_temp_scaled ;
93+ int32_t cm_vref_scaled = cm_ctat_scaled + (int32_t )(vref_numerator /
94+ (NXP_PMC_TMPSNS_VREF_SCALE_FACTOR * NXP_PMC_TMPSNS_TEMP_SCALE_FACTOR ));
95+
96+ if (cm_vref_scaled == 0 ) {
97+ return - EINVAL ;
98+ }
99+
100+ /* Calculate temperature in millidegrees Celsius */
101+ int64_t temp_ratio = ((int64_t )NXP_PMC_TMPSNS_TEMP_COEFFICIENT_SCALED *
102+ cm_temp_scaled ) / cm_vref_scaled ;
103+
104+ return (int32_t )temp_ratio - NXP_PMC_TMPSNS_TEMP_KELVIN_TO_CELSIUS_SCALED ;
105+ }
106+ #endif
107+
30108static int nxp_pmc_tmpsns_sample_fetch (const struct device * dev , enum sensor_channel chan )
31109{
32110 uint8_t pmc_tmpsns_select [15 ] = {0 , 1 , 3 , 2 , 6 , 7 , 5 , 4 , 5 , 7 , 6 , 2 , 3 , 1 , 0 };
33111 const struct nxp_pmc_tmpsns_config * config = dev -> config ;
34112 struct nxp_pmc_tmpsns_data * data = dev -> data ;
35113 uint16_t pmc_tmpsns_value [15 ] = {0 };
114+ #if CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
36115 float cm_vref , cm_ctat , cm_temp ;
37116 int8_t calibration = 0 ;
117+ #endif
38118 int ret ;
39119
40120 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP ) {
@@ -52,6 +132,7 @@ static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_cha
52132 pmc_tmpsns_value [index ] = data -> buffer ;
53133 }
54134
135+ #if CONFIG_NXP_PMC_TMPSNS_USE_FLOAT_CALC
55136 cm_ctat = (float )(2 * pmc_tmpsns_value [1 ] - pmc_tmpsns_value [2 ] +
56137 2 * pmc_tmpsns_value [13 ] - pmc_tmpsns_value [12 ] +
57138 2 * pmc_tmpsns_value [6 ] - pmc_tmpsns_value [5 ] +
@@ -67,6 +148,9 @@ static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_cha
67148 cm_vref = cm_ctat + (953.36f + calibration ) * cm_temp / 2048 ;
68149
69150 data -> pmc_tmpsns_value = 370.98f * (cm_temp / cm_vref ) - 273.15f ;
151+ #else
152+ data -> pmc_tmpsns_value = get_temperature_millidegrees (data , pmc_tmpsns_value ) / 1000.0f ;
153+ #endif
70154
71155 return 0 ;
72156}
0 commit comments