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