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