1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3 * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4 */
5
6 #include "hal_base.h"
7 #include <hal_bsp.h>
8
9 #if defined(RKMCU_RK2108)
10
11 /** @addtogroup RK_HAL_Driver
12 * @{
13 */
14
15 /** @addtogroup PM
16 * @{
17 */
18
19 /** @defgroup PM_How_To_Use How To Use
20 * @{
21
22 The PM driver can be used as follows:
23
24 - Invoke HAL_SYS_Suspend() when system will enter suspend.
25
26 @} */
27
28 /** @defgroup PM_Private_Definition Private Definition
29 * @{
30 */
31
32 /********************* Private MACRO Definition ******************************/
33
34 /* for pm_runtime */
35 #define SLEEP_INPUT_RATE 32000
36 #define EXPONENT_OF_FRAC_PLL 24
37 #define RK_PLL_MODE_SLOW 0
38 #define RK_PLL_MODE_NORMAL 1
39 #define RK_PLL_MODE_DEEP 2
40
41 #define PLL_POSTDIV1_SHIFT 12
42 #define PLL_POSTDIV1_MASK 0x7 << PLL_POSTDIV1_SHIFT
43 #define PLL_POSTDIV2_SHIFT 6
44 #define PLL_POSTDIV2_MASK 0x7 << PLL_POSTDIV2_SHIFT
45
46 #define PLL_GET_POSTDIV1(x) \
47 (((uint32_t)(x) & (PLL_POSTDIV1_MASK)) >> PLL_POSTDIV1_SHIFT)
48 #define PLL_GET_POSTDIV2(x) \
49 (((uint32_t)(x) & (PLL_POSTDIV2_MASK)) >> PLL_POSTDIV2_SHIFT)
50 #define UART_CLK_GET_MUX(clk) HAL_CRU_ClkGetMux(CLK_GET_MUX((clk)))
51 #define GPLL_RUNTIME_RATE (PLL_INPUT_OSC_RATE * 2)
52
53 #define PVTM_KHZ (1000)
54 #define PVTM_CALC_CNT_KHZ (PLL_INPUT_OSC_RATE / PVTM_KHZ)
55 #define PVTM_TARGET_KHZ (32)
56 #define PVTM_CALC_CNT 0x200
57
58 #define SLEEP_COUNT_TO_MS(ms) (ms * SLEEP_INPUT_RATE / 1000)
59 /********************* Private Structure Definition **************************/
60 struct UART_REG_SAVE {
61 uint32_t DLL;
62 uint32_t DLH;
63 uint32_t IER;
64 uint32_t LCR;
65 uint32_t MCR;
66 };
67 /********************* Private Variable Definition ***************************/
68 HAL_UNUSED static uint64_t pmTimerLastCount;
69 HAL_UNUSED static uint64_t pmTimerLowCount;
70 HAL_UNUSED static uint32_t pmIRQPendingFlag;
71
72 #if defined(HAL_PM_RUNTIME_MODULE_ENABLED) || defined(HAL_PM_SLEEP_MODULE_ENABLED)
73 static uint8_t pvtm32kEn = 0;
74 #endif
75 /********************* Private Function Definition ***************************/
76 #if defined(HAL_PM_RUNTIME_MODULE_ENABLED) || defined(HAL_PM_SLEEP_MODULE_ENABLED)
PVTM_ClkEnable(void)77 static void PVTM_ClkEnable(void)
78 {
79 struct GRF_REG *pGrf = GRF;
80
81 pGrf->PVTM_CON0 = VAL_MASK_WE(GRF_PVTM_CON0_PVTM_OSC_EN_MASK,
82 GRF_PVTM_CON0_PVTM_OSC_EN_MASK);
83 }
84
PVTM_ClkDisable(void)85 static void PVTM_ClkDisable(void)
86 {
87 struct GRF_REG *pGrf = GRF;
88
89 pGrf->PVTM_CON0 = VAL_MASK_WE(GRF_PVTM_CON0_PVTM_OSC_EN_MASK,
90 0);
91 }
92
PVTM_ClkRateConfig(uint32_t khz)93 static void PVTM_ClkRateConfig(uint32_t khz)
94 {
95 uint32_t pvtm_freq_khz, pvtm_div;
96 struct GRF_REG *pGrf = GRF;
97
98 pGrf->PVTM_CON0 = 0xffff0000;
99 PVTM_ClkEnable();
100
101 pGrf->PVTM_CON1 = PVTM_CALC_CNT;
102
103 pGrf->PVTM_CON0 = VAL_MASK_WE(GRF_PVTM_CON0_PVTM_START_MASK,
104 GRF_PVTM_CON0_PVTM_START_MASK);
105
106 /* pmugrf_pvtm_st0 will be clear after PVTM start,
107 * which will cost about 6 cycles of pvtm at least.
108 * So we wait 30 cycles of pvtm for security.
109 */
110 while (pGrf->PVTM_STATUS1 < 30) {
111 ;
112 }
113 while (!(pGrf->PVTM_STATUS0 & GRF_PVTM_STATUS0_PVTM_FREQ_DONE_MASK)) {
114 ;
115 }
116
117 pvtm_freq_khz =
118 ((pGrf->PVTM_STATUS1) * PVTM_CALC_CNT_KHZ + PVTM_CALC_CNT / 2) / PVTM_CALC_CNT;
119 pvtm_div = (pvtm_freq_khz + khz / 2) / khz;
120
121 if (pvtm_div > 0xfff) {
122 pvtm_div = 0xfff;
123 }
124
125 pGrf->PVTM_CON0 = VAL_MASK_WE(GRF_PVTM_CON0_PVTM_START_MASK,
126 0);
127 pGrf->PVTM_CON0 = VAL_MASK_WE(GRF_PVTM_CON0_PVTM_CLKOUT_DIV_MASK,
128 pvtm_div << GRF_PVTM_CON0_PVTM_CLKOUT_DIV_SHIFT);
129 }
130 #endif
131
132 #ifdef HAL_PM_RUNTIME_MODULE_ENABLED
PM_GetPllPostDivEven(uint32_t rateIn,uint32_t rateOut,uint32_t * postDiv1,uint32_t * postDiv2)133 static uint32_t PM_GetPllPostDivEven(uint32_t rateIn, uint32_t rateOut, uint32_t *postDiv1, uint32_t *postDiv2)
134 {
135 uint32_t div1, div2, div;
136
137 div = rateIn / rateOut;
138 if (div < 7) {
139 *postDiv1 = div;
140 *postDiv2 = 1;
141
142 return 0;
143 }
144
145 for (div2 = 2; div2 <= 6;) {
146 div1 = div / div2;
147 if (div1 <= 7) {
148 break;
149 }
150 div2 += 2;
151 }
152 if (div1 < div2) {
153 return 2;
154 }
155
156 *postDiv1 = div1;
157 *postDiv2 = div2;
158
159 if ((div1 * div2) != div) {
160 return 1;
161 } else {
162 return 0;
163 }
164 }
165
PM_CruAsEnable(uint8_t en)166 static void PM_CruAsEnable(uint8_t en)
167 {
168 #ifdef HAL_CRU_AS_FEATURE_ENABLED
169 HAL_CRU_AsEnable(1, en);
170 HAL_CRU_AsEnable(2, en);
171 HAL_CRU_AsEnable(3, en);
172 HAL_CRU_AsEnable(4, en);
173 #endif
174 }
175
PM_RuntimeEnter(ePM_RUNTIME_idleMode idleMode)176 static uint32_t PM_RuntimeEnter(ePM_RUNTIME_idleMode idleMode)
177 {
178 uint32_t gpllCon1, gpllDiv2, gpllDiv2New;
179 uint32_t gpllCon0 = 0, gpllDiv1, gpllDiv1New;
180 uint32_t clkSelCon2 = 0, clkSelCon33 = 0, clkSelCon40 = 0;
181 uint32_t cruMode;
182 uint32_t gpllRateNew;
183 uint32_t mDiv;
184 static uint32_t gpllRate;
185 const struct PM_RUNTIME_INFO *pdata = HAL_PM_RuntimeGetData();
186
187 #ifdef HAL_WDT_DYNFREQ_FEATURE_ENABLED
188 uint32_t tmpDiv;
189 static uint32_t pmDynWdtFreqNor;
190 static uint32_t pmWdtFreq;
191 static uint32_t pmDynWdtFreq;
192 #endif
193
194 if (PM_DISPLAY_REQUESTED(pdata)) {
195 return HAL_BIT(PM_RUNTIME_TYPE_DISPLAY);
196 }
197
198 if (PM_UART_REQUESTED(pdata)) {
199 if ((PM_UART_REQUESTED(pdata) & HAL_BIT(0)) &&
200 (UART_CLK_GET_MUX(CLK_UART0) != SCLK_UART0_SEL_XIN_OSC0_FUNC)) {
201 return HAL_BIT(PM_RUNTIME_TYPE_UART);
202 } else if ((PM_UART_REQUESTED(pdata) & HAL_BIT(1)) &&
203 (UART_CLK_GET_MUX(CLK_UART1) != SCLK_UART1_SEL_XIN_OSC0_FUNC)) {
204 return HAL_BIT(PM_RUNTIME_TYPE_UART);
205 } else if ((PM_UART_REQUESTED(pdata) & HAL_BIT(2)) &&
206 (UART_CLK_GET_MUX(CLK_UART2) != SCLK_UART2_SEL_XIN_OSC0_FUNC)) {
207 return HAL_BIT(PM_RUNTIME_TYPE_UART);
208 }
209 }
210
211 if (PM_I2C_REQUESTED(pdata)) {
212 return HAL_BIT(PM_RUNTIME_TYPE_I2C);
213 }
214
215 if (PM_HS_INTF_REQUESTED(pdata)) {
216 return HAL_BIT(PM_RUNTIME_TYPE_HS_INTF);
217 }
218
219 if (PM_SPI_REQUESTED(pdata)) {
220 return HAL_BIT(PM_RUNTIME_TYPE_SPI);
221 }
222
223 if (idleMode == PM_RUNTIME_IDLE_DEEP1) {
224 if (!pvtm32kEn) {
225 PVTM_ClkRateConfig(PVTM_TARGET_KHZ / 8);
226 pvtm32kEn = 1;
227 } else {
228 PVTM_ClkEnable();
229 }
230 }
231
232 PM_CruAsEnable(0);
233 if (!gpllRate) {
234 gpllRate = HAL_CRU_ClkGetFreq(PLL_GPLL);
235 }
236
237 #ifdef HAL_WDT_DYNFREQ_FEATURE_ENABLED
238 if (!pmWdtFreq) {
239 pmWdtFreq = HAL_CRU_ClkGetFreq(PCLK_WDT);
240 tmpDiv = (gpllRate / pmWdtFreq);
241 pmDynWdtFreq = PLL_INPUT_OSC_RATE / tmpDiv;
242 pmDynWdtFreqNor = GPLL_RUNTIME_RATE / tmpDiv;
243 }
244 #endif
245 if (idleMode == PM_RUNTIME_IDLE_DEEP || idleMode == PM_RUNTIME_IDLE_DEEP1) {
246 cruMode = CRU->CRU_MODE_CON00 |
247 MASK_TO_WE(CRU_CRU_MODE_CON00_CLK_GPLL_MODE_MASK);
248 gpllCon1 = CRU->GPLL_CON[1] |
249 MASK_TO_WE(CRU_GPLL_CON1_PLLPD0_MASK);
250
251 clkSelCon33 = CRU->CRU_CLKSEL_CON[33] |
252 MASK_TO_WE(CRU_CRU_CLKSEL_CON33_HCLK_M4_DIV_MASK);
253 clkSelCon2 = CRU->CRU_CLKSEL_CON[2] |
254 MASK_TO_WE(CRU_CRU_CLKSEL_CON02_SCLK_SHRM_DIV_MASK);
255 clkSelCon40 = CRU->CRU_CLKSEL_CON[40] |
256 MASK_TO_WE(CRU_CRU_CLKSEL_CON40_ACLK_LOGIC_DIV_MASK);
257
258 CRU->CRU_MODE_CON00 =
259 VAL_MASK_WE(CRU_CRU_MODE_CON00_CLK_GPLL_MODE_MASK,
260 RK_PLL_MODE_SLOW << CRU_CRU_MODE_CON00_CLK_GPLL_MODE_SHIFT);
261
262 CRU->CRU_CLKSEL_CON[33] =
263 VAL_MASK_WE(CRU_CRU_CLKSEL_CON33_HCLK_M4_DIV_MASK, 0);
264 CRU->CRU_CLKSEL_CON[2] =
265 VAL_MASK_WE(CRU_CRU_CLKSEL_CON02_SCLK_SHRM_DIV_MASK, 0);
266 CRU->CRU_CLKSEL_CON[40] =
267 VAL_MASK_WE(CRU_CRU_CLKSEL_CON40_ACLK_LOGIC_DIV_MASK, 0);
268
269 HAL_ASSERT(!(CRU->GPLL_CON[1] & CRU_GPLL_CON1_PLLPD0_MASK));
270 HAL_ASSERT(!(CRU->GPLL_CON[1] & CRU_GPLL_CON1_PLLPDSEL_MASK));
271
272 #ifdef HAL_WDT_DYNFREQ_FEATURE_ENABLED
273 HAL_WDT_DynFreqUpdata(pmDynWdtFreq);
274 #endif
275
276 CRU->GPLL_CON[1] = VAL_MASK_WE(CRU_GPLL_CON1_PLLPD0_MASK,
277 CRU_GPLL_CON1_PLLPD0_MASK);
278
279 if (idleMode == PM_RUNTIME_IDLE_DEEP1) {
280 CRU->CRU_MODE_CON00 =
281 VAL_MASK_WE(CRU_CRU_MODE_CON00_CLK_GPLL_MODE_MASK,
282 RK_PLL_MODE_DEEP << CRU_CRU_MODE_CON00_CLK_GPLL_MODE_SHIFT);
283 }
284 } else if (idleMode == PM_RUNTIME_IDLE_NORMAL) {
285 cruMode = 0;
286 clkSelCon2 = 0;
287
288 HAL_ASSERT(HAL_CRU_ClkGetFreq(HCLK_M4) > GPLL_RUNTIME_RATE);
289 gpllRate = HAL_CRU_ClkGetFreq(PLL_GPLL);
290
291 gpllCon1 = CRU->GPLL_CON[1] |
292 MASK_TO_WE(CRU_GPLL_CON1_POSTDIV2_MASK);
293 gpllCon0 = CRU->GPLL_CON[0] |
294 MASK_TO_WE(CRU_GPLL_CON0_POSTDIV1_MASK);
295
296 gpllDiv1 = PLL_GET_POSTDIV1(gpllCon0);
297 gpllDiv2 = PLL_GET_POSTDIV2(gpllCon1);
298
299 gpllRate = (gpllRate * gpllDiv1 * gpllDiv2);
300
301 if (PM_GetPllPostDivEven(gpllRate, GPLL_RUNTIME_RATE, &gpllDiv1New, &gpllDiv2New) >= 2) {
302 return UINT32_MAX;
303 }
304
305 gpllRateNew = gpllRate / (gpllDiv1New * gpllDiv2New);
306 mDiv = gpllRateNew / GPLL_RUNTIME_RATE;
307
308 HAL_ASSERT(mDiv > 0);
309 HAL_ASSERT((gpllRateNew * mDiv) >= GPLL_RUNTIME_RATE);
310
311 if (mDiv > 0) {
312 mDiv -= 1;
313 }
314
315 #ifdef HAL_WDT_DYNFREQ_FEATURE_ENABLED
316 HAL_WDT_DynFreqUpdata(pmDynWdtFreqNor);
317 #endif
318
319 clkSelCon33 = CRU->CRU_CLKSEL_CON[33] |
320 MASK_TO_WE(CRU_CRU_CLKSEL_CON33_HCLK_M4_DIV_MASK);
321
322 CRU->GPLL_CON[0] = VAL_MASK_WE(CRU_GPLL_CON0_POSTDIV1_MASK,
323 gpllDiv1New << CRU_GPLL_CON0_POSTDIV1_SHIFT);
324
325 CRU->GPLL_CON[1] = VAL_MASK_WE(CRU_GPLL_CON1_POSTDIV2_MASK,
326 gpllDiv2New << CRU_GPLL_CON1_POSTDIV2_SHIFT);
327
328 CRU->CRU_CLKSEL_CON[33] = VAL_MASK_WE(CRU_CRU_CLKSEL_CON33_HCLK_M4_DIV_MASK,
329 mDiv << CRU_CRU_CLKSEL_CON33_HCLK_M4_DIV_SHIFT);
330 } else {
331 goto _ret_err;
332 }
333
334 __DSB();
335 __WFI();
336
337 if (idleMode == PM_RUNTIME_IDLE_DEEP || idleMode == PM_RUNTIME_IDLE_DEEP1) {
338 CRU->GPLL_CON[1] = gpllCon1;
339 CRU->CRU_CLKSEL_CON[33] = clkSelCon33;
340 CRU->CRU_CLKSEL_CON[2] = clkSelCon2;
341 CRU->CRU_CLKSEL_CON[40] = clkSelCon40;
342
343 while ((CRU->GPLL_CON[1] & CRU_CPLL_CON1_PLL_LOCK_MASK) !=
344 CRU_CPLL_CON1_PLL_LOCK_MASK) {
345 ;
346 }
347 CRU->CRU_MODE_CON00 = cruMode;
348 if (idleMode == PM_RUNTIME_IDLE_DEEP1) {
349 PVTM_ClkDisable();
350 }
351 } else if (idleMode == PM_RUNTIME_IDLE_NORMAL) {
352 CRU->CRU_CLKSEL_CON[33] = clkSelCon33;
353 CRU->GPLL_CON[1] = gpllCon1;
354 CRU->GPLL_CON[0] = gpllCon0;
355 }
356 #ifdef HAL_WDT_DYNFREQ_FEATURE_ENABLED
357 HAL_WDT_DynFreqResume();
358 #endif
359
360 PM_CruAsEnable(1);
361
362 return 0;
363 _ret_err:
364
365 return UINT32_MAX;
366 }
367
HAL_PM_RuntimeEnter(ePM_RUNTIME_idleMode idleMode)368 uint32_t HAL_PM_RuntimeEnter(ePM_RUNTIME_idleMode idleMode)
369 {
370 uint32_t ret;
371
372 if (idleMode) {
373 ret = PM_RuntimeEnter(idleMode);
374 } else {
375 ret = UINT32_MAX;
376 }
377
378 if (!idleMode || ret) {
379 __DSB();
380 __WFI();
381 }
382
383 return ret;
384 }
385
386 #endif
387
388 #ifdef HAL_PM_SLEEP_MODULE_ENABLED
SOC_GetWakeupStatus(struct PMU_REG * pPmu)389 HAL_UNUSED static void SOC_GetWakeupStatus(struct PMU_REG *pPmu)
390 {
391 HAL_DBG("\nwakeup source:\n");
392 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_WAKEUP_PWRMODE_INT_STATUS_SHIFT)) {
393 HAL_DBG("\tPower mode state machine wakeup status by interrupt\n");
394 }
395 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_GPIO_INT_STATUS_SHIFT)) {
396 HAL_DBG("\tPower mode state machine wakeup status by gpio interrupt\n");
397 }
398 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_TIMEOUT_STATUS_SHIFT)) {
399 HAL_DBG("\tPower mode state machine wakeup status by timeout\n");
400 }
401 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_DSP_SFT_STATUS_SHIFT)) {
402 HAL_DBG("\tPower mode state machine wakeup status by DSP software\n");
403 }
404 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_TIMER_STATUS_SHIFT)) {
405 HAL_DBG("\tPower mode state machine wakeup status by timer interrupt\n");
406 }
407 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_VAD_STATUS_SHIFT)) {
408 HAL_DBG("\tPower mode state machine wakeup status by vad\n");
409 }
410 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_WAKEUP_DSP_INT_STATUS_SHIFT)) {
411 HAL_DBG("\tDSP auto power down state machine wakeup status by interrupt\n");
412 }
413 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_GPIO_INT_STATUS_SHIFT)) {
414 HAL_DBG("\tDSP auto power down state machine wakeup status by gpio interrupt\n");
415 }
416 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_TIMEOUT_STATUS_SHIFT)) {
417 HAL_DBG("\tDSP auto power down state machine wakeup status by timeout\n");
418 }
419 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_SFT_STATUS_SHIFT)) {
420 HAL_DBG("\tDSP auto power down state machine wakeup status by MCU software\n");
421 }
422 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_TIMER_STATUS_SHIFT)) {
423 HAL_DBG("\tauto power down state machine wakeup status by timer\n");
424 }
425 if (pPmu->WAKEUP_STATUS & (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_VAD_STATUS_SHIFT)) {
426 HAL_DBG("\tDSP auto power down state machine wakeup status by vad\n");
427 }
428
429 pPmu->WAKEUP_STATUS = (1 << PMU_WAKEUP_STATUS_WAKEUP_PWRMODE_INT_STATUS_SHIFT) |
430 (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_GPIO_INT_STATUS_SHIFT) |
431 (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_TIMEOUT_STATUS_SHIFT) |
432 (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_DSP_SFT_STATUS_SHIFT) |
433 (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_TIMER_STATUS_SHIFT) |
434 (1 << PMU_WAKEUP_STATUS_PWRMODE_WAKEUP_VAD_STATUS_SHIFT) |
435 (1 << PMU_WAKEUP_STATUS_WAKEUP_DSP_INT_STATUS_SHIFT) |
436 (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_GPIO_INT_STATUS_SHIFT) |
437 (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_TIMEOUT_STATUS_SHIFT) |
438 (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_SFT_STATUS_SHIFT) |
439 (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_TIMER_STATUS_SHIFT) |
440 (1 << PMU_WAKEUP_STATUS_DSP_WAKEUP_VAD_STATUS_SHIFT);
441 }
442
SOC_FastBootEnable(struct GRF_REG * pGrf)443 HAL_UNUSED static void SOC_FastBootEnable(struct GRF_REG *pGrf)
444 {
445 #ifdef HAL_PM_CPU_SLEEP_MODULE_ENABLED
446 pGrf->FAST_BOOT_ADDR = (uint32_t)HAL_CPU_DoResume;
447 pGrf->FAST_BOOT_EN = 1;
448 #endif
449 }
450
SOC_FastBootDisable(struct GRF_REG * pGrf)451 HAL_UNUSED static void SOC_FastBootDisable(struct GRF_REG *pGrf)
452 {
453 #ifdef HAL_PM_CPU_SLEEP_MODULE_ENABLED
454 pGrf->FAST_BOOT_EN = 0;
455 #endif
456 }
457
SOC_SleepModeInit(struct PMU_REG * pPmu)458 HAL_UNUSED static void SOC_SleepModeInit(struct PMU_REG *pPmu)
459 {
460 uint32_t mask = 0, value = 0;
461
462 mask = PMU_PWRMODE_CON_POWER_MODE_EN_MASK |
463 PMU_PWRMODE_CON_OSC_DISABLE_MASK |
464 PMU_PWRMODE_CON_PMU_USE_LF_MASK |
465 PMU_PWRMODE_CON_PLL_PD_EN_MASK |
466 PMU_PWRMODE_CON_LOGIC_PD_EN_MASK |
467 PMU_PWRMODE_CON_PWRMODE_LDO_ADJ_EN_MASK |
468 PMU_PWRMODE_CON_BYPASS_PLL_LOCK_MASK |
469 PMU_PWRMODE_CON_BYPASS_HF_EN_MASK |
470 PMU_PWRMODE_CON_GLOBAL_INT_DISABLE_CFG_MASK |
471 PMU_PWRMODE_CON_SHRM_PD_EN_MASK |
472 PMU_PWRMODE_CON_SHRM_MEM_RETPD_EN_MASK;
473
474 value = (1 << PMU_PWRMODE_CON_POWER_MODE_EN_SHIFT) |
475 /*(1 << PMU_PWRMODE_CON_PMU_USE_LF_SHIFT) |*/
476 (1 << PMU_PWRMODE_CON_PLL_PD_EN_SHIFT) |
477 (1 << PMU_PWRMODE_CON_LOGIC_PD_EN_SHIFT) |
478 (1 << PMU_PWRMODE_CON_PWRMODE_LDO_ADJ_EN_SHIFT) |
479 /*(1 << PMU_PWRMODE_CON_BYPASS_PLL_LOCK_SHIFT) |*/
480 /*(1 << PMU_PWRMODE_CON_BYPASS_HF_EN_SHIFT) |*/
481 (1 << PMU_PWRMODE_CON_SHRM_PD_EN_SHIFT) |
482 (1 << PMU_PWRMODE_CON_SHRM_MEM_RETPD_EN_SHIFT);
483
484 /* if PD_DSP and PD_AUDIO power down, PMU low frequency mode enable */
485 if (pPmu->PWRDN_ST &
486 ((1 << PMU_PWRDN_ST_PD_AUDIO_PWR_STAT_SHIFT) | (1 << PMU_PWRDN_ST_PD_DSP_PWR_STAT_SHIFT))) {
487 value |= (1 << PMU_PWRMODE_CON_PMU_USE_LF_SHIFT) |
488 (1 << PMU_PWRMODE_CON_OSC_DISABLE_SHIFT);
489 pPmu->PWRMODE_LDO_ADJ_CNT = SLEEP_COUNT_TO_MS(1);
490 pPmu->PLLLOCK_CNT = SLEEP_COUNT_TO_MS(1);
491 pPmu->DSP_LDO_ADJ_CNT = SLEEP_COUNT_TO_MS(1);
492 pPmu->OSC_CNT = SLEEP_COUNT_TO_MS(1);
493
494 if (!pvtm32kEn) {
495 PVTM_ClkRateConfig(PVTM_TARGET_KHZ);
496 pvtm32kEn = 1;
497 } else {
498 PVTM_ClkEnable();
499 }
500 }
501 pPmu->PWRMODE_CON = VAL_MASK_WE(mask, value);
502
503 if (pPmu->PWRMODE_CON & (1 << PMU_PWRMODE_CON_LOGIC_PD_EN_SHIFT)) {
504 mask = PMU_BUS_CLR_CLR_LOGIC_MASK;
505 value = (1 << PMU_BUS_CLR_CLR_LOGIC_SHIFT);
506 pPmu->BUS_CLR |= VAL_MASK_WE(mask, value);
507 }
508
509 if (pPmu->PWRMODE_CON & (1 << PMU_PWRMODE_CON_SHRM_MEM_RETPD_EN_SHIFT)) {
510 mask = PMU_SHRM_CON1_PWRMODE_SHRM_PWRDWN_EN_MASK |
511 PMU_SHRM_CON1_PWRMODE_SHRM_RET2N_MASK;
512 value = (0xf << PMU_SHRM_CON1_PWRMODE_SHRM_PWRDWN_EN_SHIFT);
513 pPmu->SHRM_CON1 = VAL_MASK_WE(mask, value);
514
515 mask = PMU_BUS_CLR_CLR_SHRM_MASK;
516 value = (1 << PMU_BUS_CLR_CLR_SHRM_SHIFT);
517 pPmu->BUS_CLR |= VAL_MASK_WE(mask, value);
518 }
519
520 if (pPmu->PWRMODE_CON & (1 << PMU_PWRMODE_CON_PWRMODE_LDO_ADJ_EN_SHIFT)) {
521 mask = PMU_LDO_CON1_PWRMODE_LDOCORE_ADJ_MASK;
522 pPmu->LDO_CON[1] = VAL_MASK_WE(mask, 0x10);
523 }
524
525 if (pPmu->PWRMODE_CON & (1 << PMU_PWRMODE_CON_PLL_PD_EN_SHIFT)) {
526 mask = PMU_PLL_CON_PLL_PD_CFG_MASK;
527 /* if PD_DSP and PD_AUDIO power down, CPLL, GPLL and 32K PLL power down by hardware */
528 if (pPmu->PWRDN_ST &
529 ((1 << PMU_PWRDN_ST_PD_AUDIO_PWR_STAT_SHIFT) | (1 << PMU_PWRDN_ST_PD_DSP_PWR_STAT_SHIFT))) {
530 pPmu->PLL_CON = VAL_MASK_WE(mask, 0x07);
531 } else {
532 pPmu->PLL_CON = VAL_MASK_WE(mask, 0x05);
533 }
534 }
535
536 if (pPmu->PWRMODE_CON & (1 << PMU_PWRMODE_CON_PMU_USE_LF_SHIFT)) {
537 mask = PMU_SFT_CON_PMU_LF_MODE_CFG_MASK;
538 value = (1 << PMU_SFT_CON_PMU_LF_MODE_CFG_SHIFT);
539 pPmu->SFT_CON = VAL_MASK_WE(mask, value);
540 }
541 }
542
SOC_WakeupSourceConfig(struct PMU_REG * pPmu)543 HAL_UNUSED static void SOC_WakeupSourceConfig(struct PMU_REG *pPmu)
544 {
545 uint32_t mask = 0, value = 0;
546
547 mask = PMU_WAKEUP_CFG6_GPIO_INT_EN_MASK |
548 PMU_WAKEUP_CFG6_TIMER_EN_MASK;
549 value = (1 << PMU_WAKEUP_CFG6_GPIO_INT_EN_SHIFT) |
550 (1 << PMU_WAKEUP_CFG6_TIMER_EN_SHIFT);
551 pPmu->WAKEUP_CFG6 = VAL_MASK_WE(mask, value);
552 }
553
SOC_SleepModeReinit(struct PMU_REG * pPmu)554 HAL_UNUSED static void SOC_SleepModeReinit(struct PMU_REG *pPmu)
555 {
556 uint32_t mask = 0, value = 0;
557
558 mask = PMU_PWRMODE_CON_POWER_MODE_EN_MASK |
559 PMU_PWRMODE_CON_PLL_PD_EN_MASK |
560 PMU_PWRMODE_CON_LOGIC_PD_EN_MASK |
561 PMU_PWRMODE_CON_PWRMODE_LDO_ADJ_EN_MASK |
562 PMU_PWRMODE_CON_BYPASS_PLL_LOCK_MASK |
563 PMU_PWRMODE_CON_BYPASS_HF_EN_MASK |
564 PMU_PWRMODE_CON_GLOBAL_INT_DISABLE_CFG_MASK |
565 PMU_PWRMODE_CON_SHRM_PD_EN_MASK |
566 PMU_PWRMODE_CON_SHRM_MEM_RETPD_EN_MASK;
567 pPmu->PWRMODE_CON = VAL_MASK_WE(mask, value);
568 if (pPmu->PWRDN_ST &
569 ((1 << PMU_PWRDN_ST_PD_AUDIO_PWR_STAT_SHIFT) | (1 << PMU_PWRDN_ST_PD_DSP_PWR_STAT_SHIFT))) {
570 PVTM_ClkDisable();
571 }
572 }
573
SOC_PutChar(char c,struct UART_REG * pUart)574 HAL_UNUSED static void SOC_PutChar(char c, struct UART_REG *pUart)
575 {
576 if (pUart) {
577 pUart->THR = c;
578 while ((pUart->USR & UART_USR_BUSY)) {
579 ;
580 }
581 }
582 }
583
SOC_UartSave(struct UART_REG_SAVE * pUartSave,struct UART_REG * pUart)584 HAL_UNUSED static void SOC_UartSave(struct UART_REG_SAVE *pUartSave, struct UART_REG *pUart)
585 {
586 if (pUartSave && pUart) {
587 while (!(pUart->USR & UART_USR_TX_FIFO_EMPTY)) {
588 ;
589 }
590 pUartSave->LCR = pUart->LCR;
591 pUartSave->IER = pUart->IER;
592 pUartSave->MCR = pUart->MCR;
593 if (pUart->USR & UART_USR_BUSY) {
594 HAL_DelayMs(10);
595 }
596 if (pUart->USR & UART_USR_BUSY) {
597 pUart->SRR = UART_SRR_XFR | UART_SRR_RFR;
598 }
599 pUart->LCR = UART_LCR_DLAB;
600 pUartSave->DLL = pUart->DLL;
601 pUartSave->DLH = pUart->DLH;
602 pUart->LCR = pUartSave->LCR;
603 }
604 }
605
SOC_UartRestore(struct UART_REG_SAVE * pUartSave,struct UART_REG * pUart)606 HAL_UNUSED static void SOC_UartRestore(struct UART_REG_SAVE *pUartSave, struct UART_REG *pUart)
607 {
608 if (pUartSave && pUart) {
609 pUart->SRR = UART_SRR_XFR | UART_SRR_RFR | UART_SRR_UR;
610 pUart->MCR = UART_MCR_LOOP;
611 pUart->LCR = UART_LCR_DLAB;
612 pUart->DLL = pUartSave->DLL;
613 pUart->DLH = pUartSave->DLH;
614 pUart->LCR = pUartSave->LCR;
615 pUart->IER = pUartSave->IER;
616 pUart->FCR = UART_FCR_ENABLE_FIFO;
617 pUart->MCR = pUartSave->MCR;
618 }
619 }
620
621 #ifdef HAL_PM_CPU_SLEEP_MODULE_ENABLED
SOC_SuspendEnter(uint32_t flag)622 static int SOC_SuspendEnter(uint32_t flag)
623 {
624 HAL_DCACHE_CleanInvalidate();
625 __WFI();
626
627 /* The PD_LOGIC power down when in power mode, the code will not execute
628 */
629 pmIRQPendingFlag = 1;
630 HAL_CPU_DoResume();
631
632 return HAL_OK;
633 }
634 #endif
635
636 /** @} */
637 /********************* Public Function Definition ****************************/
638 /** @defgroup PM_Exported_Functions_Group5 Other Functions
639 * @{
640 */
641
HAL_PM_TimerStart(uint64_t timeoutCount,bool needTimeout)642 HAL_Status HAL_PM_TimerStart(uint64_t timeoutCount, bool needTimeout)
643 {
644 pmTimerLastCount = HAL_GetSysTimerCount();
645 pmTimerLowCount = 0;
646
647 return 0;
648 }
649
HAL_PM_TimerStop(void)650 HAL_Status HAL_PM_TimerStop(void)
651 {
652 return 0;
653 }
654
HAL_PM_GetTimerCount(void)655 uint64_t HAL_PM_GetTimerCount(void)
656 {
657 return HAL_GetSysTimerCount() - pmTimerLastCount;
658 }
659
HAL_SYS_Suspend(struct PM_SUSPEND_INFO * suspendInfo)660 int HAL_SYS_Suspend(struct PM_SUSPEND_INFO *suspendInfo)
661 {
662 #ifdef HAL_PM_CPU_SLEEP_MODULE_ENABLED
663 struct PMU_REG *pPmu = PMU;
664 struct GRF_REG *pGrf = GRF;
665 struct UART_REG *pUart = NULL;
666 struct UART_REG_SAVE pUartSave = { 0 };
667 uint64_t timerCount;
668
669 HAL_ASSERT(suspendInfo != NULL);
670
671 #ifdef HAL_SYSTICK_MODULE_ENABLED
672 SysTick->CTRL &= (~SysTick_CTRL_ENABLE_Msk);
673 #endif
674
675 #ifdef HAL_UART_MODULE_ENABLED
676 if (suspendInfo->flag.uartValid) {
677 if (suspendInfo->flag.uartChannel == 0) {
678 pUart = UART0;
679 } else if (suspendInfo->flag.uartChannel == 1) {
680 pUart = UART1;
681 } else if (suspendInfo->flag.uartChannel == 2) {
682 pUart = UART2;
683 }
684 }
685 #endif
686
687 SOC_PutChar('0', pUart);
688 SOC_SleepModeInit(pPmu);
689 SOC_PutChar('1', pUart);
690 SOC_FastBootEnable(pGrf);
691 SOC_PutChar('2', pUart);
692 SOC_WakeupSourceConfig(pPmu);
693 SOC_PutChar('3', pUart);
694 HAL_NVIC_SuspendSave();
695 SOC_PutChar('4', pUart);
696 HAL_SCB_SuspendSave();
697 SOC_PutChar('5', pUart);
698 SOC_UartSave(&pUartSave, pUart);
699 timerCount = HAL_GetSysTimerCount();
700 HAL_CPU_SuspendEnter(suspendInfo->suspendFlag, SOC_SuspendEnter);
701 pmTimerLowCount = HAL_GetSysTimerCount() - timerCount;
702 SOC_SleepModeReinit(pPmu);
703 SOC_UartRestore(&pUartSave, pUart);
704 SOC_PutChar('5', pUart);
705 if (pmIRQPendingFlag == 0) {
706 SOC_PutChar('4', pUart);
707 BSP_MPU_Init();
708 HAL_DCACHE_Enable();
709 HAL_DCACHE_EnableInt();
710 HAL_ICACHE_Enable();
711 HAL_ICACHE_EnableInt();
712 }
713 pmIRQPendingFlag = 0;
714 SOC_PutChar('3', pUart);
715 HAL_SCB_ResumeRestore();
716 SOC_PutChar('2', pUart);
717 HAL_NVIC_ResumeRestore();
718 SOC_PutChar('1', pUart);
719 SOC_GetWakeupStatus(pPmu);
720 SOC_FastBootDisable(pGrf);
721 SOC_PutChar('0', pUart);
722 #ifdef HAL_SYSTICK_MODULE_ENABLED
723 HAL_SYSTICK_CLKSourceConfig(HAL_SYSTICK_CLKSRC_EXT);
724 HAL_SYSTICK_Enable();
725 #endif
726
727 HAL_DBG("\n");
728 #endif
729
730 return HAL_OK;
731 }
732
733 /** @} */
734 #endif
735
736 /** @} */
737
738 /** @} */
739
740 #endif /* RKMCU_RK2108 */
741