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 
8 #ifdef HAL_PM_RUNTIME_MODULE_ENABLED
9 
10 /** @addtogroup RK_HAL_Driver
11  *  @{
12  */
13 
14 /** @addtogroup PM_CPU
15  *  @{
16  */
17 
18 /** @defgroup PM_CPU_How_To_Use How To Use
19  *  @{
20 
21  The PM_CPU_SLEEP driver can be used as follows:
22  - Invoke HAL_NVIC_SuspendSave() when NVIC needs to be save.
23  - Invoke HAL_NVIC_ResumeRestore() when NVIC needs to be resume.
24  - Invoke HAL_CPU_SuspendSave() when cpu may need save some info.
25 
26  The PM_Runtime driver can be used as follows:
27  - Invoke HAL_PM_RuntimeRequest() when a device is in runtime.
28  - Invoke HAL_PM_RuntimeRelease() when a device is release runtime.
29  - Invoke HAL_PM_RuntimeGetData() when need get all of device status.
30 
31  @} */
32 
33 static struct PM_RUNTIME_INFO runtimeStatus;
34 
35 /** @defgroup PM_PM_RUNTIME_Exported_Functions_Group5 Other Functions
36  *  @{
37  */
38 
39 /**
40  * @brief  request a runtime status by runtimeId.
41  * @param  runtimeId: a runtime request id.
42  * @return HAL_Status
43  */
HAL_PM_RuntimeRequest(ePM_RUNTIME_ID runtimeId)44 HAL_Status HAL_PM_RuntimeRequest(ePM_RUNTIME_ID runtimeId)
45 {
46     uint8_t runtimeType, typeOffset;
47 
48     HAL_ASSERT(runtimeId < PM_RUNTIME_ID_END);
49 
50     runtimeType = PM_RUNTIME_ID_TO_TYPE(runtimeId);
51     typeOffset = PM_RUNTIME_ID_TO_TYPE_OFFSET(runtimeId);
52     HAL_ASSERT(runtimeType < PM_RUNTIME_TYPE_END);
53     HAL_ASSERT(typeOffset < PM_RUNTIME_PER_TYPE_NUM);
54 
55     runtimeStatus.bits[runtimeType] |= HAL_BIT(typeOffset);
56 
57     return HAL_OK;
58 }
59 
60 /**
61  * @brief  release a runtime status by runtimeId.
62  * @param  runtimeId: a runtime request id.
63  * @return HAL_Status
64  */
HAL_PM_RuntimeRelease(ePM_RUNTIME_ID runtimeId)65 HAL_Status HAL_PM_RuntimeRelease(ePM_RUNTIME_ID runtimeId)
66 {
67     uint8_t runtimeType, typeOffset;
68 
69     HAL_ASSERT(runtimeId < PM_RUNTIME_ID_END);
70 
71     runtimeType = PM_RUNTIME_ID_TO_TYPE(runtimeId);
72     typeOffset = PM_RUNTIME_ID_TO_TYPE_OFFSET(runtimeId);
73 
74     HAL_ASSERT(runtimeType < PM_RUNTIME_TYPE_END);
75     HAL_ASSERT(typeOffset < PM_RUNTIME_PER_TYPE_NUM);
76 
77     runtimeStatus.bits[runtimeType] &= ~HAL_BIT(typeOffset);
78 
79     return HAL_OK;
80 }
81 
82 /**
83  * @brief  get the runitme data poiniter.
84  * @return the runitme data poiniter.
85  */
HAL_PM_RuntimeGetData(void)86 const struct PM_RUNTIME_INFO *HAL_PM_RuntimeGetData(void)
87 {
88     return &runtimeStatus;
89 }
90 
91 /** @} */
92 
93 #endif
94 
95 #ifdef HAL_PM_SLEEP_MODULE_ENABLED
96 
97 /** @defgroup PM_Private_Definition Private Definition
98  *  @{
99  */
100 /********************* Private Variable Definition ***************************/
101 static struct SLEEP_CONFIG_DATA sleepConfigData;
102 
103 /** @} */
104 /********************* Public Function Definition ***************************/
105 /** @defgroup PM_CPU_SLEEP_Exported_Functions_Group5 Other Functions
106  *  @{
107  */
108 
109 /**
110  * @brief  get sleepConfigData.
111  * @return addr of sleepConfigData.
112  */
HAL_SYS_GetSuspendConfig(void)113 struct SLEEP_CONFIG_DATA *HAL_SYS_GetSuspendConfig(void)
114 {
115     return &sleepConfigData;
116 }
117 
118 /**
119  * @brief  config parameters to control suspend flow.
120  * @param  id: select parameters to be config.
121  * @param  data: data assigned to parameters.
122  * @return HAL_Status.
123  */
HAL_SYS_SuspendConfig(uint32_t id,uint32_t data)124 HAL_Status HAL_SYS_SuspendConfig(uint32_t id, uint32_t data)
125 {
126     switch (id) {
127     case PM_SLEEP_MODE_CONFIG:
128         sleepConfigData.suspendMode = data;
129         break;
130 
131     case PM_SLEEP_WAKEUP_SOURCE:
132         sleepConfigData.suspendWkupSrc = data;
133         break;
134 
135     default:
136         break;
137     }
138 
139     return HAL_OK;
140 }
141 
142 /** @} */
143 
144 #endif /* HAL_PM_SLEEP_MODULE_ENABLED */
145 
146 #if defined(HAL_PM_CPU_SLEEP_MODULE_ENABLED)
147 #if defined(__CM3_REV) || defined(__CM4_REV)
148 
149 /** @defgroup PM_CPU_Private_Definition Private Definition
150  *  @{
151  */
152 /********************* Private MACRO Definition ******************************/
153 
154 #define NVIC_EXT_ISER_NUM (8)
155 #define NVIC_EXT_IP_NUM   (240)
156 #define SHP_NUM           (12)
157 /********************* Private Structure Definition **************************/
158 
159 struct NVIC_SAVE_S {
160     uint32_t iser[NVIC_EXT_ISER_NUM];/* Interrupt Set Enable Register */
161     uint8_t ip[NVIC_EXT_IP_NUM]; /* Interrupt Priority Register */
162     uint32_t pg;  /* Interrupt Priority Group Register */
163 };
164 
165 /********************* Private Variable Definition ***************************/
166 
167 static struct NVIC_SAVE_S nvicSave;
168 static NVIC_Type *pnvic = NVIC;
169 static SCB_Type scbSave;
170 
171 /********************* Private Function Definition ***************************/
172 
173 /** @} */
174 /********************* Public Function Definition ***************************/
175 /** @defgroup PM_CPU_SLEEP_Exported_Functions_Group5 Other Functions
176  *  @{
177  */
178 
179 /**
180  * @brief  save nvic registers for resume nvic.
181  */
HAL_NVIC_SuspendSave(void)182 void HAL_NVIC_SuspendSave(void)
183 {
184     int i;
185 
186     for (i = 0; i < NVIC_EXT_ISER_NUM; i++) {
187         nvicSave.iser[i] = pnvic->ISER[i];
188     }
189 
190     for (i = 0; i < NVIC_EXT_IP_NUM; i++) {
191         nvicSave.ip[i] = pnvic->IP[i];
192     }
193 
194     nvicSave.pg = NVIC_GetPriorityGrouping();
195 }
196 
197 /**
198  * @brief  resume nvic registers.
199  */
HAL_NVIC_ResumeRestore(void)200 void HAL_NVIC_ResumeRestore(void)
201 {
202     int i;
203 
204     NVIC_SetPriorityGrouping(nvicSave.pg);
205     for (i = 0; i < NVIC_EXT_IP_NUM; i++) {
206         pnvic->IP[i] = nvicSave.ip[i];
207     }
208 
209     for (i = 0; i < NVIC_EXT_ISER_NUM; i++) {
210         pnvic->ICER[i] = 0xffffffff;
211     }
212 
213     for (i = 0; i < NVIC_EXT_ISER_NUM; i++) {
214         pnvic->ISER[i] = nvicSave.iser[i];
215     }
216 }
217 
218 /**
219  * @brief  save scb registers for resume nvic.
220  */
HAL_SCB_SuspendSave(void)221 void HAL_SCB_SuspendSave(void)
222 {
223     int i;
224 
225     scbSave.ICSR = SCB->ICSR;
226     scbSave.AIRCR = SCB->AIRCR;
227     scbSave.SCR = SCB->SCR;
228     for (i = 0; i < SHP_NUM; i++) {
229         scbSave.SHP[i] = SCB->SHP[i];
230     }
231     scbSave.SHCSR = SCB->SHCSR;
232     scbSave.CFSR = SCB->CFSR;
233     scbSave.DFSR = SCB->DFSR;
234     scbSave.MMFAR = SCB->MMFAR;
235     scbSave.BFAR = SCB->BFAR;
236     scbSave.AFSR = SCB->AFSR;
237     scbSave.CPACR = SCB->CPACR;
238 }
239 
240 /**
241  * @brief  resume nvic registers.
242  */
HAL_SCB_ResumeRestore(void)243 void HAL_SCB_ResumeRestore(void)
244 {
245     int i;
246 
247     SCB->ICSR = scbSave.ICSR;
248     SCB->AIRCR = scbSave.AIRCR;
249     SCB->SCR = scbSave.SCR;
250     for (i = 0; i < SHP_NUM; i++) {
251         SCB->SHP[i] = scbSave.SHP[i];
252     }
253     SCB->SHCSR = scbSave.SHCSR;
254     SCB->CFSR = scbSave.CFSR;
255     SCB->DFSR = scbSave.DFSR;
256     SCB->MMFAR = scbSave.MMFAR;
257     SCB->BFAR = scbSave.BFAR;
258     SCB->AFSR = scbSave.AFSR;
259     SCB->CPACR = scbSave.CPACR;
260 }
261 
262 /**
263  * @brief  it is for saving cpu's register.
264  * @param  ptr: base addr for saving
265  * @param  ptrsz: size of the mem for saving
266  * @param  sp: the system stack needed be saved
267  * @param  ptrSave: save the param ptr.
268  */
HAL_CPU_SuspendSave(uint32_t * ptr,uint32_t ptrsz,uint32_t sp,uint32_t * ptrSave)269 void HAL_CPU_SuspendSave(uint32_t *ptr, uint32_t ptrsz, uint32_t sp, uint32_t *ptrSave)
270 {
271     *ptrSave = (uint32_t)ptr;
272     *ptr++ = sp;
273     *ptr++ = (uint32_t)HAL_CPU_ArchResume + 1;
274     HAL_CPU_ArchSuspend(ptr);
275 }
276 
277 /** @} */
278 
279 #endif /* __CM3_REV || __CM4_REV */
280 
281 /** @} */
282 
283 /** @} */
284 
285 #endif /* HAL_PM_CPU_SLEEP_MODULE_ENABLED */
286