1 /*
2  * Copyright (c) 2021-2024, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== hal_cc23x0rx.c ========
34  */
35 
36 #include <ti/drivers/Power.h>
37 
38 #include <ti/drivers/Temperature.h>
39 
40 #include <ti/devices/DeviceFamily.h>
41 #include DeviceFamily_constructPath(inc/hw_types.h)
42 #include DeviceFamily_constructPath(inc/hw_memmap.h)
43 #include DeviceFamily_constructPath(inc/hw_systim.h)
44 #include DeviceFamily_constructPath(inc/hw_ints.h)
45 #include DeviceFamily_constructPath(inc/hw_evtsvt.h)
46 #include DeviceFamily_constructPath(inc/hw_clkctl.h)
47 #include DeviceFamily_constructPath(inc/hw_ckmd.h)
48 
49 #include DeviceFamily_constructPath(inc/hw_lrfdmdm.h)
50 #include DeviceFamily_constructPath(inc/hw_lrfddbell.h)
51 
52 #include DeviceFamily_constructPath(driverlib/lrfd.h)
53 
54 #include <ti/log/Log.h>
55 
56 #include <ti/drivers/rcl/hal/hal.h>
57 
58 #ifndef SOCFPGA
59 /* FPGA doesn't support Standby */
60 static int hal_power_post_notify_fxn(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg);
61 Power_NotifyObj powerAwakeStandbyObj;
62 Power_NotifyObj powerEnterStandbyObj;
63 
64 static void (*rclPowerNotify)(RCL_PowerEvent) = NULL;
65 #endif
66 static void hal_cancel_lrfd_systim0(void);
67 
68 #define RCL_DEFAULT_HFTRACKCTL_RATIO    CKMD_HFTRACKCTL_RATIO_REF48M
69 
70 static HwiP_Struct schedHwi;
71 void (*halSchedFsmCb)(void) = NULL;
72 
RF_schedHwi(uintptr_t a)73 static void RF_schedHwi(uintptr_t a)
74 {
75     (void) a;
76     if (halSchedFsmCb != NULL)
77     {
78         halSchedFsmCb();
79     }
80 }
81 
82 static HwiP_Struct dispatchHwi;
83 void (*halDispatchFsmCb)(void) = NULL;
RF_dispatchHwi(uintptr_t a)84 static void RF_dispatchHwi(uintptr_t a)
85 {
86     (void) a;
87     if (halDispatchFsmCb != NULL)
88     {
89         halDispatchFsmCb();
90     }
91 }
92 
93 static HwiP_Struct commandHwi;
94 void (*halCommandFsmCb)(void) = NULL;
RF_commandHwi(uintptr_t a)95 static void RF_commandHwi(uintptr_t a)
96 {
97     (void) a;
98     if (halCommandFsmCb != NULL)
99     {
100         halCommandFsmCb();
101     }
102 }
103 
hal_get_command_ifg_reg(void)104 uint32_t hal_get_command_ifg_reg(void)
105 {
106     uint32_t dbellIrq;
107     /* Using masked interrupt */
108     dbellIrq = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_MIS0);
109     /* Remove SYSTIM 0 and 1 interrupts, as they should be handled by hal_check_clear_timer_compare() */
110     dbellIrq &= ~(LRFDDBELL_MIS0_SYSTIM0_M | LRFDDBELL_MIS0_SYSTIM1_M);
111     /* Clear interrupts (unmasked only) */
112     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = dbellIrq;
113 
114     return dbellIrq;
115 }
116 
hal_get_dispatch_ifg_reg(void)117 uint32_t hal_get_dispatch_ifg_reg(void)
118 {
119     uint32_t dbellIrq;
120     /* Using masked interrupt */
121     dbellIrq = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_MIS1);
122     /* Clear interrupts (unmasked only) */
123     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR1) = dbellIrq;
124 
125     return dbellIrq;
126 }
127 
128 /*
129  * Initialize RCL interrupt handlers
130  */
hal_init_fsm(void (* dispatchFsmCb)(void),void (* schedFsmCb)(void),void (* commandFsmCb)(void))131 void hal_init_fsm(void (*dispatchFsmCb)(void), void (*schedFsmCb)(void),
132                   void (*commandFsmCb)(void))
133 {
134     HwiP_Params hp;
135     HwiP_Params_init(&hp);
136 #ifdef DeviceFamily_CC27XX
137     hp.priority = INT_PRI_LEVEL4;
138 #else
139     hp.priority = INT_PRI_LEVEL2;
140 #endif
141     HwiP_construct(&schedHwi, INT_CPUIRQ4, RF_schedHwi, &hp);
142 #ifdef DeviceFamily_CC27XX
143     hp.priority = INT_PRI_LEVEL2;
144 #else
145     hp.priority = INT_PRI_LEVEL1;
146 #endif
147     HwiP_construct(&dispatchHwi, INT_LRFD_IRQ1, RF_dispatchHwi,  &hp);
148 #ifdef DeviceFamily_CC27XX
149     hp.priority = INT_PRI_LEVEL1;
150 #else
151     hp.priority = INT_PRI_LEVEL0;
152 #endif
153     HwiP_construct(&commandHwi, INT_LRFD_IRQ0, RF_commandHwi,  &hp);
154 
155     halDispatchFsmCb = dispatchFsmCb;
156     halSchedFsmCb = schedFsmCb;
157     halCommandFsmCb = commandFsmCb;
158     /* TODO: See RCL-345 */
159 
160     HWREG(EVTSVT_BASE + EVTSVT_O_CPUIRQ4SEL) = 0xE; /* LRFDIRQ2 */
161 }
162 
163 
hal_trigger_command_fsm(void)164 void hal_trigger_command_fsm(void)
165 {
166     /* Software trig command FSM */
167     HwiP_post(INT_LRFD_IRQ0);
168 }
169 
hal_trigger_dispatch_fsm(void)170 void hal_trigger_dispatch_fsm(void)
171 {
172     /* Software trig dispatch IRQ */
173     HwiP_post(INT_LRFD_IRQ1);
174 }
175 
hal_trigger_scheduler_fsm(void)176 void hal_trigger_scheduler_fsm(void)
177 {
178     /* Software schedule IRQ */
179     HwiP_post(INT_CPUIRQ4);
180 }
181 
hal_get_current_time(void)182 uint32_t hal_get_current_time(void)
183 {
184     return HWREG(SYSTIM_BASE + SYSTIM_O_TIME250N);
185 }
186 
187 enum {
188     SYSTIM_CH2_SETUP = 1, /* Early start, to kick off setup */
189     SYSTIM_CH2_START = 2, /* Start event to radio */
190     SYSTIM_CH2_STOP = 3,  /* Hard stop time */
191 } channel2usage = SYSTIM_CH2_SETUP;
192 
hal_enable_setup_time_irq(void)193 void hal_enable_setup_time_irq(void)
194 {
195     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | LRFDDBELL_IMASK0_SYSTIM0_M;
196 }
197 
hal_setup_setup_time(uint32_t time)198 void hal_setup_setup_time(uint32_t time)
199 {
200     channel2usage = SYSTIM_CH2_SETUP;
201     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM0_M;
202     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CC) = time;
203     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | LRFDDBELL_IMASK0_SYSTIM0_M;
204 #ifndef SOCFPGA
205     /* The power driver uses SYSTIM_0_IMASK to restore the timeouts (including CH2).
206        Therefore, we need to set this register in case the system goes into standby. */
207     HWREG(SYSTIM_BASE + SYSTIM_O_IMSET) = SYSTIM_IMSET_EV2_SET;
208 #endif
209 }
210 
hal_setup_start_time(uint32_t time)211 void hal_setup_start_time(uint32_t time)
212 {
213     channel2usage = SYSTIM_CH2_START;
214     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM0_M;
215     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CC) = time;
216     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | LRFDDBELL_IMASK0_SYSTIM0_M;
217 }
218 
hal_setup_hard_stop_time(uint32_t time)219 void hal_setup_hard_stop_time(uint32_t time)
220 {
221     channel2usage = SYSTIM_CH2_STOP;
222     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM0_M;
223     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CC) = time;
224     /* Interrupt is not always needed, as event will be handled by PBE */
225 }
226 
hal_enable_hard_stop_time_irq(void)227 void hal_enable_hard_stop_time_irq(void)
228 {
229     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | LRFDDBELL_IMASK0_SYSTIM0_M;
230 }
231 
hal_disable_hard_stop_time_irq(void)232 void hal_disable_hard_stop_time_irq(void)
233 {
234     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & ~LRFDDBELL_IMASK0_SYSTIM0_M;
235 }
236 
hal_setup_graceful_stop_time(uint32_t time)237 void hal_setup_graceful_stop_time(uint32_t time)
238 {
239     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM1_M;
240     HWREG(SYSTIM_BASE + SYSTIM_O_CH3CC) = time;
241     /* Interrupt is not always needed, as event will be handled by PBE */
242 }
243 
hal_enable_graceful_stop_time_irq(void)244 void hal_enable_graceful_stop_time_irq(void)
245 {
246     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | LRFDDBELL_IMASK0_SYSTIM1_M;
247 }
248 
hal_cancel_lrfd_systim0(void)249 static void hal_cancel_lrfd_systim0(void)
250 {
251     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CC) = 0;
252     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CFG) = SYSTIM_CH2CFG_MODE_CAPT;
253     HWREG(SYSTIM_BASE + SYSTIM_O_CH2CFG) = SYSTIM_CH2CFG_MODE_DIS;
254     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & (~LRFDDBELL_IMASK0_SYSTIM0_M);
255 #ifndef SOCFPGA
256     /* The power driver uses SYSTIM_0_IMASK to restore the timeouts (including CH2).
257        Therefore, we need to clear the CH2 IMASK field in addition. */
258     HWREG(SYSTIM_BASE + SYSTIM_O_IMCLR) = SYSTIM_IMCLR_EV2_CLR;
259 #endif
260 }
261 
hal_cancel_setup_time(void)262 void hal_cancel_setup_time(void)
263 {
264     hal_cancel_lrfd_systim0();
265 }
266 
hal_cancel_start_time(void)267 void hal_cancel_start_time(void)
268 {
269     hal_cancel_lrfd_systim0();
270 }
271 
hal_cancel_hard_stop_time(void)272 void hal_cancel_hard_stop_time(void)
273 {
274     hal_cancel_lrfd_systim0();
275 }
276 
hal_cancel_graceful_stop_time(void)277 void hal_cancel_graceful_stop_time(void)
278 {
279     HWREG(SYSTIM_BASE + SYSTIM_O_CH3CC) = 0;
280     HWREG(SYSTIM_BASE + SYSTIM_O_CH3CFG) = SYSTIM_CH3CFG_MODE_CAPT;
281     HWREG(SYSTIM_BASE + SYSTIM_O_CH3CFG) = SYSTIM_CH3CFG_MODE_DIS;
282     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) =  HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & ~LRFDDBELL_IMASK0_SYSTIM1_M;
283 }
284 
hal_enable_clk_buffer(void)285 void hal_enable_clk_buffer(void)
286 {
287 #ifndef SOCFPGA
288     /* FPGA doesn't support standby */
289     HWREG( CKMD_BASE + CKMD_O_HFXTCTL ) |= CKMD_HFXTCTL_HPBUFEN;
290 #endif
291 }
292 
hal_setup_sync_found_cap(void)293 void hal_setup_sync_found_cap(void)
294 {
295     /* SRAT sync found repeat capture config */
296     /* Route event_ibus(21) (mdm) to DBELL input (capt_sources[0]) */
297     HWREG_WRITE_LRF(LRFDMDM_BASE + LRFDMDM_O_SYSTIMEVTMUX0) = (21 << LRFDMDM_SYSTIMEVTMUX0_SEL0_S);
298     /* Route through DBELL */
299     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_SYSTIMOEV) = (LRFDDBELL_SYSTIMOEV_SRC2_MCESYSTIM0);
300     /* SYSTIM channel 4 uses srat_ievent(0) as repeated capture trigger */
301     HWREG(SYSTIM_BASE + SYSTIM_O_CH4CFG) |= SYSTIM_CH4CFG_INP_RISE | SYSTIM_CH4CFG_MODE_CAPT | SYSTIM_CH4CFG_REARM_EN;
302 }
303 
hal_check_clear_timer_compare(void)304 HalTimerEvent hal_check_clear_timer_compare(void)
305 {
306     HalTimerEvent event = HAL_TIMER_EVT_NONE;
307 
308     uint32_t mis0 = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_MIS0);
309 
310     /* Start or hard-stop takes priority, meaning hard-stop takes priority over graceful. */
311     if (mis0 & LRFDDBELL_MIS0_SYSTIM0_M)
312     {
313         HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & (~LRFDDBELL_IMASK0_SYSTIM0_M);
314         HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM0_M;
315 #ifndef SOCFPGA
316         /* The power driver uses SYSTIM_0_IMASK to restore the timeouts (including CH2).
317         Therefore, we need to clear the CH2 IMASK field in addition. */
318         HWREG(SYSTIM_BASE + SYSTIM_O_IMCLR) = SYSTIM_IMCLR_EV2_CLR;
319 #endif
320         switch (channel2usage)
321         {
322             case SYSTIM_CH2_SETUP:
323                 event = HAL_TIMER_EVT_SETUP;
324                 break;
325             case SYSTIM_CH2_START:
326                 event = HAL_TIMER_EVT_START;
327                 break;
328             case SYSTIM_CH2_STOP:
329                 event = HAL_TIMER_EVT_HARD_STOP;
330                 break;
331             default:
332                 break;
333         }
334     }
335     else if (mis0 & LRFDDBELL_MIS0_SYSTIM1_M)
336     {
337         HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & (~LRFDDBELL_IMASK0_SYSTIM1_M);
338         HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = LRFDDBELL_ICLR0_SYSTIM1_M;
339         event = HAL_TIMER_EVT_GRACEFUL_STOP;
340     }
341     return event;
342 }
343 
hal_init_dispatch_radio_interrupts(uint32_t mask)344 void hal_init_dispatch_radio_interrupts(uint32_t mask)
345 {
346     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR1) = ~0;
347     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK1) = mask;
348 }
349 
hal_enable_command_radio_interrupt(uint32_t mask)350 void hal_enable_command_radio_interrupt(uint32_t mask)
351 {
352     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) =
353         HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) | mask;
354 }
355 
hal_clear_command_radio_interrupt(uint32_t mask)356 void hal_clear_command_radio_interrupt(uint32_t mask)
357 {
358     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = mask;
359 }
360 
hal_disable_command_radio_interrupt(uint32_t mask)361 void hal_disable_command_radio_interrupt(uint32_t mask)
362 {
363     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) =
364             HWREG_READ_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) & ~mask;
365 }
366 
hal_disable_all_command_radio_interrupts(void)367 void hal_disable_all_command_radio_interrupts(void)
368 {
369     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK0) = 0;
370     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR0) = ~0;
371 }
372 
hal_disable_all_dispatch_radio_interrupts(void)373 void hal_disable_all_dispatch_radio_interrupts(void)
374 {
375     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_IMASK1) = 0;
376     HWREG_WRITE_LRF(LRFDDBELL_BASE + LRFDDBELL_O_ICLR1) = ~0;
377 }
378 
hal_set_rcl_clock_enable(uint16_t mask)379 void hal_set_rcl_clock_enable(uint16_t mask)
380 {
381     uintptr_t key = HwiP_disable();
382     LRFDSetClockDependency(mask, LRFD_CLK_DEP_RCL);
383     HwiP_restore(key);
384 }
385 
hal_clear_rcl_clock_enable(uint16_t mask)386 void hal_clear_rcl_clock_enable(uint16_t mask)
387 {
388     uintptr_t key = HwiP_disable();
389     LRFDReleaseClockDependency(mask, LRFD_CLK_DEP_RCL);
390     HwiP_restore(key);
391 }
392 
393 #ifndef SOCFPGA
hal_power_post_notify_fxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)394 static int hal_power_post_notify_fxn(unsigned int eventType, uintptr_t eventArg, uintptr_t clientArg)
395 {
396     (void) eventArg;
397     (void) clientArg;
398 
399     if (rclPowerNotify != NULL)
400     {
401         if (eventType == PowerLPF3_AWAKE_STANDBY)
402         {
403             rclPowerNotify(RCL_POWER_STANDBY_AWAKE);
404         }
405         else if (eventType == PowerLPF3_ENTERING_STANDBY)
406         {
407             rclPowerNotify(RCL_POWER_STANDBY_ENTER);
408         }
409     }
410     return (Power_NOTIFYDONE);
411 }
412 #endif
413 
hal_power_set_constraint(void)414 void hal_power_set_constraint(void)
415 {
416 #ifndef SOCFPGA
417     /* FPGA doesn't support standby */
418     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
419     Log_printf(RclCore, Log_INFO, "Power constraints set");
420 #endif
421 }
422 
hal_power_release_constraint(void)423 void hal_power_release_constraint(void)
424 {
425 #ifndef SOCFPGA
426     /* FPGA doesn't support standby */
427     Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
428     Log_printf(RclCore, Log_INFO, "Power constraints released");
429 #endif
430 }
431 
hal_power_open(void (* f)(RCL_PowerEvent))432 void hal_power_open(void (*f)(RCL_PowerEvent))
433 {
434 #ifndef SOCFPGA
435     rclPowerNotify = f;
436 
437    /* Register power notification functions */
438     Power_registerNotify(&powerEnterStandbyObj, PowerLPF3_ENTERING_STANDBY, hal_power_post_notify_fxn, (uintptr_t)NULL);
439     Power_registerNotify(&powerAwakeStandbyObj, PowerLPF3_AWAKE_STANDBY, hal_power_post_notify_fxn, (uintptr_t)NULL);
440 #endif
441 }
442 
hal_power_close(void)443 void hal_power_close(void)
444 {
445 #ifndef SOCFPGA
446     /* Unregister power notification objects */
447     Power_unregisterNotify(&powerEnterStandbyObj);
448     Power_unregisterNotify(&powerAwakeStandbyObj);
449 #endif
450 }
451 
hal_temperature_init(void)452 void hal_temperature_init(void)
453 {
454     Temperature_init();
455 }
456 
457 /* Make function weak to allow tests to override reported temperature */
hal_get_temperature(void)458 __attribute__((weak)) int16_t hal_get_temperature(void)
459 {
460     return Temperature_getTemperature();
461 }
462 
hal_get_hfxt_ratio(void)463 uint32_t hal_get_hfxt_ratio(void)
464 {
465     return (HWREG(CKMD_BASE + CKMD_O_HFTRACKCTL) & CKMD_HFTRACKCTL_RATIO_M) >> CKMD_HFTRACKCTL_RATIO_S;
466 }
467 
hal_get_hfxt_ratio_default(void)468 uint32_t hal_get_hfxt_ratio_default(void)
469 {
470 #ifdef DeviceFamily_CC27XX
471     return 0x00200000U;
472 #else
473     return RCL_DEFAULT_HFTRACKCTL_RATIO;
474 #endif
475 }
476