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