216 lines
5.1 KiB
C
216 lines
5.1 KiB
C
/*
|
|
* Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved.
|
|
* Description: pm dev operations code
|
|
*/
|
|
|
|
#include "pm.h"
|
|
#include "pm_sleep.h"
|
|
#include "pm_veto.h"
|
|
#include "pm_dev.h"
|
|
#include "pm_fsm.h"
|
|
#include "clocks_core.h"
|
|
#include "chip_io.h"
|
|
#include "rtc.h"
|
|
#include "watchdog.h"
|
|
#include "watchdog_porting.h"
|
|
#include "securec.h"
|
|
#include "pmu_interrupt.h"
|
|
#include "calendar_porting.h"
|
|
|
|
typedef struct {
|
|
uint32_t slp_ms;
|
|
uint32_t handle;
|
|
rtc_callback_t cb;
|
|
} pm_rtc_timer_t;
|
|
|
|
typedef struct {
|
|
pm_dev_id_t dev_id;
|
|
pm_dev_ops_t dev_ops;
|
|
} pm_dev_t;
|
|
|
|
#if CORE == MASTER_BY_ALL
|
|
static clocks_clk_cfg_t g_cpu_cfg;
|
|
#endif
|
|
|
|
#define PM_SHIPMODE_DELAY_SLEEP_MS 100
|
|
|
|
// ostimer
|
|
static uint32_t pm_dev_ostimer_ioctl(uint8_t type, uint8_t *data, uint32_t len)
|
|
{
|
|
UNUSED(data);
|
|
UNUSED(len);
|
|
switch (type) {
|
|
case DEV_OSTIMER_ENABLE:
|
|
pm_os_timer_enable();
|
|
break;
|
|
case DEV_OSTIMER_DISABLE:
|
|
pm_os_timer_disable();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// rtc
|
|
static uint32_t rtc_start_wkup_timer(uint8_t *data, uint32_t len)
|
|
{
|
|
if (len != sizeof(pm_rtc_timer_t)) {
|
|
return (uint32_t)ERRCODE_PM_ERROR;
|
|
}
|
|
|
|
pm_rtc_timer_t *timer = (pm_rtc_timer_t *)data;
|
|
uint32_t wakeup_time = timer->slp_ms;
|
|
rtc_handle_t *handle = (rtc_handle_t)(timer->handle);
|
|
if (handle == NULL) {
|
|
return (uint32_t)ERRCODE_PM_ERROR;
|
|
}
|
|
if (*handle == NULL) {
|
|
uapi_rtc_create(RTC_0, handle);
|
|
uapi_rtc_start(*handle, wakeup_time, (rtc_callback_t)timer->cb, 0);
|
|
} else {
|
|
uapi_rtc_start(*handle, wakeup_time, (rtc_callback_t)timer->cb, 0);
|
|
}
|
|
return (uint32_t)ERRCODE_SUCC;
|
|
}
|
|
|
|
static uint32_t pm_dev_rtc_ioctl(uint8_t type, uint8_t *data, uint32_t len)
|
|
{
|
|
UNUSED(data);
|
|
UNUSED(len);
|
|
switch (type) {
|
|
case DEV_RTC_START:
|
|
return rtc_start_wkup_timer(data, len);
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t pm_dev_wdt_ioctl(uint8_t type, uint8_t *data, uint32_t len)
|
|
{
|
|
UNUSED(data);
|
|
UNUSED(len);
|
|
switch (type) {
|
|
case DEV_WDT_ENABLE:
|
|
watchdog_turnon_clk();
|
|
uapi_watchdog_set_time(watchdog_get_conifgtime);
|
|
uapi_watchdog_enable(WDT_MODE_INTERRUPT);
|
|
break;
|
|
case DEV_WDT_DISABLE:
|
|
watchdog_turnon_clk();
|
|
uapi_watchdog_disable();
|
|
watchdog_turnoff_clk();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void pm_dev_register_sleep_ops(void)
|
|
{
|
|
pm_dev_t all_devs[] = PM_ALL_DEV;
|
|
|
|
for (uint8_t i = 0; i < sizeof(all_devs) / sizeof(pm_dev_t); i++) {
|
|
uapi_pm_register_dev_ops(all_devs[i].dev_id, &(all_devs[i].dev_ops));
|
|
}
|
|
}
|
|
|
|
static uint32_t core_crg_switch(uint8_t *data, uint32_t len)
|
|
{
|
|
UNUSED(data);
|
|
UNUSED(len);
|
|
#if CORE == MASTER_BY_ALL
|
|
if (data == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (data[0] == PM_STATE_DEEP_SLEEP) {
|
|
// todo
|
|
} else if (data[0] == PM_STATE_WKUP_FROM_DEEP_SLEEP) {
|
|
// todo
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static void pm_fsm_register_sleep_handler(void)
|
|
{
|
|
uint8_t state = PM_STATE_DEEP_SLEEP;
|
|
pm_fsm_content_t content = {&state, 1, core_crg_switch};
|
|
uapi_pm_register_fsm_handler(PM_ID_SYS, PM_STATE_DEEP_SLEEP, &content);
|
|
|
|
state = PM_STATE_WKUP_FROM_DEEP_SLEEP;
|
|
uapi_pm_register_fsm_handler(PM_ID_SYS, PM_STATE_WKUP_FROM_DEEP_SLEEP, &content);
|
|
}
|
|
|
|
void uapi_pm_init(void)
|
|
{
|
|
pm_veto_init();
|
|
pm_dev_register_sleep_ops();
|
|
pm_fsm_register_sleep_handler();
|
|
#if ENABLE_LOW_POWER == YES
|
|
#ifdef __LITEOS__
|
|
LOS_LowpowerHookReg(uapi_pm_enter_sleep);
|
|
#endif
|
|
uapi_pm_add_sleep_veto(PM_ID_DEBUG);
|
|
#endif
|
|
}
|
|
|
|
void uapi_sys_force_mcu_only_deep_sleep_mode(uint32_t arg)
|
|
{
|
|
UNUSED(arg);
|
|
uint32_t irq = osal_irq_lock();
|
|
|
|
reg16_clrbit(0x57000168, 0x2); // close watchdog clock
|
|
pm_enter_deep_sleep_only_ulp_wakeup();
|
|
osal_irq_restore(irq);
|
|
}
|
|
|
|
void uapi_sys_shipmode(uint32_t arg)
|
|
{
|
|
uapi_calendar_calibration_enable();
|
|
UNUSED(arg);
|
|
uint32_t irq = osal_irq_lock();
|
|
uapi_pm_control(PM_BT_POWER_OFF);
|
|
uapi_pm_control(PM_DSP_POWER_OFF);
|
|
uapi_pm_control(PM_DISPLAY_POWER_OFF);
|
|
|
|
/* clr ulp reg0 */
|
|
writew(0x5702c010, 0);
|
|
|
|
/* clr ulp int and event */
|
|
writel(0x5702C1E4, 0x3F);
|
|
writel(0x5702C1EC, 0x3F);
|
|
uapi_tcxo_delay_us(PM_SHIPMODE_DELAY_SLEEP_MS);
|
|
|
|
reg16_clrbit(0x5702c508, POS_14);
|
|
writew(0x5700450c, 0x100);
|
|
|
|
// gpio
|
|
writew(0x5702C200, 0x0);
|
|
writew(0x5702C204, 0x0);
|
|
writew(0x5702C208, 0x0);
|
|
writew(0x5702C20c, 0x0);
|
|
writew(0x5702C210, 0x0);
|
|
|
|
writew(0x5702c200, 0x7);
|
|
writew(0x57030004, 0x0);
|
|
writew(0x57030038, 0x1);
|
|
writew(0x5703003c, 0x1);
|
|
writew(0x57030034, 0x0);
|
|
writew(0x57030030, 0x1);
|
|
|
|
writew(0x570040d8, 0xc000);
|
|
writew(0x5702c028, 0x0);
|
|
writew(0x5702c024, 0x3);
|
|
writew(0x5702c1d0, 0x1);
|
|
writew(0x5702C038, 0x0);
|
|
writew(0x5702C1F0, 0x1C);
|
|
writew(0x5702C110, 0x101);
|
|
writew(0x570040d0, 0x1);
|
|
writew(0x570040e0, 0x1);
|
|
osal_irq_restore(irq);
|
|
}
|