1 /*
2 * Copyright 2021-2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_syspm.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.syspm"
18 #endif
19
20 /*******************************************************************************
21 * Prototypes
22 ******************************************************************************/
23
24 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) && defined(SYSPM_CLOCKS)
25 /*!
26 * @brief Get instance number for ESYSPM.
27 *
28 * @param base ESYSPM peripheral base address.
29 */
30 static uint32_t SYSPM_GetInstance(SYSPM_Type *base);
31 #endif
32
33 /*******************************************************************************
34 * Variables
35 ******************************************************************************/
36 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) && defined(SYSPM_CLOCKS)
37 /*! @brief Array to map SYSPM instance number to base pointer. */
38 static SYSPM_Type *const s_syspmBases[] = SYSPM_BASE_PTRS;
39
40 /*! @brief Array to map SYSPM instance number to clock name. */
41 static const clock_ip_name_t s_syspmClockName[] = SYSPM_CLOCKS;
42 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
43
44 /*******************************************************************************
45 * Code
46 ******************************************************************************/
47 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) && defined(SYSPM_CLOCKS)
SYSPM_GetInstance(SYSPM_Type * base)48 static uint32_t SYSPM_GetInstance(SYSPM_Type *base)
49 {
50 uint32_t instance;
51
52 /* Find the instance index from base address mappings. */
53 for (instance = 0; instance < ARRAY_SIZE(s_syspmBases); instance++)
54 {
55 if (s_syspmBases[instance] == base)
56 {
57 break;
58 }
59 }
60
61 assert(instance < ARRAY_SIZE(s_syspmBases));
62
63 return instance;
64 }
65 #endif
66
67 /*
68 * brief Initializes the SYSPM
69 *
70 * This function enables the SYSPM clock.
71 *
72 * param base SYSPM peripheral base address.
73 */
SYSPM_Init(SYSPM_Type * base)74 void SYSPM_Init(SYSPM_Type *base)
75 {
76 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) && defined(SYSPM_CLOCKS)
77 CLOCK_EnableClock(s_syspmClockName[SYSPM_GetInstance(base)]);
78 #endif
79 }
80
81 /*
82 * brief Deinitializes the SYSPM
83 *
84 * This function disables the SYSPM clock.
85 *
86 * param base SYSPM peripheral base address.
87 */
SYSPM_Deinit(SYSPM_Type * base)88 void SYSPM_Deinit(SYSPM_Type *base)
89 {
90 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) && defined(SYSPM_CLOCKS)
91 CLOCK_DisableClock(s_syspmClockName[SYSPM_GetInstance(base)]);
92 #endif
93 }
94
95 /*!
96 * @brief Select event counters
97 *
98 * @param base SYSPM peripheral base address.
99 * @param monitor syspm control monitor, see to #syspm_monitor_t.
100 * @param event syspm select event, see to #syspm_event_t.
101 * @param eventCode select which event to be counted in PMECTRx., see to table Events.
102 */
SYSPM_SelectEvent(SYSPM_Type * base,syspm_monitor_t monitor,syspm_event_t event,uint8_t eventCode)103 void SYSPM_SelectEvent(SYSPM_Type *base, syspm_monitor_t monitor, syspm_event_t event, uint8_t eventCode)
104 {
105 uint32_t pmcr;
106 uint8_t shift;
107
108 shift = 7U * (uint8_t)event;
109
110 pmcr = base->PMCR[(uint8_t)monitor].PMCR;
111 pmcr &= ~(SYSPM_PMCR_SELEVT1_MASK << shift);
112 pmcr |= SYSPM_PMCR_SELEVT1(eventCode) << shift;
113
114 base->PMCR[(uint8_t)monitor].PMCR = pmcr;
115 }
116
117 /*!
118 * @brief Reset event counters
119 *
120 * @param base SYSPM peripheral base address.
121 * @param monitor syspm control monitor, see to #syspm_monitor_t.
122 */
SYSPM_ResetEvent(SYSPM_Type * base,syspm_monitor_t monitor,syspm_event_t event)123 void SYSPM_ResetEvent(SYSPM_Type *base, syspm_monitor_t monitor, syspm_event_t event)
124 {
125 base->PMCR[(uint8_t)monitor].PMCR |= ((uint32_t)SYSPM_PMCR_RECTR1_MASK << (uint8_t)event);
126 }
127
128 #if !((defined(FSL_FEATURE_SYSPM_HAS_PMCR_RICTR) && (FSL_FEATURE_SYSPM_HAS_PMCR_RICTR == 0U)))
129 /*!
130 * @brief Reset Instruction Counter
131 *
132 * @param base SYSPM peripheral base address.
133 * @param monitor syspm control monitor, see to #syspm_monitor_t.
134 */
SYSPM_ResetInstructionEvent(SYSPM_Type * base,syspm_monitor_t monitor)135 void SYSPM_ResetInstructionEvent(SYSPM_Type *base, syspm_monitor_t monitor)
136 {
137 base->PMCR[(uint8_t)monitor].PMCR |= SYSPM_PMCR_RICTR_MASK;
138 }
139 #endif /* FSL_FEATURE_SYSPM_HAS_PMCR_RICTR */
140
141 /*!
142 * @brief Set count mode
143 *
144 * @param base SYSPM peripheral base address.
145 * @param monitor syspm control monitor, see to #syspm_monitor_t.
146 * @param mode syspm select counter mode, see to #syspm_mode_t.
147 */
SYSPM_SetCountMode(SYSPM_Type * base,syspm_monitor_t monitor,syspm_mode_t mode)148 void SYSPM_SetCountMode(SYSPM_Type *base, syspm_monitor_t monitor, syspm_mode_t mode)
149 {
150 base->PMCR[(uint8_t)monitor].PMCR =
151 (base->PMCR[(uint8_t)monitor].PMCR & ~SYSPM_PMCR_CMODE_MASK) | SYSPM_PMCR_CMODE(mode);
152 }
153
154 /*!
155 * @brief Set Start/Stop Control
156 *
157 * @param base SYSPM peripheral base address.
158 * @param monitor syspm control monitor, see to #syspm_monitor_t.
159 * @param ssc This 3-bit field provides a three-phase mechanism to start/stop the counters. It includes a
160 * prioritized scheme with local start > local stop > global start > global stop > conditional
161 * TSTART > TSTOP. The global and conditional start/stop affect all configured PM/PSAM module concurrently so counters
162 * are "coherent". see to #syspm_startstop_control_t
163 */
SYSPM_SetStartStopControl(SYSPM_Type * base,syspm_monitor_t monitor,syspm_startstop_control_t ssc)164 void SYSPM_SetStartStopControl(SYSPM_Type *base, syspm_monitor_t monitor, syspm_startstop_control_t ssc)
165 {
166 base->PMCR[(uint8_t)monitor].PMCR =
167 (base->PMCR[(uint8_t)monitor].PMCR & ~SYSPM_PMCR_SSC_MASK) | SYSPM_PMCR_SSC(ssc);
168 }
169
170 #if !((defined(FSL_FEATURE_SYSPM_HAS_PMCR_DCIFSH)) && (FSL_FEATURE_SYSPM_HAS_PMCR_DCIFSH == 0U))
171 /*!
172 * @brief Disable Counters if Stopped or Halted
173 *
174 * @param base SYSPM peripheral base address.
175 * @param monitor syspm control monitor, see to #syspm_monitor_t.
176 */
SYSPM_DisableCounter(SYSPM_Type * base,syspm_monitor_t monitor)177 void SYSPM_DisableCounter(SYSPM_Type *base, syspm_monitor_t monitor)
178 {
179 base->PMCR[(uint8_t)monitor].PMCR |= SYSPM_PMCR_DCIFSH_MASK;
180 }
181 #endif /* FSL_FEATURE_SYSPM_HAS_PMCR_DCIFSH */
182
183 /*!
184 * @brief This is the the 40-bits of eventx counter.
185 The value in this register increments each time the event
186 selected in PMCRx[SELEVTx] occurs.
187 *
188 * @param base SYSPM peripheral base address.
189 * @param monitor syspm control monitor, see to #syspm_monitor_t.
190 * @param event syspm select event, see to #syspm_event_t.
191 * @return get the the 40 bits of eventx counter.
192 */
SYSPM_GetEventCounter(SYSPM_Type * base,syspm_monitor_t monitor,syspm_event_t event)193 uint64_t SYSPM_GetEventCounter(SYSPM_Type *base, syspm_monitor_t monitor, syspm_event_t event)
194 {
195 uint32_t highOld;
196 uint32_t high;
197 uint32_t low;
198
199 highOld = base->PMCR[(uint8_t)monitor].PMECTR[(uint8_t)event].HI;
200 while (true)
201 {
202 low = base->PMCR[(uint8_t)monitor].PMECTR[(uint8_t)event].LO;
203 high = base->PMCR[(uint8_t)monitor].PMECTR[(uint8_t)event].HI;
204 if (high == highOld)
205 {
206 break;
207 }
208 else
209 {
210 highOld = high;
211 }
212 }
213
214 return ((uint64_t)high << 32U) + low;
215 }
216