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