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