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