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_sched_pri.h"
35 #include "los_init.h"
36 #include "los_memory.h"
37 #include "los_spinlock.h"
38 #include "los_swtmr.h"
39 #include "los_mp.h"
40 
41 #define OS_MS_PER_TICK (OS_SYS_MS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND)
42 
43 #ifdef LOSCFG_KERNEL_PM
44 #define PM_INFO_SHOW(seqBuf, arg...) do {                   \
45     if (seqBuf != NULL) {                                   \
46         (void)LosBufPrintf((struct SeqBuf *)seqBuf, ##arg); \
47     } else {                                                \
48         PRINTK(arg);                                        \
49     }                                                       \
50 } while (0)
51 
52 #define OS_PM_LOCK_MAX         0xFFFFU
53 #define OS_PM_LOCK_NAME_MAX    28
54 #define OS_PM_SYS_EARLY        1
55 #define OS_PM_SYS_DEVICE_EARLY 2
56 
57 typedef UINT32 (*Suspend)(UINT32 mode);
58 
59 typedef struct {
60     CHAR         name[OS_PM_LOCK_NAME_MAX];
61     UINT32       count;
62     UINT32       swtmrID;
63     LOS_DL_LIST  list;
64 } OsPmLockCB;
65 
66 typedef struct {
67     LOS_SysSleepEnum  pmMode;
68     LOS_SysSleepEnum  sysMode;
69     UINT16            lock;
70     BOOL              isWake;
71     LosPmDevice       *device;
72     LosPmSysctrl      *sysctrl;
73     UINT64            enterSleepTime;
74     LOS_DL_LIST       lockList;
75 } LosPmCB;
76 
77 #define PM_EVENT_LOCK_MASK    0xF
78 #define PM_EVENT_LOCK_RELEASE 0x1
79 STATIC EVENT_CB_S g_pmEvent;
80 STATIC LosPmCB g_pmCB;
81 STATIC SPIN_LOCK_INIT(g_pmSpin);
82 STATIC LosPmSysctrl g_sysctrl;
83 
84 STATIC VOID OsPmSysctrlInit(VOID);
85 
OsPmTickTimerStart(LosPmCB *pm)86 STATIC VOID OsPmTickTimerStart(LosPmCB *pm)
87 {
88     (VOID)pm;
89     return;
90 }
91 
OsPmTickTimerStop(LosPmCB *pm)92 STATIC BOOL OsPmTickTimerStop(LosPmCB *pm)
93 {
94     (VOID)pm;
95     return FALSE;
96 }
97 
OsPmCpuResume(LosPmCB *pm)98 STATIC VOID OsPmCpuResume(LosPmCB *pm)
99 {
100     if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) && (pm->sysctrl->normalResume != NULL)) {
101         pm->sysctrl->normalResume();
102     } else if ((pm->sysMode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightResume != NULL)) {
103         pm->sysctrl->lightResume();
104     } else if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepResume != NULL)) {
105         pm->sysctrl->deepResume();
106     }
107 }
108 
OsPmCpuSuspend(LosPmCB *pm)109 VOID OsPmCpuSuspend(LosPmCB *pm)
110 {
111     /* cpu enter low power mode */
112     LOS_ASSERT(pm->sysctrl != NULL);
113 
114     if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) {
115         pm->sysctrl->normalSuspend();
116     } else if (pm->sysMode == LOS_SYS_LIGHT_SLEEP) {
117         pm->sysctrl->lightSuspend();
118     } else if (pm->sysMode == LOS_SYS_DEEP_SLEEP) {
119         pm->sysctrl->deepSuspend();
120     } else {
121         pm->sysctrl->shutdownSuspend();
122     }
123 }
124 
OsPmResumePrepare(LosPmCB *pm, UINT32 mode, UINT32 prepare)125 STATIC VOID OsPmResumePrepare(LosPmCB *pm, UINT32 mode, UINT32 prepare)
126 {
127     if ((prepare == 0) && (pm->device != NULL) && (pm->device->resume != NULL)) {
128         pm->device->resume(mode);
129     }
130 
131     if (((prepare == 0) || (prepare == OS_PM_SYS_DEVICE_EARLY)) && (pm->sysctrl->late != NULL)) {
132         pm->sysctrl->late(mode);
133     }
134 }
135 
OsPmSuspendPrepare(Suspend sysSuspendEarly, Suspend deviceSuspend, UINT32 mode, UINT32 *prepare)136 STATIC UINT32 OsPmSuspendPrepare(Suspend sysSuspendEarly, Suspend deviceSuspend, UINT32 mode, UINT32 *prepare)
137 {
138     UINT32 ret;
139 
140     if (sysSuspendEarly != NULL) {
141         ret = sysSuspendEarly(mode);
142         if (ret != LOS_OK) {
143             *prepare = OS_PM_SYS_EARLY;
144             return ret;
145         }
146     }
147 
148     if (deviceSuspend != NULL) {
149         ret = deviceSuspend(mode);
150         if (ret != LOS_OK) {
151             *prepare = OS_PM_SYS_DEVICE_EARLY;
152             return ret;
153         }
154     }
155 
156     return LOS_OK;
157 }
158 
OsPmSuspendCheck(LosPmCB *pm, Suspend *sysSuspendEarly, Suspend *deviceSuspend, LOS_SysSleepEnum *mode)159 STATIC UINT32 OsPmSuspendCheck(LosPmCB *pm, Suspend *sysSuspendEarly, Suspend *deviceSuspend, LOS_SysSleepEnum *mode)
160 {
161     LOS_SpinLock(&g_pmSpin);
162     pm->sysMode = pm->pmMode;
163     if (pm->lock > 0) {
164         pm->sysMode = LOS_SYS_NORMAL_SLEEP;
165         LOS_SpinUnlock(&g_pmSpin);
166         return LOS_NOK;
167     }
168 
169     pm->isWake = FALSE;
170     *mode = pm->sysMode;
171     *sysSuspendEarly = pm->sysctrl->early;
172     if (pm->device != NULL) {
173         *deviceSuspend = pm->device->suspend;
174     } else {
175         *deviceSuspend = NULL;
176     }
177     LOS_SpinUnlock(&g_pmSpin);
178     return LOS_OK;
179 }
180 
OsPmSuspendSleep(LosPmCB *pm)181 STATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
182 {
183     UINT32 ret, intSave;
184     Suspend sysSuspendEarly, deviceSuspend;
185     LOS_SysSleepEnum mode;
186     UINT32 prepare = 0;
187     BOOL tickTimerStop = FALSE;
188 
189     ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode);
190     if (ret != LOS_OK) {
191         PRINT_ERR("Pm suspend mode is normal sleep! lock count %d\n", pm->lock);
192         return ret;
193     }
194 
195     ret = OsPmSuspendPrepare(sysSuspendEarly, deviceSuspend, (UINT32)mode, &prepare);
196     if (ret != LOS_OK) {
197         LOS_SpinLockSave(&g_pmSpin, &intSave);
198         LOS_TaskLock();
199         goto EXIT;
200     }
201 
202     LOS_SpinLockSave(&g_pmSpin, &intSave);
203     LOS_TaskLock();
204     if (pm->isWake || (pm->lock > 0)) {
205         goto EXIT;
206     }
207 
208     tickTimerStop = OsPmTickTimerStop(pm);
209     if (!tickTimerStop) {
210         OsSchedResponseTimeReset(0);
211         OsSchedExpireTimeUpdate();
212     }
213 
214     OsPmCpuSuspend(pm);
215 
216     OsPmCpuResume(pm);
217 
218     OsPmTickTimerStart(pm);
219 
220 EXIT:
221     pm->sysMode = LOS_SYS_NORMAL_SLEEP;
222     OsPmResumePrepare(pm, (UINT32)mode, prepare);
223 
224     LOS_SpinUnlockRestore(&g_pmSpin, intSave);
225     LOS_TaskUnlock();
226     return ret;
227 }
228 
OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)229 STATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
230 {
231     if ((device->suspend == NULL) || (device->resume == NULL)) {
232         return LOS_EINVAL;
233     }
234 
235     LOS_SpinLock(&g_pmSpin);
236     pm->device = device;
237     LOS_SpinUnlock(&g_pmSpin);
238 
239     return LOS_OK;
240 }
241 
OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)242 STATIC UINT32 OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)
243 {
244     LOS_SpinLock(&g_pmSpin);
245     if (sysctrl->early != NULL) {
246         pm->sysctrl->early = sysctrl->early;
247     }
248     if (sysctrl->late != NULL) {
249         pm->sysctrl->late = sysctrl->late;
250     }
251     if (sysctrl->normalSuspend != NULL) {
252         pm->sysctrl->normalSuspend = sysctrl->normalSuspend;
253     }
254     if (sysctrl->normalResume != NULL) {
255         pm->sysctrl->normalResume = sysctrl->normalResume;
256     }
257     if (sysctrl->lightSuspend != NULL) {
258         pm->sysctrl->lightSuspend = sysctrl->lightSuspend;
259     }
260     if (sysctrl->lightResume != NULL) {
261         pm->sysctrl->lightResume = sysctrl->lightResume;
262     }
263     if (sysctrl->deepSuspend != NULL) {
264         pm->sysctrl->deepSuspend = sysctrl->deepSuspend;
265     }
266     if (sysctrl->deepResume != NULL) {
267         pm->sysctrl->deepResume = sysctrl->deepResume;
268     }
269     if (sysctrl->shutdownSuspend != NULL) {
270         pm->sysctrl->shutdownSuspend = sysctrl->shutdownSuspend;
271     }
272     if (sysctrl->shutdownResume != NULL) {
273         pm->sysctrl->shutdownResume = sysctrl->shutdownResume;
274     }
275     LOS_SpinUnlock(&g_pmSpin);
276 
277     return LOS_OK;
278 }
279 
LOS_PmRegister(LOS_PmNodeType type, VOID *node)280 UINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node)
281 {
282     LosPmCB *pm = &g_pmCB;
283 
284     if (node == NULL) {
285         return LOS_EINVAL;
286     }
287 
288     switch (type) {
289         case LOS_PM_TYPE_DEVICE:
290             return OsPmDeviceRegister(pm, (LosPmDevice *)node);
291         case LOS_PM_TYPE_TICK_TIMER:
292             PRINT_ERR("Pm, %d is an unsupported type\n", type);
293             return LOS_EINVAL;
294         case LOS_PM_TYPE_SYSCTRL:
295             return OsPmSysctrlRegister(pm, (LosPmSysctrl *)node);
296         default:
297             break;
298     }
299 
300     return LOS_EINVAL;
301 }
302 
OsPmDeviceUnregister(LosPmCB *pm, const LosPmDevice *device)303 STATIC UINT32 OsPmDeviceUnregister(LosPmCB *pm, const LosPmDevice *device)
304 {
305     LOS_SpinLock(&g_pmSpin);
306     if (pm->device == device) {
307         pm->device = NULL;
308         pm->pmMode = LOS_SYS_NORMAL_SLEEP;
309         LOS_SpinUnlock(&g_pmSpin);
310         return LOS_OK;
311     }
312 
313     LOS_SpinUnlock(&g_pmSpin);
314     return LOS_EINVAL;
315 }
316 
OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)317 STATIC UINT32 OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)
318 {
319     (VOID)sysctrl;
320     LOS_SpinLock(&g_pmSpin);
321     OsPmSysctrlInit();
322     pm->pmMode = LOS_SYS_NORMAL_SLEEP;
323     LOS_SpinUnlock(&g_pmSpin);
324 
325     return LOS_OK;
326 }
327 
LOS_PmUnregister(LOS_PmNodeType type, VOID *node)328 UINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node)
329 {
330     LosPmCB *pm = &g_pmCB;
331 
332     if (node == NULL) {
333         return LOS_EINVAL;
334     }
335 
336     switch (type) {
337         case LOS_PM_TYPE_DEVICE:
338             return OsPmDeviceUnregister(pm, (LosPmDevice *)node);
339         case LOS_PM_TYPE_TICK_TIMER:
340             PRINT_ERR("Pm, %d is an unsupported type\n", type);
341             return LOS_EINVAL;
342         case LOS_PM_TYPE_SYSCTRL:
343             return OsPmSysctrlUnregister(pm, (LosPmSysctrl *)node);
344         default:
345             break;
346     }
347 
348     return LOS_EINVAL;
349 }
350 
LOS_PmWakeSetnull351 VOID LOS_PmWakeSet(VOID)
352 {
353     LosPmCB *pm = &g_pmCB;
354 
355     LOS_SpinLock(&g_pmSpin);
356     pm->isWake = TRUE;
357     LOS_SpinUnlock(&g_pmSpin);
358     return;
359 }
360 
LOS_PmModeGetnull361 LOS_SysSleepEnum LOS_PmModeGet(VOID)
362 {
363     LOS_SysSleepEnum mode;
364     LosPmCB *pm = &g_pmCB;
365 
366     LOS_SpinLock(&g_pmSpin);
367     mode = pm->pmMode;
368     LOS_SpinUnlock(&g_pmSpin);
369 
370     return mode;
371 }
372 
LOS_PmModeSet(LOS_SysSleepEnum mode)373 UINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
374 {
375     LosPmCB *pm = &g_pmCB;
376     INT32 sleepMode = (INT32)mode;
377 
378     if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
379         return LOS_EINVAL;
380     }
381 
382     LOS_SpinLock(&g_pmSpin);
383     if ((mode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightSuspend == NULL)) {
384         LOS_SpinUnlock(&g_pmSpin);
385         return LOS_EINVAL;
386     }
387 
388     if ((mode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepSuspend == NULL)) {
389         LOS_SpinUnlock(&g_pmSpin);
390         return LOS_EINVAL;
391     }
392 
393     if ((mode == LOS_SYS_SHUTDOWN) && (pm->sysctrl->shutdownSuspend == NULL)) {
394         LOS_SpinUnlock(&g_pmSpin);
395         return LOS_EINVAL;
396     }
397 
398     pm->pmMode = mode;
399     LOS_SpinUnlock(&g_pmSpin);
400 
401     return LOS_OK;
402 }
403 
LOS_PmLockCountGetnull404 UINT32 LOS_PmLockCountGet(VOID)
405 {
406     UINT16 count;
407     LosPmCB *pm = &g_pmCB;
408 
409     LOS_SpinLock(&g_pmSpin);
410     count = pm->lock;
411     LOS_SpinUnlock(&g_pmSpin);
412 
413     return (UINT32)count;
414 }
415 
LOS_PmLockInfoShow(struct SeqBuf *m)416 VOID LOS_PmLockInfoShow(struct SeqBuf *m)
417 {
418     LosPmCB *pm = &g_pmCB;
419     OsPmLockCB *lock = NULL;
420     LOS_DL_LIST *head = &pm->lockList;
421     LOS_DL_LIST *list = head->pstNext;
422 
423     LOS_SpinLock(&g_pmSpin);
424     while (list != head) {
425         lock = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
426         PM_INFO_SHOW(m, "%-30s%5u\n\r", lock->name, lock->count);
427         list = list->pstNext;
428     }
429     LOS_SpinUnlock(&g_pmSpin);
430 
431     return;
432 }
433 
OsPmLockRequest(const CHAR *name, UINT32 swtmrID)434 UINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID)
435 {
436     INT32 len;
437     errno_t err;
438     UINT32 ret = LOS_EINVAL;
439     LosPmCB *pm = &g_pmCB;
440     OsPmLockCB *lock = NULL;
441     LOS_DL_LIST *head = &pm->lockList;
442     LOS_DL_LIST *list = head->pstNext;
443 
444     if (OS_INT_ACTIVE) {
445         return LOS_EINTR;
446     }
447 
448     len = strlen(name);
449     if (len <= 0) {
450         return LOS_EINVAL;
451     }
452 
453     LOS_SpinLock(&g_pmSpin);
454     if (pm->lock >= OS_PM_LOCK_MAX) {
455         LOS_SpinUnlock(&g_pmSpin);
456         return LOS_EINVAL;
457     }
458 
459     while (list != head) {
460         OsPmLockCB *listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
461         if (strcmp(name, listNode->name) == 0) {
462             lock = listNode;
463             break;
464         }
465 
466         list = list->pstNext;
467     }
468 
469     if (lock == NULL) {
470         lock = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(OsPmLockCB));
471         if (lock == NULL) {
472             LOS_SpinUnlock(&g_pmSpin);
473             return LOS_ENOMEM;
474         }
475         err = memcpy_s(lock->name, OS_PM_LOCK_NAME_MAX, name, len + 1);
476         if (err != EOK) {
477             LOS_SpinUnlock(&g_pmSpin);
478             (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lock);
479             return err;
480         }
481         lock->count = 1;
482         lock->swtmrID = swtmrID;
483         LOS_ListTailInsert(head, &lock->list);
484     } else if (lock->count < OS_PM_LOCK_MAX) {
485         lock->count++;
486     }
487 
488     if ((lock->swtmrID != OS_INVALID) && (lock->count > 1)) {
489         lock->count--;
490         LOS_SpinUnlock(&g_pmSpin);
491         return LOS_EINVAL;
492     }
493 
494     if (pm->lock < OS_PM_LOCK_MAX) {
495         pm->lock++;
496         ret = LOS_OK;
497     }
498 
499     LOS_SpinUnlock(&g_pmSpin);
500     return ret;
501 }
502 
LOS_PmLockRequest(const CHAR *name)503 UINT32 LOS_PmLockRequest(const CHAR *name)
504 {
505     if (name == NULL) {
506         return LOS_EINVAL;
507     }
508 
509     return OsPmLockRequest(name, OS_INVALID);
510 }
511 
LOS_PmLockRelease(const CHAR *name)512 UINT32 LOS_PmLockRelease(const CHAR *name)
513 {
514     UINT32 ret = LOS_EINVAL;
515     LosPmCB *pm = &g_pmCB;
516     OsPmLockCB *lock = NULL;
517     LOS_DL_LIST *head = &pm->lockList;
518     LOS_DL_LIST *list = head->pstNext;
519     OsPmLockCB *lockFree = NULL;
520     BOOL isRelease = FALSE;
521     UINT32 mode;
522 
523     if (name == NULL) {
524         return LOS_EINVAL;
525     }
526 
527     if (OS_INT_ACTIVE) {
528         return LOS_EINTR;
529     }
530 
531     LOS_SpinLock(&g_pmSpin);
532     if (pm->lock == 0) {
533         LOS_SpinUnlock(&g_pmSpin);
534         return LOS_EINVAL;
535     }
536 
537     mode = (UINT32)pm->pmMode;
538     while (list != head) {
539         OsPmLockCB *listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
540         if (strcmp(name, listNode->name) == 0) {
541             lock = listNode;
542             break;
543         }
544 
545         list = list->pstNext;
546     }
547 
548     if (lock == NULL) {
549         LOS_SpinUnlock(&g_pmSpin);
550         return LOS_EINVAL;
551     } else if (lock->count > 0) {
552         lock->count--;
553         if (lock->count == 0) {
554             LOS_ListDelete(&lock->list);
555             lockFree = lock;
556         }
557     }
558 
559     if (pm->lock > 0) {
560         pm->lock--;
561         if (pm->lock == 0) {
562             isRelease = TRUE;
563         }
564         ret = LOS_OK;
565     }
566     LOS_SpinUnlock(&g_pmSpin);
567 
568     if (lockFree != NULL) {
569         (VOID)LOS_SwtmrDelete(lockFree->swtmrID);
570         (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
571     }
572 
573     if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) {
574         (VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE);
575     }
576 
577     return ret;
578 }
579 
OsPmSwtmrHandler(UINT32 arg)580 STATIC VOID OsPmSwtmrHandler(UINT32 arg)
581 {
582     const CHAR *name = (const CHAR *)arg;
583     UINT32 ret = LOS_PmLockRelease(name);
584     if (ret != LOS_OK) {
585         PRINT_ERR("Pm delay lock %s release faled! : 0x%x\n", name, ret);
586     }
587 }
588 
LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond)589 UINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond)
590 {
591     UINT32 ticks;
592     UINT16 swtmrID;
593     UINT32 ret;
594 
595     if ((name == NULL) || !millisecond) {
596         return LOS_EINVAL;
597     }
598 
599     ticks = (UINT32)((millisecond + OS_MS_PER_TICK - 1) / OS_MS_PER_TICK);
600 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
601     ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name,
602                           OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
603 #else
604     ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name);
605 #endif
606     if (ret != LOS_OK) {
607         return ret;
608     }
609 
610     ret = OsPmLockRequest(name, swtmrID);
611     if (ret != LOS_OK) {
612         (VOID)LOS_SwtmrDelete(swtmrID);
613         return ret;
614     }
615 
616     ret = LOS_SwtmrStart(swtmrID);
617     if (ret != LOS_OK) {
618         (VOID)LOS_PmLockRelease(name);
619     }
620 
621     return ret;
622 }
623 
LOS_PmReadLocknull624 UINT32 LOS_PmReadLock(VOID)
625 {
626     UINT32 ret = LOS_EventRead(&g_pmEvent, PM_EVENT_LOCK_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
627     if (ret > PM_EVENT_LOCK_MASK) {
628         PRINT_ERR("%s event read failed! ERROR: 0x%x\n", __FUNCTION__, ret);
629     }
630 
631     return LOS_OK;
632 }
633 
LOS_PmSuspend(UINT32 wakeCount)634 UINT32 LOS_PmSuspend(UINT32 wakeCount)
635 {
636     (VOID)wakeCount;
637     return OsPmSuspendSleep(&g_pmCB);
638 }
639 
OsIsPmModenull640 BOOL OsIsPmMode(VOID)
641 {
642     LosPmCB *pm = &g_pmCB;
643 
644     LOS_SpinLock(&g_pmSpin);
645     if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock == 0)) {
646         LOS_SpinUnlock(&g_pmSpin);
647         return TRUE;
648     }
649     LOS_SpinUnlock(&g_pmSpin);
650     return FALSE;
651 }
652 
OsPmSuspendDefaultHandlernull653 STATIC UINT32 OsPmSuspendDefaultHandler(VOID)
654 {
655     PRINTK("Enter pm default handler!!!\n");
656     WFI;
657     return LOS_OK;
658 }
659 
OsPmSysctrlInitnull660 STATIC VOID OsPmSysctrlInit(VOID)
661 {
662     /* Default handler functions, which are implemented by the product */
663     g_sysctrl.early = NULL;
664     g_sysctrl.late = NULL;
665     g_sysctrl.normalSuspend = OsPmSuspendDefaultHandler;
666     g_sysctrl.normalResume = NULL;
667     g_sysctrl.lightSuspend = OsPmSuspendDefaultHandler;
668     g_sysctrl.lightResume = NULL;
669     g_sysctrl.deepSuspend = OsPmSuspendDefaultHandler;
670     g_sysctrl.deepResume = NULL;
671     g_sysctrl.shutdownSuspend = NULL;
672     g_sysctrl.shutdownResume = NULL;
673 }
674 
OsPmInitnull675 UINT32 OsPmInit(VOID)
676 {
677     LosPmCB *pm = &g_pmCB;
678 
679     (VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
680 
681     pm->pmMode = LOS_SYS_NORMAL_SLEEP;
682     LOS_ListInit(&pm->lockList);
683     (VOID)LOS_EventInit(&g_pmEvent);
684 
685     OsPmSysctrlInit();
686     pm->sysctrl = &g_sysctrl;
687     return LOS_OK;
688 }
689 
690 LOS_MODULE_INIT(OsPmInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
691 #endif
692