1 /*
2 * Copyright 2024 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_sysctr.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.sysctr"
17 #endif
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22 /*!
23 * @brief Reset the System Counter Instance.
24 *
25 * Restores the System Counter to reset state. Notice that this function will set all
26 * registers to reset state except Counter Count Value register and Compare Count Value
27 * register. System Counter module can not work after calling this API.
28 *
29 * @param base System Counter peripheral base address.
30 */
31 static void SYSCTR_Reset(SYS_CTR_CONTROL_Type *ctrlBase, SYS_CTR_COMPARE_Type *cmpBase);
32
33 /*******************************************************************************
34 * Variables
35 ******************************************************************************/
36
37 /*******************************************************************************
38 * Code
39 ******************************************************************************/
40 /*!
41 * brief Reset the System Counter Instance.
42 *
43 * Restores the System Counter to reset state. Notice that this function will set all
44 * registers to reset state. System Counter module can not work after calling this API.
45 *
46 * param base System Counter peripheral base address.
47 */
SYSCTR_Reset(SYS_CTR_CONTROL_Type * ctrlBase,SYS_CTR_COMPARE_Type * cmpBase)48 static void SYSCTR_Reset(SYS_CTR_CONTROL_Type *ctrlBase, SYS_CTR_COMPARE_Type *cmpBase)
49 {
50 ctrlBase->CNTCR = SYS_CTR_CONTROL_CNTCR_EN(0) | SYS_CTR_CONTROL_CNTCR_HDBG(0) |
51 SYS_CTR_CONTROL_CNTCR_FCR0(1) | SYS_CTR_CONTROL_CNTCR_FCR1(0);
52
53 while((ctrlBase->CNTSR & SYS_CTR_CONTROL_CNTSR_FCA1_MASK) != 0)
54 {
55 }
56
57 ctrlBase->CNTCV0 = 0;
58 ctrlBase->CNTCV1 = 0;
59 cmpBase->CMPCVL0 = 0;
60 cmpBase->CMPCVH0 = 0;
61 cmpBase->CMPCVL1 = 0;
62 cmpBase->CMPCVH1 = 0;
63
64 ctrlBase->CNTCR2 = SYS_CTR_CONTROL_CNTCR2_HWFC_EN(0);
65
66 cmpBase->CMPCR0 = SYS_CTR_COMPARE_CMPCR0_EN(0) | SYS_CTR_COMPARE_CMPCR0_IMASK(0);
67 cmpBase->CMPCR1 = SYS_CTR_COMPARE_CMPCR1_EN(0) | SYS_CTR_COMPARE_CMPCR1_IMASK(0);
68 }
69
70 /*!
71 * brief Initializes a System Counter instance.
72 *
73 * This function initializes the System Counter module with user-defined settings.
74 * This example shows how to set up the sysctr_config_t parameters and how to call
75 * the SYSCTR_Init function by passing in these parameters. Default clock source
76 * is 24MHz base clock from crystal oscillator.
77 * code
78 * sysctr_config_t sysctrConfig;
79 * sysctrConfig.enableDebugHalt = false;
80 * sysctrConfig.enableHardwareFrequencyChange = false;
81 * SYSCTR_Init(SYS_CTR_CONTROL, SYS_CTR_COMPARE, &sysctr_config_t);
82 * endcode
83 *
84 * param ctrlBase System Counter peripheral control model base address.
85 * param cmpBase System Counter peripheral compare model base address.
86 * param pConfig Configuration pointer to user's System Counter config structure.
87 */
SYSCTR_Init(SYS_CTR_CONTROL_Type * ctrlBase,SYS_CTR_COMPARE_Type * cmpBase,const sysctr_config_t * pConfig)88 void SYSCTR_Init(SYS_CTR_CONTROL_Type *ctrlBase, SYS_CTR_COMPARE_Type *cmpBase, const sysctr_config_t *pConfig)
89 {
90 assert(pConfig != NULL);
91
92 uint32_t reg;
93
94 (void)CLOCK_EnableClock(kCLOCK_Syscount);
95
96 SYSCTR_Reset(ctrlBase, cmpBase);
97
98 reg = ctrlBase->CNTCR;
99
100 reg = pConfig->enableDebugHalt ? (reg | SYS_CTR_CONTROL_CNTCR_HDBG_MASK) :
101 (reg & ~SYS_CTR_CONTROL_CNTCR_HDBG_MASK);
102
103 ctrlBase->CNTCR = reg;
104
105 reg = ctrlBase->CNTCR2;
106
107 reg = pConfig->enableHardwareFrequencyChange ? (reg | SYS_CTR_CONTROL_CNTCR2_HWFC_EN_MASK) :
108 (reg & ~SYS_CTR_CONTROL_CNTCR2_HWFC_EN_MASK);
109
110 ctrlBase->CNTCR2 = reg;
111 }
112
113 /*!
114 * brief De-initializes a System Counter instance.
115 *
116 * This function disables the System Counter module clock and sets all register values
117 * to the reset value.
118 *
119 * param ctrlBase System Counter peripheral control model base address.
120 * param cmpBase System Counter peripheral compare model base address.
121 */
SYSCTR_Deinit(SYS_CTR_CONTROL_Type * ctrlBase,SYS_CTR_COMPARE_Type * cmpBase)122 void SYSCTR_Deinit(SYS_CTR_CONTROL_Type *ctrlBase, SYS_CTR_COMPARE_Type *cmpBase)
123 {
124 SYSCTR_Reset(ctrlBase, cmpBase);
125
126 (void)CLOCK_DisableClock(kCLOCK_Syscount);
127 }
128
129 /*!
130 * brief Fill in the System Counter config struct with the default settings.
131 *
132 * The default values are:
133 * code
134 * config->enableDebugHalt = false;
135 * config->enableHardwareFrequencyChange = false;
136 * endcode
137 *
138 * param pConfig Configuration pointer to user's System Counter config structure.
139 */
SYSCTR_GetDefaultConfig(sysctr_config_t * pConfig)140 void SYSCTR_GetDefaultConfig(sysctr_config_t *pConfig)
141 {
142 pConfig->enableDebugHalt = false;
143 pConfig->enableHardwareFrequencyChange = false;
144 }
145
146 /*!
147 * brief Set System Counter clock source.
148 *
149 * param base System Counter peripheral control model base address.
150 * param sysctr_clock_source_t System Counter clock source.
151 */
SYSCTR_SetCounterClockSource(SYS_CTR_CONTROL_Type * base,sysctr_clock_source_t clockSource)152 void SYSCTR_SetCounterClockSource(SYS_CTR_CONTROL_Type *base, sysctr_clock_source_t clockSource)
153 {
154 uint32_t reg;
155
156 if (clockSource == kSYSCTR_BaseFrequency)
157 {
158 reg = base->CNTCR;
159 reg |= SYS_CTR_CONTROL_CNTCR_FCR0_MASK;
160 reg &= ~SYS_CTR_CONTROL_CNTCR_FCR1_MASK;
161 base->CNTCR = reg;
162 }
163 else
164 {
165 reg = base->CNTCR;
166 reg &= ~SYS_CTR_CONTROL_CNTCR_FCR0_MASK;
167 reg |= SYS_CTR_CONTROL_CNTCR_FCR1_MASK;
168 base->CNTCR = reg;
169 }
170 }
171
172 /*!
173 * brief Enable or disable compare function of specific compare frame.
174 *
175 * param base System Counter peripheral control model base address.
176 * param cmpFrame System Counter compare frame selection.
177 * param enable true: Enable compare function; false: Disable compare function
178 */
SYSCTR_EnableCompare(SYS_CTR_COMPARE_Type * base,sysctr_compare_frame_t cmpFrame,bool enable)179 void SYSCTR_EnableCompare(SYS_CTR_COMPARE_Type *base, sysctr_compare_frame_t cmpFrame, bool enable)
180 {
181 uint32_t reg;
182
183 if (cmpFrame == kSYSCTR_CompareFrame_0)
184 {
185 reg = base->CMPCR0;
186 reg = enable ? (reg | SYS_CTR_COMPARE_CMPCR0_EN_MASK) :
187 (reg & ~SYS_CTR_COMPARE_CMPCR0_EN_MASK);
188 base->CMPCR0 = reg;
189 }
190 else if (cmpFrame == kSYSCTR_CompareFrame_1)
191 {
192 reg = base->CMPCR1;
193 reg = enable ? (reg | SYS_CTR_COMPARE_CMPCR1_EN_MASK) :
194 (reg & ~SYS_CTR_COMPARE_CMPCR1_EN_MASK);
195 base->CMPCR1 = reg;
196 }
197 else
198 {
199 /* Intentional empty */
200 }
201 }
202
203 /*!
204 * brief Set System Counter compare value of specific compare frame.
205 *
206 * Be cautious that user must set compare value while operating on the base frequency only.
207 * Set compare value while running on the alternate frequency may have unpredictable results.
208 *
209 * param ctrlBase System Counter peripheral control model base address.
210 * param cmpBase System Counter peripheral compare model base address.
211 * param cmpFrame System Counter compare frame selection.
212 * param value System Counter compare value.
213 */
SYSCTR_SetCompareValue(SYS_CTR_CONTROL_Type * ctrlBase,SYS_CTR_COMPARE_Type * cmpBase,sysctr_compare_frame_t cmpFrame,uint64_t value)214 void SYSCTR_SetCompareValue(SYS_CTR_CONTROL_Type *ctrlBase,
215 SYS_CTR_COMPARE_Type *cmpBase,
216 sysctr_compare_frame_t cmpFrame,
217 uint64_t value)
218 {
219 assert((ctrlBase->CNTSR & SYS_CTR_CONTROL_CNTSR_FCA1_MASK) == 0);
220
221 if (cmpFrame == kSYSCTR_CompareFrame_0)
222 {
223 cmpBase->CMPCVL0 = (uint32_t)(value & SYS_CTR_COMPARE_CMPCVL0_CMPCV0_MASK);
224 cmpBase->CMPCVH0 = (uint32_t)((value >> 32U) & SYS_CTR_COMPARE_CMPCVH0_CMPCV1_MASK);
225 }
226 else if (cmpFrame == kSYSCTR_CompareFrame_1)
227 {
228 cmpBase->CMPCVL1 = (uint32_t)(value & SYS_CTR_COMPARE_CMPCVL1_CMPCV0_MASK);
229 cmpBase->CMPCVH1 = (uint32_t)((value >> 32U) & SYS_CTR_COMPARE_CMPCVH1_CMPCV1_MASK);
230 }
231 else
232 {
233 /* Intentional empty */
234 }
235 }
236
237 /*!
238 * brief Get specific Frequency Modes Table value.
239 *
240 * param base System Counter peripheral control model base address.
241 * param index Frequency Modes Table index.
242 *
243 * return Frequency modes table value.
244 */
SYSCTR_GetFrequencyModesTableValue(SYS_CTR_CONTROL_Type * base,sysctr_frequency_modes_table_t index)245 uint32_t SYSCTR_GetFrequencyModesTableValue(SYS_CTR_CONTROL_Type *base, sysctr_frequency_modes_table_t index)
246 {
247 uint32_t value = 0U;
248
249 switch (index)
250 {
251 case kSYSCTR_FrequencyModesTable_0:
252 value = base->CNTFID0;
253 break;
254 case kSYSCTR_FrequencyModesTable_1:
255 value = base->CNTFID1;
256 break;
257 case kSYSCTR_FrequencyModesTable_2:
258 value = base->CNTFID2;
259 break;
260 default:
261 assert(false);
262 break;
263 }
264
265 return value;
266 }
267