• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         (pm->sysMode == LOS_SYS_NORMAL_SLEEP)) {
134         return FALSE;
135     }
136 
137 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
138     if (tickTimer->timerStart != NULL) {
139         LOS_ASSERT(expireTime > currTime);
140 
141         realSleepTime = expireTime - currTime;
142         sleepCycle = OS_SYS_CYCLE_TO_NS(realSleepTime, g_sysClock);
143         sleepCycle = OS_SYS_NS_TO_CYCLE(sleepCycle, tickTimer->freq);
144 
145         /* The main CPU reduces the frequency */
146         pm->enterSleepTime = LOS_SysCycleGet();
147         tickTimer->tickLock();
148         tickTimer->timerStart(sleepCycle);
149         return TRUE;
150     }
151 #endif
152 
153     tickTimer->tickLock();
154     return TRUE;
155 }
156 
OsPmCpuResume(LosPmCB * pm)157 STATIC VOID OsPmCpuResume(LosPmCB *pm)
158 {
159     if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) && (pm->sysctrl->normalResume != NULL)) {
160         pm->sysctrl->normalResume();
161     } else if ((pm->sysMode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightResume != NULL)) {
162         pm->sysctrl->lightResume();
163     } else if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepResume != NULL)) {
164         pm->sysctrl->deepResume();
165     }
166 }
167 
OsPmCpuSuspend(LosPmCB * pm)168 STATIC VOID OsPmCpuSuspend(LosPmCB *pm)
169 {
170     /* cpu enter low power mode */
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     LOS_ASSERT(pm->sysctrl != NULL);
230 
231     pm->isWake = FALSE;
232     *mode = pm->sysMode;
233     *sysSuspendEarly = pm->sysctrl->early;
234     *deviceSuspend = pm->device->suspend;
235     LOS_IntRestore(intSave);
236     return LOS_OK;
237 }
238 
OsPmSuspendSleep(LosPmCB * pm)239 STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
240 {
241     UINT32 ret, intSave;
242     Suspend sysSuspendEarly, deviceSuspend;
243     LOS_SysSleepEnum mode;
244     UINT32 prepare = 0;
245     BOOL tickTimerStop = FALSE;
246 
247     ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode);
248     if (ret != LOS_OK) {
249         return ret;
250     }
251 
252     ret = OsPmSuspendPrepare(sysSuspendEarly, deviceSuspend, (UINT32)mode, &prepare);
253     if (ret != LOS_OK) {
254         intSave = LOS_IntLock();
255         LOS_TaskLock();
256         goto EXIT;
257     }
258 
259     intSave = LOS_IntLock();
260     LOS_TaskLock();
261     if (pm->isWake || (pm->lock > 0)) {
262         goto EXIT;
263     }
264 
265     if (pm->sysctrl->suspendCheck != NULL) {
266         pm->sysctrl->suspendCheck(mode);
267         pm->sysMode = pm->pmMode;
268     }
269 
270     tickTimerStop = OsPmTickTimerStop(pm);
271     if (!tickTimerStop) {
272         OsSchedResetSchedResponseTime(0);
273         OsSchedUpdateExpireTime();
274     }
275 
276     OsPmCpuSuspend(pm);
277 
278     OsPmCpuResume(pm);
279 
280     OsPmTickTimerStart(pm);
281 
282 EXIT:
283     pm->sysMode = LOS_SYS_NORMAL_SLEEP;
284     OsPmResumePrepare(pm, (UINT32)mode, prepare);
285     LOS_IntRestore(intSave);
286 
287     LOS_TaskUnlock();
288     return ret;
289 }
290 
OsPmNormalSleep(VOID)291 STATIC VOID OsPmNormalSleep(VOID)
292 {
293 #if (LOSCFG_KERNEL_PM_IDLE == 1)
294     (VOID)LOS_PmSuspend(0);
295 #else
296     UINT32 intSave;
297     LosPmCB *pm = &g_pmCB;
298 
299     intSave = LOS_IntLock();
300 
301     OsPmCpuSuspend(pm);
302 
303     OsPmCpuResume(pm);
304 
305     LOS_IntRestore(intSave);
306 #endif
307 }
308 
OsPmDeviceRegister(LosPmCB * pm,LosPmDevice * device)309 STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
310 {
311     UINT32 intSave;
312 
313     if ((device->suspend == NULL) || (device->resume == NULL)) {
314         return LOS_ERRNO_PM_INVALID_PARAM;
315     }
316 
317     intSave = LOS_IntLock();
318     pm->device = device;
319     LOS_IntRestore(intSave);
320 
321     return LOS_OK;
322 }
323 
OsPmTickTimerRegister(LosPmCB * pm,LosPmTickTimer * tickTimer)324 STATIC UINT32 OsPmTickTimerRegister(LosPmCB *pm, LosPmTickTimer *tickTimer)
325 {
326     UINT32 intSave;
327 
328     if ((tickTimer->tickLock == NULL) || (tickTimer->tickUnlock == NULL)) {
329         return LOS_ERRNO_PM_INVALID_PARAM;
330     }
331 
332     if (((tickTimer->timerStart == NULL) && (tickTimer->timerStop == NULL) &&
333          (tickTimer->timerCycleGet == NULL) && (tickTimer->freq == 0)) ||
334         ((tickTimer->timerStart != NULL) && (tickTimer->timerStop != NULL) &&
335          (tickTimer->timerCycleGet != NULL) && (tickTimer->freq != 0))) {
336         intSave = LOS_IntLock();
337 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
338         pm->enterSleepTime = 0;
339 #endif
340         pm->tickTimer = tickTimer;
341         LOS_IntRestore(intSave);
342         return LOS_OK;
343     }
344 
345     return LOS_ERRNO_PM_INVALID_PARAM;
346 }
347 
OsPmSysctrlRegister(LosPmCB * pm,LosPmSysctrl * sysctrl)348 STATIC UINT32 OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)
349 {
350     UINT32 intSave = LOS_IntLock();
351     if (sysctrl->early != NULL) {
352         pm->sysctrl->early = sysctrl->early;
353     }
354     if (sysctrl->late != NULL) {
355         pm->sysctrl->late = sysctrl->late;
356     }
357     if (sysctrl->suspendCheck != NULL) {
358         pm->sysctrl->suspendCheck = sysctrl->suspendCheck;
359     }
360     if (sysctrl->normalSuspend != NULL) {
361         pm->sysctrl->normalSuspend = sysctrl->normalSuspend;
362     }
363     if (sysctrl->normalResume != NULL) {
364         pm->sysctrl->normalResume = sysctrl->normalResume;
365     }
366     if (sysctrl->lightSuspend != NULL) {
367         pm->sysctrl->lightSuspend = sysctrl->lightSuspend;
368     }
369     if (sysctrl->lightResume != NULL) {
370         pm->sysctrl->lightResume = sysctrl->lightResume;
371     }
372     if (sysctrl->deepSuspend != NULL) {
373         pm->sysctrl->deepSuspend = sysctrl->deepSuspend;
374     }
375     if (sysctrl->deepResume != NULL) {
376         pm->sysctrl->deepResume = sysctrl->deepResume;
377     }
378     if (sysctrl->shutdownSuspend != NULL) {
379         pm->sysctrl->shutdownSuspend = sysctrl->shutdownSuspend;
380     }
381     if (sysctrl->shutdownResume != NULL) {
382         pm->sysctrl->shutdownResume = sysctrl->shutdownResume;
383     }
384     LOS_IntRestore(intSave);
385     return LOS_OK;
386 }
387 
LOS_PmRegister(LOS_PmNodeType type,VOID * node)388 UINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node)
389 {
390     LosPmCB *pm = &g_pmCB;
391 
392     if (node == NULL) {
393         return LOS_ERRNO_PM_INVALID_PARAM;
394     }
395 
396     switch (type) {
397         case LOS_PM_TYPE_DEVICE:
398             return OsPmDeviceRegister(pm, (LosPmDevice *)node);
399         case LOS_PM_TYPE_TICK_TIMER:
400             return OsPmTickTimerRegister(pm, (LosPmTickTimer *)node);
401         case LOS_PM_TYPE_SYSCTRL:
402             return OsPmSysctrlRegister(pm, (LosPmSysctrl *)node);
403         default:
404             break;
405     }
406 
407     return LOS_ERRNO_PM_INVALID_TYPE;
408 }
409 
OsPmDeviceUnregister(LosPmCB * pm,LosPmDevice * device)410 STATIC UINT32 OsPmDeviceUnregister(LosPmCB *pm, LosPmDevice *device)
411 {
412     UINT32 intSave;
413 
414     intSave = LOS_IntLock();
415     if (pm->device == device) {
416         pm->device = NULL;
417         pm->pmMode = LOS_SYS_NORMAL_SLEEP;
418         LOS_IntRestore(intSave);
419         return LOS_OK;
420     }
421 
422     LOS_IntRestore(intSave);
423     return LOS_ERRNO_PM_INVALID_NODE;
424 }
425 
OsPmTickTimerUnregister(LosPmCB * pm,LosPmTickTimer * tickTimer)426 STATIC UINT32 OsPmTickTimerUnregister(LosPmCB *pm, LosPmTickTimer *tickTimer)
427 {
428     UINT32 intSave;
429 
430     intSave = LOS_IntLock();
431     if (pm->tickTimer == tickTimer) {
432         pm->tickTimer = NULL;
433         if ((pm->pmMode != LOS_SYS_NORMAL_SLEEP) && (pm->pmMode != LOS_SYS_LIGHT_SLEEP)) {
434             pm->pmMode = LOS_SYS_NORMAL_SLEEP;
435         }
436         LOS_IntRestore(intSave);
437         return LOS_OK;
438     }
439 
440     LOS_IntRestore(intSave);
441     return LOS_ERRNO_PM_INVALID_NODE;
442 }
443 
OsPmSysctrlUnregister(LosPmCB * pm,LosPmSysctrl * sysctrl)444 STATIC UINT32 OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)
445 {
446     (VOID)sysctrl;
447 
448     UINT32 intSave = LOS_IntLock();
449     OsPmSysctrlInit();
450     pm->pmMode = LOS_SYS_NORMAL_SLEEP;
451     LOS_IntRestore(intSave);
452     return LOS_OK;
453 }
454 
LOS_PmUnregister(LOS_PmNodeType type,VOID * node)455 UINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node)
456 {
457     LosPmCB *pm = &g_pmCB;
458 
459     if (node == NULL) {
460         return LOS_ERRNO_PM_INVALID_PARAM;
461     }
462 
463     switch (type) {
464         case LOS_PM_TYPE_DEVICE:
465             return OsPmDeviceUnregister(pm, (LosPmDevice *)node);
466         case LOS_PM_TYPE_TICK_TIMER:
467             return OsPmTickTimerUnregister(pm, (LosPmTickTimer *)node);
468         case LOS_PM_TYPE_SYSCTRL:
469             return OsPmSysctrlUnregister(pm, (LosPmSysctrl *)node);
470         default:
471             break;
472     }
473 
474     return LOS_ERRNO_PM_INVALID_TYPE;
475 }
476 
LOS_PmWakeSet(VOID)477 VOID LOS_PmWakeSet(VOID)
478 {
479     UINT32 intSave;
480     LosPmCB *pm = &g_pmCB;
481 
482     intSave = LOS_IntLock();
483     pm->isWake = TRUE;
484     LOS_IntRestore(intSave);
485     return;
486 }
487 
LOS_PmModeGet(VOID)488 LOS_SysSleepEnum LOS_PmModeGet(VOID)
489 {
490     LOS_SysSleepEnum mode;
491     LosPmCB *pm = &g_pmCB;
492 
493     UINT32 intSave = LOS_IntLock();
494     mode = pm->pmMode;
495     LOS_IntRestore(intSave);
496 
497     return mode;
498 }
499 
LOS_PmModeSet(LOS_SysSleepEnum mode)500 UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
501 {
502     UINT32 intSave;
503     LosPmCB *pm = &g_pmCB;
504     INT32 sleepMode = (INT32)mode;
505 
506     if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
507         return LOS_ERRNO_PM_INVALID_MODE;
508     }
509 
510     intSave = LOS_IntLock();
511     if ((mode != LOS_SYS_NORMAL_SLEEP) && (pm->device == NULL)) {
512         LOS_IntRestore(intSave);
513         return LOS_ERRNO_PM_DEVICE_NULL;
514     }
515 
516     if ((mode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightSuspend == NULL)) {
517         LOS_IntRestore(intSave);
518         return LOS_ERRNO_PM_HANDLER_NULL;
519     }
520 
521     if ((mode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepSuspend == NULL)) {
522         LOS_IntRestore(intSave);
523         return LOS_ERRNO_PM_HANDLER_NULL;
524     }
525 
526     if ((mode == LOS_SYS_SHUTDOWN) && (pm->sysctrl->shutdownSuspend == NULL)) {
527         LOS_IntRestore(intSave);
528         return LOS_ERRNO_PM_HANDLER_NULL;
529     }
530 
531     pm->pmMode = mode;
532     LOS_IntRestore(intSave);
533 
534     return LOS_OK;
535 }
536 
537 #if (LOSCFG_KERNEL_PM_DEBUG == 1)
LOS_PmLockInfoShow(VOID)538 VOID LOS_PmLockInfoShow(VOID)
539 {
540     UINT32 intSave;
541     LosPmCB *pm = &g_pmCB;
542     OsPmLockCB *lock = NULL;
543     LOS_DL_LIST *head = &pm->lockList;
544     LOS_DL_LIST *list = head->pstNext;
545 
546     PRINTK("Name                          Count\n\r");
547 
548     intSave = LOS_IntLock();
549     while (list != head) {
550         lock = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
551         PRINTK("%-30s%5u\n\r", lock->name, lock->count);
552         list = list->pstNext;
553     }
554     LOS_IntRestore(intSave);
555 
556     return;
557 }
558 #endif
559 
OsPmLockRequest(const CHAR * name,UINT32 swtmrID)560 UINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID)
561 {
562     UINT32 intSave;
563     UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
564     LosPmCB *pm = &g_pmCB;
565     OsPmLockCB *listNode = NULL;
566     OsPmLockCB *lock = NULL;
567     LOS_DL_LIST *head = &pm->lockList;
568     LOS_DL_LIST *list = head->pstNext;
569 
570     intSave = LOS_IntLock();
571     while (list != head) {
572         listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
573         if (strcmp(name, listNode->name) == 0) {
574             lock = listNode;
575             break;
576         }
577 
578         list = list->pstNext;
579     }
580 
581     if (lock == NULL) {
582         lock = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(OsPmLockCB));
583         if (lock == NULL) {
584             LOS_IntRestore(intSave);
585             return LOS_NOK;
586         }
587         lock->name = (CHAR *)name;
588         lock->count = 1;
589         lock->swtmrID = swtmrID;
590         LOS_ListTailInsert(head, &lock->list);
591     } else if (lock->count < OS_PM_LOCK_MAX) {
592         lock->count++;
593     }
594 
595     if ((lock->swtmrID != OS_INVALID) && (lock->count > 1)) {
596         lock->count--;
597         LOS_IntRestore(intSave);
598         return LOS_ERRNO_PM_ALREADY_LOCK;
599     }
600 
601     if (pm->lock < OS_PM_LOCK_MAX) {
602         pm->lock++;
603         ret = LOS_OK;
604     }
605 
606     LOS_IntRestore(intSave);
607     return ret;
608 }
609 
LOS_PmLockRequest(const CHAR * name)610 UINT32 LOS_PmLockRequest(const CHAR *name)
611 {
612     if (name == NULL) {
613         return LOS_ERRNO_PM_INVALID_PARAM;
614     }
615 
616     return OsPmLockRequest(name, OS_INVALID);
617 }
618 
LOS_PmLockRelease(const CHAR * name)619 UINT32 LOS_PmLockRelease(const CHAR *name)
620 {
621     UINT32 intSave;
622     UINT32 ret = LOS_ERRNO_PM_NOT_LOCK;
623     LosPmCB *pm = &g_pmCB;
624     OsPmLockCB *lock = NULL;
625     OsPmLockCB *listNode = NULL;
626     LOS_DL_LIST *head = &pm->lockList;
627     LOS_DL_LIST *list = head->pstNext;
628     OsPmLockCB *lockFree = NULL;
629     BOOL isRelease = FALSE;
630     UINT32 mode;
631 
632     if (name == NULL) {
633         return LOS_ERRNO_PM_INVALID_PARAM;
634     }
635 
636     intSave = LOS_IntLock();
637     mode = (UINT32)pm->pmMode;
638     while (list != head) {
639         listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
640         if (strcmp(name, listNode->name) == 0) {
641             lock = listNode;
642             break;
643         }
644 
645         list = list->pstNext;
646     }
647 
648     if (lock == NULL) {
649         LOS_IntRestore(intSave);
650         return LOS_ERRNO_PM_NOT_LOCK;
651     } else if (lock->count > 0) {
652         lock->count--;
653         if (lock->count == 0) {
654             LOS_ListDelete(&lock->list);
655             lockFree = lock;
656         }
657     }
658 
659     if (pm->lock > 0) {
660         pm->lock--;
661         if (pm->lock == 0) {
662             isRelease = TRUE;
663         }
664         ret = LOS_OK;
665     }
666     LOS_IntRestore(intSave);
667 
668     if (lockFree != NULL) {
669         (VOID)LOS_SwtmrDelete(lockFree->swtmrID);
670         (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
671     }
672 
673     if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) {
674         (VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE);
675     }
676 
677     return ret;
678 }
679 
OsPmSwtmrHandler(UINT32 arg)680 STATIC VOID OsPmSwtmrHandler(UINT32 arg)
681 {
682     const CHAR *name = (const CHAR *)(UINTPTR)arg;
683     UINT32 ret = LOS_PmLockRelease(name);
684     if (ret != LOS_OK) {
685         PRINT_ERR("Pm delay lock %s release faled! : 0x%x\n", name, ret);
686     }
687 }
688 
LOS_PmTimeLockRequest(const CHAR * name,UINT64 millisecond)689 UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond)
690 {
691     UINT32 ticks;
692     UINT32 swtmrID;
693     UINT32 ret;
694 
695     if ((name == NULL) || !millisecond) {
696         return LOS_ERRNO_PM_INVALID_PARAM;
697     }
698 
699     ticks = (UINT32)((millisecond + OS_MS_PER_TICK - 1) / OS_MS_PER_TICK);
700 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
701     ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name,
702                           OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
703 #else
704     ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name);
705 #endif
706     if (ret != LOS_OK) {
707         return ret;
708     }
709 
710     ret = OsPmLockRequest(name, swtmrID);
711     if (ret != LOS_OK) {
712         (VOID)LOS_SwtmrDelete(swtmrID);
713         return ret;
714     }
715 
716     ret = LOS_SwtmrStart(swtmrID);
717     if (ret != LOS_OK) {
718         (VOID)LOS_PmLockRelease(name);
719     }
720 
721     return ret;
722 }
723 
LOS_PmReadLock(VOID)724 UINT32 LOS_PmReadLock(VOID)
725 {
726     UINT32 ret = LOS_EventRead(&g_pmEvent, PM_EVENT_LOCK_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
727     if (ret > PM_EVENT_LOCK_MASK) {
728         PRINT_ERR("%s event read failed! ERROR: 0x%x\n", __FUNCTION__, ret);
729     }
730 
731     return LOS_OK;
732 }
733 
LOS_PmSuspend(UINT32 wakeCount)734 UINT32 LOS_PmSuspend(UINT32 wakeCount)
735 {
736     (VOID)wakeCount;
737     return OsPmSuspendSleep(&g_pmCB);
738 }
739 
OsIsPmMode(VOID)740 BOOL OsIsPmMode(VOID)
741 {
742     LosPmCB *pm = &g_pmCB;
743 
744     UINT32 intSave = LOS_IntLock();
745     if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock == 0)) {
746         LOS_IntRestore(intSave);
747         return TRUE;
748     }
749     LOS_IntRestore(intSave);
750     return FALSE;
751 }
752 
OsPmInit(VOID)753 UINT32 OsPmInit(VOID)
754 {
755     UINT32 ret;
756     LosPmCB *pm = &g_pmCB;
757 
758     (VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
759 
760     pm->pmMode = LOS_SYS_NORMAL_SLEEP;
761     LOS_ListInit(&pm->lockList);
762     (VOID)LOS_EventInit(&g_pmEvent);
763 
764     ret = OsPmEnterHandlerSet(OsPmNormalSleep);
765     if (ret != LOS_OK) {
766         return ret;
767     }
768 
769     OsPmSysctrlInit();
770     pm->sysctrl = &g_sysctrl;
771     return ret;
772 }
773 #endif
774