1 /*******************************************************************************
2 * @file rsi_pll.c
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29
30 // Includes
31
32 #include "rsi_ccp_user_config.h"
33 #include <math.h>
34 #include "rsi_rom_clks.h"
35 #ifndef PLL_ROMDRIVER_PRESENT
36 /** @addtogroup SOC3
37 * @{
38 */
39 /*==============================================*/
40 /**
41 * @fn boolean_t clk_check_pll_lock(PLL_TYPE_T pllType)
42 * @brief This API is used to check the lock status of pll
43 * @param[in] pllType : PLL type
44 * @return Enable on success
45 * Disable on failure
46 */
47
clk_check_pll_lock(PLL_TYPE_T pllType)48 boolean_t clk_check_pll_lock(PLL_TYPE_T pllType)
49 {
50 uint16_t lock = 0;
51
52 if (pllType == SOC_PLL) {
53 lock = SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG13) >> 14;
54 } else if (pllType == INTF_PLL) {
55 lock = SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG13) >> 14;
56 } else {
57 lock = SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG13) >> 14;
58 }
59 if (lock & 1) {
60 return Enable;
61 } else {
62 return Disable;
63 }
64 }
65
66 /*==============================================*/
67 /**
68 * @fn rsi_error_t clk_soc_pll_clk_enable(boolean_t clkEnable)
69 * @brief This API is used to enable SoC-PLL output clock
70 * @param[in] clkEnable : enable the clock for SoC-PLL output clock
71 * @return RSI_OK on success
72 */
73
clk_soc_pll_clk_enable(boolean_t clkEnable)74 rsi_error_t clk_soc_pll_clk_enable(boolean_t clkEnable)
75 {
76 if (clkEnable == Enable) {
77 /*Enable SoC-PLL*/
78 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) |= PLL_500_CLK_ENABLE;
79 } else {
80 /*Disable SoC-PLL*/
81 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_CLK_ENABLE));
82 }
83 return RSI_OK;
84 }
85
86 /*==============================================*/
87 /**
88 * @fn rsi_error_t clk_set_soc_pll_freq(const M4CLK_Type *pCLK, uint32_t socPllFreq, uint32_t pllRefClk)
89 * @brief This API is used to set the Soc PLL clock to particular frequency
90 * @param[in] pCLK : pointer to the processor clock source
91 * @param[in] socPllFreq : SoC PLL frequency for Soc PLL clock to particular frequency
92 * @param[in] pllRefClk : PLL reference clock for Soc PLL clock to particular frequency
93 * @return RSI_OK on success
94 */
95
clk_set_soc_pll_freq(const M4CLK_Type * pCLK,uint32_t socPllFreq,uint32_t pllRefClk)96 rsi_error_t clk_set_soc_pll_freq(const M4CLK_Type *pCLK, uint32_t socPllFreq, uint32_t pllRefClk)
97 {
98 uint16_t shiftFac = 0;
99 uint16_t socPllMulFac = 0;
100 uint16_t dcoFreq = 0;
101 uint16_t reg = 0;
102 uint16_t socPllDivFac = 0;
103 uint16_t socreg1 = 0x31c9;
104 uint16_t socreg3 = 0;
105 uint16_t socPllTvRead = 0;
106
107 /*parameter validation*/
108
109 if ((pCLK == NULL) || (socPllFreq < SOC_PLL_MIN_FREQUECY) || (socPllFreq > SOC_PLL_MAX_FREQUECY)) {
110 return INVALID_PARAMETERS;
111 }
112 socPllFreq = (socPllFreq / 1000000);
113 pllRefClk = (pllRefClk / 1000000);
114
115 if ((MCU_RET->CHIP_CONFIG_MCU_READ_b.LIMIT_M4_FREQ_110MHZ_b == 1) || (M4_BBFF_STORAGE1 & BIT(10))) {
116 if (socPllFreq >= 201) {
117 /*New table*/
118 /* Program PLL to 200Mhz */
119 /* Call low level API with m,n,p values for 200Mhz configuration. */
120 clk_soc_pll_set_freq_div(pCLK, 1, 0, 39, 199, 0, 1, 1);
121 return ERROR_INVALID_INPUT_FREQUENCY;
122 } else {
123 /* Derive the m,n,p values as per the newer table*/
124 /* program PLL with derived values */
125 /* Wait for PLL lock*/
126 if (socPllFreq < 2) {
127 shiftFac = 7;
128 } else if (socPllFreq < 3) {
129 shiftFac = 6;
130 } else if (socPllFreq < 6) {
131 shiftFac = 5;
132 } else if (socPllFreq < 12) {
133 shiftFac = 4;
134 } else if (socPllFreq < 23) {
135 shiftFac = 3;
136 } else if (socPllFreq < 46) {
137 shiftFac = 2;
138 } else if (socPllFreq < 91) {
139 shiftFac = 1;
140 } else {
141 shiftFac = 0;
142 }
143
144 socPllDivFac = (uint16_t)((1 << shiftFac) - 1);
145
146 socPllMulFac = (uint16_t)(((socPllDivFac + 1) * socPllFreq) - 1);
147
148 /*RESET PLL*/
149 clk_soc_pll_clk_reset();
150
151 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
152 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift */
153 reg &= (uint16_t)~LDO_PROG_SOCPLL;
154 reg |= 1 << 13;
155
156 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
157
158 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
159 /*writing the value into the dco_fix_sel=1*/
160 socreg1 |= 1;
161
162 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(socPllDivFac << 9 | (pllRefClk - 1) << 3);
163 socreg1 &= (uint16_t)~PLL_500_M_MASK;
164 socreg1 |= (uint16_t)((socPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
165 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
166
167 /*Enable */
168 clk_soc_pll_clk_set(pCLK); /* wait for lock */
169 /* Set and clear(read modify write) PLL500CTRLREG7 BIT[4] : TV value will be latched */
170
171 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG7) |= SPI_INP_RD_EN;
172 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG7) &= (uint16_t)(~(SPI_INP_RD_EN));
173
174 /* Read the TV value from PLL500CTRLREG12 BIT[15 : 11]*/
175 socPllTvRead = (SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG12) & 0xF800) >> 11;
176
177 if (socPllTvRead <= (M4_BBFF_STORAGE1 & 0x001F)) {
178 /*New table*/
179 /* Program PLL to 200Mhz */
180 /* Call low level API with m,n,p values for 200Mhz configuration. */
181 clk_soc_pll_set_freq_div(pCLK, 1, 0, 39, 199, 0, 1, 1);
182 return ERROR_INVALID_INPUT_FREQUENCY;
183
184 } else {
185 /*Program the required frequency by user*/
186 return RSI_OK;
187 }
188 }
189 } else {
190 /*Older table*/
191 if (socPllFreq < 2) {
192 shiftFac = 7;
193 } else if (socPllFreq < 4) {
194 shiftFac = 6;
195 } else if (socPllFreq < 8) {
196 shiftFac = 5;
197 } else if (socPllFreq < 16) {
198 shiftFac = 4;
199 } else if (socPllFreq < 32) {
200 shiftFac = 3;
201 } else if (socPllFreq < 64) {
202 shiftFac = 2;
203 } else if (socPllFreq < 127) {
204 shiftFac = 1;
205 } else {
206 shiftFac = 0;
207 }
208 dcoFreq = (uint16_t)(socPllFreq << shiftFac);
209 socPllMulFac = (uint16_t)((socPllFreq << shiftFac) - 1);
210 socPllDivFac = (uint16_t)((1 << shiftFac) - 1);
211
212 /*RESET PLL*/
213 clk_soc_pll_clk_reset();
214
215 if (socPllFreq >= 201) {
216 if ((socPllFreq % 2) == 0) {
217 socreg3 &= (uint16_t)~FCW_F_MASK;
218 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG3) = socreg3;
219 } else {
220 socreg3 |= (8192 << 2);
221 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG3) = socreg3;
222 }
223 }
224 if (dcoFreq >= 251) {
225 /*clearing the two bits i.e dco_fix_sel*/
226 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
227 /*writing the value into the dco_fix_sel=2*/
228 socreg1 |= 2;
229 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
230 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift*/
231 reg &= (uint16_t)~LDO_PROG_SOCPLL;
232 reg |= 5 << 13;
233 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
234 socPllMulFac = ((dcoFreq / 2) - 1);
235 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(socPllDivFac << 9 | (pllRefClk - 1) << 3);
236 socreg1 &= (uint16_t)~PLL_500_M_MASK;
237 socreg1 |= (uint16_t)((socPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
238 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
239 } else if ((dcoFreq >= 201) && (dcoFreq <= 250)) {
240 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
241 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
242 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift*/
243 reg &= (uint16_t)~LDO_PROG_SOCPLL;
244 reg |= 5 << 13;
245 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
246 socPllMulFac = ((dcoFreq / 2) - 1);
247 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(socPllDivFac << 9 | (pllRefClk - 1) << 3);
248 socreg1 &= (uint16_t)~PLL_500_M_MASK;
249 socreg1 |= (uint16_t)((socPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
250 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
251 } else {
252 socreg3 &= (uint16_t)~FCW_F_MASK;
253 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG3) = socreg3;
254 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
255 socreg1 |= 1;
256 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
257 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift*/
258 reg &= (uint16_t)~LDO_PROG_SOCPLL;
259 reg |= 4 << 13;
260 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
261 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(socPllDivFac << 9 | (pllRefClk - 1) << 3);
262 socreg1 &= (uint16_t)~PLL_500_M_MASK;
263 socreg1 |= (uint16_t)((socPllMulFac << 6) | PLL_500_CLK_ENABLE); // m factor
264 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
265 }
266 /*Enable */
267 clk_soc_pll_clk_set(pCLK);
268 }
269 return RSI_OK;
270 }
271
272 /*==============================================*/
273 /**
274 * @fn rsi_error_t clk_soc_pll_set_freq_div(const M4CLK_Type *pCLK,
275 * boolean_t clk_en,
276 * uint16_t divFactor,
277 * uint16_t nFactor,
278 * uint16_t mFactor,
279 * uint16_t fcwF,
280 * uint16_t dcoFixSel,
281 * uint16_t ldoProg)
282 * @brief This API is used to configure the SOC PLL clock frequency
283 * @param[in] pCLK : pointer to the processor clock source
284 * @param[in] clk_en : enable the clock for SOC PLL clock frequency
285 * @param[in] divFactor : division factor for SOC PLL clock frequency
286 * @param[in] nFactor : n number of factor for SOC PLL clock frequency
287 * @param[in] mFactor : m number of factor for SOC PLL clock frequency
288 * @param[in] fcwF : frequency for SOC PLL clock frequency
289 * @param[in] dcoFixSel : fixed select for SOC PLL clock frequency
290 * @param[in] ldoProg : ldo program for SOC PLL clock frequency
291 * @return RSI_OK on success
292 */
293
clk_soc_pll_set_freq_div(const M4CLK_Type * pCLK,boolean_t clk_en,uint16_t divFactor,uint16_t nFactor,uint16_t mFactor,uint16_t fcwF,uint16_t dcoFixSel,uint16_t ldoProg)294 rsi_error_t clk_soc_pll_set_freq_div(const M4CLK_Type *pCLK,
295 boolean_t clk_en,
296 uint16_t divFactor,
297 uint16_t nFactor,
298 uint16_t mFactor,
299 uint16_t fcwF,
300 uint16_t dcoFixSel,
301 uint16_t ldoProg)
302 {
303 uint16_t socreg1 = 0x31c9;
304 uint16_t socreg3 = 0;
305 uint16_t reg = 0;
306 uint16_t socPllTvRead = 0;
307 if (pCLK == NULL) {
308 return INVALID_PARAMETERS;
309 }
310 /*RESET PLL*/
311 clk_soc_pll_clk_reset();
312 if ((MCU_RET->CHIP_CONFIG_MCU_READ_b.LIMIT_M4_FREQ_110MHZ_b == 1) || (M4_BBFF_STORAGE1 & BIT(10))) {
313 if (clk_en) {
314 socreg3 &= (uint16_t)~FCW_F_MASK;
315 socreg3 = (uint16_t)(fcwF << 2);
316 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG3) = socreg3;
317 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
318 socreg1 |= 1;
319 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
320 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift*/
321 reg &= (uint16_t)~LDO_PROG_SOCPLL;
322 reg |= 1 << 13;
323 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
324 socreg1 |= PLL_500_CLK_ENABLE;
325 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(divFactor << 9 | nFactor << 3);
326 socreg1 &= (uint16_t)~PLL_500_M_MASK;
327 socreg1 |= (uint16_t)(mFactor << 6 | PLL_500_CLK_ENABLE);
328 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
329 } else {
330 socreg1 &= (uint16_t)(~PLL_500_CLK_ENABLE); /*soc_pll_clk o/p disable */
331 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
332 }
333
334 /*wait for lock */
335 clk_soc_pll_clk_set(pCLK);
336 /* Set and clear(read modify write) PLL500CTRLREG7 BIT[4] : TV value will be latched */
337
338 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG7) |= SPI_INP_RD_EN;
339 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG7) &= (uint16_t)(~(SPI_INP_RD_EN));
340
341 /* Read the TV value from PLL500CTRLREG12 BIT[15 : 11]*/
342 socPllTvRead = (SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG12) & 0xF800) >> 11;
343
344 if ((socPllTvRead <= (M4_BBFF_STORAGE1 & 0x001F)) && (divFactor == 0)) {
345 /*RESET PLL*/
346 clk_soc_pll_clk_reset();
347 return ERROR_INVALID_INPUT_FREQUENCY;
348 } else {
349 /*Program the required frequency by user*/
350 return RSI_OK;
351 }
352 } else {
353 if (clk_en) {
354 socreg3 &= (uint16_t)~FCW_F_MASK;
355 socreg3 = (uint16_t)(fcwF << 2);
356 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG3) = socreg3;
357 socreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
358 socreg1 |= dcoFixSel;
359 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
360 reg = (uint16_t)(reg << 1); // according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift
361 reg &= (uint16_t)~LDO_PROG_SOCPLL;
362 reg |= (uint16_t)(ldoProg << 13);
363 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
364 socreg1 |= PLL_500_CLK_ENABLE;
365 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG2) = (uint16_t)(divFactor << 9 | nFactor << 3);
366 socreg1 &= (uint16_t)~PLL_500_M_MASK;
367 socreg1 |= (uint16_t)((mFactor << 6) | PLL_500_CLK_ENABLE);
368 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
369 } else {
370 socreg1 &= (uint16_t)(~PLL_500_CLK_ENABLE); // soc_pll_clk o/p disable
371 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
372 }
373
374 /*Enable */
375 clk_soc_pll_clk_set(pCLK);
376 }
377 return RSI_OK;
378 }
379
380 /*==============================================*/
381 /**
382 * @fn rsi_error_t clk_soc_pll_clk_set(const M4CLK_Type *pCLK)
383 * @brief This API is used to Enables the SoC-PLL
384 * @param[in] pCLK : pointer to the processor clock source
385 * @return RSI_OK on success
386 */
387
clk_soc_pll_clk_set(const M4CLK_Type * pCLK)388 rsi_error_t clk_soc_pll_clk_set(const M4CLK_Type *pCLK)
389 {
390 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG11) = 0xFFFF;
391 /*Wait for lock*/
392 while ((pCLK->PLL_STAT_REG_b.SOCPLL_LOCK) != 1)
393 ;
394 return RSI_OK;
395 }
396
397 /*==============================================*/
398 /**
399 * @fn rsi_error_t clk_soc_pll_clk_bypass_enable(boolean_t clkEnable)
400 * @brief This API is used to Enable bypass clock
401 * @param[in] clkEnable : enable the clock
402 * @return RSI_OK on success
403 */
404
clk_soc_pll_clk_bypass_enable(boolean_t clkEnable)405 rsi_error_t clk_soc_pll_clk_bypass_enable(boolean_t clkEnable)
406 {
407 if (clkEnable == Enable) {
408 /*Enable PLL clock*/
409 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) |= PLL_500_BYPASS;
410 } else {
411 /*Disable PLL clock*/
412 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_BYPASS));
413 }
414 return RSI_OK;
415 }
416
417 /*==============================================*/
418 /**
419 * @fn rsi_error_t clk_soc_pll_clk_reset(void)
420 * @brief This API is used to Reset the Soc_pll_clk
421 * @return RSI_OK on success
422 */
423
clk_soc_pll_clk_reset(void)424 rsi_error_t clk_soc_pll_clk_reset(void)
425 {
426 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG11) = 0x01FF;
427 return RSI_OK;
428 }
429
430 /*==============================================*/
431 /**
432 * @fn rsi_error_t clk_soc_pll_pd_enable(boolean_t en)
433 * @brief This API is used to Enable the PdEnable(power down)
434 * @param[in] en : enable
435 * @return RSI_OK on success
436 */
437
clk_soc_pll_pd_enable(boolean_t en)438 rsi_error_t clk_soc_pll_pd_enable(boolean_t en)
439 {
440 if (en == Enable) {
441 /*Enable power down*/
442 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) |= PLL_500_PD;
443 } else {
444 /*Disable power down*/
445 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_PD));
446 }
447 return RSI_OK;
448 }
449
450 /*==============================================*/
451 /**
452 * @fn rsi_error_t clk_soc_pll_turn_off(void)
453 * @brief This API is used to TurnOff the SOC_PLL
454 * @return RSI_OK on success
455 */
456
clk_soc_pll_turn_off(void)457 rsi_error_t clk_soc_pll_turn_off(void)
458 {
459 uint16_t socreg1 = 0x31c9;
460 /*Set PLL PD Bit*/
461 socreg1 |= PLL_500_PD;
462 socreg1 |= PLL_500_RST;
463 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
464 return RSI_OK;
465 }
466
467 /*==============================================*/
468 /**
469 * @fn rsi_error_t clk_soc_pll_turn_on(void)
470 * @brief This API is used to TurnOn the SOC_PLL
471 * @return RSI_OK on success
472 */
473
clk_soc_pll_turn_on(void)474 rsi_error_t clk_soc_pll_turn_on(void)
475 {
476 uint16_t socreg1 = 0x31c9;
477 /*Disable power down */
478 socreg1 &= (uint16_t)(~(PLL_500_RST));
479 socreg1 &= (uint16_t)(~(PLL_500_PD));
480 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG1) = socreg1;
481 return RSI_OK;
482 }
483
484 /*==============================================*/
485 /**
486 * @fn rsi_error_t clk_i2s_pll_clk_enable(boolean_t clkEnable)
487 * @brief This API is used to Enable the I2s_PLL output clock
488 * @param[in] clkEnable : enable the clock for I2s_PLL output clock
489 * @return RSI_OK on success
490 */
491
clk_i2s_pll_clk_enable(boolean_t clkEnable)492 rsi_error_t clk_i2s_pll_clk_enable(boolean_t clkEnable)
493 {
494 if (clkEnable == Enable) {
495 /*Enable SoC-PLL*/
496 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) |= PLL_500_CLK_ENABLE;
497 } else {
498 /*Disable SoC-PLL*/
499 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) &= (uint16_t)(~(PLL_500_CLK_ENABLE));
500 }
501 return RSI_OK;
502 }
503
504 /*==============================================*/
505 /**
506 * @fn rsi_error_t clk_i2s_pll_clk_bypass_enable(boolean_t clkEnable)
507 * @brief This API is used to Enable bypass clock
508 * @param[in] clkEnable : enable the clock for bypass clock
509 * @return RSI_OK on success
510 */
511
clk_i2s_pll_clk_bypass_enable(boolean_t clkEnable)512 rsi_error_t clk_i2s_pll_clk_bypass_enable(boolean_t clkEnable)
513 {
514 if (clkEnable == Enable) {
515 /*Enable PLL clock*/
516 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) |= PLL_500_BYPASS;
517 } else {
518 /*Disable PLL clock*/
519 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) &= (uint16_t)(~(PLL_500_BYPASS));
520 }
521 return RSI_OK;
522 }
523
524 /*==============================================*/
525 /**
526 * @fn rsi_error_t clk_i2s_pll_pd_enable(boolean_t en)
527 * @brief This API is used to Enable the PdEnable(power down)
528 * @param[in] en : enable
529 * @return RSI_OK on success
530 */
531
clk_i2s_pll_pd_enable(boolean_t en)532 rsi_error_t clk_i2s_pll_pd_enable(boolean_t en)
533 {
534 if (en == Enable) {
535 /*Enable power down*/
536 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) |= PLL_500_PD;
537 } else {
538 /*Disable power down*/
539 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) &= (uint16_t)(~(PLL_500_PD));
540 }
541 return RSI_OK;
542 }
543
544 /*==============================================*/
545 /**
546 * @fn rsi_error_t clk_i2s_pll_turn_off(void)
547 * @brief This API is used to TurnOff the I2s_PLL
548 * @return RSI_OK on success
549 */
550
clk_i2s_pll_turn_off(void)551 rsi_error_t clk_i2s_pll_turn_off(void)
552 {
553 uint16_t i2sreg1 = 0x1244;
554 /*Set PLL PD Bit*/
555 i2sreg1 |= PLL_500_PD;
556 i2sreg1 |= PLL_500_RST;
557 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) |= i2sreg1;
558 return RSI_OK;
559 }
560
561 /*==============================================*/
562 /**
563 * @fn rsi_error_t clk_i2s_pll_turn_on(void)
564 * @brief This API is used to TurnOn the I2s_PLL
565 * @return RSI_OK on success
566 */
567
clk_i2s_pll_turn_on(void)568 rsi_error_t clk_i2s_pll_turn_on(void)
569 {
570 uint16_t i2sreg1 = 0x1244;
571 i2sreg1 &= (uint16_t)(~(PLL_500_PD));
572 i2sreg1 &= (uint16_t)(~(PLL_500_RST));
573 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) = i2sreg1;
574 return RSI_OK;
575 }
576
577 /*==============================================*/
578 /**
579 * @fn rsi_error_t clk_set_i2s_pll_freq(const M4CLK_Type *pCLK, uint32_t i2sPllFreq, uint32_t fXtal)
580 * @brief This API is used to set the I2s_pll clock to particular frequency
581 * @param[in] pCLK : pointer to the processor clock source
582 * @param[in] i2sPllFreq : PLL clock of I2S for particular frequency
583 * @param[in] fXtal : frequency oscillator for particular frequency
584 * @return RSI_OK on success
585 */
586
clk_set_i2s_pll_freq(const M4CLK_Type * pCLK,uint32_t i2sPllFreq,uint32_t fXtal)587 rsi_error_t clk_set_i2s_pll_freq(const M4CLK_Type *pCLK, uint32_t i2sPllFreq, uint32_t fXtal)
588 {
589 uint16_t p_div = 0;
590 uint16_t u16DivFactor1 = 0;
591 uint16_t u16DivFactor2 = 0;
592 uint16_t N = 0;
593 uint16_t M = 0;
594 uint16_t FCW_F = 0;
595 uint32_t fref = 0;
596 uint32_t Fdco;
597 float g;
598 double FCW;
599 double frac;
600 uint16_t i2sreg1 = 0x1244;
601 uint16_t i2sreg2 = 0x5850;
602 uint16_t i2sreg3 = 0xba60;
603 if (pCLK == NULL) {
604 return INVALID_PARAMETERS;
605 }
606
607 if (!((fXtal == 9600000) || (fXtal == 19200000) || (fXtal == 38400000))) {
608 fref = 1000000; /* One Mega herz steps*/
609 } else {
610 fref = 960000; /* 0.96 Mega herz steps*/
611 }
612 /*Calculating p_div value*/
613 g = ((float)I2S_DCO_FREQ1 / (float)i2sPllFreq);
614 if (g - (float)(int)g == 0) /* checking if the value is an integer */
615 {
616 p_div = (uint16_t)(g);
617 Fdco = I2S_DCO_FREQ1;
618 } else {
619 p_div = (uint16_t)(I2S_DCO_FREQ2 / i2sPllFreq);
620 Fdco = I2S_DCO_FREQ2;
621 }
622 N = (uint16_t)(fXtal / fref); /*calculating N value*/
623 /*deriving M and FCW_F value*/
624 FCW = (float)Fdco / (float)fref;
625 M = (uint16_t)FCW;
626 frac = (FCW - M);
627 FCW_F = (uint16_t)(frac * (1 << 14)); // (1 << 14) == pow(2, 14)
628 if (Fdco == I2S_DCO_FREQ1) {
629 FCW_F = (FCW_F + 1);
630 }
631 /*deriving the p_div1 and p_div2 values from p_div value*/
632 /*From the refernce of PLL Programming table*/
633 if (p_div >= 288) {
634 u16DivFactor2 = 4;
635 u16DivFactor1 = ((p_div >> 4) - 1);
636 } else if ((p_div >= 96) && (p_div <= 144)) {
637 u16DivFactor2 = 3;
638 u16DivFactor1 = ((p_div >> 3) - 1);
639 } else if (p_div == 72) {
640 u16DivFactor2 = 2;
641 u16DivFactor1 = ((p_div >> 2) - 1);
642 } else if ((p_div >= 36) && (p_div <= 48)) {
643 u16DivFactor2 = 1;
644 u16DivFactor1 = ((p_div >> 1) - 1);
645 } else {
646 u16DivFactor2 = 0;
647 u16DivFactor1 = (p_div - 1);
648 }
649 /*RESET PLL*/
650 clk_i2s_pll_clk_reset();
651 i2sreg2 &= (uint16_t)~N_DIV_MASK;
652 i2sreg2 |= (uint16_t)(N << 1);
653 i2sreg3 &= (uint16_t)~FCW_F_MASK;
654 i2sreg3 |= (uint16_t)(FCW_F << 2);
655 i2sreg1 &= (uint16_t)~PLL_500_M_MASK;
656 i2sreg1 |= (uint16_t)(M << 6);
657 i2sreg2 &= (uint16_t)~0xff00;
658 i2sreg2 |= (uint16_t)((u16DivFactor1 << 11) | (u16DivFactor2 << 8));
659 i2sreg1 &= (uint16_t)(~PLL_500_PD);
660 i2sreg1 &= (uint16_t)(~PLL_500_RST);
661 i2sreg1 |= PLL_500_BYPASS;
662 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) = i2sreg1;
663 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG2) = i2sreg2;
664 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG3) = i2sreg3;
665 clk_i2s_pll_clk_set(pCLK);
666 return RSI_OK;
667 }
668
669 /*==============================================*/
670 /**
671 * @fn rsi_error_t clk_i2s_pll_set_freq_div(const M4CLK_Type *pCLK,
672 * uint16_t u16DivFactor1,
673 * uint16_t u16DivFactor2,
674 * uint16_t nFactor,
675 * uint16_t mFactor,
676 * uint16_t fcwF)
677 * @brief This API is used to divide I2s_PLL Clock
678 * @param[in] pCLK : pointer to the processor clock source
679 * @param[in] u16DivFactor1 : division factor of 1
680 * @param[in] u16DivFactor2 : division factor of 2
681 * @param[in] nFactor : n number of factor for I2s_PLL Clock
682 * @param[in] mFactor : m number of factor for I2s_PLL Clock
683 * @param[in] fcwF : frequency for for I2s_PLL Clock
684 * @return RSI_OK on success
685 */
686
clk_i2s_pll_set_freq_div(const M4CLK_Type * pCLK,uint16_t u16DivFactor1,uint16_t u16DivFactor2,uint16_t nFactor,uint16_t mFactor,uint16_t fcwF)687 rsi_error_t clk_i2s_pll_set_freq_div(const M4CLK_Type *pCLK,
688 uint16_t u16DivFactor1,
689 uint16_t u16DivFactor2,
690 uint16_t nFactor,
691 uint16_t mFactor,
692 uint16_t fcwF)
693 {
694 uint16_t i2sreg1 = 0x1244;
695 uint16_t i2sreg2 = 0x5850;
696 uint16_t i2sreg3 = 0xba60;
697 if (pCLK == NULL) {
698 return INVALID_PARAMETERS;
699 }
700 clk_i2s_pll_clk_reset();
701 if (u16DivFactor1) {
702 i2sreg2 &= (uint16_t)~N_DIV_MASK;
703 i2sreg2 |= (uint16_t)(nFactor << 1);
704 i2sreg3 &= (uint16_t)~FCW_F_MASK;
705 i2sreg3 |= (uint16_t)(fcwF << 2);
706 i2sreg1 &= (uint16_t)~PLL_500_M_MASK;
707 i2sreg1 |= (uint16_t)(mFactor << 6);
708 i2sreg2 &= (uint16_t)~0xff00;
709 i2sreg2 |= (uint16_t)((u16DivFactor1 << 11) | (u16DivFactor2 << 8));
710 i2sreg1 &= (uint16_t)~PLL_500_PD;
711 i2sreg1 &= (uint16_t)(~PLL_500_RST);
712 i2sreg1 |= PLL_500_BYPASS;
713 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG1) = i2sreg1;
714 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG2) = i2sreg2;
715 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG3) = i2sreg3;
716 }
717 clk_i2s_pll_clk_set(pCLK);
718 return RSI_OK;
719 }
720
721 /*==============================================*/
722 /**
723 * @fn rsi_error_t clk_i2s_pll_clk_set(const M4CLK_Type *pCLK)
724 * @brief This API is used to set the I2s_pll_clk
725 * @param[in] pCLK : pointer to the processor clock source
726 * @return RSI_OK on success
727 */
728
clk_i2s_pll_clk_set(const M4CLK_Type * pCLK)729 rsi_error_t clk_i2s_pll_clk_set(const M4CLK_Type *pCLK)
730 {
731 if (pCLK == NULL) {
732 return INVALID_PARAMETERS;
733 }
734 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG11) = 0xFFFF;
735 while ((pCLK->PLL_STAT_REG_b.I2SPLL_LOCK) != 1)
736 ; /* checking for pll lck */
737 return RSI_OK;
738 }
739
740 /*==============================================*/
741 /**
742 * @fn rsi_error_t clk_i2s_pll_clk_reset(void)
743 * @brief This API is used to set the I2s_pll_clk
744 * @return RSI_OK on success
745 */
746
clk_i2s_pll_clk_reset(void)747 rsi_error_t clk_i2s_pll_clk_reset(void)
748 {
749 SPI_MEM_MAP_PLL(I2S_PLL_CTRL_REG11) = 0x01FF;
750 return RSI_OK;
751 }
752
753 /*==============================================*/
754 /**
755 * @fn rsi_error_t clk_intf_pll_clk_enable(boolean_t clkEnable)
756 * @brief This API is used to Enable the Intf_PLL output clock
757 * @param[in] clkEnable : enable the clock
758 * @return RSI_OK on success
759 */
760
clk_intf_pll_clk_enable(boolean_t clkEnable)761 rsi_error_t clk_intf_pll_clk_enable(boolean_t clkEnable)
762 {
763 if (clkEnable == Enable) {
764 /*Enable SoC-PLL*/
765 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) |= PLL_500_CLK_ENABLE;
766 } else {
767 /*Disable SoC-PLL*/
768 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_CLK_ENABLE));
769 }
770 return RSI_OK;
771 }
772
773 /*==============================================*/
774 /**
775 * @fn rsi_error_t clk_intf_pll_pd_enable(boolean_t en)
776 * @brief This API is used to Enable the PdEnable(power down)
777 * @param[in] en : enable
778 * @return RSI_OK on success
779 */
780
clk_intf_pll_pd_enable(boolean_t en)781 rsi_error_t clk_intf_pll_pd_enable(boolean_t en)
782 {
783 if (en == Enable) {
784 /*Enable power down*/
785 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) |= PLL_500_PD;
786 } else {
787 /*Disable power down*/
788 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_PD));
789 }
790 return RSI_OK;
791 }
792
793 /*==============================================*/
794 /**
795 * @fn rsi_error_t clk_intf_pll_turn_off(void)
796 * @brief This API is used to TurnOff the Intf_PLL
797 * @return RSI_OK on success
798 */
799
clk_intf_pll_turn_off(void)800 rsi_error_t clk_intf_pll_turn_off(void)
801 {
802 uint16_t intfreg1 = 0x31c9;
803 /*Set PLL PD Bit*/
804 intfreg1 |= PLL_500_PD;
805 /* setting the bit reset */
806 intfreg1 |= PLL_500_RST;
807 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
808 return RSI_OK;
809 }
810
811 /*==============================================*/
812 /**
813 * @fn rsi_error_t clk_set_intf_pll_freq(const M4CLK_Type *pCLK, uint32_t intfPllFreq, uint32_t pllRefClk)
814 * @brief This API is used to set the INTFPLL clock to particular frequency
815 * @param[in] pCLK : pointer to the processor clock source
816 * @param[in] intfPllFreq : input frequency of PLL frequency
817 * @param[in] pllRefClk : PLL reference clock
818 * @return RSI_OK on success
819 */
820
clk_set_intf_pll_freq(const M4CLK_Type * pCLK,uint32_t intfPllFreq,uint32_t pllRefClk)821 rsi_error_t clk_set_intf_pll_freq(const M4CLK_Type *pCLK, uint32_t intfPllFreq, uint32_t pllRefClk)
822 {
823 uint16_t shiftFac = 0;
824 uint16_t intfPllMulFac = 0;
825 uint16_t intfPllDivFac = 0;
826 uint16_t reg = 0;
827 uint16_t dcoFreq = 0;
828 uint16_t intfreg1 = 0x31c9;
829 uint16_t intfreg3 = 0;
830 uint16_t intfPllTvRead = 0;
831
832 /*Parameter validation */
833 if ((pCLK == NULL) || (intfPllFreq < INTF_PLL_MIN_FREQUECY) || (intfPllFreq > INTF_PLL_MAX_FREQUECY)) {
834 return INVALID_PARAMETERS;
835 }
836 intfPllFreq = (intfPllFreq / 1000000);
837 pllRefClk = (pllRefClk / 1000000);
838
839 if ((MCU_RET->CHIP_CONFIG_MCU_READ_b.LIMIT_M4_FREQ_110MHZ_b == 1) || (M4_BBFF_STORAGE1 & BIT(10))) {
840 if (intfPllFreq >= 201) {
841 /*New table*/
842 /* Program PLL to 200Mhz */
843 /* Call low level API with m,n,p values for 200Mhz configuration. */
844 clk_intf_pll_set_freq_div(pCLK, 1, 0, 39, 199, 0, 1, 1);
845 return ERROR_INVALID_INPUT_FREQUENCY;
846 } else {
847 /* Derive the m,n,p values as per the newer table*/
848 /* program PLL with derived values */
849 /* Wait for PLL lock*/
850 if (intfPllFreq < 2) {
851 shiftFac = 7;
852 } else if (intfPllFreq < 3) {
853 shiftFac = 6;
854 } else if (intfPllFreq < 6) {
855 shiftFac = 5;
856 } else if (intfPllFreq < 12) {
857 shiftFac = 4;
858 } else if (intfPllFreq < 23) {
859 shiftFac = 3;
860 } else if (intfPllFreq < 46) {
861 shiftFac = 2;
862 } else if (intfPllFreq < 91) {
863 shiftFac = 1;
864 } else {
865 shiftFac = 0;
866 }
867
868 intfPllDivFac = (uint16_t)((1 << shiftFac) - 1);
869
870 intfPllMulFac = (uint16_t)(((intfPllDivFac + 1) * intfPllFreq) - 1);
871
872 /*RESET PLL*/
873 clk_intf_pll_clk_reset();
874
875 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
876 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift */
877 reg &= (uint16_t)~LDO_PROG_INTFPLL;
878 reg |= 1 << 10;
879
880 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
881
882 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
883 /*writing the value into the dco_fix_sel=1*/
884 intfreg1 |= 1;
885
886 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)(intfPllDivFac << 9 | (pllRefClk - 1) << 3);
887 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
888 intfreg1 |= (uint16_t)((intfPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
889 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
890
891 /*Enable */
892 clk_intf_pll_clk_set(pCLK);
893 /* Set and clear(read modify write) INTFPLL500CTRLREG7 BIT[4] : TV value will be latched */
894
895 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG7) |= SPI_INP_RD_EN;
896 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG7) &= (uint16_t)(~(SPI_INP_RD_EN));
897 /* Read the TV value from INTFPLL500CTRLREG12 BIT[15 : 11]*/
898 intfPllTvRead = (SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG12) & 0xF800) >> 11;
899
900 if (intfPllTvRead <= ((M4_BBFF_STORAGE1 & 0x03E0) >> 5)) {
901 /*New table*/
902 /* Program PLL to 200Mhz */
903 /* Call low level API with m,n,p values for 200Mhz configuration.*/
904 clk_intf_pll_set_freq_div(pCLK, 1, 0, 39, 199, 0, 1, 1);
905 return ERROR_INVALID_INPUT_FREQUENCY;
906
907 } else {
908 /*Program the required frequency by user*/
909 return RSI_OK;
910 }
911 }
912
913 } else { /* older table */
914 if (intfPllFreq < 2) {
915 shiftFac = 7;
916 } else if (intfPllFreq < 4) {
917 shiftFac = 6;
918 } else if (intfPllFreq < 8) {
919 shiftFac = 5;
920 } else if (intfPllFreq < 16) {
921 shiftFac = 4;
922 } else if (intfPllFreq < 32) {
923 shiftFac = 3;
924 } else if (intfPllFreq < 64) {
925 shiftFac = 2;
926 } else if (intfPllFreq < 127) {
927 shiftFac = 1;
928 } else {
929 shiftFac = 0;
930 }
931 dcoFreq = (uint16_t)(intfPllFreq << shiftFac);
932 intfPllMulFac = (uint16_t)((intfPllFreq << shiftFac) - 1);
933 intfPllDivFac = (uint16_t)((1 << shiftFac) - 1);
934 /*RESET PLL*/
935 clk_intf_pll_clk_reset();
936 if (intfPllFreq >= 201) {
937 if ((intfPllFreq % 2) == 0) {
938 intfreg3 &= (uint16_t)~FCW_F_MASK;
939 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG3) = intfreg3;
940 } else {
941 intfreg3 |= (8192 << 2);
942 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG3) = intfreg3;
943 }
944 }
945
946 if (dcoFreq >= 251) {
947
948 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
949 /*writing the value into the dco_fix_sel=2*/
950 intfreg1 |= 2;
951 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
952 reg = (uint16_t)(reg << 1);
953 reg &= (uint16_t)~LDO_PROG_INTFPLL;
954 reg |= 5 << 10;
955 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
956 intfPllMulFac = ((dcoFreq / 2) - 1);
957 intfreg1 |= PLL_500_CLK_ENABLE; /* soc_pll_clk o/p en */
958 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)((intfPllDivFac << 9) | ((pllRefClk - 1) << 3));
959 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
960 intfreg1 |= (uint16_t)((intfPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
961 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
962 } else if ((dcoFreq >= 201) && (dcoFreq <= 250)) {
963 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
964 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
965 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift */
966 reg &= (uint16_t)~LDO_PROG_INTFPLL;
967 reg |= 5 << 10;
968 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
969 intfPllMulFac = ((dcoFreq / 2) - 1);
970 intfreg1 |= PLL_500_CLK_ENABLE; /* soc_pll_clk o/p en */
971 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)((intfPllDivFac << 9) | ((pllRefClk - 1) << 3));
972 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
973 intfreg1 |= (uint16_t)((intfPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
974 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
975 } else {
976 intfreg3 &= (uint16_t)~FCW_F_MASK;
977 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG3) = intfreg3;
978 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
979 intfreg1 |= 1;
980 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
981 reg = (uint16_t)(reg << 1);
982 reg &= (uint16_t)~LDO_PROG_INTFPLL;
983 reg |= 4 << 10;
984 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
985 intfreg1 |= PLL_500_CLK_ENABLE; /* soc_pll_clk o/p en */
986 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)((intfPllDivFac << 9) | ((pllRefClk - 1) << 3));
987 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
988 intfreg1 |= (uint16_t)((intfPllMulFac << 6) | PLL_500_CLK_ENABLE); /* m factor */
989 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
990 }
991 /*Enable */
992
993 clk_intf_pll_clk_set(pCLK);
994 }
995 return RSI_OK;
996 }
997
998 /*==============================================*/
999 /**
1000 * @fn rsi_error_t clk_intf_pll_set_freq_div(const M4CLK_Type *pCLK,
1001 * boolean_t clk_en,
1002 * uint16_t divFactor,
1003 * uint16_t nFactor,
1004 * uint16_t mFactor,
1005 * uint16_t fcwF,
1006 * uint16_t dcoFixSel,
1007 * uint16_t ldoProg)
1008 * @brief This API is used to divide the Intf PLL clock frequency
1009 * @param[in] pCLK : pointer to the processor clock source
1010 * @param[in] clk_en : enable the clock for Intf PLL clock frequency
1011 * @param[in] divFactor : division factor for Intf PLL clock frequency
1012 * @param[in] nFactor : n number of factor for Intf PLL clock frequency
1013 * @param[in] mFactor : m number of factor for Intf PLL clock frequency
1014 * @param[in] fcwF : frequency for Intf PLL clock frequency
1015 * @param[in] dcoFixSel : fixed select for Intf PLL clock frequency
1016 * @param[in] ldoProg : ldo program for Intf PLL clock frequency
1017 * @return RSI_OK on success
1018 */
1019
clk_intf_pll_set_freq_div(const M4CLK_Type * pCLK,boolean_t clk_en,uint16_t divFactor,uint16_t nFactor,uint16_t mFactor,uint16_t fcwF,uint16_t dcoFixSel,uint16_t ldoProg)1020 rsi_error_t clk_intf_pll_set_freq_div(const M4CLK_Type *pCLK,
1021 boolean_t clk_en,
1022 uint16_t divFactor,
1023 uint16_t nFactor,
1024 uint16_t mFactor,
1025 uint16_t fcwF,
1026 uint16_t dcoFixSel,
1027 uint16_t ldoProg)
1028 {
1029 uint16_t intfreg1 = 0x31c9;
1030 uint16_t intfreg3 = 0;
1031 uint16_t reg = 0;
1032 uint16_t intfPllTvRead = 0;
1033
1034 if (pCLK == NULL) {
1035 return INVALID_PARAMETERS;
1036 }
1037 /*RESET PLL*/
1038 clk_intf_pll_clk_reset();
1039 if ((MCU_RET->CHIP_CONFIG_MCU_READ_b.LIMIT_M4_FREQ_110MHZ_b == 1) || (M4_BBFF_STORAGE1 & BIT(10))) {
1040 if (clk_en) {
1041 intfreg3 &= (uint16_t)~FCW_F_MASK;
1042 intfreg3 = (uint16_t)(fcwF << 2);
1043 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG3) = intfreg3;
1044 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
1045 intfreg1 |= 1;
1046 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
1047 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift */
1048 reg &= (uint16_t)~LDO_PROG_INTFPLL;
1049 reg |= 1 << 10;
1050 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
1051 intfreg1 |= PLL_500_CLK_ENABLE; /* soc_pll_clk o/p en */
1052 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)((divFactor << 9) | (nFactor << 3));
1053 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
1054 intfreg1 |= (uint16_t)((mFactor << 6) | PLL_500_CLK_ENABLE); /* m factor */
1055 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
1056 } else {
1057 intfreg1 &= (uint16_t)(~PLL_500_CLK_ENABLE);
1058 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1; /* soc_pll_clk o/p disable */
1059 }
1060 /*Enable */
1061 clk_intf_pll_clk_set(pCLK);
1062 /* Set and clear(read modify write) PLL500CTRLREG7 BIT[4] : TV value will be latched */
1063
1064 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG7) |= SPI_INP_RD_EN;
1065 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG7) &= (uint16_t)(~(SPI_INP_RD_EN));
1066
1067 /* Read the TV value from PLL500CTRLREG12 BIT[15 : 11] */
1068 intfPllTvRead = (SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG12) & 0xF800) >> 11;
1069
1070 if ((intfPllTvRead <= ((M4_BBFF_STORAGE1 & 0x03E0) >> 5)) && (divFactor == 0)) {
1071 /*RESET PLL*/
1072 clk_intf_pll_clk_reset();
1073 return ERROR_INVALID_INPUT_FREQUENCY;
1074 } else {
1075 /*Program the required frequency by user*/
1076 return RSI_OK;
1077 }
1078 } else {
1079 if (clk_en) {
1080 intfreg3 &= (uint16_t)~FCW_F_MASK;
1081 intfreg3 = (uint16_t)(fcwF << 2);
1082 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG3) = intfreg3;
1083 intfreg1 &= (uint16_t)~DCO_FIX_SEL_MASK;
1084 intfreg1 |= dcoFixSel;
1085 reg = SPI_MEM_MAP_PLL(SOCPLLMACROREG3);
1086 reg = (uint16_t)(reg << 1); /* according to RTL bug SOCPLLMACROREG3 (read issue) will shift to one left shift */
1087 reg &= (uint16_t)~LDO_PROG_INTFPLL;
1088 reg |= (uint16_t)(ldoProg << 10);
1089 SPI_MEM_MAP_PLL(SOCPLLMACROREG3) = reg;
1090 intfreg1 |= PLL_500_CLK_ENABLE; /* soc_pll_clk o/p en */
1091 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG2) = (uint16_t)((divFactor << 9) | (nFactor << 3));
1092 intfreg1 &= (uint16_t)~PLL_500_M_MASK;
1093 intfreg1 |= (uint16_t)((mFactor << 6) | PLL_500_CLK_ENABLE); /* m factor */
1094 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
1095 } else {
1096 intfreg1 &= (uint16_t)(~PLL_500_CLK_ENABLE);
1097 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1; /* soc_pll_clk o/p disable */
1098 }
1099 /*Enable */
1100 clk_intf_pll_clk_set(pCLK);
1101 }
1102 return RSI_OK;
1103 }
1104
1105 /*==============================================*/
1106 /**
1107 * @fn rsi_error_t clk_intf_pll_clk_bypass_enable(boolean_t clkEnable)
1108 * @brief This API is used to Enable bypass clock
1109 * @param[in] clkEnable : enable the clock
1110 * @return RSI_OK on success
1111 */
1112
clk_intf_pll_clk_bypass_enable(boolean_t clkEnable)1113 rsi_error_t clk_intf_pll_clk_bypass_enable(boolean_t clkEnable)
1114 {
1115 if (clkEnable == Enable) {
1116 /*Enable PLL clock*/
1117 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) |= PLL_500_BYPASS;
1118 } else {
1119 /*Disable PLL clock*/
1120 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) &= (uint16_t)(~(PLL_500_BYPASS));
1121 }
1122 return RSI_OK;
1123 }
1124
1125 /*==============================================*/
1126 /**
1127 * @fn rsi_error_t clk_intf_pll_turn_on()
1128 * @brief This API is used to TurnOn the Intf_PLL
1129 * @return RSI_OK on success
1130 */
1131
clk_intf_pll_turn_on()1132 rsi_error_t clk_intf_pll_turn_on()
1133 {
1134 uint16_t intfreg1 = 0x31c9;
1135
1136 intfreg1 &= (uint16_t)(~PLL_500_PD); /* clearing pd */
1137 intfreg1 &= (uint16_t)(~PLL_500_RST); /* clearing reset */
1138 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG1) = intfreg1;
1139
1140 return RSI_OK;
1141 }
1142
1143 /*==============================================*/
1144 /**
1145 * @fn rsi_error_t clk_intf_pll_clk_reset(void)
1146 * @brief This API is used to Reset the Intf_PLL
1147 * @return RSI_OK on success
1148 */
1149
clk_intf_pll_clk_reset(void)1150 rsi_error_t clk_intf_pll_clk_reset(void)
1151 {
1152 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG11) = 0x01FF;
1153 return RSI_OK;
1154 }
1155
1156 /*==============================================*/
1157 /**
1158 * @fn rsi_error_t clk_intf_pll_clk_set(const M4CLK_Type *pCLK)
1159 * @brief This API is used to Enable the Intf_PLL
1160 * @param[in] pCLK : pointer to the processor clock source
1161 * @return RSI_OK on success
1162 */
1163
clk_intf_pll_clk_set(const M4CLK_Type * pCLK)1164 rsi_error_t clk_intf_pll_clk_set(const M4CLK_Type *pCLK)
1165 {
1166 if (pCLK == NULL) {
1167 return INVALID_PARAMETERS;
1168 }
1169 SPI_MEM_MAP_PLL(INTF_PLL_500_CTRL_REG11) = 0xFFFF;
1170 while ((pCLK->PLL_STAT_REG_b.INTFPLL_LOCK) != 1)
1171 ; // checking for pll lck
1172 return RSI_OK;
1173 }
1174
1175 /*==============================================*/
1176 /**
1177 * @fn rsi_error_t clk_peripheral_clk_enable1(M4CLK_Type *pCLK, uint32_t flags)
1178 * @brief This API is used to Enable the peripheral cloks for SET1 register
1179 * @param[in] pCLK : pointer to the processor clock source
1180 * @param[in] flags : flags for SET1 register
1181 * @return RSI_OK on success
1182 */
1183
clk_peripheral_clk_enable1(M4CLK_Type * pCLK,uint32_t flags)1184 rsi_error_t clk_peripheral_clk_enable1(M4CLK_Type *pCLK, uint32_t flags)
1185 {
1186 if (pCLK == NULL) {
1187 return INVALID_PARAMETERS;
1188 }
1189 pCLK->CLK_ENABLE_SET_REG1 = flags;
1190 return RSI_OK;
1191 }
1192
1193 /*==============================================*/
1194 /**
1195 * @fn rsi_error_t clk_peripheral_clk_disable1(M4CLK_Type *pCLK, uint32_t flags)
1196 * @brief This API is used to disable the peripheral cloks for CLR1 register
1197 * @param[in] pCLK : pointer to the processor clock source
1198 * @param[in] flags : flags for CLR1 register
1199 * @return RSI_OK on success
1200 */
1201
clk_peripheral_clk_disable1(M4CLK_Type * pCLK,uint32_t flags)1202 rsi_error_t clk_peripheral_clk_disable1(M4CLK_Type *pCLK, uint32_t flags)
1203 {
1204 if (pCLK == NULL) {
1205 return INVALID_PARAMETERS;
1206 }
1207 pCLK->CLK_ENABLE_CLEAR_REG1 = flags;
1208 return RSI_OK;
1209 }
1210
1211 /*==============================================*/
1212 /**
1213 * @fn rsi_error_t clk_peripheral_clk_enable2(M4CLK_Type *pCLK, uint32_t flags)
1214 * @brief This API is used to Enable the peripheral cloks for SET2 register
1215 * @param[in] pCLK : pointer to the processor clock source
1216 * @param[in] flags : flags for SET2 register
1217 * @return RSI_OK on success
1218 */
1219
clk_peripheral_clk_enable2(M4CLK_Type * pCLK,uint32_t flags)1220 rsi_error_t clk_peripheral_clk_enable2(M4CLK_Type *pCLK, uint32_t flags)
1221 {
1222 if (pCLK == NULL) {
1223 return INVALID_PARAMETERS;
1224 }
1225 pCLK->CLK_ENABLE_SET_REG2 = flags;
1226 return RSI_OK;
1227 }
1228
1229 /*==============================================*/
1230 /**
1231 * @fn rsi_error_t clk_peripheral_clk_disable2(M4CLK_Type *pCLK, uint32_t flags)
1232 * @brief This API is used to disable the peripheral cloks for CLR2 register
1233 * @param[in] pCLK : pointer to the processor clock source
1234 * @param[in] flags : flags for CLR2 register
1235 * @return RSI_OK on success
1236 */
1237
clk_peripheral_clk_disable2(M4CLK_Type * pCLK,uint32_t flags)1238 rsi_error_t clk_peripheral_clk_disable2(M4CLK_Type *pCLK, uint32_t flags)
1239 {
1240 if (pCLK == NULL) {
1241 return INVALID_PARAMETERS;
1242 }
1243 pCLK->CLK_ENABLE_CLEAR_REG2 = flags;
1244 return RSI_OK;
1245 }
1246
1247 /*==============================================*/
1248 /**
1249 * @fn rsi_error_t clk_peripheral_clk_enable3(M4CLK_Type *pCLK, uint32_t flags)
1250 * @brief This API is used to Enable the peripheral cloks for SET3 register
1251 * @param[in] pCLK : pointer to the processor clock source
1252 * @param[in] flags : flags for SET3 register
1253 * @return RSI_OK on success
1254 */
1255
clk_peripheral_clk_enable3(M4CLK_Type * pCLK,uint32_t flags)1256 rsi_error_t clk_peripheral_clk_enable3(M4CLK_Type *pCLK, uint32_t flags)
1257 {
1258 if (pCLK == NULL) {
1259 return INVALID_PARAMETERS;
1260 }
1261 pCLK->CLK_ENABLE_SET_REG3 = flags;
1262 return RSI_OK;
1263 }
1264
1265 /*==============================================*/
1266 /**
1267 * @fn rsi_error_t clk_peripheral_clk_disable3(M4CLK_Type *pCLK, uint32_t flags)
1268 * @brief This API is used to disable the peripheral cloks for CLR3 register
1269 * @param[in] pCLK : pointer to the processor clock source
1270 * @param[in] flags : flags for CLR3 register
1271 * @return RSI_OK on success
1272 */
1273
clk_peripheral_clk_disable3(M4CLK_Type * pCLK,uint32_t flags)1274 rsi_error_t clk_peripheral_clk_disable3(M4CLK_Type *pCLK, uint32_t flags)
1275 {
1276 if (pCLK == NULL) {
1277 return INVALID_PARAMETERS;
1278 }
1279 pCLK->CLK_ENABLE_CLEAR_REG3 = flags;
1280 return RSI_OK;
1281 }
1282
1283 /*==============================================*/
1284 /**
1285 * @fn rsi_error_t clk_dynamic_clk_gate_disable(M4CLK_Type *pCLK, uint32_t flags)
1286 * @brief This API is used to disable the dynamic clock gate for peripherals
1287 * @param[in] pCLK : pointer to the processor clock source
1288 * @param[in] flags : flags for dynamic clock gate of peripherals
1289 * @return RSI_OK on success
1290 */
1291
clk_dynamic_clk_gate_disable(M4CLK_Type * pCLK,uint32_t flags)1292 rsi_error_t clk_dynamic_clk_gate_disable(M4CLK_Type *pCLK, uint32_t flags)
1293 {
1294 if (pCLK == NULL) {
1295 return INVALID_PARAMETERS;
1296 }
1297 pCLK->DYN_CLK_GATE_DISABLE_REG = (pCLK->DYN_CLK_GATE_DISABLE_REG) & (0xFFFFFFFF & ~flags);
1298 return RSI_OK;
1299 }
1300
1301 /*==============================================*/
1302 /**
1303 * @fn rsi_error_t clk_dynamic_clk_gate_disable2(M4CLK_Type *pCLK, uint32_t flags)
1304 * @brief This API is used to disable the dynamic clock gate for peripherals
1305 * @param[in] pCLK : pointer to the processor clock source
1306 * @param[in] flags : flags for dynamic clock gate of peripherals
1307 * @return RSI_OK on success
1308 */
1309
clk_dynamic_clk_gate_disable2(M4CLK_Type * pCLK,uint32_t flags)1310 rsi_error_t clk_dynamic_clk_gate_disable2(M4CLK_Type *pCLK, uint32_t flags)
1311 {
1312 if (pCLK == NULL) {
1313 return INVALID_PARAMETERS;
1314 }
1315 pCLK->DYN_CLK_GATE_DISABLE_REG2 = (pCLK->DYN_CLK_GATE_DISABLE_REG2) & (0xFFFFFFFF & ~flags);
1316 return RSI_OK;
1317 }
1318
1319 /*==============================================*/
1320 /**
1321 * @fn rsi_error_t clk_dynamic_clk_gate_enable(M4CLK_Type *pCLK, uint32_t flags)
1322 * @brief This API is used to enable the dynamic clock gate for peripherals
1323 * @param[in] pCLK : pointer to the processor clock source
1324 * @param[in] flags : flags for dynamic clock gate of peripherals
1325 * @return RSI_OK on success
1326 */
1327
clk_dynamic_clk_gate_enable(M4CLK_Type * pCLK,uint32_t flags)1328 rsi_error_t clk_dynamic_clk_gate_enable(M4CLK_Type *pCLK, uint32_t flags)
1329 {
1330 if (pCLK == NULL) {
1331 return INVALID_PARAMETERS;
1332 }
1333 pCLK->DYN_CLK_GATE_DISABLE_REG = (pCLK->DYN_CLK_GATE_DISABLE_REG | flags) & 0xFFFFFFFF;
1334 return RSI_OK;
1335 }
1336
1337 /*==============================================*/
1338 /**
1339 * @fn rsi_error_t clk_dynamic_clk_gate_enable2(M4CLK_Type *pCLK, uint32_t flags)
1340 * @brief This API is used to enable the dynamic clock gate for peripherals
1341 * @param[in] pCLK : pointer to the processor clock source
1342 * @param[in] flags : flags for dynamic clock gate of peripherals
1343 * @return RSI_OK on success
1344 */
1345
clk_dynamic_clk_gate_enable2(M4CLK_Type * pCLK,uint32_t flags)1346 rsi_error_t clk_dynamic_clk_gate_enable2(M4CLK_Type *pCLK, uint32_t flags)
1347 {
1348 if (pCLK == NULL) {
1349 return INVALID_PARAMETERS;
1350 }
1351 pCLK->DYN_CLK_GATE_DISABLE_REG2 = (pCLK->DYN_CLK_GATE_DISABLE_REG2 | flags) & 0xFFFFFFFF;
1352 return RSI_OK;
1353 }
1354
1355 /*==============================================*/
1356 /**
1357 * @fn rsi_error_t clk_qspi_clk_config(M4CLK_Type *pCLK,
1358 * QSPI_CLK_SRC_SEL_T clkSource,
1359 * boolean_t swalloEn,
1360 * boolean_t OddDivEn,
1361 * uint32_t divFactor)
1362 * @brief This API is used to configure the Qspi clocks
1363 * @param[in] pCLK : pointer to the processor clock source
1364 * @param[in] clkSource : clock source for configure the Qspi clocks
1365 * @param[in] swalloEn : enable for Qspi clocks
1366 * @param[in] oddDivEn : enable for Qspi clocks
1367 * @param[in] divFactor : division factor for Qspi clocks
1368 * @return clock spi on success
1369 */
1370
clk_qspi_clk_config(M4CLK_Type * pCLK,QSPI_CLK_SRC_SEL_T clkSource,boolean_t swalloEn,boolean_t OddDivEn,uint32_t divFactor)1371 rsi_error_t clk_qspi_clk_config(M4CLK_Type *pCLK,
1372 QSPI_CLK_SRC_SEL_T clkSource,
1373 boolean_t swalloEn,
1374 boolean_t OddDivEn,
1375 uint32_t divFactor)
1376 {
1377 rsi_error_t errorCode = RSI_OK;
1378
1379 /*Parameter validation */
1380 if ((pCLK == NULL) || (divFactor > QSPI_MAX_CLK_DIVISION_FACTOR)) {
1381 return INVALID_PARAMETERS;
1382 }
1383
1384 /*disabling the clocks*/
1385 clk_peripheral_clk_disable(pCLK, QSPI_CLK);
1386
1387 /*Select clock MUX*/
1388 switch (clkSource) {
1389 case QSPI_ULPREFCLK:
1390 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SEL = clkSource;
1391 break;
1392
1393 case QSPI_INTFPLLCLK:
1394 /*Check clock is present is or not before switching*/
1395 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1396 errorCode = ERROR_CLOCK_NOT_ENABLED;
1397 break;
1398 } /*Update the clock MUX*/
1399 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SEL = 0x01;
1400 break;
1401
1402 case QSPI_MODELPLLCLK2:
1403 /*Check clock is present is or not before switching*/
1404 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1405 errorCode = ERROR_CLOCK_NOT_ENABLED;
1406 break;
1407 }
1408 /*Update the clock MUX*/
1409 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SEL = 0x02;
1410 break;
1411
1412 case QSPI_SOCPLLCLK:
1413 /*Check clock is present is or not before switching*/
1414 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1415 errorCode = ERROR_CLOCK_NOT_ENABLED;
1416 break;
1417 }
1418 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SEL = clkSource;
1419 break;
1420
1421 case M4_SOCCLKNOSWLSYNCCLKTREEGATED:
1422 /*incase of qspi in sync with soc*/
1423 pCLK->CLK_ENABLE_SET_REG3 = QSPI_M4_SOC_SYNC;
1424 break;
1425
1426 default:
1427 errorCode = INVALID_PARAMETERS;
1428 break;
1429 }
1430
1431 if (errorCode == RSI_OK) {
1432 /*wait for QSPI clock switched */
1433 while ((pCLK->PLL_STAT_REG_b.QSPI_CLK_SWITCHED) != true)
1434 ;
1435
1436 /*update the division factor */
1437 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
1438 /*Specifies whether QSPI clock is in sync with Soc clock.
1439 Before enabling this make sure that qspi_clk_onehot_enable is 1\92b0 to enable glitch free switching*/
1440 /*Enable the QSPI clock*/
1441 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SWALLOW_SEL = swalloEn ? ENABLE : DISABLE;
1442 pCLK->CLK_CONFIG_REG2_b.QSPI_ODD_DIV_SEL = OddDivEn ? ENABLE : DISABLE;
1443 }
1444 clk_peripheral_clk_enable(pCLK, QSPI_CLK, ENABLE_STATIC_CLK);
1445
1446 return errorCode;
1447 }
1448 #if defined(SLI_SI917B0) || defined(SLI_SI915)
1449 /*==============================================*/
1450 /**
1451 * @fn rsi_error_t clk_qspi_2_clk_config(M4CLK_Type *pCLK,
1452 * QSPI_CLK_SRC_SEL_T clkSource,
1453 * boolean_t swalloEn,
1454 * boolean_t OddDivEn,
1455 * uint32_t divFactor)
1456 * @brief This API is used to configure the Qspi clocks
1457 * @param[in] pCLK : pointer to the processor clock source
1458 * @param[in] clkSource : clock source for configure the Qspi clocks
1459 * @param[in] swalloEn : enable for Qspi clocks
1460 * @param[in] oddDivEn : enable for Qspi clocks
1461 * @param[in] divFactor : division factor for Qspi clocks
1462 * @return clock spi on success
1463 */
1464
clk_qspi_2_clk_config(M4CLK_Type * pCLK,QSPI_CLK_SRC_SEL_T clkSource,boolean_t swalloEn,boolean_t OddDivEn,uint32_t divFactor)1465 rsi_error_t clk_qspi_2_clk_config(M4CLK_Type *pCLK,
1466 QSPI_CLK_SRC_SEL_T clkSource,
1467 boolean_t swalloEn,
1468 boolean_t OddDivEn,
1469 uint32_t divFactor)
1470 {
1471
1472 rsi_error_t errorCode = RSI_OK;
1473 /*Parameter validation */
1474 if ((pCLK == NULL) || (divFactor > QSPI_MAX_CLK_DIVISION_FACTOR)) {
1475 return INVALID_PARAMETERS;
1476 }
1477
1478 /*disabling the clocks*/
1479 clk_peripheral_clk_disable(pCLK, QSPI_2_CLK);
1480 /*Select clock MUX*/
1481 switch (clkSource) {
1482 case QSPI_ULPREFCLK:
1483 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SEL = 0x00;
1484 break;
1485
1486 case QSPI_MODELPLLCLK2:
1487 /*Check clock is present is or not before switching*/
1488 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1489 errorCode = ERROR_CLOCK_NOT_ENABLED;
1490 break;
1491 }
1492 /*Update the clock MUX*/
1493 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SEL = 0x02;
1494 break;
1495
1496 case QSPI_INTFPLLCLK:
1497 /*Check clock is present is or not before switching*/
1498 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1499 errorCode = ERROR_CLOCK_NOT_ENABLED;
1500 break;
1501 } /*Update the clock MUX*/
1502 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SEL = 0x01;
1503 break;
1504
1505 case QSPI_SOCPLLCLK:
1506 /*Check clock is present is or not before switching*/
1507 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1508 errorCode = ERROR_CLOCK_NOT_ENABLED;
1509 break;
1510 }
1511 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SEL = 0x03;
1512 break;
1513
1514 case M4_SOCCLKNOSWLSYNCCLKTREEGATED:
1515 /*incase of qspi in sync with soc*/
1516 pCLK->CLK_ENABLE_SET_REG1 = QSPI_2_M4_SOC_SYNC;
1517 break;
1518
1519 default:
1520 errorCode = INVALID_PARAMETERS;
1521 break;
1522 }
1523 if (errorCode == RSI_OK) {
1524 /*wait for QSPI clock switched */
1525 while ((pCLK->PLL_STAT_REG_b.QSPI_2_CLK_SWITCHED) != 1)
1526 ;
1527
1528 /*update the division factor */
1529 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
1530 /*Specifies whether QSPI clock is in sync with Soc clock.
1531 Before enabling this make sure that qspi_clk_onehot_enable is 1\92b0 to enable glitch free switching*/
1532 /*Enable the QSPI clock*/
1533 if (swalloEn) {
1534 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SWALLOW_SEL = 1;
1535 } else {
1536 pCLK->CLK_CONFIG_REG6_b.QSPI_2_CLK_SWALLOW_SEL = 0;
1537 }
1538 if (OddDivEn) {
1539 pCLK->CLK_CONFIG_REG6_b.QSPI_2_ODD_DIV_SEL = 1;
1540 } else {
1541 pCLK->CLK_CONFIG_REG6_b.QSPI_2_ODD_DIV_SEL = 0;
1542 }
1543 }
1544 clk_peripheral_clk_enable(pCLK, QSPI_2_CLK, ENABLE_STATIC_CLK);
1545 return errorCode;
1546 }
1547 #endif
1548 /*==============================================*/
1549 /**
1550 * @fn rsi_error_t clk_ssi_mst_clk_config(M4CLK_Type *pCLK,
1551 * CLK_ENABLE_T clkType,
1552 * SSI_MST_CLK_SRC_SEL_T clkSource,
1553 * uint32_t divFactor)
1554 * @brief This API is used to configure the SSI clocks
1555 * @param[in] pCLK : pointer to the processor clock source
1556 * @param[in] clkType : clock type for SSI clocks
1557 * @param[in] clkSource : cource clock for SSI clocks
1558 * @param[in] divFactor : division factor for SSI clocks
1559 * @return RSI_OK on success
1560 */
1561
clk_ssi_mst_clk_config(M4CLK_Type * pCLK,CLK_ENABLE_T clkType,SSI_MST_CLK_SRC_SEL_T clkSource,uint32_t divFactor)1562 rsi_error_t clk_ssi_mst_clk_config(M4CLK_Type *pCLK,
1563 CLK_ENABLE_T clkType,
1564 SSI_MST_CLK_SRC_SEL_T clkSource,
1565 uint32_t divFactor)
1566 {
1567 /*Parameter validation */
1568 if ((pCLK == NULL) || (divFactor > SSI_MAX_CLK_DIVISION_FACTOR)) {
1569 return INVALID_PARAMETERS;
1570 }
1571
1572 /*Disable the clock */
1573 clk_peripheral_clk_disable(pCLK, SSIMST_CLK);
1574 /*Master mode */
1575 switch (clkSource) {
1576 case SSI_ULPREFCLK:
1577 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x00;
1578 break;
1579
1580 case SSI_SOCPLLCLK:
1581 /*Check clock is present is or not before switching*/
1582 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1583 return ERROR_CLOCK_NOT_ENABLED;
1584 }
1585 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x01;
1586 break;
1587
1588 case SSI_MODEMPLLCLK1:
1589
1590 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1591 return ERROR_CLOCK_NOT_ENABLED;
1592 }
1593 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x02;
1594 break;
1595
1596 case SSI_INTFPLLCLK:
1597 /*Check clock is present is or not before switching*/
1598 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1599 return ERROR_CLOCK_NOT_ENABLED;
1600 }
1601 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x03;
1602 break;
1603
1604 case SSI_MODELPLLCLK2:
1605 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1606 return ERROR_CLOCK_NOT_ENABLED;
1607 }
1608 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x04;
1609 break;
1610
1611 case M4_SOCCLKFOROTHERCLKS:
1612 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
1613 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_SEL = 0x05;
1614 break;
1615
1616 default:
1617 return INVALID_PARAMETERS;
1618 }
1619 /*wait for clock switch */
1620 while ((pCLK->PLL_STAT_REG_b.SSI_MST_SCLK_SWITCHED) != 1)
1621 ;
1622 /*division factor */
1623 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
1624 /*Enable the SSI clock */
1625 clk_peripheral_clk_enable(pCLK, SSIMST_CLK, clkType);
1626 return RSI_OK;
1627 }
1628 #if !defined(SLI_SI917) && !defined(SLI_SI915)
1629
1630 /*==============================================*/
1631 /**
1632 * @fn rsi_error_t clk_sd_mem_clk_config(M4CLK_Type *pCLK, boolean_t swalloEn, SDMEM_CLK_SRC_SEL_T clkSource, uint32_t divFactor)
1633 * @brief This API is used to configure the SdMem clocks
1634 * @param[in] pCLK : pointer to the processor clock source
1635 * @param[in] swalloEn : enable for SdMem clocks
1636 * @param[in] clkSource : clock source for SdMem clocks
1637 * @param[in] divFactor : division factor for SdMem clocks
1638 * @return RSI_OK on success
1639 */
1640
clk_sd_mem_clk_config(M4CLK_Type * pCLK,boolean_t swalloEn,SDMEM_CLK_SRC_SEL_T clkSource,uint32_t divFactor)1641 rsi_error_t clk_sd_mem_clk_config(M4CLK_Type *pCLK,
1642 boolean_t swalloEn,
1643 SDMEM_CLK_SRC_SEL_T clkSource,
1644 uint32_t divFactor)
1645 {
1646 /*Parameter validation */
1647 if ((pCLK == NULL) || (divFactor > SDMEM_MAX_CLK_DIVISION_FACTOR)) {
1648 return INVALID_PARAMETERS;
1649 }
1650
1651 /*Disable the SDMEM clock*/
1652 clk_peripheral_clk_disable(pCLK, SD_MEM_CLK);
1653 switch (clkSource) {
1654 case SDMEM_SOCPLLCLK:
1655 /*Check clock is present or not before switching*/
1656 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1657 return ERROR_CLOCK_NOT_ENABLED;
1658 }
1659 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SEL = 0x00;
1660 break;
1661
1662 case SDMEM_MODEMPLLCLK1:
1663 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1664 return ERROR_CLOCK_NOT_ENABLED;
1665 }
1666 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SEL = 0x01;
1667 break;
1668
1669 case SDMEM_INTFPLLCLK:
1670 /*Check clock is present is or not before switching*/
1671 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1672 return ERROR_CLOCK_NOT_ENABLED;
1673 }
1674 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SEL = 0x02;
1675 break;
1676
1677 case M4_SOCCLKFOROTHERCLKSSDMEM:
1678 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
1679 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SEL = 0x03;
1680 break;
1681
1682 default:
1683 return INVALID_PARAMETERS;
1684 }
1685 /*wait for SD mem clock switch */
1686 while ((pCLK->PLL_STAT_REG_b.SD_MEM_INTF_CLK_SWITCHED) != 1)
1687 ;
1688 /*Update the division factor */
1689 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_DIV_FAC = divFactor;
1690 if (swalloEn) {
1691 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SWALLOW_SEL = 1;
1692 } else {
1693 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SWALLOW_SEL = 0;
1694 }
1695 /*Enable SD memory clock */
1696 clk_peripheral_clk_enable(pCLK, SD_MEM_CLK, ENABLE_STATIC_CLK);
1697 return RSI_OK;
1698 }
1699
1700 /*==============================================*/
1701 /**
1702 * @fn rsi_error_t clk_cci_clk_config(M4CLK_Type *pCLK, CCI_CLK_SRC_SEL_T clkSource, uint32_t divFactor, CLK_ENABLE_T clkType)
1703 * @brief This API is used to configure the CCI clocks
1704 * @param[in] pCLK : pointer to the processor clock source
1705 * @param[in] clkSource : source clock for configure the CCI clocks
1706 * @param[in] clkType : clock type for configure the CCI clocks
1707 * @param[in] divFactor : division factor for configure the CCI clocks
1708 * @return RSI_OK on success
1709 */
1710
clk_cci_clk_config(M4CLK_Type * pCLK,CCI_CLK_SRC_SEL_T clkSource,uint32_t divFactor,CLK_ENABLE_T clkType)1711 rsi_error_t clk_cci_clk_config(M4CLK_Type *pCLK, CCI_CLK_SRC_SEL_T clkSource, uint32_t divFactor, CLK_ENABLE_T clkType)
1712 {
1713 /*Parameter validation */
1714 if ((pCLK == NULL) || (divFactor > CCI_MAX_CLK_DIVISION_FACTOR)) {
1715 return INVALID_PARAMETERS;
1716 }
1717 /*Enable CCI clock */
1718 clk_peripheral_clk_disable(pCLK, CCI_CLK);
1719 /*cci_sync_mode_enable_for_ams = 0 */
1720 MISC_CFG_MISC_CTRL &= ~CCI_SYNC_MODE;
1721 switch (clkSource) {
1722 case CCI_M4_SOC_CLK_FOR_OTHER_CLKS:
1723 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
1724 pCLK->CLK_CONFIG_REG4_b.CCI_CLK_SEL = 0x00;
1725 break;
1726
1727 case CCI_INTF_PLL_CLK:
1728 /*Check clock is present is or not before switching*/
1729 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1730 return ERROR_CLOCK_NOT_ENABLED;
1731 }
1732 pCLK->CLK_CONFIG_REG4_b.CCI_CLK_SEL = 0x01;
1733 break;
1734
1735 case CCI_M4_SOC_CLK_NO_SWL_SYNC_CLK_TREE:
1736 /*cci_sync_mode_enable_for_ams = 1*/
1737 MISC_CFG_MISC_CTRL |= CCI_SYNC_MODE;
1738 break;
1739 default:
1740 return INVALID_PARAMETERS;
1741 }
1742 /*update the division factor */
1743 pCLK->CLK_CONFIG_REG2_b.CCI_CLK_DIV_FAC = divFactor;
1744 /*Enable the CCI clock */
1745 clk_peripheral_clk_enable(pCLK, CCI_CLK, clkType);
1746 return RSI_OK;
1747 }
1748
1749 /*==============================================*/
1750 /**
1751 * @fn rsi_error_t clk_can_clk_config(M4CLK_Type *pCLK, uint32_t divFactor, CLK_ENABLE_T clkType)
1752 * @brief This API is used to configure the Can clocks
1753 * @param[in] pCLK : pointer to the processor clock source
1754 * @param[in] divFactor : division factor for configure the Can clocks
1755 * @param[in] clkType : clock type for configure the Can clocks
1756 * @return RSI_OK on success
1757 */
1758
clk_can_clk_config(M4CLK_Type * pCLK,uint32_t divFactor,CLK_ENABLE_T clkType)1759 rsi_error_t clk_can_clk_config(M4CLK_Type *pCLK, uint32_t divFactor, CLK_ENABLE_T clkType)
1760 {
1761 if ((pCLK == NULL) || (divFactor > CAN_MAX_CLK_DIVISION_FACTOR)) {
1762 return INVALID_PARAMETERS;
1763 }
1764 if (pCLK == NULL) {
1765 return INVALID_PARAMETERS;
1766 }
1767 clk_peripheral_clk_disable(pCLK, CAN_CLK);
1768
1769 pCLK->CLK_CONFIG_REG3_b.CAN1_CLK_DIV_FAC = divFactor;
1770
1771 /*Disable the clock*/
1772 clk_peripheral_clk_enable(pCLK, CAN_CLK, clkType);
1773
1774 return RSI_OK;
1775 }
1776
1777 /*==============================================*/
1778 /**
1779 * @fn rsi_error_t clk_ethernet_clk_config(M4CLK_Type *pCLK,
1780 * boolean_t swalloEn,
1781 * ETHERNET_CLK_SRC_SEL_T clkSource,
1782 * uint32_t divFactor)
1783 * @brief This API is used to configure the PLL_INTF clock
1784 * @param[in] pCLK : pointer to the processor clock source
1785 * @param[in] swalloEn : enable for PLL_INTF clock
1786 * @param[in] clkSource : clock source for PLL_INTF clock
1787 * @param[in] divFactor : division factor for PLL_INTF clock
1788 * @return RSI_OK on success
1789 */
1790
clk_ethernet_clk_config(M4CLK_Type * pCLK,boolean_t swalloEn,ETHERNET_CLK_SRC_SEL_T clkSource,uint32_t divFactor)1791 rsi_error_t clk_ethernet_clk_config(M4CLK_Type *pCLK,
1792 boolean_t swalloEn,
1793 ETHERNET_CLK_SRC_SEL_T clkSource,
1794 uint32_t divFactor)
1795 {
1796 /*Parameter validation */
1797 if ((pCLK == NULL) || (divFactor > PLL_INTF_MAX_CLK_DIVISION_FACTOR)) {
1798 return INVALID_PARAMETERS;
1799 }
1800 /*Disable Ethernet clock*/
1801 pCLK->CLK_ENABLE_CLEAR_REG2 = PLL_INTF_CLK_ENABLE;
1802 if (clkSource == ETH_INTF_PLL_CLK) {
1803 /*Check clock is present is or not before switching*/
1804 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1805 return ERROR_CLOCK_NOT_ENABLED;
1806 }
1807 pCLK->CLK_CONFIG_REG1_b.PLL_INTF_CLK_SEL = 0;
1808 } else {
1809 /*Check clock is present or not before switching*/
1810 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1811 return ERROR_CLOCK_NOT_ENABLED;
1812 }
1813 pCLK->CLK_CONFIG_REG1_b.PLL_INTF_CLK_SEL = 1;
1814 }
1815 while ((pCLK->PLL_STAT_REG_b.PLL_INTF_CLK_SWITCHED) != 1)
1816 ;
1817 /*Update the division factor */
1818 pCLK->CLK_CONFIG_REG1_b.PLL_INTF_CLK_DIV_FAC = divFactor;
1819 if (swalloEn) {
1820 pCLK->CLK_CONFIG_REG1_b.PLL_INTF_CLK_SWALLOW_SEL = 1;
1821 } else {
1822 pCLK->CLK_CONFIG_REG1_b.PLL_INTF_CLK_SWALLOW_SEL = 0;
1823 }
1824 pCLK->CLK_ENABLE_SET_REG2 = PLL_INTF_CLK_ENABLE;
1825 return RSI_OK;
1826 }
1827
1828 /*==============================================*/
1829 /**
1830 * @fn rsi_error_t clk_cci_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
1831 * @brief This API is used to divide the CCI clock
1832 * @param[in] pCLK : pointer to the processor clock source
1833 * @param[in] divFactor : division factor for CCI clock
1834 * @return RSI_OK on success
1835 */
1836
clk_cci_clk_div(M4CLK_Type * pCLK,uint32_t divFactor)1837 rsi_error_t clk_cci_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
1838 {
1839 if (pCLK == NULL) {
1840 return INVALID_PARAMETERS;
1841 }
1842 pCLK->CLK_CONFIG_REG2_b.CCI_CLK_DIV_FAC = divFactor;
1843 return RSI_OK;
1844 }
1845
1846 /*==============================================*/
1847 /**
1848 * @fn rsi_error_t clk_sd_mem_clk_div(M4CLK_Type *pCLK, boolean_t u8SwallowEn, uint32_t divFactor)
1849 * @brief This API is used to divide the SDMEM clock
1850 * @param[in] pCLK : pointer to the processor clock source
1851 * @param[in] u8SwallowEn : enable for SDMEM clock
1852 * @param[in] divFactor : division factor for SDMEM clock
1853 * @return RSI_OK on success
1854 */
1855
clk_sd_mem_clk_div(M4CLK_Type * pCLK,boolean_t u8SwallowEn,uint32_t divFactor)1856 rsi_error_t clk_sd_mem_clk_div(M4CLK_Type *pCLK, boolean_t u8SwallowEn, uint32_t divFactor)
1857 {
1858 if (pCLK == NULL) {
1859 return INVALID_PARAMETERS;
1860 }
1861
1862 if (u8SwallowEn) {
1863 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SWALLOW_SEL = 1;
1864 } else {
1865 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_SWALLOW_SEL = 0;
1866 }
1867
1868 /*SDMEM division selection */
1869 pCLK->SD_MEM_CLOCK_REG_b.SD_MEM_INTF_CLK_DIV_FAC = divFactor;
1870 return RSI_OK;
1871 }
1872
1873 /*==============================================*/
1874 /**
1875 * @fn rsi_error_t clk_usb_clk_config(M4CLK_Type *pCLK, USB_CLK_SRC_SEL_T clkSource, uint16_t divFactor)
1876 * @brief This API is used to configure the USB clock
1877 * @param[in] pCLK : pointer to the processor clock source
1878 * @param[in] clkSource : source clock
1879 * @param[in] divFactor : division factor
1880 * @return RSI_OK on success
1881 */
1882
clk_usb_clk_config(M4CLK_Type * pCLK,USB_CLK_SRC_SEL_T clkSource,uint16_t divFactor)1883 rsi_error_t clk_usb_clk_config(M4CLK_Type *pCLK, USB_CLK_SRC_SEL_T clkSource, uint16_t divFactor)
1884 {
1885 /*Parameter validation */
1886 if ((pCLK == NULL) || (divFactor > USB_MAX_CLK_DIVISION_FACTOR)) {
1887 return INVALID_PARAMETERS;
1888 }
1889 /*clock Disable */
1890 pCLK->CLK_ENABLE_CLEAR_REG3 = USB_PHY_CLK_IN_ENABLE;
1891 switch (clkSource) {
1892 case USB_MEMS_REF_CLK:
1893 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1894 return ERROR_CLOCK_NOT_ENABLED;
1895 }
1896 /*mems_ref_clk from Modem PLL*/
1897 TASS_PLL_CTRL_SET_REG(AFEPLLCTRLREG1) |= MEMS_REF_CLK_ENABLE;
1898 pCLK->CLK_CONFIG_REG5_b.USB_CLK_SEL = 0x00;
1899 break;
1900
1901 case USB_REFERENCE_CLK:
1902 /*Reference clock*/
1903 pCLK->CLK_CONFIG_REG5_b.USB_CLK_SEL = 0x01;
1904 break;
1905 case USB_PLL_CLK:
1906 /* usb_pll_clk from Modem PLL */
1907 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
1908 return ERROR_CLOCK_NOT_ENABLED;
1909 }
1910 pCLK->CLK_CONFIG_REG5_b.USB_CLK_SEL = 0x02;
1911 break;
1912 default:
1913 return INVALID_PARAMETERS;
1914 }
1915 /*Program the division factor */
1916 pCLK->CLK_CONFIG_REG6_b.USB_PHY_CLK_DIV_FAC = divFactor;
1917 /*clock Enable */
1918 pCLK->CLK_ENABLE_SET_REG3 = USB_PHY_CLK_IN_ENABLE;
1919 return RSI_OK;
1920 }
1921 #endif
1922
1923 /*==============================================*/
1924 /**
1925 * @fn rsi_error_t clk_ct_clk_config(M4CLK_Type *pCLK, CT_CLK_SRC_SEL_T clkSource, uint32_t divFactor, CLK_ENABLE_T clkType)
1926 * @brief This API is used to configure the CT clocks
1927 * @param[in] pCLK : pointer to the processor clock source
1928 * @param[in] clkSource : source clock for CT clocks
1929 * @param[in] clkType : source clock for CT clocks
1930 * @param[in] divFactor : division factor for CT clocks
1931 * @return RSI_OK on success
1932 */
1933
clk_ct_clk_config(M4CLK_Type * pCLK,CT_CLK_SRC_SEL_T clkSource,uint32_t divFactor,CLK_ENABLE_T clkType)1934 rsi_error_t clk_ct_clk_config(M4CLK_Type *pCLK, CT_CLK_SRC_SEL_T clkSource, uint32_t divFactor, CLK_ENABLE_T clkType)
1935 {
1936 /*Parameter validation */
1937 if ((pCLK == NULL) || (divFactor > CT_MAX_CLK_DIVISION_FACTOR)) {
1938 return INVALID_PARAMETERS;
1939 }
1940 /*Disable SCT clock*/
1941 clk_peripheral_clk_disable(pCLK, CT_CLK);
1942 switch (clkSource) {
1943 case CT_ULPREFCLK:
1944 pCLK->CLK_CONFIG_REG5_b.CT_CLK_SEL = 0x00;
1945 break;
1946
1947 case CT_INTFPLLCLK:
1948 /*Check clock is present is or not before switching*/
1949 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
1950 return ERROR_CLOCK_NOT_ENABLED;
1951 }
1952 pCLK->CLK_CONFIG_REG5_b.CT_CLK_SEL = 0x01;
1953 break;
1954
1955 case CT_SOCPLLCLK:
1956 /*Check clock is present is or not before switching*/
1957 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
1958 return ERROR_CLOCK_NOT_ENABLED;
1959 }
1960 pCLK->CLK_CONFIG_REG5_b.CT_CLK_SEL = 0x02;
1961 break;
1962
1963 case M4_SOCCLKFOROTHERCLKSCT:
1964 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
1965 pCLK->CLK_CONFIG_REG5_b.CT_CLK_SEL = 0x03;
1966 break;
1967 default:
1968 return INVALID_PARAMETERS;
1969 }
1970 /*wait for SCT switched */
1971 while ((pCLK->PLL_STAT_REG_b.CT_CLK_SWITCHED) != 1)
1972 ;
1973 /*Program the division factor */
1974 pCLK->CLK_CONFIG_REG5_b.CT_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
1975 clk_peripheral_clk_enable(pCLK, CT_CLK, clkType);
1976 return RSI_OK;
1977 }
1978
1979 /*==============================================*/
1980 /**
1981 * @fn rsi_error_t clk_i2s_clk_config(M4CLK_Type *pCLK, I2S_CLK_SRC_SEL_T clkSource, uint32_t divFactor)
1982 * @brief This API is used to configure the I2S clocks
1983 * @param[in] pCLK : pointer to the processor clock source
1984 * @param[in] clkSource : source clock
1985 * @param[in] divFactor : division factor
1986 * @return RSI_OK on success
1987 */
1988
clk_i2s_clk_config(M4CLK_Type * pCLK,I2S_CLK_SRC_SEL_T clkSource,uint32_t divFactor)1989 rsi_error_t clk_i2s_clk_config(M4CLK_Type *pCLK, I2S_CLK_SRC_SEL_T clkSource, uint32_t divFactor)
1990 {
1991 /*Parameter validation */
1992 if ((pCLK == NULL) || (divFactor > I2S_MAX_CLK_DIVISION_FACTOR)) {
1993 return INVALID_PARAMETERS;
1994 }
1995 /*Disable the I2S clock */
1996 clk_peripheral_clk_disable(pCLK, I2SM_CLK);
1997 MISC_CFG_MISC_CTRL1 |= I2S_MASTER_SLAVE_MODE;
1998 if (clkSource == I2S_PLLCLK) {
1999 /*Check clock is present is or not before switching*/
2000 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, I2S_PLL_CLK_PRESENT)) {
2001 return ERROR_CLOCK_NOT_ENABLED;
2002 }
2003 pCLK->CLK_CONFIG_REG5_b.I2S_CLK_SEL = 0;
2004 } else {
2005 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2006 pCLK->CLK_CONFIG_REG5_b.I2S_CLK_SEL = 1;
2007 }
2008
2009 /*Wait for I2S clock switch*/
2010 while ((pCLK->PLL_STAT_REG_b.I2S_CLK_SWITCHED) != 1)
2011 ;
2012 /*update the division factor */
2013 pCLK->CLK_CONFIG_REG5_b.I2S_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2014 /*enable the clock*/
2015 clk_peripheral_clk_enable(pCLK, I2SM_CLK, ENABLE_STATIC_CLK);
2016 return RSI_OK;
2017 }
2018
2019 /*==============================================*/
2020 /**
2021 * @fn rsi_error_t clk_mcu_clk_cut_config(M4CLK_Type *pCLK, MCU_CLKOUT_SRC_SEL_T clkSource, uint32_t divFactor)
2022 * @brief This API is used to configure the McuClkOut clocks
2023 * @param[in] pCLK : pointer to the processor clock source
2024 * @param[in] clkSource : source clock
2025 * @param[in] divFactor : division factor
2026 * @return RSI_OK on success
2027 */
2028
clk_mcu_clk_cut_config(M4CLK_Type * pCLK,MCU_CLKOUT_SRC_SEL_T clkSource,uint32_t divFactor)2029 rsi_error_t clk_mcu_clk_cut_config(M4CLK_Type *pCLK, MCU_CLKOUT_SRC_SEL_T clkSource, uint32_t divFactor)
2030 {
2031 /*Parameter validation */
2032 if ((pCLK == NULL) || (divFactor >= MCU_CLKOUT_MAX_CLK_DIVISION_FACTOR)) {
2033 return INVALID_PARAMETERS;
2034 }
2035 clk_peripheral_clk_disable(pCLK, MCUCLKOUT_CLK);
2036 /*clock out mux select */
2037 /*apply division factor */
2038 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2039 switch (clkSource) {
2040 case MCUCLKOUT_ULP_MHZ_RC_CLK:
2041 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x01;
2042 break;
2043
2044 case MCUCLKOUT_RF_REF_CLK:
2045 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x02;
2046 break;
2047
2048 case MCUCLKOUT_MEMS_REF_CLK:
2049 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2050 return ERROR_CLOCK_NOT_ENABLED;
2051 }
2052 TASS_PLL_CTRL_SET_REG(AFEPLLCTRLREG1) |= MEMS_REF_CLK_ENABLE;
2053 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x03;
2054 break;
2055
2056 case MCUCLKOUT_ULP_20MHZ_RINGOSC_CLK:
2057 ulpss_enable_ref_clks(MCU_ULP_20MHZ_RING_OSC_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2058 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x04;
2059 break;
2060
2061 case MCUCLKOUT_ULP_DOUBLER_CLK:
2062 ulpss_enable_ref_clks(MCU_ULP_DOUBLER_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2063 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x05;
2064 break;
2065
2066 case MCUCLKOUT_ULP_32KHZ_RC_CLK:
2067 ulpss_enable_ref_clks(MCU_ULP_32KHZ_RC_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2068 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x07;
2069 break;
2070
2071 case MCUCLKOUT_ULP_32KHZ_XTAL_CLK:
2072 ulpss_enable_ref_clks(MCU_ULP_32KHZ_XTAL_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2073 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x08;
2074 break;
2075
2076 case MCUCLKOUT_ULP_32KHZ_RO_CLK:
2077 ulpss_enable_ref_clks(MCU_ULP_32KHZ_RO_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2078 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x09;
2079 break;
2080
2081 case MCUCLKOUT_INTF_PLL_CLK:
2082 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
2083 return ERROR_CLOCK_NOT_ENABLED;
2084 }
2085 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0A;
2086 break;
2087
2088 case MCUCLKOUT_MODEM_PLL_CLK1:
2089 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2090 return ERROR_CLOCK_NOT_ENABLED;
2091 }
2092 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0B;
2093 break;
2094
2095 case MCUCLKOUT_MODEM_PLL_CLK2:
2096 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2097 return ERROR_CLOCK_NOT_ENABLED;
2098 }
2099 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0C;
2100 break;
2101
2102 case MCUCLKOUT_SOC_PLL_CLK:
2103 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
2104 return ERROR_CLOCK_NOT_ENABLED;
2105 }
2106 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0D;
2107 break;
2108
2109 case MCUCLKOUT_I2S_PLL_CLK:
2110 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, I2S_PLL_CLK_PRESENT)) {
2111 return ERROR_CLOCK_NOT_ENABLED;
2112 }
2113 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0E;
2114 break;
2115
2116 case MCUCLKOUT_USB_PLL_CLK:
2117 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2118 return ERROR_CLOCK_NOT_ENABLED;
2119 }
2120 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_SEL = 0x0F;
2121 break;
2122
2123 default:
2124 return INVALID_PARAMETERS;
2125 }
2126 clk_peripheral_clk_enable(pCLK, MCUCLKOUT_CLK, ENABLE_STATIC_CLK);
2127 return RSI_OK;
2128 }
2129
2130 /*==============================================*/
2131 /**
2132 * @fn rsi_error_t clk_m4_soc_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2133 * @brief This API is used to divide the M4soc clock
2134 * @param[in] pCLK : pointer to the processor clock source
2135 * @param[in] divFactor : division factor
2136 * @return RSI_OK on success
2137 */
2138
clk_m4_soc_clk_div(M4CLK_Type * pCLK,uint32_t divFactor)2139 rsi_error_t clk_m4_soc_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2140 {
2141 if (pCLK == NULL) {
2142 return INVALID_PARAMETERS;
2143 }
2144 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2145 return RSI_OK;
2146 }
2147
2148 /*==============================================*/
2149 /**
2150 * @fn rsi_error_t clk_qspi_clk_div(M4CLK_Type *pCLK, boolean_t u8SwallowEn, boolean_t u8OddDivEn, uint32_t divFactor)
2151 * @brief This API is used to divide the QSPI clock
2152 * @param[in] pCLK : pointer to the processor clock source
2153 * @param[in] u8SwallowEn : enable
2154 * @param[in] u8OddDivEn : odd division enable
2155 * @param[in] divFactor : division factor
2156 * @return RSI_OK on success
2157 */
2158
clk_qspi_clk_div(M4CLK_Type * pCLK,boolean_t u8SwallowEn,boolean_t u8OddDivEn,uint32_t divFactor)2159 rsi_error_t clk_qspi_clk_div(M4CLK_Type *pCLK, boolean_t u8SwallowEn, boolean_t u8OddDivEn, uint32_t divFactor)
2160 {
2161 if (pCLK == NULL) {
2162 return INVALID_PARAMETERS;
2163 }
2164 if (u8SwallowEn) {
2165 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SWALLOW_SEL = 1;
2166 } else {
2167 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_SWALLOW_SEL = 0;
2168 }
2169 if (u8OddDivEn) {
2170 pCLK->CLK_CONFIG_REG2_b.QSPI_ODD_DIV_SEL = 1;
2171 } else {
2172 pCLK->CLK_CONFIG_REG2_b.QSPI_ODD_DIV_SEL = 0;
2173 }
2174 pCLK->CLK_CONFIG_REG1_b.QSPI_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2175 return RSI_OK;
2176 }
2177
2178 /*==============================================*/
2179 /**
2180 * @fn rsi_error_t clk_ct_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2181 * @brief This API is used to divide the CT clock
2182 * @param[in] pCLK : pointer to the processor clock source
2183 * @param[in] divFactor : division factor
2184 * @return RSI_OK on success
2185 */
2186
clk_ct_clk_div(M4CLK_Type * pCLK,uint32_t divFactor)2187 rsi_error_t clk_ct_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2188 {
2189 if (pCLK == NULL) {
2190 return INVALID_PARAMETERS;
2191 }
2192 pCLK->CLK_CONFIG_REG5_b.CT_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2193 return RSI_OK;
2194 }
2195
2196 /*==============================================*/
2197 /**
2198 * @fn rsi_error_t clk_ssi_mst_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2199 * @brief This API is used to divide the SSI clock
2200 * @param[in] pCLK : pointer to the processor clock source
2201 * @param[in] divFactor : division factor
2202 * @return RSI_OK on success
2203 */
2204
clk_ssi_mst_clk_div(M4CLK_Type * pCLK,uint32_t divFactor)2205 rsi_error_t clk_ssi_mst_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2206 {
2207 if (pCLK == NULL) {
2208 return INVALID_PARAMETERS;
2209 }
2210 pCLK->CLK_CONFIG_REG1_b.SSI_MST_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
2211 return RSI_OK;
2212 }
2213
2214 /*==============================================*/
2215 /**
2216 * @fn rsi_error_t clk_i2s_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2217 * @brief This API is used to divide the I2S clock
2218 * @param[in] pCLK : pointer to the processor clock source
2219 * @param[in] divFactor : division factor
2220 * @return RSI_OK on success
2221 */
2222
clk_i2s_clk_div(M4CLK_Type * pCLK,uint32_t divFactor)2223 rsi_error_t clk_i2s_clk_div(M4CLK_Type *pCLK, uint32_t divFactor)
2224 {
2225 if (pCLK == NULL) {
2226 return INVALID_PARAMETERS;
2227 }
2228 pCLK->CLK_CONFIG_REG5_b.I2S_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2229 return RSI_OK;
2230 }
2231
2232 /*==============================================*/
2233 /**
2234 * @fn rsi_error_t clk_usart_clk_div(M4CLK_Type *pCLK, EN_USART_T enUsart, boolean_t u8FracDivEn, uint32_t divFactor)
2235 * @brief This API is used to divide the USART/UART clock
2236 * @param[in] pCLK : pointer to the processor clock source
2237 * @param[in] enUsart : enable UART
2238 * @param[in] u8FracDivEn : fractional divison enable
2239 * @param[in] divFactor : division factor
2240 * @return RSI_OK on success
2241 */
2242
clk_usart_clk_div(M4CLK_Type * pCLK,EN_USART_T enUsart,boolean_t u8FracDivEn,uint32_t divFactor)2243 rsi_error_t clk_usart_clk_div(M4CLK_Type *pCLK, EN_USART_T enUsart, boolean_t u8FracDivEn, uint32_t divFactor)
2244 {
2245 if (pCLK == NULL) {
2246 return INVALID_PARAMETERS;
2247 }
2248 if (enUsart == USART1) {
2249 if (u8FracDivEn) {
2250 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
2251 } else {
2252 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
2253 }
2254 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
2255 } else {
2256 if (u8FracDivEn) {
2257 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
2258 } else {
2259 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
2260 }
2261 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
2262 }
2263
2264 return RSI_OK;
2265 }
2266
2267 /*==============================================*/
2268 /**
2269 * @fn rsi_error_t clk_xtal_clk_config(uint8_t xtalPin)
2270 * @brief This API is used to configure the Xtal clock
2271 * @param[in] xtalPin : oscillator pin
2272 * @return RSI_OK on success
2273 */
2274
clk_xtal_clk_config(uint8_t xtalPin)2275 rsi_error_t clk_xtal_clk_config(uint8_t xtalPin)
2276 {
2277 if (xtalPin > 4) {
2278 return INVALID_PARAMETERS;
2279 }
2280 switch (xtalPin) {
2281 case 1:
2282 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_MODE = 3;
2283 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_REN = 1;
2284 break;
2285
2286 case 2:
2287 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_MODE = 4;
2288 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_REN = 1;
2289 break;
2290
2291 case 3:
2292 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_MODE = 5;
2293 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_REN = 1;
2294 break;
2295
2296 case 4:
2297 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_MODE = 6;
2298 MCU_RET->NPSS_GPIO_CNTRL[xtalPin].NPSS_GPIO_CTRLS_b.NPSS_GPIO_REN = 1;
2299 break;
2300
2301 default:
2302 // Handle unexpected xtalPin values
2303 // You can log an error, set a default configuration, or take other appropriate actions
2304 break;
2305 }
2306 // enables the XTAL clock
2307 MCU_AON->MCUAON_GEN_CTRLS_b.XTAL_CLK_FROM_GPIO = 1;
2308 return RSI_OK;
2309 }
2310
2311 /*==============================================*/
2312 /**
2313 * @fn rsi_error_t clk_slp_clk_config(M4CLK_Type *pCLK, SLEEP_CLK_SRC_SEL_T clkSrc)
2314 * @brief This API is used to calibrate the sleep clock
2315 * @param[in] pCLK : pointer to the processor clock source
2316 * @param[in] clkEnable : enable the clock
2317 * @param[in] clkSrc : source clock
2318 * @return RSI_OK on success
2319 */
2320
clk_slp_clk_config(M4CLK_Type * pCLK,SLEEP_CLK_SRC_SEL_T clkSrc)2321 rsi_error_t clk_slp_clk_config(M4CLK_Type *pCLK, SLEEP_CLK_SRC_SEL_T clkSrc)
2322 {
2323 /*Parameter validation */
2324 if ((pCLK == NULL) || (clkSrc > SLP_MAX_SEL)) {
2325 return INVALID_PARAMETERS;
2326 }
2327 switch (clkSrc) {
2328 case SLP_ULP_32KHZ_RC_CLK:
2329 /*Enable clock*/
2330 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RC_CLK_EN_b = 1;
2331 pCLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = clkSrc;
2332 break;
2333 case SLP_ULP_32KHZ_XTAL_CLK:
2334 /*Enable clock*/
2335 /*NOTE: In order to enable the Xtal clk source need to configure the NPSS_GPIO pins
2336 which can be done through clk_xtal_clk_config(uint8_t xtalPin) API i.e we need to call that API first*/
2337 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_XTAL_CLK_EN_b = 1;
2338 pCLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = clkSrc;
2339 break;
2340
2341 case SLP_CLK_GATED:
2342 /* default value i.e, clock is gated*/
2343 pCLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = clkSrc;
2344 break;
2345
2346 case SLP_ULP_32KHZ_RO_CLK:
2347 /*Enable clock*/
2348 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RO_CLK_EN_b = 1;
2349 pCLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = clkSrc;
2350 break;
2351
2352 default:
2353 return INVALID_PARAMETERS;
2354 }
2355 while ((pCLK->PLL_STAT_REG_b.SLEEP_CLK_SWITCHED) != 1)
2356 ;
2357 return RSI_OK;
2358 }
2359
2360 /*==============================================*/
2361 /**
2362 * @fn uint32_t clk_slp_clk_calib_config(M4CLK_Type *pCLK, uint8_t clkCycles)
2363 * @brief This API is used to calibrate the sleep clock
2364 * @param[in] pCLK : pointer to the processor clock source
2365 * @param[in] clkCycles : clock cycle
2366 * @return pCLK on success
2367 */
2368
clk_slp_clk_calib_config(M4CLK_Type * pCLK,uint8_t clkCycles)2369 uint32_t clk_slp_clk_calib_config(M4CLK_Type *pCLK, uint8_t clkCycles)
2370 {
2371 if (pCLK == NULL || clkCycles > MAX_SLP_CYCLES) {
2372 return INVALID_PARAMETERS;
2373 }
2374 pCLK->SLEEP_CALIB_REG_b.SLP_CALIB_CYCLES = (unsigned int)(clkCycles & 0x03);
2375 /* Start the sleep clock */
2376 pCLK->SLEEP_CALIB_REG_b.SLP_CALIB_START_b = 1;
2377 /* Wait for calib done */
2378 while (pCLK->SLEEP_CALIB_REG_b.SLP_CALIB_DONE_b != 1)
2379 ;
2380 /* Return the value */
2381 return pCLK->SLEEP_CALIB_REG_b.SLP_CALIB_DURATION_b;
2382 }
2383
2384 /*==============================================*/
2385 /**
2386 * @fn rsi_error_t clk_gspi_clk_config(M4CLK_Type *pCLK, GSPI_CLK_SRC_SEL_T clkSel)
2387 * @brief This API is used to configure the GSPI Clocks
2388 * @param[in] pCLK : pointer to the processor clock source
2389 * @param[in] clkSel : clock select
2390 * @return RSI_OK on success
2391 */
2392
clk_gspi_clk_config(M4CLK_Type * pCLK,GSPI_CLK_SRC_SEL_T clkSel)2393 rsi_error_t clk_gspi_clk_config(M4CLK_Type *pCLK, GSPI_CLK_SRC_SEL_T clkSel)
2394 {
2395 if (pCLK == NULL) {
2396 return INVALID_PARAMETERS;
2397 }
2398 /*Disable the clocks*/
2399 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x07;
2400 /*Without this clk enabled, div_fac and mux select for sclk cannot be programmed) */
2401 pCLK->CLK_ENABLE_SET_REG2 = GEN_SPI_MST1_HCLK_ENABLE;
2402
2403 switch (clkSel) {
2404 case GSPI_M4_SOC_CLK_FOR_OTHER_CLKS:
2405 /*M4 SOC Clock for others enable*/
2406 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2407 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x00;
2408 break;
2409
2410 case GSPI_ULP_REF_CLK:
2411 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x01;
2412 break;
2413
2414 case GSPI_SOC_PLL_CLK:
2415 /*Check clock is present is or not before switching*/
2416 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
2417 return ERROR_CLOCK_NOT_ENABLED;
2418 }
2419 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x02;
2420 break;
2421
2422 case GSPI_MODEM_PLL_CLK2:
2423 /*Check clock is present is or not before switching*/
2424 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2425 return ERROR_CLOCK_NOT_ENABLED;
2426 }
2427 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x03;
2428 break;
2429
2430 case GSPI_INTF_PLL_CLK:
2431 /*Check clock is present is or not before switching*/
2432 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
2433 return ERROR_CLOCK_NOT_ENABLED;
2434 }
2435 pCLK->CLK_CONFIG_REG1_b.GEN_SPI_MST1_SCLK_SEL = 0x04;
2436 break;
2437 }
2438 /*Wait for GSPI switched */
2439 while ((pCLK->PLL_STAT_REG_b.GEN_SPI_MST1_SCLK_SWITCHED) != 1)
2440 ;
2441 return RSI_OK;
2442 }
2443
2444 /*==============================================*/
2445 /**
2446 * @fn rsi_error_t clk_i2c_clk_config(M4CLK_Type *pCLK, boolean_t clkEnable, EN_I2C_T enI2C)
2447 * @brief This API is used to configure the I2C clock
2448 * @param[in] pCLK : pointer to the processor clock source
2449 * @param[in] clkEnable : module for I2C clock
2450 * @param[in] enI2C : enable I2C bus for I2C clock
2451 * @return RSI_OK on success
2452 */
2453
clk_i2c_clk_config(M4CLK_Type * pCLK,boolean_t clkEnable,EN_I2C_T enI2C)2454 rsi_error_t clk_i2c_clk_config(M4CLK_Type *pCLK, boolean_t clkEnable, EN_I2C_T enI2C)
2455 {
2456 if (pCLK == NULL) {
2457 return INVALID_PARAMETERS;
2458 }
2459 if (enI2C == I2C1_INSTAN) {
2460 if (clkEnable) {
2461 /*I2C 1 bus clock enable*/
2462 pCLK->CLK_ENABLE_SET_REG2 = I2C_BUS_CLK_ENABLE;
2463 /*I2C clk enable */
2464 pCLK->CLK_ENABLE_SET_REG3 = I2C_CLK_ENABLE;
2465 } else {
2466 /*I2C bus clock disable*/
2467 pCLK->CLK_ENABLE_CLEAR_REG2 = I2C_BUS_CLK_ENABLE;
2468 /*I2C clk disable */
2469 pCLK->CLK_ENABLE_CLEAR_REG3 = I2C_CLK_ENABLE;
2470 }
2471 } else {
2472 if (clkEnable) {
2473 /*I2C2 bus clock enable*/
2474 pCLK->CLK_ENABLE_SET_REG2 = I2C_2_BUS_CLK_ENABLE;
2475 /*I2C2 clk enable */
2476 pCLK->CLK_ENABLE_SET_REG3 = I2C_2_CLK_ENABLE;
2477 } else {
2478 /*I2C2 bus clock disable*/
2479 pCLK->CLK_ENABLE_CLEAR_REG2 = I2C_2_BUS_CLK_ENABLE;
2480 /*I2C2 clk disable */
2481 pCLK->CLK_ENABLE_CLEAR_REG3 = I2C_2_CLK_ENABLE;
2482 }
2483 }
2484 return RSI_OK;
2485 }
2486
2487 /*==============================================*/
2488 /**
2489 * @fn rsi_error_t clk_peripheral_clk_enable(M4CLK_Type *pCLK, PERIPHERALS_CLK_T module, CLK_ENABLE_T clkType)
2490 * @brief This API is used to enable the particular clock
2491 * @param[in] pCLK : pointer to the processor clock source
2492 * @param[in] module : module for particular clock
2493 * @param[in] clkType : clock type for particular clock
2494 * @return RSI_OK on success
2495 */
2496
clk_peripheral_clk_enable(M4CLK_Type * pCLK,PERIPHERALS_CLK_T module,CLK_ENABLE_T clkType)2497 rsi_error_t clk_peripheral_clk_enable(M4CLK_Type *pCLK, PERIPHERALS_CLK_T module, CLK_ENABLE_T clkType)
2498 {
2499 /*valid parameter check*/
2500 if (pCLK == NULL) {
2501 return INVALID_PARAMETERS;
2502 }
2503 switch (module) {
2504 case USART1_CLK:
2505 if (clkType == ENABLE_STATIC_CLK) {
2506 pCLK->CLK_ENABLE_SET_REG1 = (USART1_SCLK_ENABLE | USART1_PCLK_ENABLE);
2507 } else {
2508 pCLK->CLK_ENABLE_CLEAR_REG1 = (USART1_SCLK_ENABLE | USART1_PCLK_ENABLE);
2509 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART1_SCLK_DYN_CTRL_DISABLE_b = 0;
2510 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART1_PCLK_DYN_CTRL_DISABLE_b = 0;
2511 }
2512 break;
2513 case USART2_CLK:
2514 if (clkType == ENABLE_STATIC_CLK) {
2515 pCLK->CLK_ENABLE_SET_REG1 = (USART2_SCLK_ENABLE | USART2_PCLK_ENABLE);
2516 } else {
2517 pCLK->CLK_ENABLE_CLEAR_REG1 = (USART2_SCLK_ENABLE | USART2_PCLK_ENABLE);
2518 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART2_SCLK_DYN_CTRL_DISABLE_b = 0;
2519 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART2_PCLK_DYN_CTRL_DISABLE_b = 0;
2520 }
2521 break;
2522 case SSIMST_CLK:
2523 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2524 if (clkType == ENABLE_STATIC_CLK) {
2525 pCLK->CLK_ENABLE_SET_REG2 = (SSI_MST_SCLK_ENABLE | SSI_MST_PCLK_ENABLE);
2526 } else {
2527 pCLK->CLK_ENABLE_CLEAR_REG2 = (SSI_MST_SCLK_ENABLE | SSI_MST_PCLK_ENABLE);
2528 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_MST_SCLK_DYN_CTRL_DISABLE_b = 0;
2529 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_MST_PCLK_DYN_CTRL_DISABLE_b = 0;
2530 }
2531 break;
2532 case SSISLAVE_CLK:
2533 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2534 if (clkType == ENABLE_STATIC_CLK) {
2535 pCLK->CLK_ENABLE_SET_REG2 = (SSI_SLV_SCLK_ENABLE | SSI_SLV_PCLK_ENABLE);
2536 } else {
2537 pCLK->CLK_ENABLE_CLEAR_REG2 = (SSI_SLV_SCLK_ENABLE | SSI_SLV_PCLK_ENABLE);
2538 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_SLV_SCLK_DYN_CTRL_DISABLE_b = 0;
2539 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_SLV_PCLK_DYN_CTRL_DISABLE_b = 0;
2540 }
2541 break;
2542
2543 case CT_CLK:
2544 pCLK->CLK_ENABLE_SET_REG1 = CT_CLK_ENABLE;
2545 if (clkType == ENABLE_STATIC_CLK) {
2546 pCLK->CLK_ENABLE_SET_REG1 = CT_PCLK_ENABLE;
2547 } else {
2548 pCLK->CLK_ENABLE_CLEAR_REG1 = CT_PCLK_ENABLE;
2549 pCLK->DYN_CLK_GATE_DISABLE_REG2_b.CT_PCLK_DYN_CTRL_DISABLE_b = 0;
2550 }
2551 break;
2552 #if !defined(SLI_SI917) && !defined(SLI_SI915)
2553 case SD_MEM_CLK:
2554 pCLK->CLK_ENABLE_SET_REG1 = SD_MEM_INTF_CLK_ENABLE;
2555 break;
2556
2557 case CCI_CLK:
2558 pCLK->CLK_ENABLE_SET_REG1 = (CCI_CLK_ENABLE | CCI_HCLK_ENABLE);
2559 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2560 if (clkType == ENABLE_STATIC_CLK) {
2561 pCLK->CLK_ENABLE_SET_REG1 = CCI_PCLK_ENABLE;
2562 } else {
2563 pCLK->CLK_ENABLE_CLEAR_REG1 = CCI_PCLK_ENABLE;
2564 pCLK->DYN_CLK_GATE_DISABLE_REG_b.CCI_PCLK_DYN_CTRL_DISABLE_b = 0;
2565 }
2566 break;
2567 case CAN_CLK:
2568 /*Enable the clock */
2569 pCLK->CLK_ENABLE_SET_REG2 = CAN1_CLK_ENABLE;
2570 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2571 if (clkType == ENABLE_STATIC_CLK) {
2572 pCLK->CLK_ENABLE_SET_REG2 = CAN1_PCLK_ENABLE;
2573 } else {
2574 pCLK->CLK_ENABLE_CLEAR_REG2 = CAN1_PCLK_ENABLE;
2575 pCLK->DYN_CLK_GATE_DISABLE_REG2_b.CAN1_PCLK_DYN_CTRL_DISABLE_b = 0;
2576 }
2577 break;
2578 #endif
2579 case QSPI_CLK:
2580 pCLK->CLK_ENABLE_SET_REG2 = (QSPI_CLK_ENABLE | QSPI_HCLK_ENABLE);
2581 pCLK->CLK_ENABLE_SET_REG3 = QSPI_CLK_ONEHOT_ENABLE;
2582 break;
2583 #if defined(SLI_SI917B0) || defined(SLI_SI915)
2584 case QSPI_2_CLK:
2585 pCLK->CLK_ENABLE_SET_REG1 = (QSPI_2_CLK_ENABLE | QSPI_2_HCLK_ENABLE);
2586 pCLK->CLK_ENABLE_SET_REG1 = QSPI_2_CLK_ONEHOT_ENABLE;
2587 break;
2588 #endif
2589 case RPDMA_CLK:
2590 pCLK->CLK_ENABLE_SET_REG1 = RPDMA_HCLK_ENABLE;
2591 break;
2592 case UDMA_CLK:
2593 pCLK->CLK_ENABLE_SET_REG2 = UDMA_HCLK_ENABLE;
2594 break;
2595 case PWM_CLK:
2596 pCLK->CLK_ENABLE_SET_REG2 = MCPWM_PCLK_ENABLE;
2597 break;
2598 case GSPI_CLK:
2599 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2600 pCLK->CLK_ENABLE_SET_REG2 = GEN_SPI_MST1_HCLK_ENABLE;
2601 break;
2602 case EGPIO_CLK:
2603 pCLK->CLK_ENABLE_SET_REG3 = EGPIO_CLK_ENABLE;
2604 pCLK->CLK_ENABLE_SET_REG2 = EGPIO_PCLK_ENABLE;
2605 break;
2606 case ETHERNET_CLK:
2607 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2608 pCLK->CLK_ENABLE_SET_REG1 = ETH_HCLK_ENABLE;
2609 break;
2610 case MCUCLKOUT_CLK:
2611 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_ENABLE = 1;
2612 break;
2613 case HWRNG_CLK:
2614 pCLK->CLK_ENABLE_SET_REG1 = HWRNG_PCLK_ENABLE;
2615 break;
2616 case I2SM_CLK:
2617 pCLK->CLK_ENABLE_SET_REG2 = (I2SM_INTF_SCLK_ENABLE | I2SM_SCLK_ENABLE | I2SM_PCLK_ENABLE | I2SM_SCLK_ENABLE);
2618 break;
2619 default:
2620 return INVALID_PARAMETERS;
2621 }
2622 return RSI_OK;
2623 }
2624
2625 /*==============================================*/
2626 /**
2627 * @fn rsi_error_t clk_peripheral_clk_disable(M4CLK_Type *pCLK, PERIPHERALS_CLK_T module)
2628 * @brief This API is used to disable the particular clock
2629 * @param[in] pCLK : pointer to the processor clock source
2630 * @param[in] module : module
2631 * @return RSI_OK on success
2632 */
2633
clk_peripheral_clk_disable(M4CLK_Type * pCLK,PERIPHERALS_CLK_T module)2634 rsi_error_t clk_peripheral_clk_disable(M4CLK_Type *pCLK, PERIPHERALS_CLK_T module)
2635 {
2636 /*valid parameter check*/
2637 if (pCLK == NULL) {
2638 return INVALID_PARAMETERS;
2639 }
2640 switch (module) {
2641 case USART1_CLK:
2642 pCLK->CLK_ENABLE_CLEAR_REG1 = (USART1_SCLK_ENABLE | USART1_PCLK_ENABLE);
2643 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART1_SCLK_DYN_CTRL_DISABLE_b = 1;
2644 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART1_PCLK_DYN_CTRL_DISABLE_b = 1;
2645 break;
2646 case USART2_CLK:
2647 pCLK->CLK_ENABLE_CLEAR_REG1 = (USART2_SCLK_ENABLE | USART2_PCLK_ENABLE);
2648 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART2_SCLK_DYN_CTRL_DISABLE_b = 1;
2649 pCLK->DYN_CLK_GATE_DISABLE_REG_b.USART2_PCLK_DYN_CTRL_DISABLE_b = 1;
2650 break;
2651 case SSIMST_CLK:
2652 pCLK->CLK_ENABLE_CLEAR_REG2 = SSI_MST_SCLK_ENABLE;
2653 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_MST_SCLK_DYN_CTRL_DISABLE_b = 1;
2654 break;
2655 case SSISLAVE_CLK:
2656 pCLK->CLK_ENABLE_CLEAR_REG2 = (SSI_SLV_SCLK_ENABLE | SSI_SLV_PCLK_ENABLE);
2657 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_SLV_SCLK_DYN_CTRL_DISABLE_b = 1;
2658 pCLK->DYN_CLK_GATE_DISABLE_REG_b.SSI_SLV_PCLK_DYN_CTRL_DISABLE_b = 1;
2659 break;
2660 case CT_CLK:
2661 pCLK->CLK_ENABLE_CLEAR_REG1 = CT_CLK_ENABLE;
2662 break;
2663 case SD_MEM_CLK:
2664 pCLK->CLK_ENABLE_CLEAR_REG1 = SD_MEM_INTF_CLK_ENABLE;
2665 break;
2666 case CCI_CLK:
2667 pCLK->CLK_ENABLE_CLEAR_REG1 = CCI_CLK_ENABLE;
2668 pCLK->CLK_ENABLE_CLEAR_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
2669 break;
2670 case QSPI_CLK:
2671 pCLK->CLK_ENABLE_CLEAR_REG2 = QSPI_CLK_ENABLE;
2672 pCLK->CLK_ENABLE_CLEAR_REG3 = (QSPI_CLK_ONEHOT_ENABLE | QSPI_M4_SOC_SYNC);
2673 break;
2674 #if defined(SLI_SI917B0) || defined(SLI_SI915)
2675 case QSPI_2_CLK:
2676 pCLK->CLK_ENABLE_CLEAR_REG1 = QSPI_2_CLK_ENABLE;
2677 pCLK->CLK_ENABLE_CLEAR_REG1 = (QSPI_2_CLK_ONEHOT_ENABLE | QSPI_2_M4_SOC_SYNC);
2678 break;
2679 #endif
2680 case RPDMA_CLK:
2681 pCLK->CLK_ENABLE_CLEAR_REG1 = RPDMA_HCLK_ENABLE;
2682 break;
2683 case UDMA_CLK:
2684 pCLK->CLK_ENABLE_CLEAR_REG2 = UDMA_HCLK_ENABLE;
2685 break;
2686 case PWM_CLK:
2687 pCLK->CLK_ENABLE_CLEAR_REG2 = MCPWM_PCLK_ENABLE;
2688 break;
2689 case CAN_CLK:
2690 pCLK->CLK_ENABLE_CLEAR_REG2 = CAN1_CLK_ENABLE;
2691 break;
2692 case GSPI_CLK:
2693 pCLK->CLK_ENABLE_CLEAR_REG2 = GEN_SPI_MST1_HCLK_ENABLE;
2694 break;
2695 case EGPIO_CLK:
2696 pCLK->CLK_ENABLE_CLEAR_REG2 = EGPIO_PCLK_ENABLE;
2697 pCLK->CLK_ENABLE_CLEAR_REG3 = EGPIO_CLK_ENABLE;
2698 break;
2699 case ETHERNET_CLK:
2700 pCLK->CLK_ENABLE_CLEAR_REG1 = ETH_HCLK_ENABLE;
2701 break;
2702 case MCUCLKOUT_CLK:
2703 pCLK->CLK_CONFIG_REG3_b.MCU_CLKOUT_ENABLE = 0;
2704 break;
2705 case HWRNG_CLK:
2706 pCLK->CLK_ENABLE_CLEAR_REG1 = HWRNG_PCLK_ENABLE;
2707 break;
2708 case I2SM_CLK:
2709 #if !defined(SLI_SI917) && !defined(SLI_SI915)
2710 pCLK->DYN_CLK_GATE_DISABLE_REG_b.I2SM_INTF_SCLK_DYN_CTRL_DISABLE_b = 1;
2711 #endif
2712 pCLK->CLK_ENABLE_CLEAR_REG2 = (I2SM_INTF_SCLK_ENABLE | I2SM_SCLK_ENABLE);
2713 break;
2714 default:
2715 return INVALID_PARAMETERS;
2716 }
2717 return RSI_OK;
2718 }
2719
2720 /*==============================================*/
2721 /**
2722 * @fn void clk_config_pll_ref_clk(uint8_t ref_clk_src)
2723 * @brief This API is used to Configures the PLL lock configurations
2724 * @param[in] ref_clk_src : reference clock source
2725 * @return none
2726 */
2727
clk_config_pll_ref_clk(uint8_t ref_clk_src)2728 void clk_config_pll_ref_clk(uint8_t ref_clk_src)
2729 {
2730 uint32_t reg_read = 0;
2731 reg_read = SPI_MEM_MAP_PLL(SOCPLLMACROREG2);
2732 reg_read &= ~((uint16_t)(0x3 << 14));
2733 reg_read |= (ref_clk_src << 14U);
2734 SPI_MEM_MAP_PLL(SOCPLLMACROREG2) = (uint16_t)reg_read;
2735 }
2736 #endif //PLL_ROMDRIVER_PRESENT
2737
2738 #if !defined(CHIP_9118) || !defined(A11_ROM) || !defined(PLL_ROMDRIVER_PRESENT)
2739
2740 /*==============================================*/
2741 /**
2742 * @fn void clk_config_pll_lock(boolean_t manual_lock, boolean_t bypass_manual_lock, uint8_t mm_count_limit)
2743 * @brief This API is used to Configures the PLL lock configurations
2744 * @param[in] manual_clock : manual clock
2745 * @param[in] bypass_manual_clock : bypass manual clock
2746 * @param[in] mm_count_limit : count limit
2747 * @return none
2748 */
2749
clk_config_pll_lock(boolean_t manual_lock,boolean_t bypass_manual_lock,uint8_t mm_count_limit)2750 void clk_config_pll_lock(boolean_t manual_lock, boolean_t bypass_manual_lock, uint8_t mm_count_limit)
2751 {
2752 uint32_t reg_read = 0;
2753 reg_read = SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG9);
2754 reg_read &= ~((0xFF << 6) | BIT(15) | BIT(14));
2755 reg_read |= (uint32_t)((manual_lock << 15U) | (bypass_manual_lock << 14U) | (mm_count_limit << 6U));
2756 SPI_MEM_MAP_PLL(SOC_PLL_500_CTRL_REG9) = (uint16_t)reg_read;
2757 }
2758 #endif
2759
2760 /*==============================================*/
2761 /**
2762 * @fn uint32_t RSI_CLK_CheckPresent(const M4CLK_Type *pCLK ,CLK_PRESENT_T clkPresent)
2763 * @brief This API is used to enable the dynamic clock gate for peripherals
2764 * @param[in] pCLK : Pointer to the pll register instance \ref M4CLK_Type
2765 * @param[in] clkPresent : structure variable of CLK_PRESENT_T , \ref CLK_PRESENT_T
2766 * @return zero on success
2767 * RSI_OK on error error code
2768 * ERROR_CLOCK_NOT_ENABLED
2769 */
2770
RSI_CLK_CheckPresent(const M4CLK_Type * pCLK,CLK_PRESENT_T clkPresent)2771 uint32_t RSI_CLK_CheckPresent(const M4CLK_Type *pCLK, CLK_PRESENT_T clkPresent)
2772 {
2773 uint32_t errorReturn = 0;
2774 switch (clkPresent) {
2775 case SOC_PLL_CLK_PRESENT:
2776 if (pCLK->PLL_STAT_REG_b.SOCPLL_LOCK == 1) {
2777 errorReturn = RSI_OK;
2778 } else {
2779 errorReturn = ERROR_CLOCK_NOT_ENABLED;
2780 }
2781 break;
2782 case INTF_PLL_CLK_PRESENT:
2783 if (pCLK->PLL_STAT_REG_b.INTFPLL_LOCK == 1) {
2784 errorReturn = RSI_OK;
2785 } else {
2786 errorReturn = ERROR_CLOCK_NOT_ENABLED;
2787 }
2788 break;
2789 case I2S_PLL_CLK_PRESENT:
2790 if (pCLK->PLL_STAT_REG_b.I2SPLL_LOCK == 1) {
2791 errorReturn = RSI_OK;
2792 } else {
2793 errorReturn = ERROR_CLOCK_NOT_ENABLED;
2794 }
2795 break;
2796 case MODEM_PLL_CLK_PRESENT:
2797 if (pCLK->PLL_STAT_REG_b.MODEMPLL_LOCK == 1) {
2798 errorReturn = RSI_OK;
2799 } else {
2800 errorReturn = ERROR_CLOCK_NOT_ENABLED;
2801 }
2802 break;
2803 }
2804 return errorReturn;
2805 }
2806
2807 /*==============================================*/
2808 /**
2809 * @fn rsi_error_t clk_m4ss_ref_clk_config(const M4CLK_Type *pCLK, M4SS_REF_CLK_SEL_T clkSource)
2810 * @brief This API is used to configure the m4ss_ref clocks
2811 * @param[in] pCLK is pointer to the processor clock source
2812 * @param[in] clkSource is source clock
2813 * @return RSI_OK on success
2814 */
2815
clk_m4ss_ref_clk_config(const M4CLK_Type * pCLK,M4SS_REF_CLK_SEL_T clkSource)2816 rsi_error_t clk_m4ss_ref_clk_config(const M4CLK_Type *pCLK, M4SS_REF_CLK_SEL_T clkSource)
2817 {
2818 if (pCLK == NULL) {
2819 return INVALID_PARAMETERS;
2820 }
2821
2822 switch (clkSource) {
2823 case ULP_MHZ_RC_BYP_CLK:
2824 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2825 system_clocks.m4_ref_clock_source = clkSource;
2826 system_clocks.m4ss_ref_clk = system_clocks.byp_rc_ref_clock;
2827 break;
2828
2829 case ULP_MHZ_RC_CLK:
2830 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2831 system_clocks.m4_ref_clock_source = clkSource;
2832 system_clocks.m4ss_ref_clk = system_clocks.rc_mhz_clock;
2833 break;
2834
2835 case EXT_40MHZ_CLK:
2836 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2837 system_clocks.m4_ref_clock_source = clkSource;
2838 system_clocks.m4ss_ref_clk = system_clocks.rf_ref_clock;
2839 break;
2840
2841 case MEMS_REF_CLK:
2842 TASS_PLL_CTRL_SET_REG(AFEPLLCTRLREG1) = MEMS_REF_CLK_ENABLE;
2843 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2844 system_clocks.m4_ref_clock_source = clkSource;
2845 system_clocks.m4ss_ref_clk = system_clocks.mems_ref_clock;
2846 break;
2847
2848 case ULP_20MHZ_RINGOSC_CLK:
2849 /*Enable clock*/
2850 ulpss_enable_ref_clks(MCU_ULP_20MHZ_RING_OSC_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2851 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2852 system_clocks.m4_ref_clock_source = clkSource;
2853 system_clocks.m4ss_ref_clk = system_clocks.ro_20mhz_clock;
2854 break;
2855
2856 case ULP_DOUBLER_CLK:
2857 /*6: ulp_doubler_clk*/
2858 /*Enable clock*/
2859 ulpss_enable_ref_clks(MCU_ULP_DOUBLER_CLK_EN, ULP_PERIPHERAL_CLK, 0);
2860 MCU_FSM->MCU_FSM_REF_CLK_REG_b.M4SS_REF_CLK_SEL = clkSource;
2861 system_clocks.m4_ref_clock_source = clkSource;
2862 system_clocks.m4ss_ref_clk = system_clocks.doubler_clock;
2863 break;
2864
2865 default:
2866 return INVALID_PARAMETERS;
2867 }
2868
2869 /*wait for clock switched*/
2870 while ((pCLK->PLL_STAT_REG_b.ULP_REF_CLK_SWITCHED) != true)
2871 ;
2872
2873 return RSI_OK;
2874 }
2875
2876 /*==============================================*/
2877 /**
2878 * @fn rsi_error_t ulpss_disable_ref_clks(REF_CLK_ENABLE_T clk_type)
2879 * @brief This API is used to enable the ULP reference clocks and provide delay for clock starting
2880 * @param[in] clk_Type : clock type
2881 * @return RSI_OK on success
2882 */
2883
ulpss_disable_ref_clks(REF_CLK_ENABLE_T clk_type)2884 rsi_error_t ulpss_disable_ref_clks(REF_CLK_ENABLE_T clk_type)
2885 {
2886 /*Select clock source*/
2887 switch (clk_type) {
2888 case MCU_ULP_40MHZ_CLK_EN:
2889 /*Cleaners are disabled */
2890 *(volatile uint32_t *)0x2404811C |= (BIT(7) | BIT(23));
2891 *(volatile uint32_t *)0x2404811C &= ~(BIT(8) | BIT(24)); /////// API with XTAL Clock disabled ///////
2892 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_40MHZ_CLK_EN_b = 0;
2893 break;
2894
2895 case MCU_ULP_DOUBLER_CLK_EN:
2896 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_DOUBLER_CLK_EN_b = 0;
2897 break;
2898
2899 case MCU_ULP_20MHZ_RING_OSC_CLK_EN:
2900 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_20MHZ_RING_OSC_CLK_EN_b = 0;
2901 break;
2902
2903 case MCU_ULP_MHZ_RC_CLK_EN:
2904 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_MHZ_RC_CLK_EN_b = 0;
2905 break;
2906
2907 case MCU_ULP_32KHZ_XTAL_CLK_EN:
2908 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_XTAL_CLK_EN_b = 0;
2909 break;
2910 case MCU_ULP_32KHZ_RO_CLK_EN:
2911 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RO_CLK_EN_b = 0;
2912 break;
2913
2914 case MCU_ULP_32KHZ_RC_CLK_EN:
2915 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RC_CLK_EN_b = 0;
2916 break;
2917 }
2918 return RSI_OK;
2919 }
2920
2921 /*==============================================*/
2922 /**
2923 * @fn rsi_error_t clk_m4_soc_clk_config(M4CLK_Type *pCLK, M4_SOC_CLK_SRC_SEL_T clkSource, uint32_t divFactor)
2924 * @brief This API is used to configure the m4_soc clocks
2925 * @param[in] pCLK : pointer to the processor clock source
2926 * @param[in] clkSource : source clock
2927 * @param[in] divFactor : division factor
2928 * @return RSI_OK on success
2929 */
2930
clk_m4_soc_clk_config(M4CLK_Type * pCLK,M4_SOC_CLK_SRC_SEL_T clkSource,uint32_t divFactor)2931 rsi_error_t clk_m4_soc_clk_config(M4CLK_Type *pCLK, M4_SOC_CLK_SRC_SEL_T clkSource, uint32_t divFactor)
2932 {
2933 /*check valid parameters*/
2934 if ((pCLK == NULL) || (divFactor >= SOC_MAX_CLK_DIVISION_FACTOR)) {
2935 return INVALID_PARAMETERS;
2936 }
2937
2938 /*Added for MCU 100 MHz variant mode setting
2939 * Clock will be max/2 in this mode*/
2940 if (MCU_RET->CHIP_CONFIG_MCU_READ_b.LIMIT_M4_FREQ_110MHZ_b == 1) {
2941 divFactor = divFactor / 2;
2942 }
2943 /*Selects one of the clock sources for M4 SoC clock*/
2944 switch (clkSource) {
2945 case M4_ULPREFCLK:
2946 /*Update the clock MUX*/
2947 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_SEL = clkSource;
2948 SystemCoreClock = system_clocks.m4ss_ref_clk;
2949 break;
2950
2951 case M4_SOCPLLCLK:
2952 /*Check clock is present is or not before switching*/
2953 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
2954 return ERROR_CLOCK_NOT_ENABLED;
2955 }
2956 /*Update the clock MUX*/
2957 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_SEL = clkSource;
2958 SystemCoreClock = system_clocks.soc_pll_clock;
2959 break;
2960
2961 case M4_MODEMPLLCLK1:
2962 /*Check clock is present is or not before switching*/
2963 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
2964 return ERROR_CLOCK_NOT_ENABLED;
2965 }
2966 /*Update the clock MUX*/
2967 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_SEL = clkSource;
2968 SystemCoreClock = system_clocks.modem_pll_clock;
2969 break;
2970
2971 case M4_INTFPLLCLK:
2972 /*Check clock is present is or not before switching*/
2973 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
2974 return ERROR_CLOCK_NOT_ENABLED;
2975 } /*Update the clock MUX*/
2976 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_SEL = clkSource;
2977 SystemCoreClock = system_clocks.intf_pll_clock;
2978 break;
2979
2980 case M4_SLEEPCLK:
2981 /*Check clock is present is or not before switching*/
2982 if (ULPCLK->M4LP_CTRL_REG_b.ULP_M4_CORE_CLK_ENABLE_b == 1) {
2983 /*Update the clock MUX*/
2984 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_SEL = clkSource;
2985 } else {
2986 /*If clock is not presented return the error */
2987 return ERROR_CLOCK_NOT_ENABLED;
2988 }
2989 SystemCoreClock = system_clocks.sleep_clock;
2990 break;
2991 default:
2992 return INVALID_PARAMETERS;
2993 }
2994 /*wait for clock switched*/
2995 while ((pCLK->PLL_STAT_REG_b.M4_SOC_CLK_SWITCHED) != 1)
2996 ;
2997 /*update the division factor */
2998 pCLK->CLK_CONFIG_REG5_b.M4_SOC_CLK_DIV_FAC = (unsigned int)(divFactor & 0x3F);
2999
3000 if (divFactor) {
3001 SystemCoreClock /= divFactor;
3002 }
3003 system_clocks.soc_clock = SystemCoreClock;
3004 return RSI_OK;
3005 }
3006
3007 #if defined(CHIP_9118) || !defined(A11_ROM) || !defined(PLL_ROMDRIVER_PRESENT)
3008
3009 /*==============================================*/
3010 /**
3011 * @fn rsi_error_t clk_usart_clk_config(M4CLK_Type *pCLK,
3012 * CLK_ENABLE_T clkType,
3013 * boolean_t FracDivEn,
3014 * EN_USART_T enUsart,
3015 * USART_CLK_SRC_SEL_T clkSource,
3016 * uint32_t divFactor)
3017 * @brief This API is used to configure the Usart clocks
3018 * @param[in] pCLK : pointer to the processor clock source
3019 * @param[in] clkType : enable the clock
3020 * @param[in] FracDivEn : fractional clock divider
3021 * @param[in] enUsart : used for enable Usart
3022 * @param[in] clkSource: clock source
3023 * @param[in] divFactor : division factor
3024 * @return RSI_OK on success
3025 */
3026
clk_usart_clk_config(M4CLK_Type * pCLK,CLK_ENABLE_T clkType,boolean_t FracDivEn,EN_USART_T enUsart,USART_CLK_SRC_SEL_T clkSource,uint32_t divFactor)3027 rsi_error_t clk_usart_clk_config(M4CLK_Type *pCLK,
3028 CLK_ENABLE_T clkType,
3029 boolean_t FracDivEn,
3030 EN_USART_T enUsart,
3031 USART_CLK_SRC_SEL_T clkSource,
3032 uint32_t divFactor)
3033 {
3034
3035 /*Parameter validation */
3036 if ((pCLK == NULL) || (divFactor > USART_MAX_CLK_DIVISION_FACTOR)) {
3037 return INVALID_PARAMETERS;
3038 }
3039
3040 /*Disable the USART clock*/
3041 if (enUsart == USART1) {
3042 RSI_CLK_PeripheralClkDisable(pCLK, USART1_CLK);
3043 } else {
3044 RSI_CLK_PeripheralClkDisable(pCLK, USART2_CLK);
3045 }
3046 /*Select clock MUX*/
3047 switch (clkSource) {
3048 case USART_ULPREFCLK:
3049 if (enUsart == USART1) {
3050 /*select the MUX for the USART 1*/
3051 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_SEL = 0x00;
3052 /*Wait for the clock MUX switch status */
3053 while ((pCLK->PLL_STAT_REG_b.USART1_SCLK_SWITCHED) != 1)
3054 ;
3055 /*Update the division factor */
3056 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3057 /*fractional clock divider select */
3058 if (FracDivEn) {
3059 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
3060 } else {
3061 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
3062 }
3063 } else if (enUsart == USART2) {
3064 /*select the MUX for the USART 1*/
3065 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_SEL = 0x00;
3066 /*Wait for the clock MUX switch status */
3067 while ((pCLK->PLL_STAT_REG_b.USART2_SCLK_SWITCHED) != 1)
3068 ;
3069 /*fractional clock divider select */
3070 /*Update the division factor */
3071 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3072
3073 if (FracDivEn) {
3074 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
3075 } else {
3076 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
3077 }
3078 }
3079 break;
3080
3081 case USART_MODELPLLCLK2:
3082 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, MODEM_PLL_CLK_PRESENT)) {
3083 return ERROR_CLOCK_NOT_ENABLED;
3084 }
3085 if (enUsart == USART1) {
3086 /*select the MUX for the USART 1*/
3087 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_SEL = 0x02;
3088 /*Wait for the clock MUX switch status */
3089 while ((pCLK->PLL_STAT_REG_b.USART1_SCLK_SWITCHED) != 1)
3090 ;
3091 /*Update the division factor */
3092 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3093 /*fractional clock divider select */
3094 if (FracDivEn) {
3095 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
3096 } else {
3097 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
3098 }
3099 } else if (enUsart == USART2) {
3100 /*select the MUX for the USART 1*/
3101 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_SEL = 0x02;
3102 /*Wait for the clock MUX switch status */
3103 while ((pCLK->PLL_STAT_REG_b.USART2_SCLK_SWITCHED) != 1)
3104 ;
3105 /*fractional clock divider select */
3106 /*Update the division factor */
3107 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3108 if (FracDivEn) {
3109 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
3110 } else {
3111 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
3112 }
3113 }
3114 break;
3115
3116 case USART_INTFPLLCLK:
3117 /*Check clock is present is or not before switching*/
3118 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, INTF_PLL_CLK_PRESENT)) {
3119 return ERROR_CLOCK_NOT_ENABLED;
3120 }
3121 if (enUsart == USART1) {
3122 /*select the MUX for the USART 1*/
3123 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_SEL = 0x03;
3124 /*Wait for the clock MUX switch status */
3125 while ((pCLK->PLL_STAT_REG_b.USART1_SCLK_SWITCHED) != 1)
3126 ;
3127 /*fractional clock divider select */
3128 /*Update the division factor */
3129 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3130 if (FracDivEn) {
3131 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
3132 } else {
3133 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
3134 }
3135 } else if (enUsart == USART2) {
3136 /*select the MUX for the USART 1*/
3137 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_SEL = 0x03;
3138 /*Wait for the clock MUX switch status */
3139 while ((pCLK->PLL_STAT_REG_b.USART2_SCLK_SWITCHED) != 1)
3140 ;
3141 /*Update the division factor */
3142 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3143
3144 /*fractional clock divider select */
3145 if (FracDivEn) {
3146 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
3147 } else {
3148 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
3149 }
3150 }
3151 break;
3152
3153 case USART_SOCPLLCLK:
3154 /*Check clock is present is or not before switching*/
3155 if (RSI_OK != RSI_CLK_CheckPresent(pCLK, SOC_PLL_CLK_PRESENT)) {
3156 return ERROR_CLOCK_NOT_ENABLED;
3157 }
3158 if (enUsart == USART1) {
3159 /*select the MUX for the USART 1*/
3160 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_SEL = 0x01;
3161 /*Wait for the clock MUX switch status */
3162 while ((pCLK->PLL_STAT_REG_b.USART1_SCLK_SWITCHED) != 1)
3163 ;
3164 /*Update the division factor */
3165 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3166 /*fractional clock divider select */
3167 if (FracDivEn) {
3168 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
3169 } else {
3170 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
3171 }
3172 } else if (enUsart == USART2) {
3173 /*select the MUX for the USART 1*/
3174 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_SEL = 0x01;
3175 /*Wait for the clock MUX switch status */
3176 while ((pCLK->PLL_STAT_REG_b.USART2_SCLK_SWITCHED) != 1)
3177 ;
3178 /*Update the division factor */
3179 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3180 /*fractional clock divider select */
3181 if (FracDivEn) {
3182 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
3183 } else {
3184 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
3185 }
3186 }
3187 break;
3188
3189 case M4_SOCCLKFOROTHERCLOCKS:
3190
3191 if (enUsart == USART1) {
3192 /*select the MUX for the USART 1*/
3193 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_SEL = 0x04;
3194 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
3195 /*Wait for the clock MUX switch status */
3196 while ((pCLK->PLL_STAT_REG_b.USART1_SCLK_SWITCHED) != 1)
3197 ;
3198 /*Update the division factor */
3199 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3200 /*fractional clock divider select */
3201 if (FracDivEn) {
3202 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 0;
3203 } else {
3204 pCLK->CLK_CONFIG_REG2_b.USART1_SCLK_FRAC_SEL = 1;
3205 }
3206 } else if (enUsart == USART2) {
3207 /*select the MUX for the USART 1*/
3208 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_SEL = 0x04;
3209 pCLK->CLK_ENABLE_SET_REG3 = M4_SOC_CLK_FOR_OTHER_ENABLE;
3210 /*Wait for the clock MUX switch status */
3211 while ((pCLK->PLL_STAT_REG_b.USART2_SCLK_SWITCHED) != 1)
3212 ;
3213 /*Update the division factor */
3214 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_DIV_FAC = (unsigned int)(divFactor & 0x0F);
3215 /*fractional clock divider select */
3216 if (FracDivEn) {
3217 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 0;
3218 } else {
3219 pCLK->CLK_CONFIG_REG2_b.USART2_SCLK_FRAC_SEL = 1;
3220 }
3221 }
3222 break;
3223 default:
3224 return INVALID_PARAMETERS;
3225 }
3226 /*Enable USART clock */
3227 if (enUsart == USART1) {
3228 RSI_CLK_PeripheralClkEnable(pCLK, USART1_CLK, clkType);
3229 } else {
3230 RSI_CLK_PeripheralClkEnable(pCLK, USART2_CLK, clkType);
3231 }
3232 return RSI_OK;
3233 }
3234 #endif
3235
3236 /*==============================================*/
3237 /**
3238 * @fn rsi_error_t ulpss_enable_ref_clks(REF_CLK_ENABLE_T enable, SRC_TYPE_T srcType, cdDelay delayFn)
3239 * @brief This API is used to enable the ULP reference clocks and provide delay for clock starting
3240 * @param[in] enable : enable
3241 * @param[in] srcType : source type
3242 * @param[in] delayFn : delay function
3243 * @return RSI_OK on success
3244 */
3245
ulpss_enable_ref_clks(REF_CLK_ENABLE_T enable,SRC_TYPE_T srcType,cdDelay delayFn)3246 rsi_error_t ulpss_enable_ref_clks(REF_CLK_ENABLE_T enable, SRC_TYPE_T srcType, cdDelay delayFn)
3247 {
3248 /*Select clock source*/
3249 switch (enable) {
3250 case MCU_ULP_40MHZ_CLK_EN:
3251 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_40MHZ_CLK_EN_b == 1) {
3252 /*Clock is enabled by default*/
3253 /*Do Nothing*/
3254 } else {
3255 /*Enable the clock source */
3256 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_40MHZ_CLK_EN_b = 1;
3257 }
3258 /*Wait for the time out only in case of ULP processor clock configuration */
3259 if (srcType == ULP_PROCESSOR_CLK) {
3260 /*wait for clock source is enabled*/
3261 _usdelay(MCU_ULP_40MHZ_CLK_EN_TRUN_ON_DELAY, delayFn);
3262 }
3263 /*Cleaners are Enabled */
3264 *(volatile uint32_t *)0x2404811C &= ~(BIT(7) | BIT(23)); /////// API with XTAL Clock disabled ///////
3265 *(volatile uint32_t *)0x2404811C |= (BIT(8) | BIT(24)); /////// API with XTAL Clock disabled ///////
3266 break;
3267 case MCU_ULP_DOUBLER_CLK_EN:
3268 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_DOUBLER_CLK_EN_b == 1) {
3269 /*Clock is enabled by default*/
3270 /*Do Nothing*/
3271 } else {
3272 /*NOTE : 320Mhz RC is interdependent on Doubler clock*/
3273 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_20MHZ_RING_OSC_CLK_EN_b = 1;
3274 /*Enable the clock source */
3275 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_DOUBLER_CLK_EN_b = 1;
3276 }
3277 if (srcType == ULP_PROCESSOR_CLK) {
3278 /*wait for clock source is enabled*/
3279 _usdelay(MCU_ULP_DOUBLER_CLK_EN_TRUN_ON_DELAY, delayFn);
3280 }
3281 break;
3282
3283 case MCU_ULP_20MHZ_RING_OSC_CLK_EN:
3284 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_20MHZ_RING_OSC_CLK_EN_b == 1) {
3285 /*Clock is enabled by default*/
3286 /*Do Nothing*/
3287 } else {
3288 /*Enable the clock source */
3289 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_20MHZ_RING_OSC_CLK_EN_b = 1;
3290 }
3291 if (srcType == ULP_PROCESSOR_CLK) {
3292 /*wait for clock source is enabled*/
3293 _usdelay(MCU_ULP_20MHZ_RING_OSC_CLK_EN_TRUN_ON_DELAY, delayFn);
3294 }
3295 break;
3296 case MCU_ULP_MHZ_RC_CLK_EN:
3297 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_MHZ_RC_CLK_EN_b == 1) {
3298 /*Clock is enabled by default*/
3299 /*Do Nothing*/
3300 } else {
3301 /*Enable the clock*/
3302 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_MHZ_RC_CLK_EN_b = 1;
3303 }
3304 if (srcType == ULP_PROCESSOR_CLK) {
3305 /*wait for clock source is enabled*/
3306 _usdelay(MCU_ULP_MHZ_RC_CLK_EN_TRUN_ON_DELAY, delayFn);
3307 }
3308 break;
3309 case MCU_ULP_32KHZ_XTAL_CLK_EN:
3310 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_XTAL_CLK_EN_b == 1) {
3311 /*Clock is enabled by default*/
3312 /*Do Nothing*/
3313 } else {
3314 /* Program the IPMU structure */
3315
3316 /* Enable the clock source from NPSS */
3317 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_XTAL_CLK_EN_b = 1;
3318
3319 /*Wait for 0.5 sec delay*/
3320 _usdelay(MCU_ULP_32KHZ_XTAL_CLK_EN_TRUN_ON_DELAY_1, delayFn);
3321
3322 /* Program the IPMU structure */
3323
3324 /* Wait for clock source to be enabled for 1.5 seconds */
3325 _usdelay(MCU_ULP_32KHZ_XTAL_CLK_EN_TRUN_ON_DELAY_2, delayFn);
3326 }
3327 break;
3328
3329 case MCU_ULP_32KHZ_RO_CLK_EN:
3330 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RO_CLK_EN_b == 1) {
3331 /*Clock is enabled by default*/
3332 /*Do Nothing*/
3333 } else {
3334 /*Enable the clock source */
3335 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RO_CLK_EN_b = 1;
3336 }
3337 if (srcType == ULP_PROCESSOR_CLK) {
3338 /*wait for clock source is enabled*/
3339 _usdelay(MCU_ULP_32KHZ_RO_CLK_EN_TRUN_ON_DELAY, delayFn);
3340 }
3341 break;
3342 case MCU_ULP_32KHZ_RC_CLK_EN:
3343 if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RC_CLK_EN_b == 1) {
3344 /*Clock is enabled by default*/
3345 /*Do Nothing*/
3346 } else {
3347 /*Enable the clock source */
3348 MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.MCU_ULP_32KHZ_RC_CLK_EN_b = 1;
3349 }
3350 if (srcType == ULP_PROCESSOR_CLK) {
3351 /*wait for clock source is enabled*/
3352 _usdelay(MCU_ULP_32KHZ_RC_CLK_EN_TRUN_ON_DELAY, delayFn);
3353 }
3354 break;
3355 }
3356 return RSI_OK;
3357 }
3358 /** @} */
3359
3360 /* End of file not truncated */
3361