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