1 /*
2  * Copyright 2020-2022 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  */
47 
TMPSNS_Init(TMPSNS_Type * base,const tmpsns_config_t * config)48 void TMPSNS_Init(TMPSNS_Type *base, const tmpsns_config_t *config)
49 {
50     assert(NULL != config);
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     if (config->measureMode == kTEMPSENSOR_SingleMode)
60     {
61         controlVal = TMPSNS_CTRL1_FREQ(0x00U);
62     }
63     else if (config->measureMode == kTEMPSENSOR_ContinuousMode)
64     {
65         controlVal = TMPSNS_CTRL1_FREQ(config->frequency);
66     }
67     else
68     {
69         ; /* Intentional empty for MISRA C-2012 rule 15.7*/
70     }
71 
72     /* Enable finish interrupt status */
73     controlVal |= TMPSNS_CTRL1_FINISH_IE_MASK;
74 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
75     /* Power up the temperature sensor */
76     controlVal &= ~TMPSNS_CTRL1_PWD_MASK;
77     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal);
78 #else
79     base->CTRL1 |= controlVal;
80     /* Power up the temperature sensor */
81     base->CTRL1 &= ~TMPSNS_CTRL1_PWD_MASK;
82 #endif
83 
84     /* Set alarm temperature */
85     TMPSNS_SetTempAlarm(base, config->highAlarmTemp, kTEMPMON_HighAlarmMode);
86     TMPSNS_SetTempAlarm(base, config->panicAlarmTemp, kTEMPMON_PanicAlarmMode);
87     TMPSNS_SetTempAlarm(base, config->lowAlarmTemp, kTEMPMON_LowAlarmMode);
88 }
89 
90 /*!
91  * brief Deinitializes the TMPSNS module.
92  *
93  * param base TMPSNS base pointer
94  */
TMPSNS_Deinit(TMPSNS_Type * base)95 void TMPSNS_Deinit(TMPSNS_Type *base)
96 {
97 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
98     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), TMPSNS_CTRL1_PWD_MASK);
99 #else
100     base->CTRL1 |= TMPSNS_CTRL1_PWD_MASK;
101 #endif
102 }
103 
104 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
105 /*!
106  * brief AI interface write access.
107  *
108  * param base TMPSNS base pointer
109  */
TMPSNS_AIWriteAccess(uint32_t address,uint32_t data)110 static void TMPSNS_AIWriteAccess(uint32_t address, uint32_t data)
111 {
112     /* AI bridge setting: AIRWB and ADDR
113        Write: 0x00
114        Address: offset from base address
115      */
116     ANADIG_MISC->VDDLPSR_AI_CTRL = (0x00UL << 16) | (address & 0xFFFFU);
117     /* Write data into related register through AI bridge */
118     ANADIG_MISC->VDDLPSR_AI_WDATA = data;
119     /* AI toggle */
120     ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
121 }
122 
123 /*!
124  * brief AI interface read access.
125  *
126  * param base TMPSNS base pointer
127  */
TMPSNS_AIReadAccess(uint32_t address)128 static uint32_t TMPSNS_AIReadAccess(uint32_t address)
129 {
130     uint32_t ret;
131 
132     /* AI bridge setting: AIRWB and ADDR
133        Read: 0x01
134        Address: offset from base address
135      */
136     ANADIG_MISC->VDDLPSR_AI_CTRL = (0x01UL << 16) | (address & 0xFFFFU);
137     /* AI toggle */
138     ANADIG_TEMPSENSOR->TEMPSENSOR ^= ANADIG_TEMPSENSOR_TEMPSENSOR_TEMPSNS_AI_TOGGLE_MASK;
139     /* Read data from related register through AI bridge */
140     ret = ANADIG_MISC->VDDLPSR_AI_RDATA_TMPSNS;
141 
142     return ret;
143 }
144 #endif /* FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE */
145 
146 /*!
147  * brief Gets the default configuration structure.
148  *
149  * This function initializes the TMPSNS configuration structure to a default value. The default
150  * values are:
151  *   tempmonConfig->frequency = 0x00U;
152  *   tempmonConfig->highAlarmTemp = 25U;
153  *   tempmonConfig->panicAlarmTemp = 80U;
154  *   tempmonConfig->lowAlarmTemp = 20U;
155  *
156  * param config Pointer to a configuration structure.
157  */
TMPSNS_GetDefaultConfig(tmpsns_config_t * config)158 void TMPSNS_GetDefaultConfig(tmpsns_config_t *config)
159 {
160     assert(config);
161 
162     /* Initializes the configure structure to zero. */
163     (void)memset(config, 0, sizeof(*config));
164 
165     /* Default measurement mode */
166     config->measureMode = kTEMPSENSOR_SingleMode;
167     /* Default measure frequency */
168     config->frequency = 0x00U;
169     /* Default high alarm temperature */
170     config->highAlarmTemp = 25;
171     /* Default panic alarm temperature */
172     config->panicAlarmTemp = 80;
173     /* Default low alarm temperature */
174     config->lowAlarmTemp = 5;
175 }
176 
177 /*!
178  * @brief start the temperature measurement process.
179  *
180  * @param base TMPSNS base pointer.
181  */
TMPSNS_StartMeasure(TMPSNS_Type * base)182 void TMPSNS_StartMeasure(TMPSNS_Type *base)
183 {
184 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
185     uint32_t controlVal;
186     /* Read CTRL1 value*/
187     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
188     /* Start measurement */
189     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal | TMPSNS_CTRL1_SET_START_MASK);
190 #else
191     base->CTRL1 |= TMPSNS_CTRL1_SET_START_MASK;
192 #endif
193 }
194 
195 /*!
196  * @brief stop the measurement process.
197  *
198  * @param base TMPSNS base pointer
199  */
TMPSNS_StopMeasure(TMPSNS_Type * base)200 void TMPSNS_StopMeasure(TMPSNS_Type *base)
201 {
202 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
203     uint32_t controlVal;
204     /* Read CTRL1 value*/
205     controlVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
206     /* Start measurement */
207     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), controlVal & (~TMPSNS_CTRL1_SET_START_MASK));
208 #else
209     base->CTRL1 &= ~TMPSNS_CTRL1_SET_START_MASK;
210 #endif
211 }
212 
213 /*!
214  * brief Get current temperature with the fused temperature calibration data.
215  *
216  * param base TMPSNS base pointer
217  * return current temperature with degrees Celsius.
218  */
TMPSNS_GetCurrentTemperature(TMPSNS_Type * base)219 float TMPSNS_GetCurrentTemperature(TMPSNS_Type *base)
220 {
221     uint32_t measureTempVal;
222     float actualTempVal;
223 
224 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
225     /* Waiting for measurement finished */
226     while (0U == (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_FINISH_MASK))
227     {
228     }
229     /* Ready to read measured temperature value */
230     measureTempVal = (TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0)) & TMPSNS_STATUS0_TEMP_VAL_MASK) >>
231                      TMPSNS_STATUS0_TEMP_VAL_SHIFT;
232 #else
233     /* Waiting for measurement finished */
234     while (0U == (base->STATUS0 & TMPSNS_STATUS0_FINISH_MASK))
235     {
236     }
237     /* Ready to read measured temperature value */
238     measureTempVal = (base->STATUS0 & TMPSNS_STATUS0_TEMP_VAL_MASK) >> TMPSNS_STATUS0_TEMP_VAL_SHIFT;
239 #endif
240 
241     /* Calculate actual temperature */
242     actualTempVal =
243         (-s_Ts21 - sqrtf(s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c - (float)measureTempVal))) / (2.0f * s_Ts22);
244 
245 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
246     uint32_t statusVal;
247     /* Read STATUS0 value */
248     statusVal = TMPSNS_AIReadAccess((uint32_t) & (base->STATUS0));
249     /* Clear the FINISH flag */
250     TMPSNS_AIWriteAccess((uint32_t) & (base->STATUS0), statusVal | TMPSNS_STATUS0_FINISH_MASK);
251 #else
252     /* Clear the FINISH flag */
253     base->STATUS0 |= TMPSNS_STATUS0_FINISH_MASK;
254 #endif
255 
256     return actualTempVal;
257 }
258 
259 /*!
260  * brief Set the temperature count (raw sensor output) that will generate an alarm interrupt.
261  *
262  * param base TMPSNS base pointer
263  * param tempVal The alarm temperature with degrees Celsius
264  * param alarmMode The alarm mode.
265  */
TMPSNS_SetTempAlarm(TMPSNS_Type * base,int32_t tempVal,tmpsns_alarm_mode_t alarmMode)266 void TMPSNS_SetTempAlarm(TMPSNS_Type *base, int32_t tempVal, tmpsns_alarm_mode_t alarmMode)
267 {
268     float temp;
269     int32_t tempCodeVal;
270     uint32_t tempRegVal;
271 
272     /* Calculate alarm temperature code value */;
273     temp        = (-2.0f * s_Ts22 * (float)tempVal - s_Ts21) * (-2.0f * s_Ts22 * (float)tempVal - s_Ts21);
274     temp        = (temp - (s_Ts21_2 - 4.0f * s_Ts22 * (s_Ts20 + s_Ts25c))) / (4.0f * s_Ts22);
275     tempCodeVal = (int32_t)temp;
276 
277     switch (alarmMode)
278     {
279         case kTEMPMON_HighAlarmMode:
280             /* Clear alarm value and set a new high alarm temperature code value */
281 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
282             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
283             tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
284             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0), tempRegVal);
285 #else
286             tempRegVal = (base->RANGE0 & ~TMPSNS_RANGE0_HIGH_TEMP_VAL_MASK) | TMPSNS_RANGE0_HIGH_TEMP_VAL(tempCodeVal);
287             base->RANGE0 = tempRegVal;
288 #endif
289             /* Enable high temperature interrupt */
290             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_HighTempInterruptStatusEnable);
291             break;
292 
293         case kTEMPMON_PanicAlarmMode:
294             /* Clear panic alarm value and set a new panic alarm temperature code value */
295 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
296             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE1));
297             tempRegVal = (tempRegVal & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
298             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE1), tempRegVal);
299 #else
300             tempRegVal =
301                 (base->RANGE1 & ~TMPSNS_RANGE1_PANIC_TEMP_VAL_MASK) | TMPSNS_RANGE1_PANIC_TEMP_VAL(tempCodeVal);
302             base->RANGE1 = tempRegVal;
303 #endif
304             /* Enable panic temperature interrupt */
305             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_PanicTempInterruptStatusEnable);
306             break;
307 
308         case kTEMPMON_LowAlarmMode:
309             /* Clear low alarm value and set a new low alarm temperature code value */
310 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
311             tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->RANGE0));
312             tempRegVal = (tempRegVal & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
313             TMPSNS_AIWriteAccess((uint32_t) & (base->RANGE0_SET), tempRegVal);
314 #else
315             tempRegVal   = (base->RANGE0 & ~TMPSNS_RANGE0_LOW_TEMP_VAL_MASK) | TMPSNS_RANGE0_LOW_TEMP_VAL(tempCodeVal);
316             base->RANGE0 = tempRegVal;
317 #endif
318             /* Enable low temperature interrupt */
319             TMPSNS_EnableInterrupt(base, kTEMPSENSOR_LowTempInterruptStatusEnable);
320             break;
321 
322         default:
323             assert(false);
324             break;
325     }
326 }
327 
328 /*!
329  * brief Enable interrupt status.
330  *
331  * param base TMPSNS base pointer
332  * param mask The interrupts to enable from tmpsns_interrupt_status_enable_t.
333  */
TMPSNS_EnableInterrupt(TMPSNS_Type * base,uint32_t mask)334 void TMPSNS_EnableInterrupt(TMPSNS_Type *base, uint32_t mask)
335 {
336 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
337     uint32_t tempRegVal;
338     tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
339     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal | mask);
340 #else
341     base->CTRL1 |= mask;
342 #endif
343 }
344 
345 /*!
346  * brief Disable interrupt status.
347  *
348  * param base TMPSNS base pointer
349  * param mask The interrupts to disable from tmpsns_interrupt_status_enable_t.
350  */
TMPSNS_DisableInterrupt(TMPSNS_Type * base,uint32_t mask)351 void TMPSNS_DisableInterrupt(TMPSNS_Type *base, uint32_t mask)
352 {
353 #if defined(FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE) && FSL_FEATURE_TMPSNS_HAS_AI_INTERFACE
354     uint32_t tempRegVal;
355     tempRegVal = TMPSNS_AIReadAccess((uint32_t) & (base->CTRL1));
356     TMPSNS_AIWriteAccess((uint32_t) & (base->CTRL1), tempRegVal & (~mask));
357 #else
358     base->CTRL1 &= ~mask;
359 #endif
360 }
361