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