10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci#include "los_pm.h"
330d163575Sopenharmony_ci#include "securec.h"
340d163575Sopenharmony_ci#include "los_sched_pri.h"
350d163575Sopenharmony_ci#include "los_init.h"
360d163575Sopenharmony_ci#include "los_memory.h"
370d163575Sopenharmony_ci#include "los_spinlock.h"
380d163575Sopenharmony_ci#include "los_swtmr.h"
390d163575Sopenharmony_ci#include "los_mp.h"
400d163575Sopenharmony_ci
410d163575Sopenharmony_ci#define OS_MS_PER_TICK (OS_SYS_MS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND)
420d163575Sopenharmony_ci
430d163575Sopenharmony_ci#ifdef LOSCFG_KERNEL_PM
440d163575Sopenharmony_ci#define PM_INFO_SHOW(seqBuf, arg...) do {                   \
450d163575Sopenharmony_ci    if (seqBuf != NULL) {                                   \
460d163575Sopenharmony_ci        (void)LosBufPrintf((struct SeqBuf *)seqBuf, ##arg); \
470d163575Sopenharmony_ci    } else {                                                \
480d163575Sopenharmony_ci        PRINTK(arg);                                        \
490d163575Sopenharmony_ci    }                                                       \
500d163575Sopenharmony_ci} while (0)
510d163575Sopenharmony_ci
520d163575Sopenharmony_ci#define OS_PM_LOCK_MAX         0xFFFFU
530d163575Sopenharmony_ci#define OS_PM_LOCK_NAME_MAX    28
540d163575Sopenharmony_ci#define OS_PM_SYS_EARLY        1
550d163575Sopenharmony_ci#define OS_PM_SYS_DEVICE_EARLY 2
560d163575Sopenharmony_ci
570d163575Sopenharmony_citypedef UINT32 (*Suspend)(UINT32 mode);
580d163575Sopenharmony_ci
590d163575Sopenharmony_citypedef struct {
600d163575Sopenharmony_ci    CHAR         name[OS_PM_LOCK_NAME_MAX];
610d163575Sopenharmony_ci    UINT32       count;
620d163575Sopenharmony_ci    UINT32       swtmrID;
630d163575Sopenharmony_ci    LOS_DL_LIST  list;
640d163575Sopenharmony_ci} OsPmLockCB;
650d163575Sopenharmony_ci
660d163575Sopenharmony_citypedef struct {
670d163575Sopenharmony_ci    LOS_SysSleepEnum  pmMode;
680d163575Sopenharmony_ci    LOS_SysSleepEnum  sysMode;
690d163575Sopenharmony_ci    UINT16            lock;
700d163575Sopenharmony_ci    BOOL              isWake;
710d163575Sopenharmony_ci    LosPmDevice       *device;
720d163575Sopenharmony_ci    LosPmSysctrl      *sysctrl;
730d163575Sopenharmony_ci    UINT64            enterSleepTime;
740d163575Sopenharmony_ci    LOS_DL_LIST       lockList;
750d163575Sopenharmony_ci} LosPmCB;
760d163575Sopenharmony_ci
770d163575Sopenharmony_ci#define PM_EVENT_LOCK_MASK    0xF
780d163575Sopenharmony_ci#define PM_EVENT_LOCK_RELEASE 0x1
790d163575Sopenharmony_ciSTATIC EVENT_CB_S g_pmEvent;
800d163575Sopenharmony_ciSTATIC LosPmCB g_pmCB;
810d163575Sopenharmony_ciSTATIC SPIN_LOCK_INIT(g_pmSpin);
820d163575Sopenharmony_ciSTATIC LosPmSysctrl g_sysctrl;
830d163575Sopenharmony_ci
840d163575Sopenharmony_ciSTATIC VOID OsPmSysctrlInit(VOID);
850d163575Sopenharmony_ci
860d163575Sopenharmony_ciSTATIC VOID OsPmTickTimerStart(LosPmCB *pm)
870d163575Sopenharmony_ci{
880d163575Sopenharmony_ci    (VOID)pm;
890d163575Sopenharmony_ci    return;
900d163575Sopenharmony_ci}
910d163575Sopenharmony_ci
920d163575Sopenharmony_ciSTATIC BOOL OsPmTickTimerStop(LosPmCB *pm)
930d163575Sopenharmony_ci{
940d163575Sopenharmony_ci    (VOID)pm;
950d163575Sopenharmony_ci    return FALSE;
960d163575Sopenharmony_ci}
970d163575Sopenharmony_ci
980d163575Sopenharmony_ciSTATIC VOID OsPmCpuResume(LosPmCB *pm)
990d163575Sopenharmony_ci{
1000d163575Sopenharmony_ci    if ((pm->sysMode == LOS_SYS_NORMAL_SLEEP) && (pm->sysctrl->normalResume != NULL)) {
1010d163575Sopenharmony_ci        pm->sysctrl->normalResume();
1020d163575Sopenharmony_ci    } else if ((pm->sysMode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightResume != NULL)) {
1030d163575Sopenharmony_ci        pm->sysctrl->lightResume();
1040d163575Sopenharmony_ci    } else if ((pm->sysMode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepResume != NULL)) {
1050d163575Sopenharmony_ci        pm->sysctrl->deepResume();
1060d163575Sopenharmony_ci    }
1070d163575Sopenharmony_ci}
1080d163575Sopenharmony_ci
1090d163575Sopenharmony_ciVOID OsPmCpuSuspend(LosPmCB *pm)
1100d163575Sopenharmony_ci{
1110d163575Sopenharmony_ci    /* cpu enter low power mode */
1120d163575Sopenharmony_ci    LOS_ASSERT(pm->sysctrl != NULL);
1130d163575Sopenharmony_ci
1140d163575Sopenharmony_ci    if (pm->sysMode == LOS_SYS_NORMAL_SLEEP) {
1150d163575Sopenharmony_ci        pm->sysctrl->normalSuspend();
1160d163575Sopenharmony_ci    } else if (pm->sysMode == LOS_SYS_LIGHT_SLEEP) {
1170d163575Sopenharmony_ci        pm->sysctrl->lightSuspend();
1180d163575Sopenharmony_ci    } else if (pm->sysMode == LOS_SYS_DEEP_SLEEP) {
1190d163575Sopenharmony_ci        pm->sysctrl->deepSuspend();
1200d163575Sopenharmony_ci    } else {
1210d163575Sopenharmony_ci        pm->sysctrl->shutdownSuspend();
1220d163575Sopenharmony_ci    }
1230d163575Sopenharmony_ci}
1240d163575Sopenharmony_ci
1250d163575Sopenharmony_ciSTATIC VOID OsPmResumePrepare(LosPmCB *pm, UINT32 mode, UINT32 prepare)
1260d163575Sopenharmony_ci{
1270d163575Sopenharmony_ci    if ((prepare == 0) && (pm->device != NULL) && (pm->device->resume != NULL)) {
1280d163575Sopenharmony_ci        pm->device->resume(mode);
1290d163575Sopenharmony_ci    }
1300d163575Sopenharmony_ci
1310d163575Sopenharmony_ci    if (((prepare == 0) || (prepare == OS_PM_SYS_DEVICE_EARLY)) && (pm->sysctrl->late != NULL)) {
1320d163575Sopenharmony_ci        pm->sysctrl->late(mode);
1330d163575Sopenharmony_ci    }
1340d163575Sopenharmony_ci}
1350d163575Sopenharmony_ci
1360d163575Sopenharmony_ciSTATIC UINT32 OsPmSuspendPrepare(Suspend sysSuspendEarly, Suspend deviceSuspend, UINT32 mode, UINT32 *prepare)
1370d163575Sopenharmony_ci{
1380d163575Sopenharmony_ci    UINT32 ret;
1390d163575Sopenharmony_ci
1400d163575Sopenharmony_ci    if (sysSuspendEarly != NULL) {
1410d163575Sopenharmony_ci        ret = sysSuspendEarly(mode);
1420d163575Sopenharmony_ci        if (ret != LOS_OK) {
1430d163575Sopenharmony_ci            *prepare = OS_PM_SYS_EARLY;
1440d163575Sopenharmony_ci            return ret;
1450d163575Sopenharmony_ci        }
1460d163575Sopenharmony_ci    }
1470d163575Sopenharmony_ci
1480d163575Sopenharmony_ci    if (deviceSuspend != NULL) {
1490d163575Sopenharmony_ci        ret = deviceSuspend(mode);
1500d163575Sopenharmony_ci        if (ret != LOS_OK) {
1510d163575Sopenharmony_ci            *prepare = OS_PM_SYS_DEVICE_EARLY;
1520d163575Sopenharmony_ci            return ret;
1530d163575Sopenharmony_ci        }
1540d163575Sopenharmony_ci    }
1550d163575Sopenharmony_ci
1560d163575Sopenharmony_ci    return LOS_OK;
1570d163575Sopenharmony_ci}
1580d163575Sopenharmony_ci
1590d163575Sopenharmony_ciSTATIC UINT32 OsPmSuspendCheck(LosPmCB *pm, Suspend *sysSuspendEarly, Suspend *deviceSuspend, LOS_SysSleepEnum *mode)
1600d163575Sopenharmony_ci{
1610d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
1620d163575Sopenharmony_ci    pm->sysMode = pm->pmMode;
1630d163575Sopenharmony_ci    if (pm->lock > 0) {
1640d163575Sopenharmony_ci        pm->sysMode = LOS_SYS_NORMAL_SLEEP;
1650d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
1660d163575Sopenharmony_ci        return LOS_NOK;
1670d163575Sopenharmony_ci    }
1680d163575Sopenharmony_ci
1690d163575Sopenharmony_ci    pm->isWake = FALSE;
1700d163575Sopenharmony_ci    *mode = pm->sysMode;
1710d163575Sopenharmony_ci    *sysSuspendEarly = pm->sysctrl->early;
1720d163575Sopenharmony_ci    if (pm->device != NULL) {
1730d163575Sopenharmony_ci        *deviceSuspend = pm->device->suspend;
1740d163575Sopenharmony_ci    } else {
1750d163575Sopenharmony_ci        *deviceSuspend = NULL;
1760d163575Sopenharmony_ci    }
1770d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
1780d163575Sopenharmony_ci    return LOS_OK;
1790d163575Sopenharmony_ci}
1800d163575Sopenharmony_ci
1810d163575Sopenharmony_ciSTATIC UINT32 OsPmSuspendSleep(LosPmCB *pm)
1820d163575Sopenharmony_ci{
1830d163575Sopenharmony_ci    UINT32 ret, intSave;
1840d163575Sopenharmony_ci    Suspend sysSuspendEarly, deviceSuspend;
1850d163575Sopenharmony_ci    LOS_SysSleepEnum mode;
1860d163575Sopenharmony_ci    UINT32 prepare = 0;
1870d163575Sopenharmony_ci    BOOL tickTimerStop = FALSE;
1880d163575Sopenharmony_ci
1890d163575Sopenharmony_ci    ret = OsPmSuspendCheck(pm, &sysSuspendEarly, &deviceSuspend, &mode);
1900d163575Sopenharmony_ci    if (ret != LOS_OK) {
1910d163575Sopenharmony_ci        PRINT_ERR("Pm suspend mode is normal sleep! lock count %d\n", pm->lock);
1920d163575Sopenharmony_ci        return ret;
1930d163575Sopenharmony_ci    }
1940d163575Sopenharmony_ci
1950d163575Sopenharmony_ci    ret = OsPmSuspendPrepare(sysSuspendEarly, deviceSuspend, (UINT32)mode, &prepare);
1960d163575Sopenharmony_ci    if (ret != LOS_OK) {
1970d163575Sopenharmony_ci        LOS_SpinLockSave(&g_pmSpin, &intSave);
1980d163575Sopenharmony_ci        LOS_TaskLock();
1990d163575Sopenharmony_ci        goto EXIT;
2000d163575Sopenharmony_ci    }
2010d163575Sopenharmony_ci
2020d163575Sopenharmony_ci    LOS_SpinLockSave(&g_pmSpin, &intSave);
2030d163575Sopenharmony_ci    LOS_TaskLock();
2040d163575Sopenharmony_ci    if (pm->isWake || (pm->lock > 0)) {
2050d163575Sopenharmony_ci        goto EXIT;
2060d163575Sopenharmony_ci    }
2070d163575Sopenharmony_ci
2080d163575Sopenharmony_ci    tickTimerStop = OsPmTickTimerStop(pm);
2090d163575Sopenharmony_ci    if (!tickTimerStop) {
2100d163575Sopenharmony_ci        OsSchedResponseTimeReset(0);
2110d163575Sopenharmony_ci        OsSchedExpireTimeUpdate();
2120d163575Sopenharmony_ci    }
2130d163575Sopenharmony_ci
2140d163575Sopenharmony_ci    OsPmCpuSuspend(pm);
2150d163575Sopenharmony_ci
2160d163575Sopenharmony_ci    OsPmCpuResume(pm);
2170d163575Sopenharmony_ci
2180d163575Sopenharmony_ci    OsPmTickTimerStart(pm);
2190d163575Sopenharmony_ci
2200d163575Sopenharmony_ciEXIT:
2210d163575Sopenharmony_ci    pm->sysMode = LOS_SYS_NORMAL_SLEEP;
2220d163575Sopenharmony_ci    OsPmResumePrepare(pm, (UINT32)mode, prepare);
2230d163575Sopenharmony_ci
2240d163575Sopenharmony_ci    LOS_SpinUnlockRestore(&g_pmSpin, intSave);
2250d163575Sopenharmony_ci    LOS_TaskUnlock();
2260d163575Sopenharmony_ci    return ret;
2270d163575Sopenharmony_ci}
2280d163575Sopenharmony_ci
2290d163575Sopenharmony_ciSTATIC UINT32 OsPmDeviceRegister(LosPmCB *pm, LosPmDevice *device)
2300d163575Sopenharmony_ci{
2310d163575Sopenharmony_ci    if ((device->suspend == NULL) || (device->resume == NULL)) {
2320d163575Sopenharmony_ci        return LOS_EINVAL;
2330d163575Sopenharmony_ci    }
2340d163575Sopenharmony_ci
2350d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
2360d163575Sopenharmony_ci    pm->device = device;
2370d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
2380d163575Sopenharmony_ci
2390d163575Sopenharmony_ci    return LOS_OK;
2400d163575Sopenharmony_ci}
2410d163575Sopenharmony_ci
2420d163575Sopenharmony_ciSTATIC UINT32 OsPmSysctrlRegister(LosPmCB *pm, LosPmSysctrl *sysctrl)
2430d163575Sopenharmony_ci{
2440d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
2450d163575Sopenharmony_ci    if (sysctrl->early != NULL) {
2460d163575Sopenharmony_ci        pm->sysctrl->early = sysctrl->early;
2470d163575Sopenharmony_ci    }
2480d163575Sopenharmony_ci    if (sysctrl->late != NULL) {
2490d163575Sopenharmony_ci        pm->sysctrl->late = sysctrl->late;
2500d163575Sopenharmony_ci    }
2510d163575Sopenharmony_ci    if (sysctrl->normalSuspend != NULL) {
2520d163575Sopenharmony_ci        pm->sysctrl->normalSuspend = sysctrl->normalSuspend;
2530d163575Sopenharmony_ci    }
2540d163575Sopenharmony_ci    if (sysctrl->normalResume != NULL) {
2550d163575Sopenharmony_ci        pm->sysctrl->normalResume = sysctrl->normalResume;
2560d163575Sopenharmony_ci    }
2570d163575Sopenharmony_ci    if (sysctrl->lightSuspend != NULL) {
2580d163575Sopenharmony_ci        pm->sysctrl->lightSuspend = sysctrl->lightSuspend;
2590d163575Sopenharmony_ci    }
2600d163575Sopenharmony_ci    if (sysctrl->lightResume != NULL) {
2610d163575Sopenharmony_ci        pm->sysctrl->lightResume = sysctrl->lightResume;
2620d163575Sopenharmony_ci    }
2630d163575Sopenharmony_ci    if (sysctrl->deepSuspend != NULL) {
2640d163575Sopenharmony_ci        pm->sysctrl->deepSuspend = sysctrl->deepSuspend;
2650d163575Sopenharmony_ci    }
2660d163575Sopenharmony_ci    if (sysctrl->deepResume != NULL) {
2670d163575Sopenharmony_ci        pm->sysctrl->deepResume = sysctrl->deepResume;
2680d163575Sopenharmony_ci    }
2690d163575Sopenharmony_ci    if (sysctrl->shutdownSuspend != NULL) {
2700d163575Sopenharmony_ci        pm->sysctrl->shutdownSuspend = sysctrl->shutdownSuspend;
2710d163575Sopenharmony_ci    }
2720d163575Sopenharmony_ci    if (sysctrl->shutdownResume != NULL) {
2730d163575Sopenharmony_ci        pm->sysctrl->shutdownResume = sysctrl->shutdownResume;
2740d163575Sopenharmony_ci    }
2750d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
2760d163575Sopenharmony_ci
2770d163575Sopenharmony_ci    return LOS_OK;
2780d163575Sopenharmony_ci}
2790d163575Sopenharmony_ci
2800d163575Sopenharmony_ciUINT32 LOS_PmRegister(LOS_PmNodeType type, VOID *node)
2810d163575Sopenharmony_ci{
2820d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
2830d163575Sopenharmony_ci
2840d163575Sopenharmony_ci    if (node == NULL) {
2850d163575Sopenharmony_ci        return LOS_EINVAL;
2860d163575Sopenharmony_ci    }
2870d163575Sopenharmony_ci
2880d163575Sopenharmony_ci    switch (type) {
2890d163575Sopenharmony_ci        case LOS_PM_TYPE_DEVICE:
2900d163575Sopenharmony_ci            return OsPmDeviceRegister(pm, (LosPmDevice *)node);
2910d163575Sopenharmony_ci        case LOS_PM_TYPE_TICK_TIMER:
2920d163575Sopenharmony_ci            PRINT_ERR("Pm, %d is an unsupported type\n", type);
2930d163575Sopenharmony_ci            return LOS_EINVAL;
2940d163575Sopenharmony_ci        case LOS_PM_TYPE_SYSCTRL:
2950d163575Sopenharmony_ci            return OsPmSysctrlRegister(pm, (LosPmSysctrl *)node);
2960d163575Sopenharmony_ci        default:
2970d163575Sopenharmony_ci            break;
2980d163575Sopenharmony_ci    }
2990d163575Sopenharmony_ci
3000d163575Sopenharmony_ci    return LOS_EINVAL;
3010d163575Sopenharmony_ci}
3020d163575Sopenharmony_ci
3030d163575Sopenharmony_ciSTATIC UINT32 OsPmDeviceUnregister(LosPmCB *pm, const LosPmDevice *device)
3040d163575Sopenharmony_ci{
3050d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
3060d163575Sopenharmony_ci    if (pm->device == device) {
3070d163575Sopenharmony_ci        pm->device = NULL;
3080d163575Sopenharmony_ci        pm->pmMode = LOS_SYS_NORMAL_SLEEP;
3090d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
3100d163575Sopenharmony_ci        return LOS_OK;
3110d163575Sopenharmony_ci    }
3120d163575Sopenharmony_ci
3130d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
3140d163575Sopenharmony_ci    return LOS_EINVAL;
3150d163575Sopenharmony_ci}
3160d163575Sopenharmony_ci
3170d163575Sopenharmony_ciSTATIC UINT32 OsPmSysctrlUnregister(LosPmCB *pm, LosPmSysctrl *sysctrl)
3180d163575Sopenharmony_ci{
3190d163575Sopenharmony_ci    (VOID)sysctrl;
3200d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
3210d163575Sopenharmony_ci    OsPmSysctrlInit();
3220d163575Sopenharmony_ci    pm->pmMode = LOS_SYS_NORMAL_SLEEP;
3230d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
3240d163575Sopenharmony_ci
3250d163575Sopenharmony_ci    return LOS_OK;
3260d163575Sopenharmony_ci}
3270d163575Sopenharmony_ci
3280d163575Sopenharmony_ciUINT32 LOS_PmUnregister(LOS_PmNodeType type, VOID *node)
3290d163575Sopenharmony_ci{
3300d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
3310d163575Sopenharmony_ci
3320d163575Sopenharmony_ci    if (node == NULL) {
3330d163575Sopenharmony_ci        return LOS_EINVAL;
3340d163575Sopenharmony_ci    }
3350d163575Sopenharmony_ci
3360d163575Sopenharmony_ci    switch (type) {
3370d163575Sopenharmony_ci        case LOS_PM_TYPE_DEVICE:
3380d163575Sopenharmony_ci            return OsPmDeviceUnregister(pm, (LosPmDevice *)node);
3390d163575Sopenharmony_ci        case LOS_PM_TYPE_TICK_TIMER:
3400d163575Sopenharmony_ci            PRINT_ERR("Pm, %d is an unsupported type\n", type);
3410d163575Sopenharmony_ci            return LOS_EINVAL;
3420d163575Sopenharmony_ci        case LOS_PM_TYPE_SYSCTRL:
3430d163575Sopenharmony_ci            return OsPmSysctrlUnregister(pm, (LosPmSysctrl *)node);
3440d163575Sopenharmony_ci        default:
3450d163575Sopenharmony_ci            break;
3460d163575Sopenharmony_ci    }
3470d163575Sopenharmony_ci
3480d163575Sopenharmony_ci    return LOS_EINVAL;
3490d163575Sopenharmony_ci}
3500d163575Sopenharmony_ci
3510d163575Sopenharmony_ciVOID LOS_PmWakeSet(VOID)
3520d163575Sopenharmony_ci{
3530d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
3540d163575Sopenharmony_ci
3550d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
3560d163575Sopenharmony_ci    pm->isWake = TRUE;
3570d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
3580d163575Sopenharmony_ci    return;
3590d163575Sopenharmony_ci}
3600d163575Sopenharmony_ci
3610d163575Sopenharmony_ciLOS_SysSleepEnum LOS_PmModeGet(VOID)
3620d163575Sopenharmony_ci{
3630d163575Sopenharmony_ci    LOS_SysSleepEnum mode;
3640d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
3650d163575Sopenharmony_ci
3660d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
3670d163575Sopenharmony_ci    mode = pm->pmMode;
3680d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
3690d163575Sopenharmony_ci
3700d163575Sopenharmony_ci    return mode;
3710d163575Sopenharmony_ci}
3720d163575Sopenharmony_ci
3730d163575Sopenharmony_ciUINT32 LOS_PmModeSet(LOS_SysSleepEnum mode)
3740d163575Sopenharmony_ci{
3750d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
3760d163575Sopenharmony_ci    INT32 sleepMode = (INT32)mode;
3770d163575Sopenharmony_ci
3780d163575Sopenharmony_ci    if ((sleepMode < 0) || (sleepMode > LOS_SYS_SHUTDOWN)) {
3790d163575Sopenharmony_ci        return LOS_EINVAL;
3800d163575Sopenharmony_ci    }
3810d163575Sopenharmony_ci
3820d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
3830d163575Sopenharmony_ci    if ((mode == LOS_SYS_LIGHT_SLEEP) && (pm->sysctrl->lightSuspend == NULL)) {
3840d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
3850d163575Sopenharmony_ci        return LOS_EINVAL;
3860d163575Sopenharmony_ci    }
3870d163575Sopenharmony_ci
3880d163575Sopenharmony_ci    if ((mode == LOS_SYS_DEEP_SLEEP) && (pm->sysctrl->deepSuspend == NULL)) {
3890d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
3900d163575Sopenharmony_ci        return LOS_EINVAL;
3910d163575Sopenharmony_ci    }
3920d163575Sopenharmony_ci
3930d163575Sopenharmony_ci    if ((mode == LOS_SYS_SHUTDOWN) && (pm->sysctrl->shutdownSuspend == NULL)) {
3940d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
3950d163575Sopenharmony_ci        return LOS_EINVAL;
3960d163575Sopenharmony_ci    }
3970d163575Sopenharmony_ci
3980d163575Sopenharmony_ci    pm->pmMode = mode;
3990d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
4000d163575Sopenharmony_ci
4010d163575Sopenharmony_ci    return LOS_OK;
4020d163575Sopenharmony_ci}
4030d163575Sopenharmony_ci
4040d163575Sopenharmony_ciUINT32 LOS_PmLockCountGet(VOID)
4050d163575Sopenharmony_ci{
4060d163575Sopenharmony_ci    UINT16 count;
4070d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
4080d163575Sopenharmony_ci
4090d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
4100d163575Sopenharmony_ci    count = pm->lock;
4110d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
4120d163575Sopenharmony_ci
4130d163575Sopenharmony_ci    return (UINT32)count;
4140d163575Sopenharmony_ci}
4150d163575Sopenharmony_ci
4160d163575Sopenharmony_ciVOID LOS_PmLockInfoShow(struct SeqBuf *m)
4170d163575Sopenharmony_ci{
4180d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
4190d163575Sopenharmony_ci    OsPmLockCB *lock = NULL;
4200d163575Sopenharmony_ci    LOS_DL_LIST *head = &pm->lockList;
4210d163575Sopenharmony_ci    LOS_DL_LIST *list = head->pstNext;
4220d163575Sopenharmony_ci
4230d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
4240d163575Sopenharmony_ci    while (list != head) {
4250d163575Sopenharmony_ci        lock = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
4260d163575Sopenharmony_ci        PM_INFO_SHOW(m, "%-30s%5u\n\r", lock->name, lock->count);
4270d163575Sopenharmony_ci        list = list->pstNext;
4280d163575Sopenharmony_ci    }
4290d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
4300d163575Sopenharmony_ci
4310d163575Sopenharmony_ci    return;
4320d163575Sopenharmony_ci}
4330d163575Sopenharmony_ci
4340d163575Sopenharmony_ciUINT32 OsPmLockRequest(const CHAR *name, UINT32 swtmrID)
4350d163575Sopenharmony_ci{
4360d163575Sopenharmony_ci    INT32 len;
4370d163575Sopenharmony_ci    errno_t err;
4380d163575Sopenharmony_ci    UINT32 ret = LOS_EINVAL;
4390d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
4400d163575Sopenharmony_ci    OsPmLockCB *lock = NULL;
4410d163575Sopenharmony_ci    LOS_DL_LIST *head = &pm->lockList;
4420d163575Sopenharmony_ci    LOS_DL_LIST *list = head->pstNext;
4430d163575Sopenharmony_ci
4440d163575Sopenharmony_ci    if (OS_INT_ACTIVE) {
4450d163575Sopenharmony_ci        return LOS_EINTR;
4460d163575Sopenharmony_ci    }
4470d163575Sopenharmony_ci
4480d163575Sopenharmony_ci    len = strlen(name);
4490d163575Sopenharmony_ci    if (len <= 0) {
4500d163575Sopenharmony_ci        return LOS_EINVAL;
4510d163575Sopenharmony_ci    }
4520d163575Sopenharmony_ci
4530d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
4540d163575Sopenharmony_ci    if (pm->lock >= OS_PM_LOCK_MAX) {
4550d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
4560d163575Sopenharmony_ci        return LOS_EINVAL;
4570d163575Sopenharmony_ci    }
4580d163575Sopenharmony_ci
4590d163575Sopenharmony_ci    while (list != head) {
4600d163575Sopenharmony_ci        OsPmLockCB *listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
4610d163575Sopenharmony_ci        if (strcmp(name, listNode->name) == 0) {
4620d163575Sopenharmony_ci            lock = listNode;
4630d163575Sopenharmony_ci            break;
4640d163575Sopenharmony_ci        }
4650d163575Sopenharmony_ci
4660d163575Sopenharmony_ci        list = list->pstNext;
4670d163575Sopenharmony_ci    }
4680d163575Sopenharmony_ci
4690d163575Sopenharmony_ci    if (lock == NULL) {
4700d163575Sopenharmony_ci        lock = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(OsPmLockCB));
4710d163575Sopenharmony_ci        if (lock == NULL) {
4720d163575Sopenharmony_ci            LOS_SpinUnlock(&g_pmSpin);
4730d163575Sopenharmony_ci            return LOS_ENOMEM;
4740d163575Sopenharmony_ci        }
4750d163575Sopenharmony_ci        err = memcpy_s(lock->name, OS_PM_LOCK_NAME_MAX, name, len + 1);
4760d163575Sopenharmony_ci        if (err != EOK) {
4770d163575Sopenharmony_ci            LOS_SpinUnlock(&g_pmSpin);
4780d163575Sopenharmony_ci            (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lock);
4790d163575Sopenharmony_ci            return err;
4800d163575Sopenharmony_ci        }
4810d163575Sopenharmony_ci        lock->count = 1;
4820d163575Sopenharmony_ci        lock->swtmrID = swtmrID;
4830d163575Sopenharmony_ci        LOS_ListTailInsert(head, &lock->list);
4840d163575Sopenharmony_ci    } else if (lock->count < OS_PM_LOCK_MAX) {
4850d163575Sopenharmony_ci        lock->count++;
4860d163575Sopenharmony_ci    }
4870d163575Sopenharmony_ci
4880d163575Sopenharmony_ci    if ((lock->swtmrID != OS_INVALID) && (lock->count > 1)) {
4890d163575Sopenharmony_ci        lock->count--;
4900d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
4910d163575Sopenharmony_ci        return LOS_EINVAL;
4920d163575Sopenharmony_ci    }
4930d163575Sopenharmony_ci
4940d163575Sopenharmony_ci    if (pm->lock < OS_PM_LOCK_MAX) {
4950d163575Sopenharmony_ci        pm->lock++;
4960d163575Sopenharmony_ci        ret = LOS_OK;
4970d163575Sopenharmony_ci    }
4980d163575Sopenharmony_ci
4990d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
5000d163575Sopenharmony_ci    return ret;
5010d163575Sopenharmony_ci}
5020d163575Sopenharmony_ci
5030d163575Sopenharmony_ciUINT32 LOS_PmLockRequest(const CHAR *name)
5040d163575Sopenharmony_ci{
5050d163575Sopenharmony_ci    if (name == NULL) {
5060d163575Sopenharmony_ci        return LOS_EINVAL;
5070d163575Sopenharmony_ci    }
5080d163575Sopenharmony_ci
5090d163575Sopenharmony_ci    return OsPmLockRequest(name, OS_INVALID);
5100d163575Sopenharmony_ci}
5110d163575Sopenharmony_ci
5120d163575Sopenharmony_ciUINT32 LOS_PmLockRelease(const CHAR *name)
5130d163575Sopenharmony_ci{
5140d163575Sopenharmony_ci    UINT32 ret = LOS_EINVAL;
5150d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
5160d163575Sopenharmony_ci    OsPmLockCB *lock = NULL;
5170d163575Sopenharmony_ci    LOS_DL_LIST *head = &pm->lockList;
5180d163575Sopenharmony_ci    LOS_DL_LIST *list = head->pstNext;
5190d163575Sopenharmony_ci    OsPmLockCB *lockFree = NULL;
5200d163575Sopenharmony_ci    BOOL isRelease = FALSE;
5210d163575Sopenharmony_ci    UINT32 mode;
5220d163575Sopenharmony_ci
5230d163575Sopenharmony_ci    if (name == NULL) {
5240d163575Sopenharmony_ci        return LOS_EINVAL;
5250d163575Sopenharmony_ci    }
5260d163575Sopenharmony_ci
5270d163575Sopenharmony_ci    if (OS_INT_ACTIVE) {
5280d163575Sopenharmony_ci        return LOS_EINTR;
5290d163575Sopenharmony_ci    }
5300d163575Sopenharmony_ci
5310d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
5320d163575Sopenharmony_ci    if (pm->lock == 0) {
5330d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
5340d163575Sopenharmony_ci        return LOS_EINVAL;
5350d163575Sopenharmony_ci    }
5360d163575Sopenharmony_ci
5370d163575Sopenharmony_ci    mode = (UINT32)pm->pmMode;
5380d163575Sopenharmony_ci    while (list != head) {
5390d163575Sopenharmony_ci        OsPmLockCB *listNode = LOS_DL_LIST_ENTRY(list, OsPmLockCB, list);
5400d163575Sopenharmony_ci        if (strcmp(name, listNode->name) == 0) {
5410d163575Sopenharmony_ci            lock = listNode;
5420d163575Sopenharmony_ci            break;
5430d163575Sopenharmony_ci        }
5440d163575Sopenharmony_ci
5450d163575Sopenharmony_ci        list = list->pstNext;
5460d163575Sopenharmony_ci    }
5470d163575Sopenharmony_ci
5480d163575Sopenharmony_ci    if (lock == NULL) {
5490d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
5500d163575Sopenharmony_ci        return LOS_EINVAL;
5510d163575Sopenharmony_ci    } else if (lock->count > 0) {
5520d163575Sopenharmony_ci        lock->count--;
5530d163575Sopenharmony_ci        if (lock->count == 0) {
5540d163575Sopenharmony_ci            LOS_ListDelete(&lock->list);
5550d163575Sopenharmony_ci            lockFree = lock;
5560d163575Sopenharmony_ci        }
5570d163575Sopenharmony_ci    }
5580d163575Sopenharmony_ci
5590d163575Sopenharmony_ci    if (pm->lock > 0) {
5600d163575Sopenharmony_ci        pm->lock--;
5610d163575Sopenharmony_ci        if (pm->lock == 0) {
5620d163575Sopenharmony_ci            isRelease = TRUE;
5630d163575Sopenharmony_ci        }
5640d163575Sopenharmony_ci        ret = LOS_OK;
5650d163575Sopenharmony_ci    }
5660d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
5670d163575Sopenharmony_ci
5680d163575Sopenharmony_ci    if (lockFree != NULL) {
5690d163575Sopenharmony_ci        (VOID)LOS_SwtmrDelete(lockFree->swtmrID);
5700d163575Sopenharmony_ci        (VOID)LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, lockFree);
5710d163575Sopenharmony_ci    }
5720d163575Sopenharmony_ci
5730d163575Sopenharmony_ci    if (isRelease && (mode > LOS_SYS_NORMAL_SLEEP)) {
5740d163575Sopenharmony_ci        (VOID)LOS_EventWrite(&g_pmEvent, PM_EVENT_LOCK_RELEASE);
5750d163575Sopenharmony_ci    }
5760d163575Sopenharmony_ci
5770d163575Sopenharmony_ci    return ret;
5780d163575Sopenharmony_ci}
5790d163575Sopenharmony_ci
5800d163575Sopenharmony_ciSTATIC VOID OsPmSwtmrHandler(UINT32 arg)
5810d163575Sopenharmony_ci{
5820d163575Sopenharmony_ci    const CHAR *name = (const CHAR *)arg;
5830d163575Sopenharmony_ci    UINT32 ret = LOS_PmLockRelease(name);
5840d163575Sopenharmony_ci    if (ret != LOS_OK) {
5850d163575Sopenharmony_ci        PRINT_ERR("Pm delay lock %s release faled! : 0x%x\n", name, ret);
5860d163575Sopenharmony_ci    }
5870d163575Sopenharmony_ci}
5880d163575Sopenharmony_ci
5890d163575Sopenharmony_ciUINT32 LOS_PmTimeLockRequest(const CHAR *name, UINT64 millisecond)
5900d163575Sopenharmony_ci{
5910d163575Sopenharmony_ci    UINT32 ticks;
5920d163575Sopenharmony_ci    UINT16 swtmrID;
5930d163575Sopenharmony_ci    UINT32 ret;
5940d163575Sopenharmony_ci
5950d163575Sopenharmony_ci    if ((name == NULL) || !millisecond) {
5960d163575Sopenharmony_ci        return LOS_EINVAL;
5970d163575Sopenharmony_ci    }
5980d163575Sopenharmony_ci
5990d163575Sopenharmony_ci    ticks = (UINT32)((millisecond + OS_MS_PER_TICK - 1) / OS_MS_PER_TICK);
6000d163575Sopenharmony_ci#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
6010d163575Sopenharmony_ci    ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name,
6020d163575Sopenharmony_ci                          OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
6030d163575Sopenharmony_ci#else
6040d163575Sopenharmony_ci    ret = LOS_SwtmrCreate(ticks, LOS_SWTMR_MODE_ONCE, OsPmSwtmrHandler, &swtmrID, (UINT32)(UINTPTR)name);
6050d163575Sopenharmony_ci#endif
6060d163575Sopenharmony_ci    if (ret != LOS_OK) {
6070d163575Sopenharmony_ci        return ret;
6080d163575Sopenharmony_ci    }
6090d163575Sopenharmony_ci
6100d163575Sopenharmony_ci    ret = OsPmLockRequest(name, swtmrID);
6110d163575Sopenharmony_ci    if (ret != LOS_OK) {
6120d163575Sopenharmony_ci        (VOID)LOS_SwtmrDelete(swtmrID);
6130d163575Sopenharmony_ci        return ret;
6140d163575Sopenharmony_ci    }
6150d163575Sopenharmony_ci
6160d163575Sopenharmony_ci    ret = LOS_SwtmrStart(swtmrID);
6170d163575Sopenharmony_ci    if (ret != LOS_OK) {
6180d163575Sopenharmony_ci        (VOID)LOS_PmLockRelease(name);
6190d163575Sopenharmony_ci    }
6200d163575Sopenharmony_ci
6210d163575Sopenharmony_ci    return ret;
6220d163575Sopenharmony_ci}
6230d163575Sopenharmony_ci
6240d163575Sopenharmony_ciUINT32 LOS_PmReadLock(VOID)
6250d163575Sopenharmony_ci{
6260d163575Sopenharmony_ci    UINT32 ret = LOS_EventRead(&g_pmEvent, PM_EVENT_LOCK_MASK, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
6270d163575Sopenharmony_ci    if (ret > PM_EVENT_LOCK_MASK) {
6280d163575Sopenharmony_ci        PRINT_ERR("%s event read failed! ERROR: 0x%x\n", __FUNCTION__, ret);
6290d163575Sopenharmony_ci    }
6300d163575Sopenharmony_ci
6310d163575Sopenharmony_ci    return LOS_OK;
6320d163575Sopenharmony_ci}
6330d163575Sopenharmony_ci
6340d163575Sopenharmony_ciUINT32 LOS_PmSuspend(UINT32 wakeCount)
6350d163575Sopenharmony_ci{
6360d163575Sopenharmony_ci    (VOID)wakeCount;
6370d163575Sopenharmony_ci    return OsPmSuspendSleep(&g_pmCB);
6380d163575Sopenharmony_ci}
6390d163575Sopenharmony_ci
6400d163575Sopenharmony_ciBOOL OsIsPmMode(VOID)
6410d163575Sopenharmony_ci{
6420d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
6430d163575Sopenharmony_ci
6440d163575Sopenharmony_ci    LOS_SpinLock(&g_pmSpin);
6450d163575Sopenharmony_ci    if ((pm->sysMode != LOS_SYS_NORMAL_SLEEP) && (pm->lock == 0)) {
6460d163575Sopenharmony_ci        LOS_SpinUnlock(&g_pmSpin);
6470d163575Sopenharmony_ci        return TRUE;
6480d163575Sopenharmony_ci    }
6490d163575Sopenharmony_ci    LOS_SpinUnlock(&g_pmSpin);
6500d163575Sopenharmony_ci    return FALSE;
6510d163575Sopenharmony_ci}
6520d163575Sopenharmony_ci
6530d163575Sopenharmony_ciSTATIC UINT32 OsPmSuspendDefaultHandler(VOID)
6540d163575Sopenharmony_ci{
6550d163575Sopenharmony_ci    PRINTK("Enter pm default handler!!!\n");
6560d163575Sopenharmony_ci    WFI;
6570d163575Sopenharmony_ci    return LOS_OK;
6580d163575Sopenharmony_ci}
6590d163575Sopenharmony_ci
6600d163575Sopenharmony_ciSTATIC VOID OsPmSysctrlInit(VOID)
6610d163575Sopenharmony_ci{
6620d163575Sopenharmony_ci    /* Default handler functions, which are implemented by the product */
6630d163575Sopenharmony_ci    g_sysctrl.early = NULL;
6640d163575Sopenharmony_ci    g_sysctrl.late = NULL;
6650d163575Sopenharmony_ci    g_sysctrl.normalSuspend = OsPmSuspendDefaultHandler;
6660d163575Sopenharmony_ci    g_sysctrl.normalResume = NULL;
6670d163575Sopenharmony_ci    g_sysctrl.lightSuspend = OsPmSuspendDefaultHandler;
6680d163575Sopenharmony_ci    g_sysctrl.lightResume = NULL;
6690d163575Sopenharmony_ci    g_sysctrl.deepSuspend = OsPmSuspendDefaultHandler;
6700d163575Sopenharmony_ci    g_sysctrl.deepResume = NULL;
6710d163575Sopenharmony_ci    g_sysctrl.shutdownSuspend = NULL;
6720d163575Sopenharmony_ci    g_sysctrl.shutdownResume = NULL;
6730d163575Sopenharmony_ci}
6740d163575Sopenharmony_ci
6750d163575Sopenharmony_ciUINT32 OsPmInit(VOID)
6760d163575Sopenharmony_ci{
6770d163575Sopenharmony_ci    LosPmCB *pm = &g_pmCB;
6780d163575Sopenharmony_ci
6790d163575Sopenharmony_ci    (VOID)memset_s(pm, sizeof(LosPmCB), 0, sizeof(LosPmCB));
6800d163575Sopenharmony_ci
6810d163575Sopenharmony_ci    pm->pmMode = LOS_SYS_NORMAL_SLEEP;
6820d163575Sopenharmony_ci    LOS_ListInit(&pm->lockList);
6830d163575Sopenharmony_ci    (VOID)LOS_EventInit(&g_pmEvent);
6840d163575Sopenharmony_ci
6850d163575Sopenharmony_ci    OsPmSysctrlInit();
6860d163575Sopenharmony_ci    pm->sysctrl = &g_sysctrl;
6870d163575Sopenharmony_ci    return LOS_OK;
6880d163575Sopenharmony_ci}
6890d163575Sopenharmony_ci
6900d163575Sopenharmony_ciLOS_MODULE_INIT(OsPmInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
6910d163575Sopenharmony_ci#endif
692