1 /*
2 * Copyright 2017-2019 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "fsl_clock.h"
8
9 /*******************************************************************************
10 * Definitions
11 ******************************************************************************/
12 /* Component ID definition, used by tools. */
13 #ifndef FSL_COMPONENT_ID
14 #define FSL_COMPONENT_ID "platform.drivers.clock"
15 #endif
16 /* LPCG register Bits Mask. LPCG register generally comes in four bit groups, a STOP, Reserved, [P|B]CG(SWEN), HWEN
17 * nibble. The HWEN bits are optional, but the allocations of the nibble always be on four bit boundaries. */
18 #define LPCG_CLK_HWEN_MASK (0x11111111U)
19 #define LPCG_CLK_SWEN_MASK (0x22222222U)
20 #define LPCG_CLK_STOP_MASK (0x88888888U)
21
22 /*******************************************************************************
23 * Variables
24 ******************************************************************************/
25 static sc_ipc_t ipcHandle;
26
27 /*******************************************************************************
28 * Prototypes
29 ******************************************************************************/
30
31 /*******************************************************************************
32 * Code
33 ******************************************************************************/
34
35 /*!
36 * brief Initialize Clock module.
37 *
38 * param ipc IPC handle for communication with SCU, see \ref sc_ipc_t.
39 */
CLOCK_Init(sc_ipc_t ipc)40 void CLOCK_Init(sc_ipc_t ipc)
41 {
42 ipcHandle = ipc;
43 }
44
45 /*!
46 * brief Deinitialize Clock module.
47 */
CLOCK_Deinit(void)48 void CLOCK_Deinit(void)
49 {
50 }
51
52 /*!
53 * brief Enable the clock for specific IP, with gate setting.
54 *
55 * param name Which clock to enable, see \ref clock_ip_name_t.
56 * param gate 0: clock always on, 1: HW auto clock gating.
57 * return true if success, false if failure.
58 */
CLOCK_EnableClockExt(clock_ip_name_t name,uint32_t gate)59 bool CLOCK_EnableClockExt(clock_ip_name_t name, uint32_t gate)
60 {
61 sc_err_t err;
62
63 err = sc_pm_clock_enable(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, true, (bool)gate);
64
65 /* Enable the Clock Gate control in LPCG */
66 CLOCK_ConfigLPCG(name, (bool)1U, (bool)gate);
67
68 if (err != SC_ERR_NONE)
69 {
70 return false;
71 }
72 else
73 {
74 return true;
75 }
76 }
77
78 /*!
79 * brief Disable the clock for specific IP.
80 *
81 * param name Which clock to disable, see \ref clock_ip_name_t.
82 * return true for success, false for failure.
83 */
CLOCK_DisableClock(clock_ip_name_t name)84 bool CLOCK_DisableClock(clock_ip_name_t name)
85 {
86 sc_err_t err;
87
88 /* Disable the Clock Gate control in LPCG */
89 CLOCK_ConfigLPCG(name, (bool)0U, (bool)0U);
90
91 err = sc_pm_clock_enable(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, false, false);
92
93 if (err != SC_ERR_NONE)
94 {
95 return false;
96 }
97 else
98 {
99 return true;
100 }
101 }
102
103 /*!
104 * brief Set the clock frequency for specific IP module.
105 *
106 * This function sets the IP module clock frequency.
107 *
108 * param name Which peripheral to check, see \ref clock_ip_name_t.
109 * param freq Target clock frequency value in hertz.
110 * return the Real clock frequency value in hertz, or 0 if failed
111 */
CLOCK_SetIpFreq(clock_ip_name_t name,uint32_t freq)112 uint32_t CLOCK_SetIpFreq(clock_ip_name_t name, uint32_t freq)
113 {
114 uint32_t target = freq;
115 sc_err_t err;
116
117 err = sc_pm_set_clock_rate(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, &target);
118 if (err != SC_ERR_NONE)
119 {
120 return 0;
121 }
122 else
123 {
124 return target;
125 }
126 }
127
128 /*!
129 * brief Get the clock frequency for a specific IP module.
130 *
131 * This function gets the IP module clock frequency.
132 *
133 * param name Which peripheral to get, see \ref clock_ip_name_t.
134 * return Clock frequency value in hertz, or 0 if failed
135 */
CLOCK_GetIpFreq(clock_ip_name_t name)136 uint32_t CLOCK_GetIpFreq(clock_ip_name_t name)
137 {
138 uint32_t freq;
139 sc_err_t err;
140
141 err = sc_pm_get_clock_rate(ipcHandle, LPCG_TUPLE_RSRC(name), SC_PM_CLK_PER, &freq);
142 if (err != SC_ERR_NONE)
143 {
144 return 0;
145 }
146 else
147 {
148 return freq;
149 }
150 }
151
152 /*!
153 * brief Get the core clock or system clock frequency.
154 *
155 * return Clock frequency in Hz.
156 */
CLOCK_GetCoreSysClkFreq(void)157 uint32_t CLOCK_GetCoreSysClkFreq(void)
158 {
159 uint32_t freq;
160 sc_err_t err;
161
162 err = sc_pm_get_clock_rate(ipcHandle, SC_R_M4_0_PID0, SC_PM_CLK_PER, &freq);
163 if (err != SC_ERR_NONE)
164 {
165 freq = 0U;
166 }
167
168 return freq;
169 }
170
171 /*!
172 * brief Gets the clock frequency for a specific clock name.
173 *
174 * This function checks the current clock configurations and then calculates
175 * the clock frequency for a specific clock name defined in clock_name_t.
176 *
177 * param clockName Clock names defined in clock_name_t
178 * return Clock frequency value in hertz
179 */
CLOCK_GetFreq(clock_name_t name)180 uint32_t CLOCK_GetFreq(clock_name_t name)
181 {
182 uint32_t freq;
183
184 switch (name)
185 {
186 case kCLOCK_CONECTIVITY_AhbClk:
187 freq = 167000000U; /* The CONNECTIVITY SS AHB clock is fixed to 167MHZ */
188 break;
189 case kCLOCK_CoreSysClk:
190 freq = CLOCK_GetCoreSysClkFreq();
191 break;
192 default:
193 freq = 0U;
194 break;
195 }
196
197 return freq;
198 }
199
200 /*!
201 * brief Set LPCG gate for specific LPCG.
202 *
203 * param regBase LPCG register base address.
204 * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled
205 * param hwGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled
206 * param bitsMask The available bits in LPCG register. Each bit indicate the corresponding bit is available or not.
207 */
CLOCK_SetLpcgGate(volatile uint32_t * regBase,bool swGate,bool hwGate,uint32_t bitsMask)208 void CLOCK_SetLpcgGate(volatile uint32_t *regBase, bool swGate, bool hwGate, uint32_t bitsMask)
209 {
210 if (regBase != NULL)
211 {
212 if (swGate)
213 {
214 *regBase |= bitsMask & LPCG_CLK_SWEN_MASK;
215 }
216 else
217 {
218 *regBase &= ~(bitsMask & LPCG_CLK_SWEN_MASK);
219 }
220
221 if (hwGate)
222 {
223 *regBase |= bitsMask & LPCG_CLK_HWEN_MASK;
224 }
225 else
226 {
227 *regBase &= ~(bitsMask & LPCG_CLK_HWEN_MASK);
228 }
229 }
230 }
231
232 /*!
233 * brief Config the LPCG cell for specific IP.
234 *
235 * param name Which clock to enable, see \ref clock_ip_name_t.
236 * param swGate Software clock gating. 0: clock is gated; 1: clock is enabled
237 * param hwGate Hardware auto gating. 0: disable the HW clock gate control; 1: HW clock gating is enabled
238 */
CLOCK_ConfigLPCG(clock_ip_name_t name,bool swGate,bool hwGate)239 void CLOCK_ConfigLPCG(clock_ip_name_t name, bool swGate, bool hwGate)
240 {
241 volatile uint32_t *regBase;
242
243 regBase = LPCG_TUPLE_REG_BASE(name);
244
245 /* Return if LPCG Cell is not available. */
246 if (regBase == NULL)
247 {
248 return;
249 }
250
251 /* Config the LPCG. LPCG Cells have different configurations per each clock target. */
252 switch (name)
253 {
254 /* LPCG cell avalialbe bits field mask 0xBBAAAB, 0xBBAAAB (2 32-bits LPCG registers). */
255 case kCLOCK_CONNECTIVITY_Enet0:
256 case kCLOCK_CONNECTIVITY_Enet1:
257 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBBAAABU);
258 CLOCK_SetLpcgGate(regBase + 0x1U, swGate, hwGate, 0xAU);
259 break;
260
261 /* LPCG cell avalialbe bits field mask 0xBAB0AAB.*/
262 case kCLOCK_LSIO_Gpt0:
263 case kCLOCK_LSIO_Gpt1:
264 case kCLOCK_LSIO_Gpt2:
265 case kCLOCK_LSIO_Gpt3:
266 case kCLOCK_LSIO_Gpt4:
267 case kCLOCK_LSIO_Pwm0:
268 case kCLOCK_LSIO_Pwm1:
269 case kCLOCK_LSIO_Pwm2:
270 case kCLOCK_LSIO_Pwm3:
271 case kCLOCK_LSIO_Pwm4:
272 case kCLOCK_LSIO_Pwm5:
273 case kCLOCK_LSIO_Pwm6:
274 case kCLOCK_LSIO_Pwm7:
275 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBAB0AAB);
276 break;
277
278 /* LPCG cell avalialbe bits field mask 0xB0000.*/
279 case kCLOCK_HSIO_Gpio:
280 case kCLOCK_LSIO_Gpio0:
281 case kCLOCK_LSIO_Gpio1:
282 case kCLOCK_LSIO_Gpio2:
283 case kCLOCK_LSIO_Gpio3:
284 case kCLOCK_LSIO_Gpio4:
285 case kCLOCK_LSIO_Gpio5:
286 case kCLOCK_LSIO_Gpio6:
287 case kCLOCK_LSIO_Gpio7:
288 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB0000U);
289 break;
290 /* LPCG cell avalialbe bits field mask 0xB000A. */
291 case kCLOCK_AUDIO_Gpt0:
292 case kCLOCK_AUDIO_Gpt1:
293 case kCLOCK_AUDIO_Gpt2:
294 case kCLOCK_AUDIO_Gpt3:
295 case kCLOCK_AUDIO_Gpt4:
296 case kCLOCK_AUDIO_Gpt5:
297 case kCLOCK_LSIO_Mu5A:
298 case kCLOCK_LSIO_Mu6A:
299 case kCLOCK_LSIO_Mu7A:
300 case kCLOCK_LSIO_Mu8A:
301 case kCLOCK_LSIO_Mu9A:
302 case kCLOCK_LSIO_Mu10A:
303 case kCLOCK_LSIO_Mu11A:
304 case kCLOCK_LSIO_Mu12A:
305 case kCLOCK_LSIO_Mu13A:
306 case kCLOCK_LSIO_Mu5B:
307 case kCLOCK_LSIO_Mu6B:
308 case kCLOCK_LSIO_Mu7B:
309 case kCLOCK_LSIO_Mu8B:
310 case kCLOCK_LSIO_Mu9B:
311 case kCLOCK_LSIO_Mu10B:
312 case kCLOCK_LSIO_Mu11B:
313 case kCLOCK_LSIO_Mu12B:
314 case kCLOCK_LSIO_Mu13B:
315 case kCLOCK_AUDIO_Sai0:
316 case kCLOCK_AUDIO_Sai1:
317 case kCLOCK_AUDIO_Sai2:
318 case kCLOCK_AUDIO_Sai3:
319 case kCLOCK_AUDIO_Sai4:
320 case kCLOCK_AUDIO_Sai5:
321 case kCLOCK_AUDIO_Esai0:
322 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000AU);
323 break;
324
325 /* LPCG cell avalialbe bits field mask 0xB000B. */
326 case kCLOCK_DMA_Lpspi0:
327 case kCLOCK_DMA_Lpspi1:
328 case kCLOCK_DMA_Lpspi2:
329 case kCLOCK_DMA_Lpspi3:
330 case kCLOCK_DMA_Lpuart0:
331 case kCLOCK_DMA_Lpuart1:
332 case kCLOCK_DMA_Lpuart2:
333 case kCLOCK_DMA_Lpuart3:
334 case kCLOCK_DMA_Lpi2c0:
335 case kCLOCK_DMA_Lpi2c1:
336 case kCLOCK_DMA_Lpi2c2:
337 case kCLOCK_DMA_Lpi2c3:
338 case kCLOCK_DMA_Ftm0:
339 case kCLOCK_DMA_Ftm1:
340 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xB000BU);
341 break;
342
343 /* LPCG cell avalialbe bits field mask 0xBB000B.*/
344 case kCLOCK_DMA_Can0:
345 case kCLOCK_DMA_Can1:
346 case kCLOCK_DMA_Can2:
347 case kCLOCK_M4_0_Tpm:
348 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBB000B);
349 break;
350
351 /* LPCG cell avalialbe bits field mask 0xAB000A.*/
352 case kCLOCK_CONNECTIVITY_Usdhc0:
353 case kCLOCK_CONNECTIVITY_Usdhc1:
354 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAB000A);
355 break;
356
357 /* LPCG cell avalialbe bits field mask 0xBAA000A.*/
358 case kCLOCK_LSIO_Flexspi0:
359 case kCLOCK_LSIO_Flexspi1:
360 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xBAA000A);
361 break;
362
363 /* LPCG cells avalialbe bits field mask 0xAA, 0xAB0000.*/
364 case kCLOCK_Dpu0:
365 CLOCK_SetLpcgGate(regBase, swGate, hwGate, 0xAA);
366 CLOCK_SetLpcgGate(regBase + 0x5U, swGate, hwGate, 0xAB0000);
367 break;
368
369 /* LPCG cell avalialbe bits field mask 0xB000B.*/
370 case kCLOCK_DiMiPiDsiLvds0Lpi2c0:
371 case kCLOCK_DiMiPiDsiLvds1Lpi2c0:
372 CLOCK_SetLpcgGate(regBase + 0x4U, swGate, hwGate, 0xB000B);
373 break;
374
375 /* LPCG cell does not config due to LPCG back to back write protection. */
376 case kCLOCK_M4_0_Lpit:
377 case kCLOCK_M4_0_Lpuart:
378 case kCLOCK_M4_0_Lpi2c:
379 case kCLOCK_SCU_Lpit:
380 case kCLOCK_SCU_Lpuart:
381 case kCLOCK_SCU_Lpi2c:
382 break;
383
384 /* LPCG cell is not avaliable or is not supported by this function. */
385 default:
386 assert(false);
387 break;
388 }
389 }
390