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