1 /*
2  * Copyright 2020-2023 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_tempsensor.h"
10 #include "math.h"
11 
12 /*******************************************************************************
13  * Definitions
14  ******************************************************************************/
15 
16 /* Component ID definition, used by tools. */
17 #ifndef FSL_COMPONENT_ID
18 #define FSL_COMPONENT_ID "platform.drivers.tempsensor"
19 #endif
20 
21 /*******************************************************************************
22  * Prototypes
23  ******************************************************************************/
24 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
25 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data);
26 static uint32_t TMPSNS_AIReadAccess(uint32_t address);
27 #endif
28 
29 /*******************************************************************************
30  * Variables
31  ******************************************************************************/
32 const static float s_Ts20   = 133.6f;
33 const static float s_Ts21   = -5.39f;
34 const static float s_Ts21_2 = 29.0521f; /*!< It means (s_Ts21* s_Ts21) */
35 const static float s_Ts22   = 0.002f;
36 static float s_Ts25c;
37 
38 /*******************************************************************************
39  * Code
40  ******************************************************************************/
41 /*!
42  * brief Initializes the TMPSNS module.
43  *
44  * param base TMPSNS base pointer
45  * param config Pointer to configuration structure.
46  */
TMPSNS_Init(TMPSNS_Type * base,const tmpsns_config_t * config)47 void TMPSNS_Init(TMPSNS_Type *base, const tmpsns_config_t *config)
48 {
49     assert(NULL != config);
50 
51     uint32_t controlVal = 0x00U;
52     uint32_t temp;
53 
54     temp =
55         (ANADIG_TEMPSENSOR_TEMPSNS_OTP_TRIM_VALUE_TEMPSNS_TEMP_VAL_MASK & ANADIG_TEMPSENSOR->TEMPSNS_OTP_TRIM_VALUE) >>
56         10;
57     s_Ts25c = (float)temp;
58 
59     /* Reset Tempsensor first. */
60 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
61     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
62 #else
63     controlVal  = base->CTRL1;
64 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
65 
66     controlVal |= (TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK);
67     controlVal &= (~(TMPSNS_CTRL1_START_MASK | TMPSNS_CTRL1_FINISH_IE_MASK | TMPSNS_CTRL1_LOW_TEMP_IE_MASK |
68                      TMPSNS_CTRL1_HIGH_TEMP_IE_MASK | TMPSNS_CTRL1_PANIC_TEMP_IE_MASK | TMPSNS_CTRL1_FREQ_MASK));
69 
70 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
71     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
72 #else
73     base->CTRL1 = controlVal;
74 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
75 
76     /* Set alarm temperature */
77     TMPSNS_SetTempAlarm(base, config->highAlarmTemp, kTEMPMON_HighAlarmMode);
78     TMPSNS_SetTempAlarm(base, config->panicAlarmTemp, kTEMPMON_PanicAlarmMode);
79     TMPSNS_SetTempAlarm(base, config->lowAlarmTemp, kTEMPMON_LowAlarmMode);
80 
81 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
82     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
83 #else
84     controlVal  = base->CTRL1;
85 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
86 
87     /* Enable finish interrupt status */
88     controlVal |= TMPSNS_CTRL1_FINISH_IE_MASK;
89 
90     if (config->measureMode == kTEMPSENSOR_SingleMode)
91     {
92         controlVal |= TMPSNS_CTRL1_FREQ(0x00U);
93     }
94     else if (config->measureMode == kTEMPSENSOR_ContinuousMode)
95     {
96         controlVal |= TMPSNS_CTRL1_FREQ(config->frequency);
97     }
98     else
99     {
100         ; /* Intentional empty for MISRA C-2012 rule 15.7*/
101     }
102 
103 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
104     uint32_t statusVal;
105 
106     /* Power up the temperature sensor */
107     controlVal &= (~(TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK));
108 
109     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
110 
111     /* Read STATUS0 value */
112     statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
113 
114     /* Clear interrupt status flags. */
115     TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0),
116                          (statusVal | TMPSNS_STATUS0_HIGH_TEMP_MASK | TMPSNS_STATUS0_LOW_TEMP_MASK |
117                           TMPSNS_STATUS0_PANIC_TEMP_MASK | TMPSNS_STATUS0_FINISH_MASK));
118 #else
119     base->CTRL1 = controlVal;
120 
121     /* Power up the temperature sensor */
122     base->CTRL1 &= (~(TMPSNS_CTRL1_PWD_MASK | TMPSNS_CTRL1_PWD_FULL_MASK));
123 
124     /* Clear interrupt status flags. */
125     base->STATUS0 = (TMPSNS_STATUS0_HIGH_TEMP_MASK | TMPSNS_STATUS0_LOW_TEMP_MASK | TMPSNS_STATUS0_PANIC_TEMP_MASK |
126                      TMPSNS_STATUS0_FINISH_MASK);
127 #endif /* defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
128 }
129 
130 /*!
131  * brief Deinitializes the TMPSNS module.
132  *
133  * param base TMPSNS base pointer
134  */
TMPSNS_Deinit(TMPSNS_Type * base)135 void TMPSNS_Deinit(TMPSNS_Type *base)
136 {
137 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
138     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), TMPSNS_CTRL1_PWD_MASK);
139 #else
140     base->CTRL1 |= TMPSNS_CTRL1_PWD_MASK;
141 #endif
142 }
143 
144 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
145 /*!
146  * brief AI interface write access.
147  *
148  * param base TMPSNS base pointer
149  */
TMPSNS_AIWriteAccess(uint32_t address,uint32_t data)150 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data)
151 {
152     /* AI bridge setting: AIRWB and ADDR
153        Write: 0x00
154        Address: offset from base address
155      */
156     ANADIG_MISC->VDDLPSR_AI_CTRL = (0x00UL << 16) | (address & 0xFFFFU);
157     /* Write data into related register through AI bridge */
158     ANADIG_MISC->VDDLPSR_AI_WDATA = data;
159     /* AI toggle */
160     ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
161 }
162 
163 /*!
164  * brief AI interface read access.
165  *
166  * param base TMPSNS base pointer
167  */
TMPSNS_AIReadAccess(uint32_t address)168 static uint32_t TMPSNS_AIReadAccess(uint32_t address)
169 {
170     uint32_t ret;
171 
172     /* AI bridge setting: AIRWB and ADDR
173        Read: 0x01
174        Address: offset from base address
175      */
176     ANADIG_MISC->VDDLPSR_AI_CTRL = (0x01UL << 16) | (address & 0xFFFFU);
177     /* AI toggle */
178     ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
179     /* Read data from related register through AI bridge */
180     ret = ANADIG_MISC->VDDLPSR_AI_RDATA_TMPSNS;
181 
182     return ret;
183 }
184 #endif /* FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
185 
186 /*!
187  * brief Gets the default configuration structure.
188  *
189  * This function initializes the TMPSNS configuration structure to a default value. The default
190  * values are:
191  *   tempmonConfig->frequency = 0x00U;
192  *   tempmonConfig->highAlarmTemp = 25U;
193  *   tempmonConfig->panicAlarmTemp = 80U;
194  *   tempmonConfig->lowAlarmTemp = 20U;
195  *
196  * param config Pointer to a configuration structure.
197  */
TMPSNS_GetDefaultConfig(tmpsns_config_t * config)198 void TMPSNS_GetDefaultConfig(tmpsns_config_t *config)
199 {
200     assert(config);
201 
202     /* Initializes the configure structure to zero. */
203     (void)memset(config, 0, sizeof(*config));
204 
205     /* Default measurement mode */
206     config->measureMode = kTEMPSENSOR_SingleMode;
207     /* Default measure frequency */
208     config->frequency = 0x00U;
209     /* Default high alarm temperature */
210     config->highAlarmTemp = 25;
211     /* Default panic alarm temperature */
212     config->panicAlarmTemp = 80;
213     /* Default low alarm temperature */
214     config->lowAlarmTemp = 5;
215 }
216 
217 /*!
218  * @brief start the temperature measurement process.
219  *
220  * @param base TMPSNS base pointer.
221  */
TMPSNS_StartMeasure(TMPSNS_Type * base)222 void TMPSNS_StartMeasure(TMPSNS_Type *base)
223 {
224 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
225     uint32_t controlVal;
226     /* Read CTRL1 value*/
227     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
228     /* Start measurement */
229     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal | TMPSNS_CTRL1_SET_START_MASK);
230 #else
231     base->CTRL1 |= TMPSNS_CTRL1_SET_START_MASK;
232 #endif
233 }
234 
235 /*!
236  * @brief stop the measurement process.
237  *
238  * @param base TMPSNS base pointer
239  */
TMPSNS_StopMeasure(TMPSNS_Type * base)240 void TMPSNS_StopMeasure(TMPSNS_Type *base)
241 {
242 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
243     uint32_t controlVal;
244     /* Read CTRL1 value*/
245     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
246     /* Start measurement */
247     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal & (~TMPSNS_CTRL1_SET_START_MASK));
248 #else
249     base->CTRL1 &= ~TMPSNS_CTRL1_SET_START_MASK;
250 #endif
251 }
252 
253 /*!
254  * brief Get current temperature with the fused temperature calibration data.
255  *
256  * param base TMPSNS base pointer
257  * return current temperature with degrees Celsius.
258  */
TMPSNS_GetCurrentTemperature(TMPSNS_Type * base)259 float TMPSNS_GetCurrentTemperature(TMPSNS_Type *base)
260 {
261     uint32_t measureTempVal;
262     float actualTempVal;
263 
264 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
265     /* Waiting for measurement finished */
266     while (0U == (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_FINISH_MASK))
267     {
268     }
269     /* Ready to read measured temperature value */
270     measureTempVal = (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_TEMP_VAL_MASK) >>
271                      TMPSNS_STATUS0_TEMP_VAL_SHIFT;
272 #else
273     /* Waiting for measurement finished */
274     while (0U == (base->STATUS0 & TMPSNS_STATUS0_FINISH_MASK))
275     {
276     }
277     /* Ready to read measured temperature value */
278     measureTempVal = (base->STATUS0 & TMPSNS_STATUS0_TEMP_VAL_MASK) >> TMPSNS_STATUS0_TEMP_VAL_SHIFT;
279 #endif
280 
281     /* Calculate actual temperature */
282     actualTempVal =
283         (-s_Ts21 - sqrtf(s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c - (float)measureTempVal))) / (2.0f * s_Ts22);
284 
285 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
286     uint32_t statusVal;
287     /* Read STATUS0 value */
288     statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
289     /* Clear the FINISH flag */
290     TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0), statusVal | TMPSNS_STATUS0_FINISH_MASK);
291 #else
292     /* Clear the FINISH flag */
293     base->STATUS0 |= TMPSNS_STATUS0_FINISH_MASK;
294 #endif
295 
296     return actualTempVal;
297 }
298 
299 /*!
300  * brief Set the temperature count (raw sensor output) that will generate an alarm interrupt.
301  *
302  * param base TMPSNS base pointer
303  * param tempVal The alarm temperature with degrees Celsius
304  * param alarmMode The alarm mode.
305  */
TMPSNS_SetTempAlarm(TMPSNS_Type * base,int32_t tempVal,tmpsns_alarm_mode_t alarmMode)306 void TMPSNS_SetTempAlarm(TMPSNS_Type *base, int32_t tempVal, tmpsns_alarm_mode_t alarmMode)
307 {
308     float temp;
309     int32_t tempCodeVal;
310     uint32_t tempRegVal;
311 
312     /* Calculate alarm temperature code value */;
313     temp        = (-2.0f * s_Ts22 * (float)tempVal - s_Ts21) * (-2.0f * s_Ts22 * (float)tempVal - s_Ts21);
314     temp        = (temp - (s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c))) / (4.0f * s_Ts22);
315     tempCodeVal = (int32_t)temp;
316 
317     switch (alarmMode)
318     {
319         case kTEMPMON_HighAlarmMode:
320             /* Clear alarm value and set a new high alarm temperature code value */
321 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
322             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
323             tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
324             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0), tempRegVal);
325 #else
326             tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
327             base->RANGE0 = tempRegVal;
328 #endif
329             /* Enable high temperature interrupt */
330             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_HighTempInterruptStatusEnable);
331             break;
332 
333         case kTEMPMON_PanicAlarmMode:
334             /* Clear panic alarm value and set a new panic alarm temperature code value */
335 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
336             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE1));
337             tempRegVal = (tempRegVal & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
338             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE1), tempRegVal);
339 #else
340             tempRegVal =
341                 (base->RANGE1 & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
342             base->RANGE1 = tempRegVal;
343 #endif
344             /* Enable panic temperature interrupt */
345             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_PanicTempInterruptStatusEnable);
346             break;
347 
348         case kTEMPMON_LowAlarmMode:
349             /* Clear low alarm value and set a new low alarm temperature code value */
350 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
351             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
352             tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
353             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0_SET), tempRegVal);
354 #else
355             tempRegVal   = (base->RANGE0 & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
356             base->RANGE0 = tempRegVal;
357 #endif
358             /* Enable low temperature interrupt */
359             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_LowTempInterruptStatusEnable);
360             break;
361 
362         default:
363             assert(false);
364             break;
365     }
366 }
367 
368 /*!
369  * brief Enable interrupt status.
370  *
371  * param base TMPSNS base pointer
372  * param mask The interrupts to enable from tmpsns_interrupt_status_enable_t.
373  */
TMPSNS_EnableInterrupt(TMPSNS_Type * base,uint32_t mask)374 void TMPSNS_EnableInterrupt(TMPSNS_Type *base, uint32_t mask)
375 {
376 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
377     uint32_t tempRegVal;
378     tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
379     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal | mask);
380 #else
381     base->CTRL1 |= mask;
382 #endif
383 }
384 
385 /*!
386  * brief Disable interrupt status.
387  *
388  * param base TMPSNS base pointer
389  * param mask The interrupts to disable from tmpsns_interrupt_status_enable_t.
390  */
TMPSNS_DisableInterrupt(TMPSNS_Type * base,uint32_t mask)391 void TMPSNS_DisableInterrupt(TMPSNS_Type *base, uint32_t mask)
392 {
393 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
394     uint32_t tempRegVal;
395     tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
396     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal & (~mask));
397 #else
398     base->CTRL1 &= ~mask;
399 #endif
400 }
401