1 /*
2 * Copyright 2020-2023 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "fsl_upower.h"
8 #include "fsl_clock.h"
9
10 #ifdef FSL_RTOS_FREE_RTOS
11 #include "FreeRTOS.h"
12 #include "task.h"
13 #endif
14
15 /*******************************************************************************
16 * Definitions
17 ******************************************************************************/
18
19 /* Component ID definition, used by tools. */
20 #ifndef FSL_COMPONENT_ID
21 #define FSL_COMPONENT_ID "platform.drivers.upower"
22 #endif
23
24 #if (defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE & 0x2))
25 #define POWERSYS_MUA_RTD_BASE (0x38029000u)
26 #else
27 #define POWERSYS_MUA_RTD_BASE (0x28029000u)
28 #endif
29
30 #define POWERSYS_MUA_RTD ((MU_Type *)(POWERSYS_MUA_RTD_BASE))
31
32 #define UPOWER_MU ((struct MU_tag *)(POWERSYS_MUA_RTD_BASE))
33
34 #define PMIC_CONFIG_TAG 0x706D6963 /* Magic number for uPower PMIC driver identify */
35 #define PMIC_CONFIG_REG_ARRAY_SIZE 8 /* PMIC register access block array size */
36
37 /*******************************************************************************
38 * Variables
39 ******************************************************************************/
40 static upwr_isr_callb s_muTxRxHandler;
41 static upwr_isr_callb s_muNmiHandler;
42
43 static volatile bool callbackStatus = false;
44
45 /* BUCK2 BUCK3 DVS0 output voltage from 0.60V to 2.1875 V in 12.5 mV steps */
46 static double buck2_buck3_output_voltage_array[BUCK_OUTPUT_TABLE_SIZE] = {0.0};
47 /*******************************************************************************
48 * Prototypes
49 ******************************************************************************/
50 /* upower pmic register access block. */
51 struct pmic_reg_addr_data
52 {
53 uint32_t reg; /* the target configured register of PMIC IC */
54 uint32_t data; /* the value of the target configured register */
55 };
56
57 /* upower pmic configuration. */
58 struct pmic_config_struct
59 {
60 uint32_t cfg_tag; /* cfg_tag = PMIC_CONFIG_TAG, used to judge if the config data are valid */
61 uint32_t cfg_reg_size; /* how many registers shall be configured */
62 struct pmic_reg_addr_data reg_addr_data_array[PMIC_CONFIG_REG_ARRAY_SIZE];
63 };
64
65 /*******************************************************************************
66 * Code
67 ******************************************************************************/
uPower_IRQHandler(void)68 void uPower_IRQHandler(void)
69 {
70 if ((POWERSYS_MUA_RTD->CSSR0 & MU_CSSR0_NMIC_MASK) != 0U)
71 {
72 /* Clear NMI */
73 POWERSYS_MUA_RTD->CSSR0 = MU_CSSR0_NMIC_MASK;
74 if (s_muNmiHandler != NULL)
75 {
76 s_muNmiHandler();
77 }
78 else
79 {
80 }
81 }
82 else
83 {
84 assert(s_muTxRxHandler);
85 s_muTxRxHandler();
86 }
87 }
88
UPOWER_DummyInstallISR(upwr_isr_callb txrx,upwr_isr_callb excp)89 static void UPOWER_DummyInstallISR(upwr_isr_callb txrx, upwr_isr_callb excp)
90 {
91 s_muTxRxHandler = txrx;
92 s_muNmiHandler = excp;
93 }
94
UPOWER_LockMuInt(int lock)95 static void UPOWER_LockMuInt(int lock)
96 {
97 if (lock != 0)
98 {
99 NVIC_DisableIRQ(uPower_IRQn);
100 }
101 else
102 {
103 NVIC_EnableIRQ(uPower_IRQn);
104 }
105 }
106
UPOWER_Ready(uint32_t soc,uint32_t vmajor,uint32_t vminor)107 static void UPOWER_Ready(uint32_t soc, uint32_t vmajor, uint32_t vminor)
108 {
109 callbackStatus = true;
110
111 (void)soc;
112 (void)vmajor;
113 (void)vminor;
114 }
115
UPOWER_Callback(upwr_sg_t sg,uint32_t func,upwr_resp_t errCode,int ret)116 static void UPOWER_Callback(upwr_sg_t sg, uint32_t func, upwr_resp_t errCode, int ret)
117 {
118 callbackStatus = true;
119 }
120
121 /*!
122 * @brief Check status of current request to uPower.
123 *
124 * Will block till related callback function has been called
125 *
126 * @sg Indicate which Service Group that request point to
127 * Note: It is replaced by UPOWER_CheckReqWithArgs, pls don't use the api.
128 */
UPOWER_CheckReq(upwr_sg_t sg)129 void UPOWER_CheckReq(upwr_sg_t sg)
130 {
131 upwr_req_status_t reqStatus;
132 upwr_resp_t rsp = UPWR_RESP_COUNT;
133 int ret = -1;
134
135 /* wait callback */
136 while (!callbackStatus)
137 {
138 }
139
140 callbackStatus = false;
141
142 /* Get reply from upower */
143 reqStatus = upwr_poll_req_status(sg, NULL, &rsp, &ret, 0U);
144 if (reqStatus != UPWR_REQ_OK)
145 {
146 assert(false);
147 }
148 }
149
150 /*!
151 * @brief Check status of current request to uPower.
152 *
153 * Will block till related callback function has been called
154 *
155 * @sg Indicate which Service Group that request point to
156 * @sgfptr: pointer to the variable that will hold the function id of the last request completed
157 * @errptr: pointer to the variable that will hold the error code
158 * @retptr: pointer to the variable that will hold the value returned by the last request completed (invalid if the last
159 * request completed didn't return any value)
160 * @attempts: maximum number of polling attempts; if attempts > 0 and is reached with no service response received,
161 * upwr_poll_req_status returns UPWR_REQ_BUSY and variables pointed by sgfptr, retptr and errptr are not updated; if
162 * attempts = 0, upwr_poll_req_status waits "forever".
163 */
UPOWER_CheckReqWithArgs(upwr_sg_t sg,uint32_t * sgfptr,upwr_resp_t * errptr,int * retptr,uint32_t attempts)164 void UPOWER_CheckReqWithArgs(upwr_sg_t sg, uint32_t *sgfptr, upwr_resp_t *errptr, int *retptr, uint32_t attempts)
165 {
166 upwr_req_status_t reqStatus;
167
168 /* wait callback */
169 while (!callbackStatus)
170 {
171 }
172
173 callbackStatus = false;
174
175 /* Get reply from upower */
176 reqStatus = upwr_poll_req_status(sg, sgfptr, errptr, retptr, attempts);
177 if (reqStatus != UPWR_REQ_OK)
178 {
179 assert(false);
180 }
181 }
182
183 /*!
184 * @brief Initialize MU interface for uPower access.
185 *
186 * @param pVersion Pointer to the structure to save uPower ROM and RAM versions
187 */
UPOWER_Init(upower_version_t * pVersion)188 void UPOWER_Init(upower_version_t *pVersion)
189 {
190 int status;
191 uint32_t soc;
192 uint32_t major, minor, fixes;
193 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
194 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
195 int ret = -1; /* the value returned by the last request completed */
196
197 CLOCK_EnableClock(kCLOCK_UpowerMuARtd);
198
199 status = upwr_init(RTD_DOMAIN, UPOWER_MU, NULL, NULL, UPOWER_DummyInstallISR, UPOWER_LockMuInt);
200 if (status != 0)
201 {
202 assert(false);
203 }
204
205 NVIC_EnableIRQ(uPower_IRQn); /* fix lost upower interrupt issue(The api will enable upower interrupt and do memory
206 barrier operation dsb, isb) */
207
208 soc = upwr_rom_version(&major, &minor, &fixes);
209 if (soc == 0U)
210 {
211 assert(false);
212 }
213
214 if (pVersion != NULL)
215 {
216 pVersion->romMajor = major;
217 pVersion->romMinor = minor;
218 pVersion->romFixes = fixes;
219 }
220
221 status = upwr_start(1U, UPOWER_Ready);
222 if (status != 0)
223 {
224 assert(false);
225 }
226
227 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
228 assert(err == UPWR_RESP_OK);
229
230 major = upwr_ram_version(&minor, &fixes);
231
232 if (pVersion != NULL)
233 {
234 pVersion->ramMajor = major;
235 pVersion->ramMinor = minor;
236 pVersion->ramFixes = fixes;
237 }
238 }
239
240 /*!
241 * @brief Deinitialize MU interface for Sentinel access.
242 */
UPOWER_Deinit(void)243 void UPOWER_Deinit(void)
244 {
245 NVIC_DisableIRQ(uPower_IRQn);
246 }
247
248 /*!
249 * @brief Power on certain domain without reset.
250 *
251 * @param domain Target domain to power on.
252 * @return 0 if ok, failure otherwise.
253 */
UPOWER_PowerOnDomain(soc_domain_t domain)254 int UPOWER_PowerOnDomain(soc_domain_t domain)
255 {
256 int status;
257 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
258 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
259 int ret = -1; /* the value returned by the last request completed */
260
261 status = upwr_pwm_dom_power_on(domain, 0, UPOWER_Callback);
262 if (status == 0)
263 {
264 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
265 assert(err == UPWR_RESP_OK);
266 }
267
268 return status;
269 }
270
271 /*!
272 * @brief Reset and kick off certain domain.
273 *
274 * @param domain Target domain to boot.
275 * @return 0 if ok, failure otherwise.
276 */
UPOWER_BootDomain(soc_domain_t domain)277 int UPOWER_BootDomain(soc_domain_t domain)
278 {
279 int status;
280 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
281 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
282 int ret = -1; /* the value returned by the last request completed */
283
284 status = upwr_pwm_boot_start(domain, UPOWER_Callback);
285 if (status == 0)
286 {
287 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
288 assert(err == UPWR_RESP_OK);
289 }
290
291 return status;
292 }
293
294 /*!
295 * @brief Power on power switches.
296 *
297 * @param mask Bits to define which switch should be turned on. The value should be ORed by @ref upower_ps_mask_t.
298 * Bit value 1 means the switch is to be powered on; Value 0 means the switch keeps unchanged.
299 * @return 0 if ok, failure otherwise.
300 */
UPOWER_PowerOnSwitches(upower_ps_mask_t mask)301 int UPOWER_PowerOnSwitches(upower_ps_mask_t mask)
302 {
303 int status;
304 uint32_t switches = (uint32_t)mask;
305 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
306 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
307 int ret = -1; /* the value returned by the last request completed */
308
309 status = upwr_pwm_power_on(&switches, NULL, UPOWER_Callback);
310 if (status == 0)
311 {
312 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
313 assert(err == UPWR_RESP_OK);
314 }
315
316 return status;
317 }
318
319 /*!
320 * @brief Power off power switches.
321 *
322 * @param mask Bits to define which switch should be turned off. The value should be ORed by @ref upower_ps_mask_t.
323 * Bit value 1 means the switch is to be powered off; Value 0 means the switch keeps unchanged.
324 * @return 0 if ok, failure otherwise.
325 */
UPOWER_PowerOffSwitches(upower_ps_mask_t mask)326 int UPOWER_PowerOffSwitches(upower_ps_mask_t mask)
327 {
328 int status;
329 uint32_t switches = (uint32_t)mask;
330 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
331 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
332 int ret = -1; /* the value returned by the last request completed */
333
334 status = upwr_pwm_power_off(&switches, NULL, UPOWER_Callback);
335 if (status == 0)
336 {
337 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
338 assert(err == UPWR_RESP_OK);
339 }
340
341 return status;
342 }
343
344 /*!
345 * @brief Power on memory partitions array/periphery logic. If a memory is requested to turn on, but the
346 * power switch that feeds that memory is not, the power switch will be turned on automatically.
347 *
348 * The parameter mask bits define which memory partition should be turned on. The value should be ORed by
349 * upower_mp0_mask_t or upower_mp1_mask_t. Mask bit value 1 means the switch is to be powered on; Value 0
350 * means the switch keeps unchanged.
351 *
352 * @param mask0 memory partition group 0 mask, see @ref upower_mp0_mask_t.
353 * @param mask1 memory partition group 1 mask, see @ref upower_mp1_mask_t.
354 * @return 0 if ok, failure otherwise.
355 */
UPOWER_PowerOnMemPart(uint32_t mask0,uint32_t mask1)356 int UPOWER_PowerOnMemPart(uint32_t mask0, uint32_t mask1)
357 {
358 int status;
359 uint32_t mem[2] = {mask0, mask1};
360 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
361 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
362 int ret = -1; /* the value returned by the last request completed */
363
364 status = upwr_pwm_power_on(NULL, mem, UPOWER_Callback);
365 if (status == 0)
366 {
367 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
368 assert(err == UPWR_RESP_OK);
369 }
370
371 return status;
372 }
373
374 /*!
375 * @brief Power off memory partitions array/periphery logic.
376 *
377 * The parameter mask bits define which memory partition should be turned off. The value should be ORed by
378 * upower_mp0_mask_t and upower_mp1_mask_t. Mask bit value 1 means the switch is to be powered off; Value 0
379 * means the switch keeps unchanged.
380 *
381 * @param mask0 memory partition group 0 mask, see @ref upower_mp0_mask_t.
382 * @param mask1 memory partition group 1 mask, see @ref upower_mp1_mask_t.
383 * @return 0 if ok, failure otherwise.
384 */
UPOWER_PowerOffMemPart(uint32_t mask0,uint32_t mask1)385 int UPOWER_PowerOffMemPart(uint32_t mask0, uint32_t mask1)
386 {
387 int status;
388 uint32_t mem[2] = {mask0, mask1};
389 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
390 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
391 int ret = -1; /* the value returned by the last request completed */
392
393 status = upwr_pwm_power_off(NULL, mem, UPOWER_Callback);
394 if (status == 0)
395 {
396 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
397 assert(err == UPWR_RESP_OK);
398 }
399
400 return status;
401 }
402
403 /*!
404 * @brief Power on memory partitions array logic and power off its periphery logic. If a memory array is
405 * requested to turn on, but the power switch that feeds that memory is not, the power switch will be turned
406 * on automatically.
407 *
408 * The parameter mask bits define which memory partition should be turned on. The value should be ORed by
409 * upower_mp0_mask_t or upower_mp1_mask_t. Mask bit value 1 means the switch is to be powered on; Value 0
410 * means the switch keeps unchanged.
411 *
412 * @param mask0 memory partition group 0 mask, see @ref upower_mp0_mask_t.
413 * @param mask1 memory partition group 1 mask, see @ref upower_mp1_mask_t.
414 * @return 0 if ok, failure otherwise.
415 */
UPOWER_RetainMemPart(uint32_t mask0,uint32_t mask1)416 int UPOWER_RetainMemPart(uint32_t mask0, uint32_t mask1)
417 {
418 int status;
419 uint32_t mem[2] = {mask0, mask1};
420 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
421 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
422 int ret = -1; /* the value returned by the last request completed */
423
424 status = upwr_pwm_mem_retain(mem, UPOWER_Callback);
425 if (status == 0)
426 {
427 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
428 assert(err == UPWR_RESP_OK);
429 }
430
431 return status;
432 }
433
434 /*!
435 * @brief M33 call this API to inform uPower, M33 is using ddr.
436 *
437 * @param use_ddr not 0, true, means that RTD is using ddr. 0, false, means that, RTD is not using ddr.
438 * @return 0 if ok, failure otherwise(-1 if service group is busy, -3 if called in an invalid API state).
439 */
UPOWER_SetRtdUseDdr(bool use_ddr)440 int UPOWER_SetRtdUseDdr(bool use_ddr)
441 {
442 int status;
443 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
444 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
445 int ret = -1; /* the value returned by the last request completed */
446
447 status = upwr_xcp_set_rtd_use_ddr(RTD_DOMAIN, (uint32_t)use_ddr, UPOWER_Callback);
448 if (status == 0)
449 {
450 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
451 assert(err == UPWR_RESP_OK);
452 }
453
454 return status;
455 }
456 /*!
457 * @brief M33 call this API to Power On Application Domain when Application Domain is in Power Down/Deep Power Down
458 * mode. After upower get the msg, upower write a flag to registers according to msg. Then upower will get a WUU1
459 * interrupt request and upower change Power Down mode/Deep Power mode to Active mode when Application Domain is in
460 * Power Down/Deep Power Down mode.
461 *
462 * @return 0 if ok, failure otherwise.
463 */
UPOWER_PowerOnADInPDMode(void)464 int UPOWER_PowerOnADInPDMode(void)
465 {
466 int status;
467 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
468 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
469 int ret = -1; /* the value returned by the last request completed */
470
471 status = upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, (uint32_t)true, UPOWER_Callback);
472 if (status == 0)
473 {
474 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
475 assert(err == UPWR_RESP_OK);
476 }
477
478 return status;
479 }
480
481 /*!
482 * @brief Set SG PowerManagement parameters of uPower.
483 *
484 * Please see upower_soc_defs.h file for struct upwr_pwm_param_t
485 *
486 * @param pcfg_in User's selection for PowerManagement parameter of uPower
487 * @return 0 if ok, failure otherwise.
488 */
UPOWER_SetPwrMgmtParam(upwr_pwm_param_t * pcfg_in)489 int UPOWER_SetPwrMgmtParam(upwr_pwm_param_t *pcfg_in)
490 {
491 int status;
492 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
493 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
494 int ret = -1; /* the value returned by the last request completed */
495
496 assert(pcfg_in);
497 status = upwr_pwm_param(pcfg_in, UPOWER_Callback);
498 if (status == 0)
499 {
500 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0);
501 assert(err == UPWR_RESP_OK);
502 }
503
504 return status;
505 }
506
507 /*!
508 * @brief Reduce Buck2 and Buck3 voltage in STANDBY mode.
509 *
510 * @return 0 if ok, failure otherwise.
511 */
UPOWER_ReduceBuck23VoltInSTBY(void)512 int UPOWER_ReduceBuck23VoltInSTBY(void)
513 {
514 int status;
515 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
516 upwr_resp_t err_code = UPWR_RESP_COUNT; /* the error code */
517 int ret = -1; /* the value returned by the last request completed */
518
519 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x14, 0x7A, UPOWER_Callback);
520 if (status == 0)
521 {
522 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
523 assert(err_code == UPWR_RESP_OK);
524 }
525 else
526 {
527 goto err;
528 }
529
530 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x13, 0x50, UPOWER_Callback);
531 if (status == 0)
532 {
533 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
534 assert(err_code == UPWR_RESP_OK);
535 }
536 else
537 {
538 goto err;
539 }
540
541 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x4E, 0x5C, UPOWER_Callback);
542 if (status == 0)
543 {
544 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
545 assert(err_code == UPWR_RESP_OK);
546 }
547 else
548 {
549 goto err;
550 }
551
552 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x20, 0x04, UPOWER_Callback);
553 if (status == 0)
554 {
555 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
556 assert(err_code == UPWR_RESP_OK);
557 }
558 else
559 {
560 goto err;
561 }
562
563 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x1D, 0x04, UPOWER_Callback);
564 if (status == 0)
565 {
566 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
567 assert(err_code == UPWR_RESP_OK);
568 }
569 else
570 {
571 goto err;
572 }
573
574 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x4E, 0x5C, UPOWER_Callback);
575 if (status == 0)
576 {
577 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
578 assert(err_code == UPWR_RESP_OK);
579 }
580 else
581 {
582 goto err;
583 }
584
585 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x2D, 0x04, UPOWER_Callback);
586 if (status == 0)
587 {
588 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
589 assert(err_code == UPWR_RESP_OK);
590 }
591 else
592 {
593 goto err;
594 }
595
596 status = upwr_xcp_i2c_access(0x32, 1, 1, 0x2A, 0x04, UPOWER_Callback);
597 if (status == 0)
598 {
599 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err_code, &ret, 0);
600 assert(err_code == UPWR_RESP_OK);
601 }
602
603 err:
604 return status;
605 }
606
607 /*!
608 * @brief Set DDR retention control bit.
609 *
610 * @param domain Target domain to power on.
611 * @param enable true means set ddr retention, false means clear ddr retention.
612 * @return 0 if ok, failure otherwise.
613 */
UPOWER_SetDDRRetention(soc_domain_t domain,bool enable)614 int UPOWER_SetDDRRetention(soc_domain_t domain, bool enable)
615 {
616 int status;
617 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
618 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
619 int ret = -1; /* the value returned by the last request completed */
620
621 status = upwr_xcp_set_ddr_retention(domain, (uint32_t)enable, UPOWER_Callback);
622 if (status == 0)
623 {
624 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
625 assert(err == UPWR_RESP_OK);
626 }
627
628 return status;
629 }
630
631 /*
632 * @brief change PMIC voltage.
633 *
634 * @return 0 if ok, failure otherwise.
635 */
UPOWER_ChngPmicVoltage(uint32_t rail,int voltage)636 int UPOWER_ChngPmicVoltage(uint32_t rail, int voltage)
637 {
638 int status = -1;
639 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
640 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
641 int ret = -1; /* the value returned by the last request completed */
642
643 status = upwr_vtm_chng_pmic_voltage(rail, (uint32_t)voltage, UPOWER_Callback);
644 if (status == 0)
645 {
646 UPOWER_CheckReqWithArgs(UPWR_SG_VOLTM, &sgf, &err, &ret, 0);
647 assert(err == UPWR_RESP_OK);
648 }
649
650 return status;
651 }
652
653 /*!
654 * @brief Control LDO1 power supply.
655 *
656 * @param enable true means turn on power supply, false means off.
657 * @return 0 if ok, failure otherwise.
658 */
UPOWER_SetLDO1Power(bool enable)659 int UPOWER_SetLDO1Power(bool enable)
660 {
661 uint32_t size;
662 int status;
663 struct pmic_config_struct pmic_config_struct_data;
664 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
665 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
666 int ret = -1; /* the value returned by the last request completed */
667
668 pmic_config_struct_data.cfg_tag = PMIC_CONFIG_TAG;
669 pmic_config_struct_data.cfg_reg_size = 1;
670
671 pmic_config_struct_data.reg_addr_data_array[0].reg = 0x30;
672
673 if (enable)
674 {
675 /* Set LDO1 power to 1.1000V, according to PCA9460 */
676 pmic_config_struct_data.reg_addr_data_array[0].data = 0x9d;
677 }
678 else
679 {
680 /* Set LDO1 power to 0V, according to PCA9460 */
681 pmic_config_struct_data.reg_addr_data_array[0].data = 0x9c;
682 }
683
684 size = sizeof(pmic_config_struct_data.cfg_tag) + sizeof(pmic_config_struct_data.cfg_reg_size) +
685 pmic_config_struct_data.cfg_reg_size * (sizeof(uint32_t) + sizeof(uint32_t));
686
687 status = upwr_vtm_pmic_config((void *)&pmic_config_struct_data, size, UPOWER_Callback);
688 if (status == 0)
689 {
690 UPOWER_CheckReqWithArgs(UPWR_SG_VOLTM, &sgf, &err, &ret, 0);
691 assert(err == UPWR_RESP_OK);
692 }
693
694 return status;
695 }
696
697 /*!
698 * @brief Control Buck3 power supply.
699 *
700 * @param enable true means turn on power supply, false means off.
701 * @return 0 if ok, failure otherwise.
702 */
UPOWER_SetBuck3Power(bool enable)703 int UPOWER_SetBuck3Power(bool enable)
704 {
705 uint32_t size;
706 int status;
707 struct pmic_config_struct pmic_config_struct_data;
708 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
709 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
710 int ret = -1; /* the value returned by the last request completed */
711
712 pmic_config_struct_data.cfg_tag = PMIC_CONFIG_TAG;
713 pmic_config_struct_data.cfg_reg_size = 1;
714
715 pmic_config_struct_data.reg_addr_data_array[0].reg = 0x22;
716
717 if (enable)
718 {
719 /* Set BUCK3 power to 1.1000V, according to PCA9460 */
720 pmic_config_struct_data.reg_addr_data_array[0].data = 0x28;
721 }
722 else
723 {
724 /* Set BUCK3 power to 0.7375V, according to PCA9460 */
725 pmic_config_struct_data.reg_addr_data_array[0].data = 0xb;
726 }
727
728 size = sizeof(pmic_config_struct_data.cfg_tag) + sizeof(pmic_config_struct_data.cfg_reg_size) +
729 pmic_config_struct_data.cfg_reg_size * (sizeof(uint32_t) + sizeof(uint32_t));
730
731 status = upwr_vtm_pmic_config((void *)&pmic_config_struct_data, size, UPOWER_Callback);
732 if (status == 0)
733 {
734 UPOWER_CheckReqWithArgs(UPWR_SG_VOLTM, &sgf, &err, &ret, 0);
735 assert(err == UPWR_RESP_OK);
736 }
737
738 return status;
739 }
740
741 /*!
742 * @brief Write PMIC registers by I2C.
743 *
744 * @param reg_addr means pmic ic target address.
745 * @param reg_val means write data, specific data can be found in PCA9460.
746 * @return 0 if ok, failure otherwise.
747 */
UPOWER_SetPmicReg(uint32_t reg_addr,uint32_t reg_val)748 int UPOWER_SetPmicReg(uint32_t reg_addr, uint32_t reg_val)
749 {
750 int status;
751 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
752 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
753 int ret = -1; /* the value returned by the last request completed */
754
755 status = upwr_xcp_i2c_access(PMIC_I2C_ADDR, PMIC_WRITE_DATA_SIZE, PMIC_IC_WRITE_DATA_SIZE, reg_addr, reg_val,
756 UPOWER_Callback);
757
758 if (status == 0)
759 {
760 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
761 assert(err == UPWR_RESP_OK);
762 }
763
764 return status;
765 }
766
767 /*!
768 * @brief Read PMIC registers by I2C.
769 *
770 * @param reg_addr means pmic ic pca9460 target address.
771 * @param reg_val means value of register.
772 * @return 0 if ok, failure otherwise.
773 */
UPOWER_ReadPmicReg(uint32_t reg_addr,uint8_t * reg_val)774 int UPOWER_ReadPmicReg(uint32_t reg_addr, uint8_t *reg_val)
775 {
776 int status;
777 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
778 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
779 int ret = -1; /* the value returned by the last request completed */
780
781 status =
782 upwr_xcp_i2c_access(PMIC_I2C_ADDR, PMIC_READ_DATA_SIZE, PMIC_IC_READ_DATA_SIZE, reg_addr, 0, UPOWER_Callback);
783
784 if (status == 0)
785 {
786 UPOWER_CheckReqWithArgs(UPWR_SG_EXCEPT, &sgf, &err, &ret, 0);
787 assert(err == UPWR_RESP_OK);
788 }
789
790 *reg_val = (uint8_t)ret;
791
792 return status;
793 }
794
795 /*!
796 * @brief Init BUCK2 BUCK3 output voltage table.
797 */
UPOWER_InitBuck2Buck3Table(void)798 void UPOWER_InitBuck2Buck3Table(void)
799 {
800 int i;
801
802 buck2_buck3_output_voltage_array[0] = 0.6000;
803 for (i = 0; i < BUCK_OUTPUT_TABLE_SIZE; i++)
804 {
805 buck2_buck3_output_voltage_array[i] += BUCK2_BUCK3_VOLTAGE_STEPS;
806 }
807 }
808
809 /*
810 * @brief get PMIC voltage.
811 *
812 * @return 0 if ok, failure otherwise.
813 */
UPOWER_GetPmicVoltage(uint32_t rail,int * voltage)814 int UPOWER_GetPmicVoltage(uint32_t rail, int *voltage)
815 {
816 int status = -1;
817 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
818 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
819
820 status = upwr_vtm_get_pmic_voltage(rail, UPOWER_Callback);
821 if (status == 0)
822 {
823 UPOWER_CheckReqWithArgs(UPWR_SG_VOLTM, &sgf, &err, voltage, 0U);
824 assert(err == UPWR_RESP_OK);
825 }
826
827 return status;
828 }
829
830 /*!
831 * @brief Change Bias Configuration(biasing options: NBB, RBB, ARBB, AFBB; Bias Voltage) for RTD Domain
832 *
833 * @param drive_mode Drive Mode: UD, ND, OD.
834 * @return 0 if ok, failure otherwise.
835 */
UPOWER_ChngRTDDomBias(drive_mode_e drive_mode)836 int UPOWER_ChngRTDDomBias(drive_mode_e drive_mode)
837 {
838 // clang-format off
839 /*
840 * +---------------------------------------------------------------------------------------------------------------------------------------+
841 * | RTD Power Mode | Biasing Option | Drive Mode | Max CM33_CORECLK freq/MHz | Max CM33_BUSCLK freq/MHz | Max CM33_SLOWCLK freq/MHz |
842 * -----------------------------------------------------------------------------------------------------------------------------------------
843 * | ACTIVE | ARBB | UD | 38.4 | 20 | 12.5 |
844 * -----------------------------------------------------------------------------------------------------------------------------------------
845 * | ACTIVE } AFBB | ND | 160 | 65 | 20 |
846 * -----------------------------------------------------------------------------------------------------------------------------------------
847 * | ACTIVE | AFBB | OD | 216 | 108 | 24 |
848 * +---------------------------------------------------------------------------------------------------------------------------------------+
849 *
850 */
851 // clang-format on
852
853 uint32_t sgf = 0xFFFFFFFFU; /* the function id of the last request completed*/
854 upwr_resp_t err = UPWR_RESP_COUNT; /* the error code */
855 int ret = -1; /* the value returned by the last request completed */
856 struct upwr_dom_bias_cfg_t *bias = NULL;
857 struct upwr_dom_bias_cfg_t ud_bias = {
858 .apply = BIAS_APPLY_RTD, /* apply to RTD only */
859 .dommode = ARBB_BIAS_MODE,
860 .dombias = {
861 .rbbn = 1300, /* 1300 mV */
862 .rbbp = 1300, /* 1300 mV */
863 },
864 };
865 struct upwr_dom_bias_cfg_t nd_bias = {
866 .apply = BIAS_APPLY_RTD, /* apply to RTD only */
867 .dommode = AFBB_BIAS_MODE,
868 .dombias = {
869 .rbbn = 100, /* 100 mV */
870 .rbbp = 100, /* 100 mV */
871 },
872 };
873 struct upwr_dom_bias_cfg_t od_bias = {
874 .apply = BIAS_APPLY_RTD, /* apply to RTD only */
875 .dommode = AFBB_BIAS_MODE,
876 .dombias = {
877 .rbbn = 100, /* 100 mV */
878 .rbbp = 100, /* 100 mV */
879 },
880 };
881 int status;
882
883 switch (drive_mode)
884 {
885 case DRIVE_MODE_UD:
886 bias = &ud_bias;
887 break;
888 case DRIVE_MODE_ND:
889 bias = &nd_bias;
890 break;
891 case DRIVE_MODE_OD:
892 bias = &od_bias;
893 break;
894 default:
895 break;
896 }
897 status = upwr_pwm_chng_dom_bias(bias, UPOWER_Callback);
898 if (status == 0)
899 {
900 UPOWER_CheckReqWithArgs(UPWR_SG_PWRMGMT, &sgf, &err, &ret, 0U);
901 assert(err == UPWR_RESP_OK);
902 }
903
904 return status;
905 }
906