1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_pm.h"
33 #include "securec.h"
34 #include "los_timer.h"
35 #include "los_task.h"
36 #include "los_tick.h"
37 #include "los_event.h"
38 #include "los_sched.h"
39 #include "los_memory.h"
40 #include "los_swtmr.h"
41
42 #if (LOSCFG_KERNEL_PM == 1)
43 #define OS_PM_NODE_FREE 0x80000000U
44 #define OS_PM_LOCK_MAX 0xFFFFU
45 #define OS_PM_SYS_EARLY 1
46 #define OS_PM_SYS_DEVICE_EARLY 2
47
48 typedef UINT32 (*Suspend)(UINT32 mode);
49
50 typedef struct {
51 CHAR *name;
52 UINT32 count;
53 UINT32 swtmrID;
54 LOS_DL_LIST list;
55 } OsPmLockCB;
56
57 typedef struct {
58 LOS_SysSleepEnum pmMode;
59 LOS_SysSleepEnum sysMode;
60 UINT16 lock;
61 BOOL isWake;
62 LosPmDevice *device;
63 LosPmSysctrl *sysctrl;
64 LosPmTickTimer *tickTimer;
65 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
66 UINT64 enterSleepTime;
67 #endif
68 LOS_DL_LIST lockList;
69 } LosPmCB;
70
71 #define PM_EVENT_LOCK_MASK 0xF
72 #define PM_EVENT_LOCK_RELEASE 0x1
73 STATIC EVENT_CB_S g_pmEvent;
74 STATIC LosPmCB g_pmCB;
75 STATIC LosPmSysctrl g_sysctrl;
76
OsPmSysctrlInit(VOID)77 STATIC VOID OsPmSysctrlInit(VOID)
78 {
79 /* Default handler functions, which are implemented by the product */
80 g_sysctrl.early = NULL;
81 g_sysctrl.late = NULL;
82 g_sysctrl.normalSuspend = ArchEnterSleep;
83 g_sysctrl.normalResume = NULL;
84 g_sysctrl.lightSuspend = ArchEnterSleep;
85 g_sysctrl.lightResume = NULL;
86 g_sysctrl.deepSuspend = ArchEnterSleep;
87 g_sysctrl.deepResume = NULL;
88 g_sysctrl.shutdownSuspend = NULL;
89 g_sysctrl.shutdownResume = NULL;
90 }
91
OsPmTickTimerStart(LosPmCB * pm)92 STATIC VOID OsPmTickTimerStart(LosPmCB *pm)
93 {
94 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
95 UINT64 currTime, sleepTime, realSleepTime;
96 #endif
97 LosPmTickTimer *tickTimer = pm->tickTimer;
98
99 if ((tickTimer == NULL) || (tickTimer->tickUnlock == NULL)) {
100 return;
101 }
102
103 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
104 if ((tickTimer->timerStop != NULL) && (pm->enterSleepTime != 0)) {
105 /* Restore the main CPU frequency */
106 sleepTime = tickTimer->timerCycleGet();
107 tickTimer->timerStop();
108
109 realSleepTime = OS_SYS_CYCLE_TO_NS(sleepTime, tickTimer->freq);
110 realSleepTime = OS_SYS_NS_TO_CYCLE(realSleepTime, g_sysClock);
111 currTime = pm->enterSleepTime + realSleepTime;
112 pm->enterSleepTime = 0;
113
114 OsTickTimerBaseReset(currTime);
115 OsSchedResetSchedResponseTime(0);
116 }
117 #endif
118
119 tickTimer->tickUnlock();
120 return;
121 }
122
OsPmTickTimerStop(LosPmCB * pm)123 STATIC BOOL OsPmTickTimerStop(LosPmCB *pm)
124 {
125 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
126 UINT64 sleepCycle, realSleepTime;
127 UINT64 currTime = OsGetCurrSchedTimeCycle();
128 UINT64 expireTime = OsSchedGetNextExpireTime(currTime);
129 #endif
130 LosPmTickTimer *tickTimer = pm->tickTimer;
131
132 if ((tickTimer == NULL) || (tickTimer->tickLock == NULL)) {
133 return FALSE;
134 }
135
136 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
137 if (tickTimer->timerStart != NULL) {
138 LOS_ASSERT(expireTime > currTime);
139
140 realSleepTime = expireTime - currTime;
141 sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, g_sysClock);
142 sleepCycle = OS_SYS_NS_TO_CYCLE(sleepCycle, tickTimer->freq);
143
144 /* The main CPU reduces the frequency */
145 pm->enterSleepTime = LOS_SysCycleGet();
146 tickTimer->tickLock();
147 tickTimer->timerStart(sleepCycle);
148 return TRUE;
149 }
150 #endif
151
152 tickTimer->tickLock();
153 return TRUE;
154 }
155
OsPmCpuResume(LosPmCB * pm)156 STATIC VOID OsPmCpuResume(LosPmCB *pm)
157 {
158 if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) && (pm->sysctrl->normalResume != NULL)) {
159 pm->sysctrl->normalResume();
160 } else if ((pm->sysMode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightResume != NULL)) {
161 pm->sysctrl->lightResume();
162 } else if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepResume != NULL)) {
163 pm->sysctrl->deepResume();
164 }
165 }
166
OsPmCpuSuspend(LosPmCB * pm)167 STATIC VOID OsPmCpuSuspend(LosPmCB *pm)
168 {
169 /* cpu enter low power mode */
170 LOS_ASSERT(pm->sysctrl != NULL);
171
172 if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) {
173 pm->sysctrl->normalSuspend();
174 } else if (pm->sysMode == LOS_SYS_LIGHT_SLEEP) {
175 pm->sysctrl->lightSuspend();
176 } else if (pm->sysMode == LOS_SYS_DEEP_SLEEP) {
177 pm->sysctrl->deepSuspend();
178 } else {
179 pm->sysctrl->shutdownSuspend();
180 }
181 }
182
OsPmResumePrepare(LosPmCB * pm,UINT32 mode,UINT32 prepare)183 STATIC VOID OsPmResumePrepare(LosPmCB *pm, UINT32 mode, UINT32 prepare)
184 {
185 if ((prepare == 0) && (pm->device->resume != NULL)) {
186 pm->device->resume(mode);
187 }
188
189 if (((prepare == 0) || (prepare == OS_PM_SYS_DEVICE_EARLY)) && (pm->sysctrl->late != NULL)) {
190 pm->sysctrl->late(mode);
191 }
192 }
193
OsPmSuspendPrepare(Suspend sysSuspendEarly,Suspend deviceSuspend,UINT32 mode,UINT32 * prepare)194 STATIC UINT32 OsPmSuspendPrepare(Suspend sysSuspendEarly, Suspend deviceSuspend, UINT32 mode, UINT32 *prepare)
195 {
196 UINT32 ret;
197
198 if (sysSuspendEarly != NULL) {
199 ret = sysSuspendEarly(mode);
200 if (ret != LOS_OK) {
201 *prepare = OS_PM_SYS_EARLY;
202 return ret;
203 }
204 }
205
206 if (deviceSuspend != NULL) {
207 ret = deviceSuspend(mode);
208 if (ret != LOS_OK) {
209 *prepare = OS_PM_SYS_DEVICE_EARLY;
210 return ret;
211 }
212 }
213
214 return LOS_OK;
215 }
216
OsPmSuspendCheck(LosPmCB * pm,Suspend * sysSuspendEarly,Suspend * deviceSuspend,LOS_SysSleepEnum * mode)217 STATIC UINT32 OsPmSuspendCheck(LosPmCB *pm, Suspend *sysSuspendEarly, Suspend *deviceSuspend, LOS_SysSleepEnum *mode)
218 {
219 UINT32 intSave;
220
221 intSave = LOS_IntLock();
222 pm->sysMode = pm->pmMode;
223 if (pm->lock > 0) {
224 pm->sysMode = LOS_SYS_NORMAL_SLEEP;
225 LOS_IntRestore(intSave);
226 return LOS_NOK;
227 }
228
229 pm->isWake = FALSE;
230 *mode = pm->sysMode;
231 *sysSuspendEarly = pm->sysctrl->early;
232 *deviceSuspend = pm->device->suspend;
233 LOS_IntRestore(intSave);
234 return LOS_OK;
235 }
236
OsPmSuspendSleep(LosPmCB * pm)237 STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
238 {
239 UINT32 ret, intSave;
240 Suspend sysSuspendEarly, deviceSuspend;
241 LOS_SysSleepEnum mode;
242 UINT32 prepare = 0;
243 BOOL tickTimerStop = FALSE;
244
245 ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode);
246 if (ret != LOS_OK) {
247 return ret;
248 }
249
250 ret = OsPmSuspendPrepare(sysSuspendEarly, deviceSuspend, (UINT32)mode, &prepare);
251 if (ret != LOS_OK) {
252 intSave = LOS_IntLock();
253 LOS_TaskLock();
254 goto EXIT;
255 }
256
257 intSave = LOS_IntLock();
258 LOS_TaskLock();
259 if (pm->isWake || (pm->lock > 0)) {
260 goto EXIT;
261 }
262
263 tickTimerStop = OsPmTickTimerStop(pm);
264 if (!tickTimerStop) {
265 OsSchedResetSchedResponseTime(0);
266 OsSchedUpdateExpireTime();
267 }
268
269 OsPmCpuSuspend(pm);
270
271 OsPmCpuResume(pm);
272
273 OsPmTickTimerStart(pm);
274
275 EXIT:
276 pm->sysMode = LOS_SYS_NORMAL_SLEEP;
277 OsPmResumePrepare(pm, (UINT32)mode, prepare);
278 LOS_IntRestore(intSave);
279
280 LOS_TaskUnlock();
281 return ret;
282 }
283
OsPmNormalSleep(VOID)284 STATIC VOID OsPmNormalSleep(VOID)
285 {
286 UINT32 intSave;
287 LosPmCB *pm = &g_pmCB;
288
289 intSave = LOS_IntLock();
290
291 OsPmCpuSuspend(pm);
292
293 OsPmCpuResume(pm);
294
295 LOS_IntRestore(intSave);
296 }
297
OsPmDeviceRegister(LosPmCB * pm,LosPmDevice * device)298 STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
299 {
300 UINT32 intSave;
301
302 if ((device->suspend == NULL) || (device->resume == NULL)) {
303 return LOS_ERRNO_PM_INVALID_PARAM;
304 }
305
306 intSave = LOS_IntLock();
307 pm->device = device;
308 LOS_IntRestore(intSave);
309
310 return LOS_OK;
311 }
312
OsPmTickTimerRegister(LosPmCB * pm,LosPmTickTimer * tickTimer)313 STATIC UINT32 OsPmTickTimerRegister(LosPmCB *pm, LosPmTickTimer *tickTimer)
314 {
315 UINT32 intSave;
316
317 if ((tickTimer->tickLock == NULL) || (tickTimer->tickUnlock == NULL)) {
318 return LOS_ERRNO_PM_INVALID_PARAM;
319 }
320
321 if (((tickTimer->timerStart == NULL) && (tickTimer->timerStop == NULL) &&
322 (tickTimer->timerCycleGet == NULL) && (tickTimer->freq == 0)) ||
323 ((tickTimer->timerStart != NULL) && (tickTimer->timerStop != NULL) &&
324 (tickTimer->timerCycleGet != NULL) && (tickTimer->freq != 0))) {
325 intSave = LOS_IntLock();
326 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
327 pm->enterSleepTime = 0;
328 #endif
329 pm->tickTimer = tickTimer;
330 LOS_IntRestore(intSave);
331 return LOS_OK;
332 }
333
334 return LOS_ERRNO_PM_INVALID_PARAM;
335 }
336
OsPmSysctrlRegister(LosPmCB * pm,LosPmSysctrl * sysctrl)337 STATIC UINT32 OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)
338 {
339 UINT32 intSave = LOS_IntLock();
340 if (sysctrl->early != NULL) {
341 pm->sysctrl->early = sysctrl->early;
342 }
343 if (sysctrl->late != NULL) {
344 pm->sysctrl->late = sysctrl->late;
345 }
346 if (sysctrl->normalSuspend != NULL) {
347 pm->sysctrl->normalSuspend = sysctrl->normalSuspend;
348 }
349 if (sysctrl->normalResume != NULL) {
350 pm->sysctrl->normalResume = sysctrl->normalResume;
351 }
352 if (sysctrl->lightSuspend != NULL) {
353 pm->sysctrl->lightSuspend = sysctrl->lightSuspend;
354 }
355 if (sysctrl->lightResume != NULL) {
356 pm->sysctrl->lightResume = sysctrl->lightResume;
357 }
358 if (sysctrl->deepSuspend != NULL) {
359 pm->sysctrl->deepSuspend = sysctrl->deepSuspend;
360 }
361 if (sysctrl->deepResume != NULL) {
362 pm->sysctrl->deepResume = sysctrl->deepResume;
363 }
364 if (sysctrl->shutdownSuspend != NULL) {
365 pm->sysctrl->shutdownSuspend = sysctrl->shutdownSuspend;
366 }
367 if (sysctrl->shutdownResume != NULL) {
368 pm->sysctrl->shutdownResume = sysctrl->shutdownResume;
369 }
370 LOS_IntRestore(intSave);
371 return LOS_OK;
372 }
373
LOS_PmRegister(LOS_PmNodeType type,VOID * node)374 UINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node)
375 {
376 LosPmCB *pm = &g_pmCB;
377
378 if (node == NULL) {
379 return LOS_ERRNO_PM_INVALID_PARAM;
380 }
381
382 switch (type) {
383 case LOS_PM_TYPE_DEVICE:
384 return OsPmDeviceRegister(pm, (LosPmDevice *)node);
385 case LOS_PM_TYPE_TICK_TIMER:
386 return OsPmTickTimerRegister(pm, (LosPmTickTimer *)node);
387 case LOS_PM_TYPE_SYSCTRL:
388 return OsPmSysctrlRegister(pm, (LosPmSysctrl *)node);
389 default:
390 break;
391 }
392
393 return LOS_ERRNO_PM_INVALID_TYPE;
394 }
395
OsPmDeviceUnregister(LosPmCB * pm,LosPmDevice * device)396 STATIC UINT32 OsPmDeviceUnregister(LosPmCB *pm, LosPmDevice *device)
397 {
398 UINT32 intSave;
399
400 intSave = LOS_IntLock();
401 if (pm->device == device) {
402 pm->device = NULL;
403 pm->pmMode = LOS_SYS_NORMAL_SLEEP;
404 LOS_IntRestore(intSave);
405 return LOS_OK;
406 }
407
408 LOS_IntRestore(intSave);
409 return LOS_ERRNO_PM_INVALID_NODE;
410 }
411
OsPmTickTimerUnregister(LosPmCB * pm,LosPmTickTimer * tickTimer)412 STATIC UINT32 OsPmTickTimerUnregister(LosPmCB *pm, LosPmTickTimer *tickTimer)
413 {
414 UINT32 intSave;
415
416 intSave = LOS_IntLock();
417 if (pm->tickTimer == tickTimer) {
418 pm->tickTimer = NULL;
419 if ((pm->pmMode != LOS_SYS_NORMAL_SLEEP) && (pm->pmMode != LOS_SYS_LIGHT_SLEEP)) {
420 pm->pmMode = LOS_SYS_NORMAL_SLEEP;
421 }
422 LOS_IntRestore(intSave);
423 return LOS_OK;
424 }
425
426 LOS_IntRestore(intSave);
427 return LOS_ERRNO_PM_INVALID_NODE;
428 }
429
OsPmSysctrlUnregister(LosPmCB * pm,LosPmSysctrl * sysctrl)430 STATIC UINT32 OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)
431 {
432 (VOID)sysctrl;
433
434 UINT32 intSave = LOS_IntLock();
435 OsPmSysctrlInit();
436 pm->pmMode = LOS_SYS_NORMAL_SLEEP;
437 LOS_IntRestore(intSave);
438 return LOS_OK;
439 }
440
LOS_PmUnregister(LOS_PmNodeType type,VOID * node)441 UINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node)
442 {
443 LosPmCB *pm = &g_pmCB;
444
445 if (node == NULL) {
446 return LOS_ERRNO_PM_INVALID_PARAM;
447 }
448
449 switch (type) {
450 case LOS_PM_TYPE_DEVICE:
451 return OsPmDeviceUnregister(pm, (LosPmDevice *)node);
452 case LOS_PM_TYPE_TICK_TIMER:
453 return OsPmTickTimerUnregister(pm, (LosPmTickTimer *)node);
454 case LOS_PM_TYPE_SYSCTRL:
455 return OsPmSysctrlUnregister(pm, (LosPmSysctrl *)node);
456 default:
457 break;
458 }
459
460 return LOS_ERRNO_PM_INVALID_TYPE;
461 }
462
LOS_PmWakeSet(VOID)463 VOID LOS_PmWakeSet(VOID)
464 {
465 UINT32 intSave;
466 LosPmCB *pm = &g_pmCB;
467
468 intSave = LOS_IntLock();
469 pm->isWake = TRUE;
470 LOS_IntRestore(intSave);
471 return;
472 }
473
LOS_PmModeGet(VOID)474 LOS_SysSleepEnum LOS_PmModeGet(VOID)
475 {
476 LOS_SysSleepEnum mode;
477 LosPmCB *pm = &g_pmCB;
478
479 UINT32 intSave = LOS_IntLock();
480 mode = pm->pmMode;
481 LOS_IntRestore(intSave);
482
483 return mode;
484 }
485
LOS_PmModeSet(LOS_SysSleepEnum mode)486 UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
487 {
488 UINT32 intSave;
489 LosPmCB *pm = &g_pmCB;
490 INT32 sleepMode = (INT32)mode;
491
492 if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
493 return LOS_ERRNO_PM_INVALID_MODE;
494 }
495
496 intSave = LOS_IntLock();
497 if ((mode != LOS_SYS_NORMAL_SLEEP) && (pm->device == NULL)) {
498 LOS_IntRestore(intSave);
499 return LOS_ERRNO_PM_DEVICE_NULL;
500 }
501
502 if ((mode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightSuspend == NULL)) {
503 LOS_IntRestore(intSave);
504 return LOS_ERRNO_PM_HANDLER_NULL;
505 }
506
507 if ((mode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepSuspend == NULL)) {
508 LOS_IntRestore(intSave);
509 return LOS_ERRNO_PM_HANDLER_NULL;
510 }
511
512 if ((mode == LOS_SYS_SHUTDOWN) && (pm->sysctrl->shutdownSuspend == NULL)) {
513 LOS_IntRestore(intSave);
514 return LOS_ERRNO_PM_HANDLER_NULL;
515 }
516
517 pm->pmMode = mode;
518 LOS_IntRestore(intSave);
519
520 return LOS_OK;
521 }
522
523 #if (LOSCFG_KERNEL_PM_DEBUG == 1)
LOS_PmLockInfoShow(VOID)524 VOID LOS_PmLockInfoShow(VOID)
525 {
526 UINT32 intSave;
527 LosPmCB *pm = &g_pmCB;
528 OsPmLockCB *lock = NULL;
529 LOS_DL_LIST *head = &pm->lockList;
530 LOS_DL_LIST *list = head->pstNext;
531
532 PRINTK("Name Count\n\r");
533
534 intSave = LOS_IntLock();
535 while (list != head) {
536 lock = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
537 PRINTK("%-30s%5u\n\r", lock->name, lock->count);
538 list = list->pstNext;
539 }
540 LOS_IntRestore(intSave);
541
542 return;
543 }
544 #endif
545
OsPmLockRequest(const CHAR * name,UINT32 swtmrID)546 UINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID)
547 {
548 UINT32 intSave;
549 UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
550 LosPmCB *pm = &g_pmCB;
551 OsPmLockCB *listNode = NULL;
552 OsPmLockCB *lock = NULL;
553 LOS_DL_LIST *head = &pm->lockList;
554 LOS_DL_LIST *list = head->pstNext;
555
556 intSave = LOS_IntLock();
557 while (list != head) {
558 listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
559 if (strcmp(name, listNode->name) == 0) {
560 lock = listNode;
561 break;
562 }
563
564 list = list->pstNext;
565 }
566
567 if (lock == NULL) {
568 lock = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(OsPmLockCB));
569 if (lock == NULL) {
570 LOS_IntRestore(intSave);
571 return LOS_NOK;
572 }
573 lock->name = (CHAR *)name;
574 lock->count = 1;
575 lock->swtmrID = swtmrID;
576 LOS_ListTailInsert(head, &lock->list);
577 } else if (lock->count < OS_PM_LOCK_MAX) {
578 lock->count++;
579 }
580
581 if ((lock->swtmrID != OS_INVALID) && (lock->count > 1)) {
582 lock->count--;
583 LOS_IntRestore(intSave);
584 return LOS_ERRNO_PM_ALREADY_LOCK;
585 }
586
587 if (pm->lock < OS_PM_LOCK_MAX) {
588 pm->lock++;
589 ret = LOS_OK;
590 }
591
592 LOS_IntRestore(intSave);
593 return ret;
594 }
595
LOS_PmLockRequest(const CHAR * name)596 UINT32 LOS_PmLockRequest(const CHAR *name)
597 {
598 if (name == NULL) {
599 return LOS_ERRNO_PM_INVALID_PARAM;
600 }
601
602 return OsPmLockRequest(name, OS_INVALID);
603 }
604
LOS_PmLockRelease(const CHAR * name)605 UINT32 LOS_PmLockRelease(const CHAR *name)
606 {
607 UINT32 intSave;
608 UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
609 LosPmCB *pm = &g_pmCB;
610 OsPmLockCB *lock = NULL;
611 OsPmLockCB *listNode = NULL;
612 LOS_DL_LIST *head = &pm->lockList;
613 LOS_DL_LIST *list = head->pstNext;
614 OsPmLockCB *lockFree = NULL;
615 BOOL isRelease = FALSE;
616 UINT32 mode;
617
618 if (name == NULL) {
619 return LOS_ERRNO_PM_INVALID_PARAM;
620 }
621
622 intSave = LOS_IntLock();
623 mode = (UINT32)pm->pmMode;
624 while (list != head) {
625 listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
626 if (strcmp(name, listNode->name) == 0) {
627 lock = listNode;
628 break;
629 }
630
631 list = list->pstNext;
632 }
633
634 if (lock == NULL) {
635 LOS_IntRestore(intSave);
636 return LOS_ERRNO_PM_NOT_LOCK;
637 } else if (lock->count > 0) {
638 lock->count--;
639 if (lock->count == 0) {
640 LOS_ListDelete(&lock->list);
641 lockFree = lock;
642 }
643 }
644
645 if (pm->lock > 0) {
646 pm->lock--;
647 if (pm->lock == 0) {
648 isRelease = TRUE;
649 }
650 ret = LOS_OK;
651 }
652 LOS_IntRestore(intSave);
653
654 if (lockFree != NULL) {
655 (VOID)LOS_SwtmrDelete(lockFree->swtmrID);
656 (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
657 }
658
659 if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) {
660 (VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE);
661 }
662
663 return ret;
664 }
665
OsPmSwtmrHandler(UINT32 arg)666 STATIC VOID OsPmSwtmrHandler(UINT32 arg)
667 {
668 const CHAR *name = (const CHAR *)(UINTPTR)arg;
669 UINT32 ret = LOS_PmLockRelease(name);
670 if (ret != LOS_OK) {
671 PRINT_ERR("Pm delay lock %s release faled! : 0x%x\n", name, ret);
672 }
673 }
674
LOS_PmTimeLockRequest(const CHAR * name,UINT64 millisecond)675 UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond)
676 {
677 UINT32 ticks;
678 UINT32 swtmrID;
679 UINT32 ret;
680
681 if ((name == NULL) || !millisecond) {
682 return LOS_ERRNO_PM_INVALID_PARAM;
683 }
684
685 ticks = (UINT32)((millisecond + OS_MS_PER_TICK - 1) / OS_MS_PER_TICK);
686 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
687 ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name,
688 OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
689 #else
690 ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name);
691 #endif
692 if (ret != LOS_OK) {
693 return ret;
694 }
695
696 ret = OsPmLockRequest(name, swtmrID);
697 if (ret != LOS_OK) {
698 (VOID)LOS_SwtmrDelete(swtmrID);
699 return ret;
700 }
701
702 ret = LOS_SwtmrStart(swtmrID);
703 if (ret != LOS_OK) {
704 (VOID)LOS_PmLockRelease(name);
705 }
706
707 return ret;
708 }
709
LOS_PmReadLock(VOID)710 UINT32 LOS_PmReadLock(VOID)
711 {
712 UINT32 ret = LOS_EventRead(&g_pmEvent, PM_EVENT_LOCK_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
713 if (ret > PM_EVENT_LOCK_MASK) {
714 PRINT_ERR("%s event read failed! ERROR: 0x%x\n", __FUNCTION__, ret);
715 }
716
717 return LOS_OK;
718 }
719
LOS_PmSuspend(UINT32 wakeCount)720 UINT32 LOS_PmSuspend(UINT32 wakeCount)
721 {
722 (VOID)wakeCount;
723 return OsPmSuspendSleep(&g_pmCB);
724 }
725
OsIsPmMode(VOID)726 BOOL OsIsPmMode(VOID)
727 {
728 LosPmCB *pm = &g_pmCB;
729
730 UINT32 intSave = LOS_IntLock();
731 if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock == 0)) {
732 LOS_IntRestore(intSave);
733 return TRUE;
734 }
735 LOS_IntRestore(intSave);
736 return FALSE;
737 }
738
OsPmInit(VOID)739 UINT32 OsPmInit(VOID)
740 {
741 UINT32 ret;
742 LosPmCB *pm = &g_pmCB;
743
744 (VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
745
746 pm->pmMode = LOS_SYS_NORMAL_SLEEP;
747 LOS_ListInit(&pm->lockList);
748 (VOID)LOS_EventInit(&g_pmEvent);
749
750 ret = OsPmEnterHandlerSet(OsPmNormalSleep);
751 if (ret != LOS_OK) {
752 return ret;
753 }
754
755 OsPmSysctrlInit();
756 pm->sysctrl = &g_sysctrl;
757 return ret;
758 }
759 #endif
760