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