1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019, 2021, 2024 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_utick.h"
10 #if !(defined(FSL_FEATURE_UTICK_HAS_NO_PDCFG) && FSL_FEATURE_UTICK_HAS_NO_PDCFG)
11 #include "fsl_power.h"
12 #endif
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.utick"
20 #endif
21 
22 /* Typedef for interrupt handler. */
23 typedef void (*utick_isr_t)(UTICK_Type *base, utick_callback_t cb);
24 
25 /*******************************************************************************
26  * Prototypes
27  ******************************************************************************/
28 /*!
29  * @brief Gets the instance from the base address
30  *
31  * @param base UTICK peripheral base address
32  *
33  * @return The UTICK instance
34  */
35 static uint32_t UTICK_GetInstance(UTICK_Type *base);
36 
37 /*******************************************************************************
38  * Variables
39  ******************************************************************************/
40 /* Array of UTICK peripheral base address. */
41 static UTICK_Type *const s_utickBases[] = UTICK_BASE_PTRS;
42 /* Array of UTICK handle. */
43 static utick_callback_t s_utickHandle[ARRAY_SIZE(s_utickBases)];
44 /* Array of UTICK IRQ number. */
45 static const IRQn_Type s_utickIRQ[] = UTICK_IRQS;
46 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
47 /* Array of UTICK clock name. */
48 static const clock_ip_name_t s_utickClock[] = UTICK_CLOCKS;
49 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
50 
51 #if !(defined(FSL_FEATURE_UTICK_HAS_NO_RESET) && FSL_FEATURE_UTICK_HAS_NO_RESET)
52 /*! @brief Pointers to UTICK resets for each instance. */
53 static const reset_ip_name_t s_utickResets[] = UTICK_RSTS;
54 #endif
55 
56 /* UTICK ISR for transactional APIs. */
57 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
58 static utick_isr_t s_utickIsr = (utick_isr_t)DefaultISR;
59 #else
60 static utick_isr_t s_utickIsr;
61 #endif
62 
63 /*******************************************************************************
64  * Code
65  ******************************************************************************/
UTICK_GetInstance(UTICK_Type * base)66 static uint32_t UTICK_GetInstance(UTICK_Type *base)
67 {
68     uint32_t instance;
69 
70     /* Find the instance index from base address mappings. */
71     for (instance = 0; instance < ARRAY_SIZE(s_utickBases); instance++)
72     {
73         if (MSDK_REG_SECURE_ADDR(s_utickBases[instance]) == MSDK_REG_SECURE_ADDR(base))
74         {
75             break;
76         }
77     }
78 
79     assert(instance < ARRAY_SIZE(s_utickBases));
80 
81     return instance;
82 }
83 
84 /*!
85  * brief Starts UTICK.
86  *
87  * This function starts a repeat/onetime countdown with an optional callback
88  *
89  * param base   UTICK peripheral base address.
90  * param mode  UTICK timer mode (ie kUTICK_onetime or kUTICK_repeat)
91  * param count  UTICK timer mode (ie kUTICK_onetime or kUTICK_repeat)
92  * param cb  UTICK callback (can be left as NULL if none, otherwise should be a void func(void))
93  * return none
94  */
UTICK_SetTick(UTICK_Type * base,utick_mode_t mode,uint32_t count,utick_callback_t cb)95 void UTICK_SetTick(UTICK_Type *base, utick_mode_t mode, uint32_t count, utick_callback_t cb)
96 {
97     uint32_t instance;
98 
99     /* Get instance from peripheral base address. */
100     instance = UTICK_GetInstance(base);
101 
102     /* Save the handle in global variables to support the double weak mechanism. */
103     s_utickHandle[instance] = cb;
104 #if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) && \
105      !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS))
106     EnableDeepSleepIRQ(s_utickIRQ[instance]);
107 #else
108     (void)EnableIRQ(s_utickIRQ[instance]);
109 #endif /* FSL_FEATURE_SOC_SYSCON_COUNT && !FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
110     base->CTRL = count | UTICK_CTRL_REPEAT(mode);
111 }
112 
113 /*!
114  * brief Initializes an UTICK by turning its bus clock on
115  *
116  */
UTICK_Init(UTICK_Type * base)117 void UTICK_Init(UTICK_Type *base)
118 {
119 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
120     /* Enable utick clock */
121     CLOCK_EnableClock(s_utickClock[UTICK_GetInstance(base)]);
122 #endif
123 
124 #if !(defined(FSL_FEATURE_UTICK_HAS_NO_RESET) && FSL_FEATURE_UTICK_HAS_NO_RESET)
125     RESET_PeripheralReset(s_utickResets[UTICK_GetInstance(base)]);
126 #endif
127 
128 #if !(defined(FSL_FEATURE_UTICK_HAS_NO_PDCFG) && FSL_FEATURE_UTICK_HAS_NO_PDCFG)
129     /* Power up Watchdog oscillator*/
130     POWER_DisablePD(kPDRUNCFG_PD_WDT_OSC);
131 #endif
132 
133     s_utickIsr = UTICK_HandleIRQ;
134 }
135 
136 /*!
137  * brief Deinitializes a UTICK instance.
138  *
139  * This function shuts down Utick bus clock
140  *
141  * param base UTICK peripheral base address.
142  */
UTICK_Deinit(UTICK_Type * base)143 void UTICK_Deinit(UTICK_Type *base)
144 {
145     /* Turn off utick */
146     base->CTRL = 0;
147 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
148     /* Disable utick clock */
149     CLOCK_DisableClock(s_utickClock[UTICK_GetInstance(base)]);
150 #endif
151 }
152 
153 /*!
154  * brief Get Status Flags.
155  *
156  * This returns the status flag
157  *
158  * param base UTICK peripheral base address.
159  * return status register value
160  */
UTICK_GetStatusFlags(UTICK_Type * base)161 uint32_t UTICK_GetStatusFlags(UTICK_Type *base)
162 {
163     return (base->STAT);
164 }
165 
166 /*!
167  * brief Clear Status Interrupt Flags.
168  *
169  * This clears intr status flag
170  *
171  * param base UTICK peripheral base address.
172  * return none
173  */
UTICK_ClearStatusFlags(UTICK_Type * base)174 void UTICK_ClearStatusFlags(UTICK_Type *base)
175 {
176     base->STAT = UTICK_STAT_INTR_MASK;
177 }
178 
179 /*!
180  * brief UTICK Interrupt Service Handler.
181  *
182  * This function handles the interrupt and refers to the callback array in the driver to callback user (as per request
183  * in UTICK_SetTick()).
184  * if no user callback is scheduled, the interrupt will simply be cleared.
185  *
186  * param base   UTICK peripheral base address.
187  * param cb  callback scheduled for this instance of UTICK
188  * return none
189  */
UTICK_HandleIRQ(UTICK_Type * base,utick_callback_t cb)190 void UTICK_HandleIRQ(UTICK_Type *base, utick_callback_t cb)
191 {
192     UTICK_ClearStatusFlags(base);
193     if (cb != NULL)
194     {
195         cb();
196     }
197 }
198 
199 #if defined(UTICK0)
200 void UTICK0_DriverIRQHandler(void);
UTICK0_DriverIRQHandler(void)201 void UTICK0_DriverIRQHandler(void)
202 {
203     s_utickIsr(UTICK0, s_utickHandle[0]);
204     SDK_ISR_EXIT_BARRIER;
205 }
206 #endif
207 #if defined(UTICK1)
208 void UTICK1_DriverIRQHandler(void);
UTICK1_DriverIRQHandler(void)209 void UTICK1_DriverIRQHandler(void)
210 {
211     s_utickIsr(UTICK1, s_utickHandle[1]);
212     SDK_ISR_EXIT_BARRIER;
213 }
214 #endif
215 #if defined(UTICK2)
216 void UTICK2_DriverIRQHandler(void);
UTICK2_DriverIRQHandler(void)217 void UTICK2_DriverIRQHandler(void)
218 {
219     s_utickIsr(UTICK2, s_utickHandle[2]);
220     SDK_ISR_EXIT_BARRIER;
221 }
222 #endif
223 #if defined(UTICK)
224 void UTICK_DriverIRQHandler(void);
UTICK_DriverIRQHandler(void)225 void UTICK_DriverIRQHandler(void)
226 {
227     s_utickIsr(UTICK, s_utickHandle[0]);
228     SDK_ISR_EXIT_BARRIER;
229 }
230 #endif
231