mcu_hi3321_watch/middleware/chips/brandy/pm/pm.c
2025-05-26 20:15:20 +08:00

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);
}