• 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         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