1 /*******************************************************************************
2 * @file  rsi_ipmu.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 /**
31  * Includes
32  */
33 #include "rsi_system_config.h"
34 #include "rsi_ipmu.h"
35 #include "rsi_pll.h"
36 #include "rsi_ulpss_clk.h"
37 
38 /**
39  * Defines
40  */
41 #define SYSTEM_CLK_VAL_20MHZ ((uint32_t)(20000000)) // macro for 20MHz
42 #define SYSTEM_CLK_VAL_MHZ   ((uint32_t)(32000000)) // macro for 32MHz doubler
43 
44 /**
45  * @fn          void RSI_IPMU_UpdateIpmuCalibData_efuse(const efuse_ipmu_t *ipmu_calib_data)
46  * @brief       This function prepares the data from the ipmu calib structure content and writes to each specific register
47  * @param[in]   ipmu_calib_data : pointer of calibrate data
48  * @return      none
49  */
RSI_IPMU_UpdateIpmuCalibData_efuse(const efuse_ipmu_t * ipmu_calib_data)50 void RSI_IPMU_UpdateIpmuCalibData_efuse(const efuse_ipmu_t *ipmu_calib_data)
51 {
52   uint32_t data  = 0;
53   uint32_t value = 0;
54   uint32_t mask  = 0;
55   /* over writing the efuse arrays */
56 
57 #ifdef CHIP_9118
58   /* POC_BIAS_EFUSE */
59   data  = (ipmu_calib_data->trim_0p5na1 | ipmu_calib_data->trim_0p5na2 << 1);
60   mask  = MASK_BITS(22, 0);
61   value = poc_bias_efuse[2];
62   value &= ~mask;
63   value |= data;
64   poc_bias_efuse[2] = value;
65 #endif
66 
67 #if defined(SLI_SI917) || defined(SLI_SI915)
68   /* POC_BIAS_EFUSE */
69   data  = (ipmu_calib_data->trim_0p5na1);
70   mask  = MASK_BITS(22, 0);
71   value = poc_bias_efuse[2];
72   value &= ~mask;
73   value |= data;
74   poc_bias_efuse[2] = value;
75 #endif
76 
77 #ifdef CHIP_9118
78   /* BG_TRIM_EFUSE */
79   data  = (ipmu_calib_data->bg_r_vdd_ulp | ipmu_calib_data->bg_r_ptat_vdd_ulp << 3);
80   mask  = MASK_BITS(22, 0);
81   value = bg_trim_efuse[4];
82   value &= ~mask;
83   value |= data;
84   bg_trim_efuse[4] = value;
85 #endif
86 
87 #if defined(SLI_SI917) || defined(SLI_SI915)
88   /* BG_TRIM_EFUSE */
89   data  = (ipmu_calib_data->bg_r_ptat_vdd_ulp);
90   mask  = MASK_BITS(22, 0);
91   value = bg_trim_efuse[2];
92   value &= ~mask;
93   value |= data;
94   bg_trim_efuse[2] = value;
95 
96   /* BG_TRIM_EFUSE */
97   data  = (ipmu_calib_data->bg_r_vdd_ulp);
98   mask  = MASK_BITS(22, 0);
99   value = bg_trim_efuse[4];
100   value &= ~mask;
101   value |= data;
102   bg_trim_efuse[4] = value;
103 #endif
104 
105 #ifdef CHIP_9118
106   /*  POC2  ( blackout_trim_efuse )*/
107   data  = (ipmu_calib_data->resbank_trim);
108   mask  = MASK_BITS(22, 0);
109   value = blackout_trim_efuse[2];
110   value &= ~mask;
111   value |= data;
112   blackout_trim_efuse[2] = value;
113 #endif
114 
115   /* M32RC_EFUSE */
116   data  = ipmu_calib_data->trim_sel;
117   mask  = MASK_BITS(22, 0);
118   value = m32rc_osc_trim_efuse[2];
119   value &= ~mask;
120   value |= data;
121   m32rc_osc_trim_efuse[2] = value;
122 
123   /* dblr_32m_trim_efuse */
124   data  = ipmu_calib_data->del_2x_sel;
125   mask  = MASK_BITS(22, 0);
126   value = dblr_32m_trim_efuse[2];
127   value &= ~mask;
128   value |= data;
129   dblr_32m_trim_efuse[2] = value;
130 
131   /* ro_32khz_trim_efuse */
132   data  = ipmu_calib_data->freq_trim;
133   mask  = MASK_BITS(22, 0);
134   value = ro_32khz_trim_efuse[2];
135   value &= ~mask;
136   value |= data;
137   ro_32khz_trim_efuse[2] = value;
138 
139   /* rc_16khz_trim_efuse */
140   data  = (uint32_t)(ipmu_calib_data->coarse_trim_16k | ipmu_calib_data->fine_trim_16k << 2);
141   mask  = MASK_BITS(22, 0);
142   value = rc_16khz_trim_efuse[2];
143   value &= ~mask;
144   value |= data;
145   rc_16khz_trim_efuse[2] = value;
146 
147   /*  rc_64khz_trim_efuse */
148   data  = (uint32_t)(ipmu_calib_data->coarse_trim_64k | ipmu_calib_data->fine_trim_64k << 2);
149   mask  = MASK_BITS(22, 0);
150   value = rc_64khz_trim_efuse[2];
151   value &= ~mask;
152   value |= data;
153   rc_64khz_trim_efuse[2] = value;
154 
155   /* xtal1_bias_efuse */
156   data  = (ipmu_calib_data->xtal1_trim_32k);
157   mask  = MASK_BITS(22, 0);
158   value = xtal1_bias_efuse[2];
159   value &= ~mask;
160   value |= data;
161   xtal1_bias_efuse[2] = value;
162 
163   /* xtal2_bias_efuse  */
164   data  = (ipmu_calib_data->xtal2_trim_32k);
165   mask  = MASK_BITS(22, 0);
166   value = xtal2_bias_efuse[2];
167   value &= ~mask;
168   value |= data;
169   xtal2_bias_efuse[2] = value;
170 
171 #ifndef AT_EFUSE_DATA_1P19
172   /* m20rc_osc_trim_efuse  */
173   data  = ((ipmu_calib_data->reserved1) & 0x7F);
174   mask  = MASK_BITS(22, 0);
175   value = m20rc_osc_trim_efuse[2];
176   value &= ~mask;
177   value |= data;
178   m20rc_osc_trim_efuse[2] = value;
179 #endif
180 
181 #ifdef AT_EFUSE_DATA_1P19
182   /* m20rc_osc_trim_efuse  */
183   data  = (ipmu_calib_data->trim_sel_20Mhz);
184   mask  = MASK_BITS(22, 0);
185   value = m20rc_osc_trim_efuse[2];
186   value &= ~mask;
187   value |= data;
188   m20rc_osc_trim_efuse[2] = value;
189 #endif
190 
191   /*m20ro_osc_trim_efuse   */
192   data  = (ipmu_calib_data->trim_ring_osc);
193   mask  = MASK_BITS(22, 0);
194   value = m20ro_osc_trim_efuse[2];
195   value &= ~mask;
196   value |= data;
197   m20ro_osc_trim_efuse[2] = value;
198 
199   /* vbatt_status_trim_efuse */
200   data  = (ipmu_calib_data->vbatt_status_1);
201   mask  = MASK_BITS(22, 0);
202   value = vbatt_status_trim_efuse[2];
203   value &= ~mask;
204   value |= data;
205   vbatt_status_trim_efuse[2] = value;
206 
207   /*  ro_ts_efuse */
208   data  = (ipmu_calib_data->f2_nominal);
209   mask  = MASK_BITS(22, 0);
210   value = ro_ts_efuse[2];
211   value &= ~mask;
212   value |= data;
213   ro_ts_efuse[2] = value;
214 
215   /*  ro_tempsense_config */
216   data  = (ipmu_calib_data->str_temp_slope);
217   mask  = MASK_BITS(22, 0);
218   value = ro_tempsense_config[2];
219   value &= ~mask;
220   value |= data;
221   ro_tempsense_config[2] = value;
222 
223 #ifdef AT_EFUSE_DATA_1P19
224   /*BJT temperature sensor efuse value update*/
225   /*  delvbe_ts_efuse*/
226   data  = (ipmu_calib_data->str_bjt_temp_sense_off);
227   mask  = MASK_BITS(22, 0);
228   value = delvbe_tsbjt_efuse[2];
229   value &= ~mask;
230   value |= data;
231   delvbe_tsbjt_efuse[2] = value;
232 
233   /* vbg_ts_efuse */
234   data  = (ipmu_calib_data->vbg_tsbjt_efuse);
235   mask  = MASK_BITS(22, 0);
236   value = vbg_tsbjt_efuse[2];
237   value &= ~mask;
238   value |= data;
239   vbg_tsbjt_efuse[2] = value;
240 #endif
241 
242   /* retn_ldo_lptrim */
243   data  = (ipmu_calib_data->retn_ldo_lptrim);
244   mask  = MASK_BITS(22, 0);
245   value = retnLP_volt_trim_efuse[2];
246   value &= ~mask;
247   value |= data;
248   retnLP_volt_trim_efuse[2] = value;
249 
250   /* auxadc_off_diff_efuse  */
251   data  = (ipmu_calib_data->auxadc_offset_diff);
252   mask  = MASK_BITS(22, 0);
253   value = auxadc_off_diff_efuse[2];
254   value &= ~mask;
255   value |= data;
256   auxadc_off_diff_efuse[2] = value;
257 
258   /* auxadc_gain_diff_efuse */
259   data  = (ipmu_calib_data->auxadc_invgain_diff);
260   mask  = MASK_BITS(22, 0);
261   value = auxadc_gain_diff_efuse[2];
262   value &= ~mask;
263   value |= data;
264   auxadc_gain_diff_efuse[2] = value;
265 
266   /* auxadc_off_se_efuse */
267   data  = (ipmu_calib_data->auxadc_offset_single);
268   mask  = MASK_BITS(22, 0);
269   value = auxadc_off_se_efuse[2];
270   value &= ~mask;
271   value |= data;
272   auxadc_off_se_efuse[2] = value;
273 
274   /* auxadc_gain_se_efuse */
275   data  = (ipmu_calib_data->auxadc_invgain_single);
276   mask  = MASK_BITS(22, 0);
277   value = auxadc_gain_se_efuse[2];
278   value &= ~mask;
279   value |= data;
280   auxadc_gain_se_efuse[2] = value;
281 
282   /* rc_32khz_trim_efuse  */
283   data  = (uint32_t)(ipmu_calib_data->coarse_trim_32k | ipmu_calib_data->fine_trim_32k << 2);
284   mask  = MASK_BITS(22, 0);
285   value = rc_32khz_trim_efuse[2];
286   value &= ~mask;
287   value |= data;
288   rc_32khz_trim_efuse[2] = value;
289 
290 #ifndef AT_EFUSE_DATA_1P19
291   /*If the 13 bits of WuRx(i.e.reserved1) in E-Fuse are zeros,
292     then overwrite this structure with the contents from RO32K_EFUSE*/
293   if (!((ipmu_calib_data->reserved1) >> 7)) {
294     ro_32khz_trim00_efuse[2] = ro_32khz_trim_efuse[2];
295   } else {
296     /*then write the contents of the (reserved1) last 5 bits
297       allotted to RO32K_00 */
298     data  = ((ipmu_calib_data->reserved1) & (0xF80));
299     mask  = MASK_BITS(22, 0);
300     value = ro_32khz_trim00_efuse[2];
301     value &= ~mask;
302     value |= data;
303     ro_32khz_trim00_efuse[2] = value;
304   }
305 #endif
306 
307 #ifdef AT_EFUSE_DATA_1P19
308 
309   /*If the 13 bits of WuRx(i.e.reserved1) in E-Fuse are zeros,
310     then overwrite this structure with the contents from RO32K_EFUSE*/
311   if (!(ipmu_calib_data->ro_32khz_00_trim)) {
312     ro_32khz_trim00_efuse[2] = ro_32khz_trim_efuse[2];
313   } else {
314     /*then write the contents of the (reserved1) last 5 bits
315       allotted to RO32K_00 */
316     data  = (ipmu_calib_data->ro_32khz_00_trim);
317     mask  = MASK_BITS(22, 0);
318     value = ro_32khz_trim00_efuse[2];
319     value &= ~mask;
320     value |= data;
321     ro_32khz_trim00_efuse[2] = value;
322   }
323 #endif
324 
325   data  = ipmu_calib_data->set_vref1p3;
326   mask  = MASK_BITS(22, 0);
327   value = buck_trim_efuse[2];
328   value &= ~mask;
329   value |= data;
330   buck_trim_efuse[2] = value;
331 
332   data  = ipmu_calib_data->trim_r1_resistorladder;
333   mask  = MASK_BITS(22, 0);
334   value = ldosoc_trim_efuse[2];
335   value &= ~mask;
336   value |= data;
337   ldosoc_trim_efuse[2] = value;
338 
339   data  = ipmu_calib_data->dpwm_freq_trim;
340   mask  = MASK_BITS(22, 0);
341   value = dpwm_freq_trim_efuse[2];
342   value &= ~mask;
343   value |= data;
344   dpwm_freq_trim_efuse[2] = value;
345 
346 #ifdef AT_EFUSE_DATA_1P19
347   /* scdc_hpldo_trim */
348   data  = ipmu_calib_data->scdc_hpldo_trim;
349   mask  = MASK_BITS(22, 0);
350   value = hpldo_volt_trim_efuse[2];
351   value &= ~mask;
352   value |= data;
353   hpldo_volt_trim_efuse[2] = value;
354 
355   /* scdc_dcdc_trim */
356   data  = ipmu_calib_data->scdc_dcdc_trim;
357   mask  = MASK_BITS(22, 0);
358   value = scdc_volt_trim_efuse[2];
359   value &= ~mask;
360   value |= data;
361   scdc_volt_trim_efuse[2] = value;
362 #endif
363 
364   return;
365 }
366 
367 /*==============================================*/
368 /**
369  * @fn         void RSI_IPMU_InitCalibData(void)
370  * @brief      This function checks for magic byte in efuse/flash, copies the content if valid data present and calls to update the ipmu registers
371  * @return     none
372  */
RSI_IPMU_InitCalibData(void)373 void RSI_IPMU_InitCalibData(void)
374 {
375   efuse_ipmu_t global_ipmu_calib_data;
376 #ifdef CHIP_9118
377   uint8_t *calib_data_read_adr = NULL;
378 
379   /* Read the MCU boot status register */
380   volatile retention_boot_status_word_t *retention_reg = (retention_boot_status_word_t *)MCURET_BOOTSTATUS;
381   /* Read the NWP BBFFs storage register */
382   volatile npss_boot_status_word0_t *npss_boot_status = (npss_boot_status_word0_t *)MCU_BBFF_STORAGE1_ADDR;
383 
384   if (retention_reg->product_mode == MCU) {
385     calib_data_read_adr = (uint8_t *)(MCU_MANF_DATA_BASE_ADDR);
386   }
387   if (retention_reg->product_mode == WISEMCU) {
388     if (npss_boot_status->ta_flash_present) {
389       calib_data_read_adr = (uint8_t *)(TA_MANF_DATA_BASE_ADDR);
390     } else {
391       calib_data_read_adr = (uint8_t *)(MCU_MANF_DATA_BASE_ADDR);
392     }
393   }
394 
395   /* Checks the Calibration values are present at MCU flash */
396   if ((*(uint32_t *)(calib_data_read_adr + IPMU_VALUES_OFFSET)) == 0x00) {
397     //NO CALIB DATA. Return
398     return;
399   }
400   /* Checks the `Calibration values are present at MCU flash */
401   if ((*(uint32_t *)(calib_data_read_adr + IPMU_VALUES_OFFSET)) == 0xFFFFFFFF) {
402     //NO CALIB DATA. Return
403     return;
404   }
405 
406   memcpy((void *)&global_ipmu_calib_data, (void *)(calib_data_read_adr + IPMU_VALUES_OFFSET), sizeof(efuse_ipmu_t));
407   //rsi_cmd_m4_ta_secure_handshake(2,0,NULL,sizeof(efuse_ipmu_t),(uint8_t *)&global_ipmu_calib_data);
408 #endif
409 
410 #if defined(SLI_SI917) || defined(SLI_SI915)
411 #ifdef SLI_SI91X_MCU_COMMON_FLASH_MODE
412   /* Checks the Calibration values are present at MCU flash */
413   if ((*(uint32_t *)(COMMON_FLASH_IPMU_VALUES_OFFSET)) == 0x00) {
414     //NO CALIB DATA. Return
415     return;
416   }
417   memcpy((void *)&global_ipmu_calib_data, (void *)(COMMON_FLASH_IPMU_VALUES_OFFSET), sizeof(efuse_ipmu_t));
418 #else
419   /* Checks the Calibration values are present at MCU flash */
420   if ((*(uint32_t *)(DUAL_FLASH_IPMU_VALUES_OFFSET)) == 0x00) {
421     //NO CALIB DATA. Return
422     return;
423   }
424   memcpy((void *)&global_ipmu_calib_data, (void *)(DUAL_FLASH_IPMU_VALUES_OFFSET), sizeof(efuse_ipmu_t));
425 #endif
426 #endif
427 
428   //Dummy read
429   (void)PMU_SPI_DIRECT_ACCESS(PMU_PFM_REG_OFFSET);
430 
431   RSI_IPMU_UpdateIpmuCalibData_efuse(&global_ipmu_calib_data);
432 
433   //Dummy read
434   (void)PMU_SPI_DIRECT_ACCESS(PMU_PFM_REG_OFFSET);
435 }
436 
437 /*==============================================*/
438 /**
439  * @brief   This function Initialize IPMU and MCU FSM blocks
440  * @param   void
441  * @return  void
442  */
RSI_Ipmu_Init(void)443 void RSI_Ipmu_Init(void)
444 {
445   ipmu_init();
446 }
447 
448 /**
449  * @brief   This function configures chip supply mode
450  * @param   void
451  * @return  void
452  */
RSI_Configure_Ipmu_Mode(void)453 void RSI_Configure_Ipmu_Mode(void)
454 {
455   double temperature = 0;
456 
457 #if defined(ENABLE_1P8V) || defined(SLI_SI915)
458   (void)temperature;
459   /*configures chip supply mode to HP-LDO */
460   configure_ipmu_mode(HP_LDO_MODE);
461 #else
462   (void)temperature;
463   configure_ipmu_mode(SCDC_MODE);
464 #endif
465 }
update_efuse_system_configs(int data,uint32_t config_ptr[])466 void update_efuse_system_configs(int data, uint32_t config_ptr[])
467 {
468   uint32_t mask  = 0;
469   uint32_t value = 0;
470   mask           = MASK_BITS(22, 0);
471   value          = config_ptr[2];
472   value &= ~mask;
473   value |= (uint32_t)data;
474   config_ptr[2] = value;
475 }
476 /**
477  * @brief   This function configures the Lower voltage level for DC-DC to 1.25V based on the DC-DC Trim value(for 1.35V) obtained from Calibration
478  * @return  none
479  */
480 
RSI_Configure_DCDC_LowerVoltage(void)481 void RSI_Configure_DCDC_LowerVoltage(void)
482 {
483   uint32_t pmu_1p2_ctrl_word;
484   uint32_t bypass_curr_ctrl_data;
485 
486   bypass_curr_ctrl_data = PMU_SPI_DIRECT_ACCESS(PMU_1P3_CTRL_REG_OFFSET);
487   pmu_1p2_ctrl_word     = ((bypass_curr_ctrl_data >> 17) & 0xF) - 2;
488   bypass_curr_ctrl_data = PMU_SPI_DIRECT_ACCESS(BYPASS_CURR_CTRL_REG_OFFSET);
489   bypass_curr_ctrl_data &= (uint32_t)(~(0xF << 5));
490   PMU_SPI_DIRECT_ACCESS(BYPASS_CURR_CTRL_REG_OFFSET) = (bypass_curr_ctrl_data | (pmu_1p2_ctrl_word << 5));
491 }
492 
493 /*==============================================*/
494 /**
495  * @fn          void RSI_IPMU_PowerGateSet(uint32_t mask_vlaue)
496  * @brief     This API is used to power-up the IPMU peripherals.
497  * @param[in]   mask_vlaue   : Ored value of peripheral power gate defines
498  *                             Possible values for this parameter are the following
499  *                             CMP_NPSS_PG_ENB
500  *                             ULP_ANG_CLKS_PG_ENB
501  *                             ULP_ANG_PWRSUPPLY_PG_ENB
502  *                             WURX_PG_ENB
503  *                             WURX_CORR_PG_ENB
504  *                             AUXADC_PG_ENB
505  *                             AUXADC_BYPASS_ISO_GEN
506  *                             AUXADC_ISOLATION_ENABLE
507  *                             AUXDAC_PG_ENB
508  * @return      none
509  */
510 
RSI_IPMU_PowerGateSet(uint32_t mask_vlaue)511 void RSI_IPMU_PowerGateSet(uint32_t mask_vlaue)
512 {
513   uint32_t impuPowerGate = 0;
514   impuPowerGate          = ULP_SPI_MEM_MAP(POWERGATE_REG_WRITE);
515   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
516     ;
517   impuPowerGate = (impuPowerGate >> 5);
518   impuPowerGate |= mask_vlaue;
519   ULP_SPI_MEM_MAP(POWERGATE_REG_WRITE) = impuPowerGate;
520   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
521     ;
522   /*Dummy read*/
523   impuPowerGate = ULP_SPI_MEM_MAP(POWERGATE_REG_WRITE);
524   return;
525 }
526 
527 /*==============================================*/
528 /**
529  * @fn          void RSI_IPMU_PowerGateClr(uint32_t mask_vlaue)
530  * @brief     This API is used to power-down the IPMU peripherals.
531  * @param[in]   mask_vlaue   : Ored value of peripheral power gate defines
532  *                             Possible values for this parameter are the following
533  *                             CMP_NPSS_PG_ENB
534  *                             ULP_ANG_CLKS_PG_ENB
535  *                             ULP_ANG_PWRSUPPLY_PG_ENB
536  *                             WURX_PG_ENB
537  *                             WURX_CORR_PG_ENB
538  *                             AUXADC_PG_ENB
539  *                             AUXADC_BYPASS_ISO_GEN
540  *                             AUXADC_ISOLATION_ENABLE
541  *                             AUXDAC_PG_ENB
542  * @return      none
543  */
544 
RSI_IPMU_PowerGateClr(uint32_t mask_vlaue)545 void RSI_IPMU_PowerGateClr(uint32_t mask_vlaue)
546 {
547   uint32_t impuPowerGate = 0;
548 
549   if (mask_vlaue & (WURX_CORR_PG_ENB | WURX_PG_ENB)) {
550     ULP_SPI_MEM_MAP(0x141) &= ~BIT(20);
551     ULP_SPI_MEM_MAP(0x141) &= ~BIT(21);
552   }
553 
554   impuPowerGate = ULP_SPI_MEM_MAP(POWERGATE_REG_WRITE);
555   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
556     ;
557   impuPowerGate = (impuPowerGate >> 5);
558   impuPowerGate &= ~mask_vlaue;
559   ULP_SPI_MEM_MAP(POWERGATE_REG_WRITE) = impuPowerGate;
560   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
561     ;
562   return;
563 }
564 
565 /*==============================================*/
566 /**
567  * @fn          void RSI_IPMU_ClockMuxSel(uint8_t bg_pmu_clk)
568  * @brief     This API is used to select clock to the BG-PMU
569  * @param[in]   bg_pmu_clk : Selects the clock source to the BG-PMU module
570  *          1: RO 32KHz clock
571  *          2: MCU FSM clock
572  * @return      none
573  */
574 
RSI_IPMU_ClockMuxSel(uint8_t bg_pmu_clk)575 void RSI_IPMU_ClockMuxSel(uint8_t bg_pmu_clk)
576 {
577   bg_pmu_clk = (bg_pmu_clk - 1);
578   ULP_SPI_MEM_MAP(SELECT_BG_CLK) &= ~(BIT(0) | BIT(1));
579   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
580     ;
581   ULP_SPI_MEM_MAP(SELECT_BG_CLK) |= BIT(bg_pmu_clk);
582   while (GSPI_CTRL_REG1 & SPI_ACTIVE)
583     ;
584   return;
585 }
586 
587 /*==============================================*/
588 /**
589  * @fn          uint32_t RSI_IPMU_32MHzClkClib(void)
590  * @brief     This API is used to auto calibrate the 32MHz RC clock
591  * @return      trim value on success
592  */
593 
RSI_IPMU_32MHzClkClib(void)594 uint32_t RSI_IPMU_32MHzClkClib(void)
595 {
596   volatile int i;
597   volatile int trim_value = 0;
598   /*Enables RC 32MHz clock and*/
599   ULP_SPI_MEM_MAP(0x104) = (0x3FFFFF & 0x41368000);
600   /*Enable XTAL 40MHz clock through NPSS*/
601   *(volatile uint32_t *)0x41300120 |= BIT(22);
602   i = 1000000;
603   while (i--)
604     ;
605   /*Selects NPSS reference clock to be CLK-40M_SOC*/
606   ULP_SPI_MEM_MAP(0x106) = (0x3FFFFF & 0x41A48000);
607   /*Change spi trim select to 0*/
608   ULP_SPI_MEM_MAP(0x107) = (0x3FFFFF & 0x41C04A14);
609   /*Pointing clks test out 1 to RC 32M clock*/
610   ULP_SPI_MEM_MAP(0x10D) = (0x3FFFFF & 0x43600000);
611   /*Pointing clks test out to IPMU_TEST_OUT_0 = SOC[8] in mode 5*/
612   ULP_SPI_MEM_MAP(0x143) = (0x3FFFFF & 0x50C00610);
613   /*Enable the high frequency clock calibration
614    * Enable the clock gate for npss ref clk
615    * Select the RC32M clock to calibrate
616    * */
617   ULP_SPI_MEM_MAP(0x10A) = (0x3FFFFF & 0x42922290);
618   i                      = 100000;
619   while (i--)
620     ;
621   do {
622     /*wait for calibration done indication*/
623   } while ((!(ULP_SPI_MEM_MAP(0x30C))) & BIT(20));
624   /*Calibrated trim value*/
625   trim_value = (int)ULP_SPI_MEM_MAP(0x30C);
626   trim_value = (trim_value >> 11);
627   trim_value = (trim_value & 0x7F);
628   /*Programming the calibrated trim to SPI register.*/
629   ULP_SPI_MEM_MAP(0x104) |= (uint32_t)(trim_value << 14);
630   /*pointing the trim select to SPI*/
631   ULP_SPI_MEM_MAP(0x107) = (0x3FFFFF & 0x41C05A14);
632   return (uint32_t)trim_value;
633 }
634 
635 /*==============================================*/
636 /**
637  * @fn          rsi_error_t RSI_IPMU_ProgramConfigData(const uint32_t *config)
638  * @brief     This API is used to program the any mcu configuration structure
639  * @param[in]   config : pointer configuration
640  * @return      RSI_OK on success
641  */
642 
RSI_IPMU_ProgramConfigData(const uint32_t * config)643 rsi_error_t RSI_IPMU_ProgramConfigData(const uint32_t *config)
644 {
645   volatile uint32_t index          = 0;
646   volatile uint32_t program_len    = 0;
647   volatile uint32_t reg_addr       = 0;
648   volatile uint32_t reg_write_data = 0;
649   volatile uint32_t clear_cnt      = 0;
650   volatile uint32_t cnt            = 0;
651   volatile uint32_t reg_read_data  = 0;
652   volatile uint32_t write_mask     = 0;
653   volatile uint32_t write_bit_pos  = 0;
654   volatile uint8_t msb             = 0;
655   volatile uint8_t lsb             = 0;
656 
657   if (config == NULL) {
658     return INVALID_PARAMETERS;
659   }
660   /*Compute the number of entries in the array to program*/
661   program_len = config[index];
662   if (program_len == 0U) {
663     return INVALID_PARAMETERS;
664   }
665   for (index = 0; index < program_len; index++) {
666     reg_addr       = config[(2U * index) + 1];
667     reg_write_data = config[2U * (index + 1)];
668 
669     lsb = ((reg_write_data >> LSB_POSITION) & POSITION_BITS_MASK);
670     msb = ((reg_write_data >> MSB_POSITION) & POSITION_BITS_MASK);
671 
672     clear_cnt = (msb - lsb) + 1U;
673     /*MSB and LSB position counts validation */
674     if (clear_cnt > MAX_BIT_LEN) {
675       // Return error
676       return INVALID_PARAMETERS;
677     }
678     /*Read register*/
679     reg_read_data = *(volatile uint32_t *)reg_addr;
680     cnt           = lsb;
681     write_mask    = 0;
682     write_bit_pos = 0;
683     do {
684       reg_read_data &= ~BIT(cnt);
685       write_mask |= BIT(write_bit_pos);
686       cnt++;
687       write_bit_pos++;
688     } while (cnt < (clear_cnt + lsb));
689     reg_write_data &= write_mask;
690     /*Write to the hardware register*/
691     reg_write_data                 = (reg_read_data | (reg_write_data << lsb));
692     *(volatile uint32_t *)reg_addr = reg_write_data;
693   }
694   return RSI_OK;
695 }
696 
697 /*==============================================*/
698 /**
699  * @fn          uint32_t RSI_APB_ProgramConfigData(const uint32_t *config)
700  * @brief     This API is used to program the any mcu configuration structure
701  * @param[in]   config : pointer configuration
702  * @return      reg_write_data on success.
703  */
704 
RSI_APB_ProgramConfigData(const uint32_t * config)705 uint32_t RSI_APB_ProgramConfigData(const uint32_t *config)
706 {
707   volatile uint32_t index          = 0;
708   volatile uint32_t program_len    = 0;
709   volatile uint32_t reg_addr       = 0;
710   volatile uint32_t clear_cnt      = 0;
711   volatile uint32_t cnt            = 0;
712   volatile uint32_t reg_write_data = 0;
713   volatile uint32_t reg_read_data  = 0;
714   volatile uint32_t write_mask     = 0;
715   volatile uint32_t write_bit_pos  = 0;
716   volatile uint8_t msb             = 0;
717   volatile uint8_t lsb             = 0;
718   (void)reg_addr;
719 
720   if (config == NULL) {
721     return INVALID_PARAMETERS;
722   }
723   /*Compute the number of entries in the array to program*/
724   program_len = config[index];
725   if (program_len == 0U) {
726     return INVALID_PARAMETERS;
727   }
728   for (index = 0; index < program_len; index++) {
729 
730     reg_write_data = config[2U * (index + 1)];
731 
732     lsb = ((reg_write_data >> LSB_POSITION) & POSITION_BITS_MASK);
733     msb = ((reg_write_data >> MSB_POSITION) & POSITION_BITS_MASK);
734 
735     clear_cnt = (msb - lsb) + 1U;
736     /*MSB and LSB position counts validation */
737     if (clear_cnt > MAX_BIT_LEN) {
738       // Return error
739       return INVALID_PARAMETERS;
740     }
741     cnt           = lsb;
742     write_mask    = 0;
743     write_bit_pos = 0;
744     do {
745       write_mask |= BIT(write_bit_pos);
746       cnt++;
747       write_bit_pos++;
748     } while (cnt < (clear_cnt + lsb));
749     reg_write_data &= write_mask;
750     /*Write to the hardware register*/
751     reg_write_data = (reg_read_data | (reg_write_data << lsb));
752   }
753   return reg_write_data;
754 }
755 
756 /*==============================================*/
757 /**
758  * @fn          rsi_error_t RSI_IPMU_CommonConfig(void)
759  * @brief     This API is used to program the default system start-up IPMU hardware programming.
760  * @return      RSI_IPMU_ProgramConfigData on success.
761  */
762 
RSI_IPMU_CommonConfig(void)763 rsi_error_t RSI_IPMU_CommonConfig(void)
764 {
765   return RSI_IPMU_ProgramConfigData(ipmu_common_config);
766 }
767 
768 /*==============================================*/
769 /**
770  * @fn          rsi_error_t RSI_IPMU_PMUCommonConfig(void)
771  * @brief     This API is used to program the default system start-up PMU hardware programming.
772  * @return      RSI_IPMU_ProgramConfigData on success.
773  */
774 
RSI_IPMU_PMUCommonConfig(void)775 rsi_error_t RSI_IPMU_PMUCommonConfig(void)
776 {
777   return RSI_IPMU_ProgramConfigData(pmu_common_config);
778 }
779 
780 /*==============================================*/
781 /**
782  * @fn          rsi_error_t RSI_IPMU_PocbiasCurrent(void)
783  * @brief     This API is used to Decreasing the bias current of RETN_LDO .
784  * @return      RSI_IPMU_ProgramConfigData on success.
785  */
786 
RSI_IPMU_PocbiasCurrent(void)787 rsi_error_t RSI_IPMU_PocbiasCurrent(void)
788 {
789   return RSI_IPMU_ProgramConfigData(poc_bias_current);
790 }
791 
792 /*==============================================*/
793 /**
794  * @fn          rsi_error_t RSI_IPMU_PocbiasCurrent11(void)
795  * @brief     This API is used to increasing the bias current of RETN_LDO .
796  * @return      RSI_IPMU_ProgramConfigData on success.
797  */
798 
RSI_IPMU_PocbiasCurrent11(void)799 rsi_error_t RSI_IPMU_PocbiasCurrent11(void)
800 {
801   return RSI_IPMU_ProgramConfigData(poc_bias_current_11);
802 }
803 
804 /*==============================================*/
805 /**
806  * @fn          rsi_error_t RSI_IPMU_RO32khzTrim00Efuse(void)
807  * @brief     This API is used to trim to 32Khz RO .
808  * @return      RSI_IPMU_ProgramConfigData on success.
809  */
810 
RSI_IPMU_RO32khzTrim00Efuse(void)811 rsi_error_t RSI_IPMU_RO32khzTrim00Efuse(void)
812 {
813   return RSI_IPMU_ProgramConfigData(ro_32khz_trim00_efuse);
814 }
815 
816 /*==============================================*/
817 /**
818  * @fn          rsi_error_t RSI_IPMU_RetnLdoVoltsel(void)
819  * @brief     This API is used to setting RETN_LDO voltage to 0.7V.
820  * @return      RSI_IPMU_ProgramConfigData on success .
821  */
822 
RSI_IPMU_RetnLdoVoltsel(void)823 rsi_error_t RSI_IPMU_RetnLdoVoltsel(void)
824 {
825   return RSI_IPMU_ProgramConfigData(retn_ldo_voltsel);
826 }
827 
828 /*==============================================*/
829 /**
830  * @fn          rsi_error_t RSI_IPMU_RetnLdo0p75(void)
831  * @brief     This API is used to setting RETN_LDO voltage to 0.75V .
832  * @return      RSI_IPMU_ProgramConfigData on success.
833  */
834 
RSI_IPMU_RetnLdo0p75(void)835 rsi_error_t RSI_IPMU_RetnLdo0p75(void)
836 {
837   return RSI_IPMU_ProgramConfigData(retn_ldo_0p75);
838 }
839 
840 /*==============================================*/
841 /**
842  * @fn          void RSI_IPMU_RetnLdoLpmode(void)
843  * @brief     This API is used to program enabling the RETN_LDO LP MODE  .
844  * @return      none
845  */
846 
RSI_IPMU_RetnLdoLpmode(void)847 void RSI_IPMU_RetnLdoLpmode(void)
848 {
849   RSI_IPMU_ProgramConfigData(retn_ldo_lpmode);
850   RSI_IPMU_ProgramConfigData(retnLP_volt_trim_efuse);
851 }
852 
853 /*==============================================*/
854 /**
855  * @fn          void RSI_IPMU_Retn_Voltage_Reduction(void)
856  * @brief     This API is used to reduce the RETN_LDO voltage by 0.05V.
857  * @return      none
858  */
859 
RSI_IPMU_Retn_Voltage_Reduction(void)860 void RSI_IPMU_Retn_Voltage_Reduction(void)
861 {
862   uint32_t value;
863   uint32_t mask;
864   value = retnLP_volt_trim_efuse[2];
865   mask  = MASK_BITS(3, 0);
866   value &= mask;
867   if (value < RET_LDO_TRIM_VALUE_CHECK) {
868     retnLP_volt_trim_efuse[2] += RET_LDO_VOL_DECREASE;
869   }
870 }
871 
872 /*==============================================*/
873 /**
874  * @fn          void RSI_IPMU_Retn_Voltage_To_Default(void)
875  * @brief     This API is used to change the RETN_LDO voltage to 0.8V.
876  * @return      none
877  */
878 
RSI_IPMU_Retn_Voltage_To_Default(void)879 void RSI_IPMU_Retn_Voltage_To_Default(void)
880 {
881   uint32_t mask;
882   mask = MASK_BITS(22, 0);
883   retnLP_volt_trim_efuse[2] &= ~mask;
884 }
885 
886 /*==============================================*/
887 /**
888  * @fn          void RSI_IPMU_Set_Higher_Pwm_Ro_Frequency_Mode_to_PMU(void)
889  * @brief     This API is used to enable Higher Pwm Ro Frequency Mode for PMU.
890  * @return      none
891  */
892 
RSI_IPMU_Set_Higher_Pwm_Ro_Frequency_Mode_to_PMU(void)893 void RSI_IPMU_Set_Higher_Pwm_Ro_Frequency_Mode_to_PMU(void)
894 {
895   PMU_SPI_MEM_MAP(PMU_FREQ_MODE_REG) &= ~(LOW_FREQ_PWM);
896 }
897 /*==============================================*/
898 /**
899  * @fn          void RSI_IPMU_RetnLdoHpmode(void)
900  * @brief     This API is used to program enabling the RETN_LDO HP MODE .
901  * @return      none
902  */
903 
RSI_IPMU_RetnLdoHpmode(void)904 void RSI_IPMU_RetnLdoHpmode(void)
905 {
906   RSI_IPMU_ProgramConfigData(retn_ldo_hpmode);
907   RSI_IPMU_ProgramConfigData(retnHP_volt_trim_efuse);
908 }
909 /**
910  * @fn         void RSI_IPMU_SCDC_Enable(void)
911  * @brief     This API is used to enable SCDC mode .
912  * @return      none
913  */
RSI_IPMU_SCDC_Enable(void)914 void RSI_IPMU_SCDC_Enable(void)
915 {
916   RSI_IPMU_ProgramConfigData(ipmu_scdc_enable);
917 }
918 /**
919  * @fn         void RSI_IPMU_HP_LDO_Enable(void)
920  * @brief     This API is used to enable LDO mode .
921  * @return      none
922  */
RSI_IPMU_HP_LDO_Enable(void)923 void RSI_IPMU_HP_LDO_Enable(void)
924 {
925   RSI_IPMU_ProgramConfigData(hp_ldo_voltsel);
926 }
927 
928 /*==============================================*/
929 /**
930  * @fn          rsi_error_t RSI_IPMU_M32rc_OscTrimEfuse(void)
931  * @brief     This API is used to program the trim value for 32Mhz RC oscillator .
932  * @return      RSI_IPMU_ProgramConfigData on success.
933  */
934 
RSI_IPMU_M32rc_OscTrimEfuse(void)935 rsi_error_t RSI_IPMU_M32rc_OscTrimEfuse(void)
936 {
937   system_clocks.rc_mhz_clock = DEFAULT_MHZ_RC_CLOCK;
938 
939   if (system_clocks.m4_ref_clock_source == ULP_MHZ_RC_CLK) {
940     system_clocks.m4ss_ref_clk = DEFAULT_MHZ_RC_CLOCK;
941   }
942   if (system_clocks.ulp_ref_clock_source == ULPSS_ULP_MHZ_RC_CLK) {
943     system_clocks.ulpss_ref_clk = DEFAULT_MHZ_RC_CLOCK;
944   }
945 
946   return RSI_IPMU_ProgramConfigData(m32rc_osc_trim_efuse);
947 }
948 
949 /*==============================================*/
950 /**
951  * @fn        rsi_error_t RSI_IPMU_M20rcOsc_TrimEfuse(void)
952  * @brief     This API is used to program the trim value for 20MHz RC oscillator
953  * @return    RSI_IPMU_ProgramConfigData on success
954  */
955 
RSI_IPMU_M20rcOsc_TrimEfuse(void)956 rsi_error_t RSI_IPMU_M20rcOsc_TrimEfuse(void)
957 {
958   rsi_error_t error_status;
959 
960   error_status = RSI_IPMU_ProgramConfigData(m20rc_osc_trim_efuse);
961 
962   if (error_status == RSI_OK) {
963     system_clocks.rc_mhz_clock = SYSTEM_CLK_VAL_20MHZ;
964     if (system_clocks.m4_ref_clock_source == ULP_MHZ_RC_CLK) {
965       system_clocks.m4ss_ref_clk = SYSTEM_CLK_VAL_20MHZ;
966     }
967     if (system_clocks.ulp_ref_clock_source == ULPSS_ULP_MHZ_RC_CLK) {
968       system_clocks.ulpss_ref_clk = SYSTEM_CLK_VAL_20MHZ;
969     }
970   }
971 
972   return error_status;
973 }
974 
975 /*==============================================*/
976 /**
977  * @fn          rsi_error_t RSI_IPMU_DBLR32M_TrimEfuse(void)
978  * @brief     This API is used to program DBLR 32MHz trim value  .
979  * @return      RSI_IPMU_ProgramConfigData on success.
980  */
981 
RSI_IPMU_DBLR32M_TrimEfuse(void)982 rsi_error_t RSI_IPMU_DBLR32M_TrimEfuse(void)
983 {
984   system_clocks.doubler_clock = SYSTEM_CLK_VAL_MHZ;
985   return RSI_IPMU_ProgramConfigData(dblr_32m_trim_efuse);
986 }
987 
988 /*==============================================*/
989 /**
990  * @fn          rsi_error_t RSI_IPMU_M20roOsc_TrimEfuse(void)
991  * @brief     This API is used to program the trim value for 20Mhz RO oscillator .
992  * @return      RSI_IPMU_ProgramConfigData on success.
993  */
994 
RSI_IPMU_M20roOsc_TrimEfuse(void)995 rsi_error_t RSI_IPMU_M20roOsc_TrimEfuse(void)
996 {
997   system_clocks.ro_20mhz_clock = DEFAULT_20MHZ_RO_CLOCK;
998   if (system_clocks.m4_ref_clock_source == ULP_20MHZ_RINGOSC_CLK) {
999     system_clocks.m4ss_ref_clk = DEFAULT_20MHZ_RO_CLOCK;
1000   }
1001   if (system_clocks.ulp_ref_clock_source == ULPSS_ULP_20MHZ_RINGOSC_CLK) {
1002     system_clocks.ulpss_ref_clk = DEFAULT_20MHZ_RO_CLOCK;
1003   }
1004   return RSI_IPMU_ProgramConfigData(m20ro_osc_trim_efuse);
1005 }
1006 
1007 /*==============================================*/
1008 /**
1009  * @fn          rsi_error_t RSI_IPMU_RO32khz_TrimEfuse(void)
1010  * @brief     This API is used to program the trim value for 32KHz RO oscillator .
1011  * @return      RSI_IPMU_ProgramConfigData on success.
1012  */
1013 
RSI_IPMU_RO32khz_TrimEfuse(void)1014 rsi_error_t RSI_IPMU_RO32khz_TrimEfuse(void)
1015 {
1016   system_clocks.ro_32khz_clock = DEFAULT_32KHZ_RO_CLOCK;
1017 
1018   return RSI_IPMU_ProgramConfigData(ro_32khz_trim_efuse);
1019 }
1020 
1021 /*==============================================*/
1022 /**
1023  * @fn          rsi_error_t RSI_IPMU_RC16khz_TrimEfuse(void)
1024  * @brief     This API is used to program the trim value for 16KHz RC oscillator .
1025  * @return      RSI_IPMU_ProgramConfigData on success.
1026  */
1027 
RSI_IPMU_RC16khz_TrimEfuse(void)1028 rsi_error_t RSI_IPMU_RC16khz_TrimEfuse(void)
1029 {
1030   system_clocks.rc_32khz_clock = 16000;
1031   return RSI_IPMU_ProgramConfigData(rc_16khz_trim_efuse);
1032 }
1033 
1034 /*==============================================*/
1035 /**
1036  * @fn          rsi_error_t RSI_IPMU_RC64khz_TrimEfuse(void)
1037  * @brief     This API is used to program the trim value for 64KHz RC oscillator .
1038  * @return      RSI_IPMU_ProgramConfigData on success.
1039  */
1040 
RSI_IPMU_RC64khz_TrimEfuse(void)1041 rsi_error_t RSI_IPMU_RC64khz_TrimEfuse(void)
1042 {
1043   system_clocks.rc_32khz_clock = 64000;
1044   return RSI_IPMU_ProgramConfigData(rc_64khz_trim_efuse);
1045 }
1046 
1047 /*==============================================*/
1048 /**
1049  * @fn          rsi_error_t RSI_IPMU_RC32khz_TrimEfuse(void)
1050  * @brief     This API is used to program the trim value for 32KHz RC oscillator .
1051  * @return      RSI_IPMU_ProgramConfigData on success.
1052  */
1053 
RSI_IPMU_RC32khz_TrimEfuse(void)1054 rsi_error_t RSI_IPMU_RC32khz_TrimEfuse(void)
1055 {
1056   system_clocks.rc_32khz_clock = 32000;
1057   return RSI_IPMU_ProgramConfigData(rc_32khz_trim_efuse);
1058 }
1059 
1060 /*==============================================*/
1061 /**
1062  * @fn          uint32_t RSI_IPMU_RO_TsEfuse()
1063  * @brief     This API is used to program the nominal_count .
1064  * @return      RSI_APB_ProgramConfigData on success.
1065  */
1066 
RSI_IPMU_RO_TsEfuse()1067 uint32_t RSI_IPMU_RO_TsEfuse()
1068 {
1069   return RSI_APB_ProgramConfigData(ro_ts_efuse);
1070 }
1071 
1072 /*==============================================*/
1073 /**
1074  * @fn          uint32_t RSI_IPMU_RO_TsConfig(void)
1075  * @brief     This API is used to program the RO Temp sensor slope .
1076  * @return      RSI_APB_ProgramConfigData on success.
1077  */
1078 
RSI_IPMU_RO_TsConfig(void)1079 uint32_t RSI_IPMU_RO_TsConfig(void)
1080 {
1081   return RSI_APB_ProgramConfigData(ro_tempsense_config);
1082 }
1083 
1084 /*==============================================*/
1085 /**
1086  * @fn          rsi_error_t RSI_IPMU_Vbattstatus_TrimEfuse(void)
1087  * @brief     This API is used to program the trim value for Vbatt status .
1088  * @return      RSI_IPMU_ProgramConfigData on success.
1089  */
1090 
RSI_IPMU_Vbattstatus_TrimEfuse(void)1091 rsi_error_t RSI_IPMU_Vbattstatus_TrimEfuse(void)
1092 {
1093   return RSI_IPMU_ProgramConfigData(vbatt_status_trim_efuse);
1094 }
1095 
1096 /*==============================================*/
1097 /**
1098  * @fn          uint32_t RSI_IPMU_Vbg_Tsbjt_Efuse(void)
1099  * @brief     This API is used to program the BG voltage for BJT temperature sensor
1100  * @return      RSI_APB_ProgramConfigData on success.
1101  */
1102 
RSI_IPMU_Vbg_Tsbjt_Efuse(void)1103 uint32_t RSI_IPMU_Vbg_Tsbjt_Efuse(void)
1104 {
1105   return RSI_APB_ProgramConfigData(vbg_tsbjt_efuse);
1106 }
1107 
1108 /*==============================================*/
1109 /**
1110  * @fn          uint32_t RSI_IPMU_Auxadcoff_DiffEfuse(void)
1111  * @brief     This API is used to program The offset value for AUX ADC differential mode .
1112  * @return      RSI_APB_ProgramConfigData on success.
1113  */
1114 
RSI_IPMU_Auxadcoff_DiffEfuse(void)1115 uint32_t RSI_IPMU_Auxadcoff_DiffEfuse(void)
1116 {
1117   return RSI_APB_ProgramConfigData(auxadc_off_diff_efuse);
1118 }
1119 
1120 /*==============================================*/
1121 /**
1122  * @fn          uint32_t RSI_IPMU_Auxadcgain_DiffEfuse(void)
1123  * @brief     This API is used to program The gain value for AUX ADC differential mode   .
1124  * @return      RSI_APB_ProgramConfigData on success.
1125  */
RSI_IPMU_Auxadcgain_DiffEfuse(void)1126 uint32_t RSI_IPMU_Auxadcgain_DiffEfuse(void)
1127 {
1128   return RSI_APB_ProgramConfigData(auxadc_gain_diff_efuse);
1129 }
1130 
1131 /*==============================================*/
1132 /**
1133  * @fn          uint32_t RSI_IPMU_Auxadcoff_SeEfuse(void)
1134  * @brief     This API is used to program The offset value for AUX ADC single ended mode    .
1135  * @return      RSI_APB_ProgramConfigData on success.
1136  */
1137 
RSI_IPMU_Auxadcoff_SeEfuse(void)1138 uint32_t RSI_IPMU_Auxadcoff_SeEfuse(void)
1139 {
1140   return RSI_APB_ProgramConfigData(auxadc_off_se_efuse);
1141 }
1142 
1143 /*==============================================*/
1144 /**
1145  * @fn          uint32_t RSI_IPMU_Auxadcgain_SeEfuse(void)
1146  * @brief     This API is used to program The gain value for AUX ADC single mode    .
1147  * @return      RSI_APB_ProgramConfigData on success.
1148  */
1149 
RSI_IPMU_Auxadcgain_SeEfuse(void)1150 uint32_t RSI_IPMU_Auxadcgain_SeEfuse(void)
1151 {
1152   return RSI_APB_ProgramConfigData(auxadc_gain_se_efuse);
1153 }
1154 
1155 /*==============================================*/
1156 /**
1157  * @fn          rsi_error_t RSI_IPMU_Bg_TrimEfuse(void)
1158  * @brief     This API is used to program BG trim value.
1159  * @return      RSI_IPMU_ProgramConfigData on success.
1160  */
1161 
RSI_IPMU_Bg_TrimEfuse(void)1162 rsi_error_t RSI_IPMU_Bg_TrimEfuse(void)
1163 {
1164   return RSI_IPMU_ProgramConfigData(bg_trim_efuse);
1165 }
1166 
1167 /*==============================================*/
1168 /**
1169  * @fn          rsi_error_t RSI_IPMU_Blackout_TrimEfuse(void)
1170  * @brief     This API is used to program BLACKOUT thresholds .
1171  * @return      RSI_IPMU_ProgramConfigData on success.
1172  */
1173 
RSI_IPMU_Blackout_TrimEfuse(void)1174 rsi_error_t RSI_IPMU_Blackout_TrimEfuse(void)
1175 {
1176   return RSI_IPMU_ProgramConfigData(blackout_trim_efuse);
1177 }
1178 
1179 /*==============================================*/
1180 /**
1181  * @fn          rsi_error_t RSI_IPMU_POCbias_Efuse(void)
1182  * @brief     This API is used to program the poc bias.
1183  * @return      RSI_IPMU_ProgramConfigData on success.
1184  */
1185 
RSI_IPMU_POCbias_Efuse(void)1186 rsi_error_t RSI_IPMU_POCbias_Efuse(void)
1187 {
1188   return RSI_IPMU_ProgramConfigData(poc_bias_efuse);
1189 }
1190 
1191 /*==============================================*/
1192 /**
1193  * @fn          rsi_error_t RSI_IPMU_Buck_TrimEfuse(void)
1194  * @brief     This API is used to program BUCK value .
1195  * @return      RSI_IPMU_ProgramConfigData on success.
1196  */
1197 
RSI_IPMU_Buck_TrimEfuse(void)1198 rsi_error_t RSI_IPMU_Buck_TrimEfuse(void)
1199 {
1200   return RSI_IPMU_ProgramConfigData(buck_trim_efuse);
1201 }
1202 
1203 /*==============================================*/
1204 /**
1205  * @fn          rsi_error_t RSI_IPMU_Ldosoc_TrimEfuse(void)
1206  * @brief     This API is used to program LDO SOC value .
1207  * @return      RSI_IPMU_ProgramConfigData on success.
1208  */
1209 
RSI_IPMU_Ldosoc_TrimEfuse(void)1210 rsi_error_t RSI_IPMU_Ldosoc_TrimEfuse(void)
1211 {
1212   return RSI_IPMU_ProgramConfigData(ldosoc_trim_efuse);
1213 }
1214 
1215 /*==============================================*/
1216 /**
1217  * @fn          rsi_error_t RSI_IPMU_Dpwmfreq_TrimEfuse(void)
1218  * @brief     This API is used to program DPWM frequency value .
1219  * @return      RSI_IPMU_ProgramConfigData on success.
1220  */
1221 
RSI_IPMU_Dpwmfreq_TrimEfuse(void)1222 rsi_error_t RSI_IPMU_Dpwmfreq_TrimEfuse(void)
1223 {
1224   return RSI_IPMU_ProgramConfigData(dpwm_freq_trim_efuse);
1225 }
1226 
1227 /*==============================================*/
1228 /**
1229  * @fn          uint32_t RSI_IPMU_Delvbe_Tsbjt_Efuse(void)
1230  * @brief     This API is used to program the offset voltage
1231  * @return      RSI_APB_ProgramConfigData on success.
1232  */
1233 
RSI_IPMU_Delvbe_Tsbjt_Efuse(void)1234 uint32_t RSI_IPMU_Delvbe_Tsbjt_Efuse(void)
1235 {
1236   return RSI_APB_ProgramConfigData(delvbe_tsbjt_efuse);
1237 }
1238 
1239 /*==============================================*/
1240 /**
1241  * @fn          rsi_error_t RSI_IPMU_Xtal1bias_Efuse(void)
1242  * @brief     This API is used to program Xtal bias value .
1243  * @return      RSI_IPMU_ProgramConfigData on success.
1244  */
1245 
RSI_IPMU_Xtal1bias_Efuse(void)1246 rsi_error_t RSI_IPMU_Xtal1bias_Efuse(void)
1247 {
1248   return RSI_IPMU_ProgramConfigData(xtal1_bias_efuse);
1249 }
1250 
1251 /*==============================================*/
1252 /**
1253  * @fn          rsi_error_t RSI_IPMU_Xtal2bias_Efuse(void)
1254  * @brief     This API is used to program Xtal2 bias value .
1255  * @return      RSI_IPMU_ProgramConfigData on success.
1256  */
1257 
RSI_IPMU_Xtal2bias_Efuse(void)1258 rsi_error_t RSI_IPMU_Xtal2bias_Efuse(void)
1259 {
1260   return RSI_IPMU_ProgramConfigData(xtal2_bias_efuse);
1261 }
1262 
1263 /*==============================================*/
1264 /**
1265  * @fn          rsi_error_t RSI_IPMU_RetnHP_Volttrim_Efuse(void)
1266  * @brief     This API is used to program the HP retention voltage .
1267  * @return      RSI_IPMU_ProgramConfigData on success.
1268  */
1269 
RSI_IPMU_RetnHP_Volttrim_Efuse(void)1270 rsi_error_t RSI_IPMU_RetnHP_Volttrim_Efuse(void)
1271 {
1272   return RSI_IPMU_ProgramConfigData(retnHP_volt_trim_efuse);
1273 }
1274 
1275 /*==============================================*/
1276 /**
1277  * @fn          rsi_error_t RSI_IPMU_BOD_ClksCommonconfig1(void)
1278  * @brief     This API is used to enable bias currents to BOD.
1279  * @return      RSI_IPMU_ProgramConfigData on success.
1280  */
1281 
RSI_IPMU_BOD_ClksCommonconfig1(void)1282 rsi_error_t RSI_IPMU_BOD_ClksCommonconfig1(void)
1283 {
1284   return RSI_IPMU_ProgramConfigData(ipmu_bod_clks_common_config1);
1285 }
1286 
1287 /*==============================================*/
1288 /**
1289  * @fn          rsi_error_t RSI_IPMU_BOD_ClksCommonconfig2(void)
1290  * @brief     This API is used to disable bias currents to BOD.
1291  * @return      RSI_IPMU_ProgramConfigData on success.
1292  */
1293 
RSI_IPMU_BOD_ClksCommonconfig2(void)1294 rsi_error_t RSI_IPMU_BOD_ClksCommonconfig2(void)
1295 {
1296   return RSI_IPMU_ProgramConfigData(ipmu_bod_clks_common_config2);
1297 }
1298 
1299 /*==============================================*/
1300 /**
1301  * @fn          rsi_error_t RSI_IPMU_Hpldo_volt_trim_efuse(void)
1302  * @brief     This API is used to set the LDO to the correct voltage based on E-Fuse.
1303  * @return      RSI_IPMU_ProgramConfigData on success.
1304  */
1305 
RSI_IPMU_Hpldo_volt_trim_efuse(void)1306 rsi_error_t RSI_IPMU_Hpldo_volt_trim_efuse(void)
1307 {
1308   return RSI_IPMU_ProgramConfigData(hpldo_volt_trim_efuse);
1309 }
1310 
1311 /*==============================================*/
1312 /**
1313  * @fn          rsi_error_t RSI_IPMU_Scdc_volt_trim_efuse(void))
1314  * @brief     This API is used to set the SC-DCDC to the corrrect voltage based on E-Fuse.
1315  * @return      RSI_IPMU_ProgramConfigData on success.
1316  */
1317 
RSI_IPMU_Scdc_volt_trim_efuse(void)1318 rsi_error_t RSI_IPMU_Scdc_volt_trim_efuse(void)
1319 {
1320   return RSI_IPMU_ProgramConfigData(scdc_volt_trim_efuse);
1321 }
1322 
1323 /*==============================================*/
1324 /**
1325  * @fn          void RSI_IPMU_Reconfig_to_SCDCDC(void)
1326  * @brief     This API is used to the LDO has to be re-configured into SC-DCDC mode.
1327  * @return      none
1328  */
1329 
RSI_IPMU_Reconfig_to_SCDCDC(void)1330 void RSI_IPMU_Reconfig_to_SCDCDC(void)
1331 {
1332   RSI_IPMU_ProgramConfigData(scdc_volt_sel1);
1333   RSI_IPMU_ProgramConfigData(scdc_volt_trim_efuse);
1334   RSI_IPMU_ProgramConfigData(scdc_volt_sel2);
1335 }
1336 
1337 /*==============================================*/
1338 /**
1339  * @fn          rsi_error_t RSI_IPMU_Lp_scdc_extcapmode(void)
1340  * @brief     This API is used to SCDC into the external CAP mode.
1341  * @return      RSI_IPMU_ProgramConfigData on success.
1342  */
1343 
RSI_IPMU_Lp_scdc_extcapmode(void)1344 rsi_error_t RSI_IPMU_Lp_scdc_extcapmode(void)
1345 {
1346   return RSI_IPMU_ProgramConfigData(lp_scdc_extcapmode);
1347 }
1348 
1349 /*==============================================*/
1350 /**
1351  * @fn          rsi_error_t RSI_IPMU_BOD_Cmphyst(void)
1352  * @brief     This API is used to set the comparator hysteresis.
1353  * @return      RSI_IPMU_ProgramConfigData on success.
1354  */
1355 
RSI_IPMU_BOD_Cmphyst(void)1356 rsi_error_t RSI_IPMU_BOD_Cmphyst(void)
1357 {
1358   return RSI_IPMU_ProgramConfigData(bod_cmp_hyst);
1359 }
1360 
1361 /*==============================================*/
1362 /**
1363  * @fn          void RSI_IPMU_32KHzROClkClib(void)
1364  * @brief       This API is used to calibrate the 32Khz RO clock to 32khz frequency .
1365  * @return      none
1366  */
1367 
RSI_IPMU_32KHzROClkClib(void)1368 void RSI_IPMU_32KHzROClkClib(void)
1369 {
1370   uint32_t ro32k_trim           = 0;
1371   uint32_t no_of_tst_clk_khz_ro = 0;
1372 
1373   /*Do until clock should be 32KHz */
1374   do {
1375     /* CLK40M buffer circuit will be ON */
1376     ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) |= BIT(21);
1377     /*  Off controls for clock cleaner are taken from NPSS */
1378     ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) &= ~BIT(16);
1379     /* RO 32KHz clock enable */
1380     ULP_SPI_MEM_MAP(ULPCLKS_32KRO_CLK_REG_OFFSET) |= BIT(21);
1381     /* calibrated trim goes to the block */
1382     ULP_SPI_MEM_MAP(ULPCLKS_32KRO_CLK_REG_OFFSET) &= ~(BIT(15));
1383     /* Enable the clock gate for npss ref clk &wait for 1us*/
1384     /*  32KHz RO clock calibration */
1385     /* Binary search calibration enable signal for low frequency clocks RO and RC */
1386     ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REG_ADDR) |= (BIT(4) | BIT(15) | BIT(21));
1387     /* wait till bit 21 becomes 1 Indicates calibration done indication*/
1388     while (!(ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & BIT(21)))
1389       ;
1390     /* Read calibrated trim value after low frequency calibration done */
1391     ro32k_trim = ((ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & RO_TRIM_VALUE_LF) >> 4);
1392     /*Mask the bits where the trim value need to write */
1393     ULP_SPI_MEM_MAP(ULPCLKS_32KRO_CLK_REG_OFFSET) &= (uint32_t)(~(MASK32KRO_TRIM_VALUE_WRITE_BITS));
1394     /* Programming the calibrated trim to SPI register. */
1395     ULP_SPI_MEM_MAP(ULPCLKS_32KRO_CLK_REG_OFFSET) |= (ro32k_trim << 16);
1396     /*  trim given from spi goes to the block */
1397     ULP_SPI_MEM_MAP(ULPCLKS_32KRO_CLK_REG_OFFSET) |= (BIT(15));
1398     /* Measures MHz RC clock Clock Frequency  */
1399     no_of_tst_clk_khz_ro = RSI_Clks_Calibration(sleep_clk, khz_ro_clk);
1400     no_of_tst_clk_khz_ro /= 1000;
1401     /* Check if it is less than a particular value */
1402     if (no_of_tst_clk_khz_ro < PARTICULAR_FREQ_MIN) {
1403       ULP_SPI_MEM_MAP(iPMU_SPARE_REG1_OFFSET) |= BIT(18) | BIT(19);
1404     }
1405     /* Check if it is greater than a particular value */
1406     if (no_of_tst_clk_khz_ro > PARTICULAR_FREQ_MAX) {
1407       ULP_SPI_MEM_MAP(iPMU_SPARE_REG1_OFFSET) &= ~((BIT(18) | BIT(19)));
1408     }
1409   } while ((no_of_tst_clk_khz_ro < PARTICULAR_FREQ_MIN) || (no_of_tst_clk_khz_ro > PARTICULAR_FREQ_MAX));
1410 
1411   return;
1412 }
1413 
1414 /*==============================================*/
1415 /**
1416  * @fn          void RSI_IPMU_32KHzRCClkClib(void)
1417  * @brief       This API is used to calibrate the 32Khz RC clock to 32khz frequency.
1418  * @return      none
1419  */
1420 
RSI_IPMU_32KHzRCClkClib(void)1421 void RSI_IPMU_32KHzRCClkClib(void)
1422 {
1423   uint32_t rc32k_trim           = 0;
1424   uint32_t no_of_tst_clk_khz_rc = 0;
1425 
1426   /*Do until clock should be 32KHz */
1427   do {
1428     /* CLK40M buffer circuit will be ON */
1429     ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) |= BIT(21);
1430     /*  Off controls for clock cleaner are taken from NPSS */
1431     ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) &= ~(BIT(16));
1432     /*  RC 32KHz clock enable */
1433     ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) |= BIT(21);
1434     /*  calibrated trim goes to the block (changes spi_trim select to 0) */
1435     ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) &= ~(BIT(11));
1436     /* Enable the clock gate for npss ref clk &wait for 1us*/
1437     /*  32KHz RC clock calibration */
1438     /* Binary search calibration enable signal for low frequency clocks RO and RC */
1439     ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REG_ADDR) |= (BIT(4) | BIT(14) | BIT(21));
1440     /* wait till bit 21 becomes 1 Indicates calibration done indication*/
1441     while (!(ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & BIT(21)))
1442       ;
1443     /* Read calibrated trim value after low frequency calibration done */
1444     rc32k_trim = ((ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & RC_TRIM_VALUE_LF) >> 4);
1445     /*Mask the bits where the trim value need to write */
1446     ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) &= (uint32_t)~MASK32KRC_TRIM_VALUE_WRITE_BITS;
1447     /* Programming the calibrated trim to SPI register. */
1448     ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) |= (rc32k_trim << 14);
1449     /*pointing the trim select to SPI */
1450     ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) |= (BIT(11));
1451     /* Measures MHz RC clock Clock Frequency  */
1452     no_of_tst_clk_khz_rc = RSI_Clks_Calibration(sleep_clk, khz_rc_clk);
1453     no_of_tst_clk_khz_rc /= 1000;
1454     /* Check if it is less than a particular value */
1455     if (no_of_tst_clk_khz_rc < PARTICULAR_FREQ_MIN) {
1456       ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) |= BIT(12) | BIT(13);
1457     }
1458     /* Check if it is greater than a particular value */
1459     if (no_of_tst_clk_khz_rc > PARTICULAR_FREQ_MAX) {
1460       ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_OFFSET) &= ~((BIT(12) | BIT(13)));
1461     }
1462   } while ((no_of_tst_clk_khz_rc < PARTICULAR_FREQ_MIN) || (no_of_tst_clk_khz_rc > PARTICULAR_FREQ_MAX));
1463 
1464   return;
1465 }
1466 
1467 /*==============================================*/
1468 /**
1469  * @fn          uint32_t RSI_Clks_Trim32MHzRC(uint32_t freq)
1470  * @brief     This API is used to trim 32MHz RC clock to required frequency
1471  * @param[in]   freq :  Input is to get  required frequency from 13MHz to 32MHz.
1472  * @return      trim value for required MHz RC frequency which we can reserve for further usage  .
1473  */
1474 
RSI_Clks_Trim32MHzRC(uint32_t freq)1475 uint32_t RSI_Clks_Trim32MHzRC(uint32_t freq)
1476 {
1477   volatile uint32_t no_oftst_clk_f = 0;
1478   volatile uint32_t no_oftst_clk   = 0;
1479   volatile uint32_t reg_read       = 0;
1480   volatile uint32_t trim_value     = 0;
1481 
1482   system_clocks.rc_mhz_clock = freq;
1483 
1484   if (system_clocks.m4_ref_clock_source == ULP_MHZ_RC_CLK) {
1485     system_clocks.m4ss_ref_clk = freq;
1486   }
1487   if (system_clocks.ulp_ref_clock_source == ULPSS_ULP_MHZ_RC_CLK) {
1488     system_clocks.ulpss_ref_clk = freq;
1489   }
1490 
1491   /*Multiple the input frequency value with 10 e.g:20MHz as 200 */
1492   freq *= 10;
1493 
1494   /* Measures MHz RC clock Clock Frequency  */
1495   no_oftst_clk = RSI_Clks_Calibration(ulp_ref_clk, none);
1496   no_oftst_clk = no_oftst_clk_f / 100000;
1497   /* Trims MHz RC clock to required frequency */
1498   if (no_oftst_clk != freq) {
1499     reg_read = ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET);
1500     /* Clears Trim bits(14-20) for RC 32MHz clock */
1501     reg_read &= (uint32_t)(~(0x7F << TRIM_LSB_MHZ));
1502     ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET) = reg_read;
1503     /* check's from 20 bit to 14 bit  */
1504     for (volatile uint32_t i = TRIM_MSB_MHZ; i >= TRIM_LSB_MHZ; i--) {
1505       /* Measures MHz RC clock Clock Frequency  */
1506       no_oftst_clk_f = RSI_Clks_Calibration(ulp_ref_clk, none);
1507       /*To get in three digit of Measured frequency value in MHz e.g:20MHz as 200 */
1508       no_oftst_clk = no_oftst_clk_f / 100000;
1509       /* Halt the process for less than 0.3MHZ even  */
1510       if (freq - no_oftst_clk < MIN_DIFF_FREQ) {
1511         break;
1512       }
1513       /*Check whether the acquired frequency is higher than required frequency
1514         If higher then clear the previous bit and set the present bit     */
1515       if (no_oftst_clk >= freq) {
1516         ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET) &= ~BIT(i + 1);
1517         ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET) |= BIT(i);
1518       }
1519       /* If lesser  set the present bit   */
1520       else {
1521         ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET) |= BIT(i);
1522       }
1523     }
1524   }
1525   /* Trim bits(14-20) value for RC 32MHz clock   */
1526   trim_value = ULP_SPI_MEM_MAP(ULPCLKS_MRC_CLK_REG_OFFSET);
1527   trim_value &= (0x7F << TRIM_LSB_MHZ);
1528   trim_value = trim_value >> TRIM_LSB_MHZ;
1529 
1530   return trim_value;
1531 }
1532 
1533 /*==============================================*/
1534 /**
1535  * @fn          void RSI_IPMU_20M_ROClktrim(uint8_t clkfreq)
1536  * @brief       This API is used to trim the 20Mhz RO clock to required frequency.
1537  * @param[in]   clkfreq  :  Input is to get  required frequency from 1MHz to 50MHz.
1538  * @return      none
1539  */
1540 
RSI_IPMU_20M_ROClktrim(uint8_t clkfreq)1541 void RSI_IPMU_20M_ROClktrim(uint8_t clkfreq)
1542 {
1543   volatile uint32_t ro50m_trim = 0;
1544   system_clocks.doubler_clock  = (clkfreq * 1000000 * 2);
1545 
1546   system_clocks.ro_20mhz_clock = (clkfreq * 1000000);
1547 
1548   if (system_clocks.m4_ref_clock_source == ULP_20MHZ_RINGOSC_CLK) {
1549     system_clocks.m4ss_ref_clk = (clkfreq * 1000000);
1550   }
1551   if (system_clocks.ulp_ref_clock_source == ULPSS_ULP_20MHZ_RINGOSC_CLK) {
1552     system_clocks.ulpss_ref_clk = (clkfreq * 1000000);
1553   }
1554   /* CLK40M buffer circuit will be ON */
1555   ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) |= BIT(21);
1556   /*  Off controls for clock cleaner are taken from NPSS */
1557   ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) &= ~BIT(16);
1558 
1559   if (clkfreq > 10) {
1560     /* select input to High frequency RO */
1561     ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) |= BIT(13);
1562   } else {
1563     /*select input to Low frequency RO  */
1564     ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) &= ~BIT(13);
1565   }
1566   /* Enable the 50MHZ RO clock  */
1567   ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) |= BIT(21) | BIT(12);
1568   /*  powergate enable for calibration domain   */
1569   ULP_SPI_MEM_MAP(ULPCLKS_TRIM_SEL_REG_ADDR) = ENABLE_CALIB_DOMAIN;
1570   /* Mask the bits to write required frequency for High frequency RO clock */
1571   ULP_SPI_MEM_MAP(ULPCLKS_TRIM_SEL_REG_ADDR) &= (uint32_t)~0x3F;
1572   /*It writes that at what frequency the ROMhz need to be trim    */
1573   ULP_SPI_MEM_MAP(ULPCLKS_TRIM_SEL_REG_ADDR) |= clkfreq;
1574   /* Select the RO50M clock to calibrate */
1575   ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REG_ADDR) = SELECT_RO_CALIB;
1576   /* Waiting for calibration done indication */
1577   while (!(ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & BIT(20)))
1578     ;
1579   /* Reading calibrated trim value */
1580   ro50m_trim = ((ULP_SPI_MEM_MAP(ULPCLKS_CALIB_DONE_REG_ADDR) & TRIM_VALUE_BITS) >> 11);
1581   /*Mask the bits where the trim value need to write */
1582   ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) &= (uint32_t)~MASK_TRIM_VALUE_WRITE_BITS;
1583   /* Programming the calibrated trim to SPI register. */
1584   ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) |= (ro50m_trim << 14);
1585   /* pointing the trim select to SPI i.e write default values to that register */
1586   ULP_SPI_MEM_MAP(ULPCLKS_TRIM_SEL_REG_ADDR) = ULPCLKS_TRIM_SEL_REG_DEFAULT;
1587   /* CLK40M buffer circuit will be OFF */
1588   ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) &= ~BIT(21);
1589   /*  ON controls for clock cleaner are taken from NPSS */
1590   ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) |= BIT(16);
1591   /*  Disable the 50MHZ RO clock  */
1592   ULP_SPI_MEM_MAP(ULPCLKS_HF_RO_CLK_REG_OFFSET) &= ~BIT(21);
1593 
1594   return;
1595 }
1596 
1597 /*==============================================*/
1598 /**
1599  * @fn           uint32_t RSI_Clks_Calibration(INPUT_CLOCK_T inputclk, SLEEP_CLOCK_T sleep_clk_type)
1600  * @brief      This API is used for Clock Frequency measurement .
1601  * @param[in]    inputclk : Select the clock to be calibrated.
1602  *                          - /ref INPUT_CLOCK_T
1603  * @param[in]    sleep_clk_type : Select the type of Khz clock(RO,RC, XTAL) if it is sleep clock.
1604  *                          - /ref SLEEP_CLOCK_T
1605  * @return       Clock Frequency in Hz .
1606  */
1607 
RSI_Clks_Calibration(INPUT_CLOCK_T inputclk,SLEEP_CLOCK_T sleep_clk_type)1608 uint32_t RSI_Clks_Calibration(INPUT_CLOCK_T inputclk, SLEEP_CLOCK_T sleep_clk_type)
1609 {
1610   volatile uint32_t no_oftst_clk = 0;
1611 
1612   if (inputclk > 10) {
1613     return INVALID_PARAMETERS;
1614   }
1615 
1616   if (inputclk == sleep_clk) {
1617     if (sleep_clk_type == khz_rc_clk) {
1618       M4CLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = khz_rc_clk;
1619     }
1620     if (sleep_clk_type == khz_ro_clk) {
1621       M4CLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = khz_ro_clk;
1622     }
1623     if (sleep_clk_type == khz_xtal_clk) {
1624       M4CLK->CLK_CONFIG_REG4_b.SLEEP_CLK_SEL = khz_xtal_clk;
1625     }
1626   }
1627   /* Select the clock to be calibrated*/
1628   M4CLK->CLK_CALIB_CTRL_REG1_b.CC_CLKIN_SEL_b = inputclk;
1629   /* number of ref clock cycles to be considered for calibrating */
1630   M4CLK->CLK_CALIB_CTRL_REG2_b.CC_NUM_REF_CLKS = 39062;
1631   /* Start clock calibration */
1632   M4CLK->CLK_CALIB_CTRL_REG1_b.CC_START_b = 0x1;
1633   /* Wait until the clock calibration done */
1634   while (!M4CLK->CLK_CALIB_STS_REG1_b.CC_DONE_b)
1635     ;
1636 
1637   if ((M4CLK->CLK_CALIB_STS_REG1_b.CC_ERROR_b)) {
1638     M4CLK->CLK_CALIB_CTRL_REG1_b.CC_SOFT_RST_b = 0x1;
1639   }
1640 
1641   /*If cc_error is not set then the clock calibration is done. */
1642   if (!M4CLK->CLK_CALIB_STS_REG1_b.CC_ERROR_b) {
1643     /* number of test clock cycles occurred for the specified number
1644        of ref_clock cycles*/
1645     no_oftst_clk = M4CLK->CLK_CALIB_STS_REG2_b.CC_NUM_TEST_CLKS;
1646   }
1647 
1648   return no_oftst_clk;
1649 }
1650 
1651 /*==============================================*/
1652 /**
1653  * @fn          void RSI_IPMU_64KHZ_RCClktrim(void)
1654  * @brief       This API is used to trim the 64khz RC clock.
1655  * @return      none
1656  */
1657 
RSI_IPMU_64KHZ_RCClktrim(void)1658 void RSI_IPMU_64KHZ_RCClktrim(void)
1659 {
1660   uint32_t i;
1661   uint32_t status = 0;
1662 
1663   system_clocks.rc_32khz_clock = 64000;
1664 
1665   /*Enables RC clock and changes spi_trim select to 0*/
1666   ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_ADDR) = ENABLE_32KHZ_CLOCK_TRIM;
1667 
1668   /* Enable XTAL clock from NPSS */
1669   *(volatile uint32_t *)0x41300120 |= BIT(22);
1670 
1671   // Wait for 1ms using a delay loop
1672   for (i = 0; i < 10000; i++) {
1673     // Intentional empty loop body
1674   }
1675 
1676   /* Selects NPSS reference clock to be CLK-40M_SOC */
1677   ULP_SPI_MEM_MAP(ULPCLKS_REFCLK_REG_ADDR) = NPSS_REF_CLOCK_40MSOC;
1678 
1679   /* Select number of reference cycles to 625(No of clocks of high frequency clocks in 1 cycle of 16KHz clock Default value is 1250)*/
1680   ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REF_REG) = NUMBER_HIGH_FRQ_CLOCK;
1681 
1682   /* Pointing RC32KHz clock to NPSS_TESTMODE 0 */
1683   *(volatile uint32_t *)0x24048610 = BIT(25) | BIT(28);
1684 
1685   /*Configure NPSS_GPIO_0 in mode 6 */
1686   *(volatile uint32_t *)0x24048610 = 0x0000000E;
1687 
1688   /*Enable the low frequency clock calibration,enable the clock gate for npss ref clk and select the RC32K clock to calibrate */
1689   ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REG_ADDR) = LOW_FREQ_CLOCK_CAL;
1690 
1691   // Wait for 1us using a delay loop
1692   for (i = 0; i < 100; i++) {
1693     // Intentional empty loop body
1694   }
1695 
1696   /* wait till bit 21 becomes 1 Indicates calibration done indication*/
1697   while (!(ULP_SPI_MEM_MAP(0x30C) & BIT(21)))
1698     ;
1699 
1700   /* Calibrated trim value and write the calibrated trim into EFUSE */
1701   status = (ULP_SPI_MEM_MAP(0x30C) >> 4) & 0x7F;
1702   status = ((status << 14) | BIT(11));
1703   ULP_SPI_MEM_MAP(ULPCLKS_32KRC_CLK_REG_ADDR) |= status;
1704 
1705   /*Restore the original value of reference cycles once calibration is done */
1706   ULP_SPI_MEM_MAP(ULPCLKS_CALIB_REF_REG) = ORIGINAL_REF_VALUE_AFTER_CAL;
1707 }
1708