2025-02-27 17:59:18 +08:00

2446 lines
68 KiB
C
Executable File

// Copyright 2021-2023 Beken
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <modules/pm.h>
#include "sys_driver.h"
#include <driver/gpio.h>
#include "gpio_ll.h"
#include <driver/aon_rtc.h>
#include <os/mem.h>
#include "aon_pmu_driver.h"
#include <components/system.h>
#include "bk_fake_clock.h"
#include <driver/uart.h>
#include "uart_statis.h"
#include "bk_uart.h"
#include <driver/touch.h>
#include <driver/touch_types.h>
#include <driver/pwr_clk.h>
#include <os/os.h>
#include "bk_pm_internal_api.h"
#include <driver/psram.h>
#if CONFIG_FLASH_ORIGIN_API
#include "bk_flash.h"
#else
#include "driver/flash.h"
#endif
#if CONFIG_INT_WDT
#include <driver/wdt.h>
#include <bk_wdt.h>
#endif
#if (CONFIG_CPU_CNT > 1)
#include <driver/mailbox_channel.h>
#endif
#if CONFIG_GPIO_WAKEUP_SUPPORT
#include "gpio_driver.h"
#endif
#include <driver/rosc_32k.h>
/*=====================DEFINE SECTION START=====================*/
#define PM_WAKEUP_SOURCE_MARK (WAKEUP_SOURCE_MARK)
#define ENTER_LOW_VOLTAGE_PROTECT_TIME (3) // 3ms
#define ENTER_LOW_VOLTAGE_WAKEUP_PROTECT_TIME (5) // 5m = 3ms(dpll+xtal 26m stability time) + 2ms(mtime interval),mainly for bt wakeup handle interrupt
#define DEFAULT_WAKEUP_TIME (10000) // 10s
#define PM_LOWVOL_CB_SIZE (0x2)
#define PM_SLEEP_CB_ENTER_LOWVOL_INDEX (0x0)
#define PM_SLEEP_CB_EXIT_LOWVOL_INDEX (0x1)
#define PM_DEEPSLEEP_CB_SIZE (10)
#if CONFIG_PM_SUPER_DEEP_SLEEP
#define PM_SUPERDEEP_CB_SIZE (10)
#endif
#define PM_SLEEP_CB_IND_PRI_0 (0)
#define PM_SLEEP_CB_IND_PRI_1 (6)
#define PM_SLEEP_TIME_COMPENSATION_ENABLE (0x0)
#define SWITCH_32K_WAIT (5000) // 5s
#define SWITCH_32K_DELAY (1000) // 1s
#define PM_DEBUG_SYS_REG_BASE (SOC_SYSTEM_REG_BASE)
#define PM_DEBUG_PMU_REG_BASE (SOC_AON_PMU_REG_BASE)
#define PM_SEND_CMD_CP0_RESPONSE_TIME_OUT (100) //100ms
/*=====================DEFINE SECTION END=====================*/
/*=====================VARIABLE SECTION START=================*/
static uint8_t s_debug_en = 0;
static uint32_t s_module_wakeup_time_ms = DEFAULT_WAKEUP_TIME;
static pm_sleep_mode_e s_pm_sleep_mode = PM_MODE_DEFAULT;
static uint32_t s_pm_wakeup_source = 0;
static uint64_t s_previous_tick = 0;
static uint64_t s_current_tick = 0;
static uint32_t s_pm_on_modules;
static uint32_t s_pm_off_modules;
static uint32_t s_pm_rf_on_modules;
static uint32_t s_pm_rf_off_modules;
static uint64_t s_pm_sleeped_modules = 0;
static uint64_t s_pm_enter_low_vol_modules = 0;
static uint32_t s_pm_enter_deep_sleep_modules = 0;
static uint32_t s_pm_mcu_pm_state = 0;
static uint8_t s_pm_app_auto_vote_enable = 1;
static uint32_t s_pm_lowvol_consume_time_exit_wfi = 0;
static uint32_t s_pm_phy_calibration_state = 0;
/**
* phy reinit has two part,one in BSP,another in wifi MAC
* part 2 must follow part1
* part1 only vaild in BT close,only wifi case
*/
static bool s_pm_is_phy_reinit_flag = false;
#if CONFIG_SYS_CPU0
static uint32_t s_pm_bakp_pm_state = 0;
static uint32_t s_pm_ahpb_pm_state = 0;
static uint32_t s_pm_audio_pm_state = 0;
static uint32_t s_pm_video_pm_state = 0;
static uint32_t s_pm_phy_pm_state = 0;
static uint32_t s_pm_cp1_auto_power_down_flag = PM_CP1_AUTO_POWER_DOWN_CTRL;
static pm_mem_auto_ctrl_e s_pm_mem_auto_power_down_flag = PM_MEM_AUTO_CTRL_ENABLE;
#if (CONFIG_CPU_CNT > 1)
static uint32_t s_pm_cp1_psram_malloc_count_state = 0;
#endif
#endif
static uint64_t s_bt_need_wakeup_time = 0;
static system_wakeup_param_t s_bt_system_wakeup_param;
static touch_wakeup_param_t s_touch_wakeup_param;
#if CONFIG_SYS_CPU0
static pm_wakeup_source_e s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_NONE;
static pm_wakeup_source_e s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_NONE;
#endif
#if CONFIG_PM_LIGHT_SLEEP
static pm_cb_conf_t s_pm_light_sleep_enter_cb_conf;
static pm_cb_conf_t s_pm_light_sleep_exit_cb_conf;
#endif
static __attribute__((section(".dtcm_sec_data "))) pm_cb_conf_t s_pm_lowvol_enter_exit_cb_conf[PM_LOWVOL_CB_SIZE][PM_DEV_ID_MAX];
static __attribute__((section(".dtcm_sec_data "))) pm_sleep_cb_t s_pm_deepsleep_enter_cb_conf[PM_DEEPSLEEP_CB_SIZE];
#if CONFIG_PM_SUPER_DEEP_SLEEP
static __attribute__((section(".dtcm_sec_data "))) pm_sleep_cb_t s_pm_superdeep_enter_cb_conf[PM_SUPERDEEP_CB_SIZE];
#endif
static __attribute__((section(".dtcm_sec_data "))) uint8_t s_pm_deepsleep_enter_cb_cnt[2] = {PM_SLEEP_CB_IND_PRI_0, PM_SLEEP_CB_IND_PRI_1};
#if CONFIG_PM_SUPER_DEEP_SLEEP
static __attribute__((section(".dtcm_sec_data "))) uint8_t s_pm_superdeep_enter_cb_cnt[2] = {PM_SLEEP_CB_IND_PRI_0, PM_SLEEP_CB_IND_PRI_1};
#endif
static uint8_t s_pm_cpu_freq[PM_DEV_ID_MAX];
static pm_cpu_freq_e s_pm_current_cpu_freq;
typedef struct
{
pm_cb_extern32k_cfg_t cfg[PM_32K_MODULE_MAX];
uint32_t module_count;
} pm_cb_module_cfg_t;
static pm_cb_module_cfg_t s_pm_cb_module_cfg;
static beken_semaphore_t s_sync_sema = NULL;
#if 1
uint32_t pm_wake_int_flag2;
#endif
/*=====================VARIABLE SECTION END=================*/
/*================FUNCTION DECLARATION SECTION START========*/
#if CONFIG_SYS_CPU0
static void pm_enter_low_vol_modules_config();
static void pm_enter_deep_sleep_modules_config();
static void pm_module_check_power_on(pm_power_module_name_e module);
static void pm_module_check_power_off(pm_power_module_name_e module);
static void pm_deep_sleep_wakeup_source_set();
bk_err_t pm_debug_module_state();
#endif
static void pm_check_power_on_module();
static bk_err_t pm_wakeup_from_deepsleep_handle();
static void pm_enter_normal_sleep();
static uint32_t pm_low_voltage_process();
static void pm_deep_sleep_process();
#if CONFIG_PM_SUPER_DEEP_SLEEP
static void pm_super_deep_sleep_process();
#endif
#if CONFIG_INT_WDT
extern int wdt_init(void);
#endif
extern void delay_us(UINT32 us);
/*================FUNCTION DECLARATION SECTION END========*/
/**
* !NOTIFICATION HERE!
* pm module is divided into 3 partitions as below:
* -- 1. sleep mode switch
* -- 2. voltage & freq ctrl
* -- 3. debug
* sleep mode switch is the main partition which further
* divided into the following submodules:
* -- 1. sleep state machine
* -- 2. modules power ctrl
* -- 3. wakeup source config
* -- 4. sleep/wakeup functions
*/
void pm_hardware_init()
{
#if CONFIG_SYS_CPU0
sys_drv_low_power_hardware_init();
/*config vote for entering low vol modules*/
pm_enter_low_vol_modules_config();
/*config vote for entering deepsleep modules*/
pm_enter_deep_sleep_modules_config();
/*add sleep vote*/
pm_sleep_vote_init();
/*set the wakeup wakeup source to misc module*/
pm_deep_sleep_wakeup_source_set();
/*pm vote power on ticket for bakp module*/
#if CONFIG_BAKP_POWER_DOMAIN_PM_CONTROL
bk_pm_module_vote_power_ctrl(POWER_SUB_MODULE_NAME_BAKP_PM, PM_POWER_MODULE_STATE_ON);
#endif
#endif
}
bk_err_t pm_module_wakeup_time_set(uint32_t module_name, uint32_t wakeup_time)
{
s_module_wakeup_time_ms = wakeup_time;
return BK_OK;
}
/*=========================SLEEP STATE MACHINE START========================*/
#if CONFIG_SYS_CPU0
static void pm_enter_low_vol_modules_config()
{
uint32_t i = 0;
pm_sleep_module_name_e enter_low_vol_modules[] = PM_ENTER_LOW_VOL_MODULES_CONFIG;
for (i = 0; i < sizeof(enter_low_vol_modules) / sizeof(pm_sleep_module_name_e); i++)
{
s_pm_enter_low_vol_modules |= 0x1ULL << enter_low_vol_modules[i];
}
}
static void pm_enter_deep_sleep_modules_config()
{
uint32_t i = 0;
pm_power_module_name_e enter_deep_sleep_modules[] = PM_ENTER_DEEP_SLEEP_MODULES_CONFIG;
for (i = 0; i < sizeof(enter_deep_sleep_modules) / sizeof(pm_power_module_name_e); i++)
{
s_pm_enter_deep_sleep_modules |= 0x1 << enter_deep_sleep_modules[i];
}
}
#endif
static uint32_t pm_check_protect_time(uint64_t current_tick, uint64_t previous_tick)
{
if (s_bt_need_wakeup_time > current_tick)
{
if ((s_bt_need_wakeup_time - current_tick) < (ENTER_LOW_VOLTAGE_WAKEUP_PROTECT_TIME * bk_rtc_get_ms_tick_count()))
{
if (s_debug_en & 0x1)
{
os_printf("protect_time1 %lld %lld %d\r\n", s_bt_need_wakeup_time, current_tick, s_bt_system_wakeup_param.sleep_time);
}
return 0;
}
}
else // s_bt_need_wakeup_time not set, it will be 0,or not clear value after bt wakeup
{
if (s_debug_en & 0x1)
{
os_printf("protect_time2 %lld %lld %d\r\n", s_bt_need_wakeup_time, current_tick, s_bt_system_wakeup_param.sleep_time);
}
return 0; // do something
}
return 1;
}
static uint32_t pm_check_and_ctrl_sleep()
{
uint32_t sleep_tick = 0;
pm_check_power_on_module();
pm_wakeup_from_deepsleep_handle();
if (s_pm_sleep_mode == PM_MODE_NORMAL_SLEEP)
{
pm_enter_normal_sleep();
}
else if (s_pm_sleep_mode == PM_MODE_LOW_VOLTAGE)
{
if (s_debug_en & 0x1)
{
#if CONFIG_SYS_CPU0
os_printf("lowvol1 0x%X 0x%llX 0x%llX\r\n", s_pm_sleep_mode, s_pm_sleeped_modules, s_pm_enter_low_vol_modules);
os_printf("lowvol2 0x%X 0x%X 0x%X 0x%X\r\n", s_pm_ahpb_pm_state, s_pm_video_pm_state, s_pm_audio_pm_state, s_pm_bakp_pm_state);
#endif
}
if ((s_pm_sleeped_modules & s_pm_enter_low_vol_modules) == s_pm_enter_low_vol_modules)
{
#if CONFIG_AON_RTC
s_current_tick = (uint32_t)bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
#endif
if (s_pm_on_modules & (0x1 << POWER_MODULE_NAME_BTSP))
{
if (!pm_check_protect_time(s_current_tick, s_previous_tick))
{
return 0;
}
}
sleep_tick = pm_low_voltage_process();
#if CONFIG_AON_RTC
s_previous_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
#endif
}
else
{
pm_enter_normal_sleep();
}
}
else if (s_pm_sleep_mode == PM_MODE_DEEP_SLEEP)
{
if (s_debug_en & 0x2)
{
#if CONFIG_SYS_CPU0
os_printf("deepsleep1 0x%X 0x%X\r\n", s_pm_off_modules, s_pm_enter_deep_sleep_modules);
os_printf("deepsleep2 0x%X 0x%X 0x%X 0x%X\r\n", s_pm_ahpb_pm_state, s_pm_video_pm_state, s_pm_audio_pm_state, s_pm_bakp_pm_state);
#endif
}
if ((s_pm_off_modules & s_pm_enter_deep_sleep_modules) == s_pm_enter_deep_sleep_modules)
{
pm_deep_sleep_process();
}
else
{
pm_enter_normal_sleep();
}
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
else if (s_pm_sleep_mode == PM_MODE_SUPER_DEEP_SLEEP)
{
if (s_debug_en & 0x2)
{
#if CONFIG_SYS_CPU0
os_printf("superdeepsleep1 0x%X 0x%X\r\n", s_pm_off_modules, s_pm_enter_deep_sleep_modules);
os_printf("superdeepsleep2 0x%X 0x%X 0x%X\r\n", s_pm_ahpb_pm_state, s_pm_video_pm_state, s_pm_audio_pm_state);
#endif
}
if ((s_pm_off_modules & s_pm_enter_deep_sleep_modules) == s_pm_enter_deep_sleep_modules)
{
pm_super_deep_sleep_process();
}
else
{
pm_enter_normal_sleep();
}
}
#endif
else
{
if (s_debug_en & 0x1)
{
#if CONFIG_SYS_CPU0
os_printf("lowvol1 0x%X 0x%llX 0x%llX\r\n", s_pm_sleep_mode, s_pm_sleeped_modules, s_pm_enter_low_vol_modules);
os_printf("lowvol2 0x%X 0x%X\r\n", s_pm_video_pm_state, s_pm_audio_pm_state);
#endif
}
if ((s_pm_sleeped_modules & s_pm_enter_low_vol_modules) == s_pm_enter_low_vol_modules)
{
#if CONFIG_AON_RTC
s_current_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
#endif
if (s_pm_on_modules & (0x1 << POWER_MODULE_NAME_BTSP))
{
if (!pm_check_protect_time(s_current_tick, s_previous_tick))
{
return 0;
}
}
sleep_tick = pm_low_voltage_process();
#if CONFIG_AON_RTC
s_previous_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
#endif
}
else
{
pm_enter_normal_sleep();
}
}
return sleep_tick;
}
uint32_t pm_state_machine()
{
uint32_t missed_ticks = 0;
missed_ticks = pm_check_and_ctrl_sleep();
#if PM_SLEEP_TIME_COMPENSATION_ENABLE
missed_ticks = (missed_ticks) / (bk_rtc_get_ms_tick_count() * (rtos_get_ms_per_tick()));
#else
missed_ticks = 0;
#endif
return missed_ticks;
}
bk_err_t pm_management(uint32_t sleep_ticks)
{
#if CONFIG_MCU_PS
#if CONFIG_PM_LIGHT_SLEEP
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
uint64_t missed_ticks = 0;
int ret = 0;
if (s_pm_mcu_pm_state)
{
return BK_OK;
}
if ((s_pm_light_sleep_enter_cb_conf.cb == NULL) || (s_pm_light_sleep_exit_cb_conf.cb == NULL))
{
return BK_FAIL;
}
ret = s_pm_light_sleep_enter_cb_conf.cb(sleep_ticks * rtos_get_ms_per_tick(), s_pm_light_sleep_enter_cb_conf.args);
if (ret)
{
return BK_FAIL;
}
previous_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
current_tick = previous_tick;
while (((current_tick - previous_tick)) < (sleep_ticks * rtos_get_ms_per_tick() * bk_rtc_get_ms_tick_count()))
{
current_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
}
// os_printf("idle task after:%d \r\n",sleep_ticks);
missed_ticks = pm_state_machine();
missed_ticks = sleep_ticks;
// bk_update_tick(missed_ticks);
s_pm_light_sleep_exit_cb_conf.cb(sleep_ticks * rtos_get_ms_per_tick(), s_pm_light_sleep_exit_cb_conf.args);
#else
uint32_t missed_ticks = 0;
if (s_pm_mcu_pm_state)
{
return BK_OK;
}
missed_ticks = pm_state_machine();
if (missed_ticks != 0)
{
// bk_update_tick(missed_ticks);
}
#endif
#else
#if CONFIG_SYS_CPU1
if (bk_pm_cp1_ctrl_state_get() == 0x0)
{
bk_pm_cp1_ctrl_state_set(PM_MAILBOX_COMMUNICATION_FINISH);
pm_cp1_mailbox_response(PM_CPU1_BOOT_READY_CMD, 0x1);
// os_printf("cpu1 already\r\n");
}
pm_enter_normal_sleep();
#endif
#endif
return BK_OK;
}
bk_err_t bk_pm_suppress_ticks_and_sleep(uint32_t sleep_ticks)
{
return pm_management(sleep_ticks);
}
/*=========================SLEEP STATE MACHINE END========================*/
/*=========================COMMON PM API START========================*/
bk_err_t bk_pm_module_vote_power_ctrl(pm_power_module_name_e module, pm_power_module_state_e power_state)
{
#if CONFIG_SYS_CPU1
#if CONFIG_MAILBOX
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
bk_pm_cp1_pwr_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_POWER_CTRL_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = power_state;
mb_cmd.param3 = 0;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
previous_tick = pm_cp1_aon_rtc_counter_get();
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_SEND_CMD_CP0_RESPONSE_TIME_OUT*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_pwr_ctrl_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_pwr_ctrl_state_get())
{
os_printf("cp1 power ctrl[%d] time out\r\n",module);
}
if (s_debug_en & 0x2)
os_printf("cpu1 vote power \r\n");
#endif
return BK_OK;
#elif CONFIG_SYS_CPU2
return BK_OK;
#elif CONFIG_SYS_CPU0
uint32_t off_modules = 0;
GLOBAL_INT_DECLARATION();
if (power_state == PM_POWER_MODULE_STATE_ON) // power on
{
if ( (module == PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART2)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SADC)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_TRNG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_IRDA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_COMSEG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_LA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PM))
{
GLOBAL_INT_DISABLE();
s_pm_bakp_pm_state |= 0x1 << (module % (PM_POWER_MODULE_NAME_BAKP * PM_MODULE_SUB_POWER_DOMAIN_MAX));
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_BAKP);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_BAKP;
GLOBAL_INT_RESTORE();
if (0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_BAKP))
{
return BK_OK;
}
else
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_BAKP, power_state);
}
}
else if ( (module == PM_POWER_SUB_MODULE_NAME_AHBP_CAN)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_USB)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_ENET)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_SCR)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_LIN))
{
GLOBAL_INT_DISABLE();
s_pm_ahpb_pm_state |= 0x1 << (module % (PM_POWER_MODULE_NAME_AHBP * PM_MODULE_SUB_POWER_DOMAIN_MAX));
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_AHBP);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_AHBP;
GLOBAL_INT_RESTORE();
if (0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AHBP))
{
return BK_OK;
}
else
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_AHBP, power_state);
}
}
else if ( (module == PM_POWER_SUB_MODULE_NAME_AUDP_FFT)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_SBC)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_AUDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_I2S))
{
GLOBAL_INT_DISABLE();
s_pm_audio_pm_state |= 0x1 << (module % (PM_POWER_MODULE_NAME_AUDP * PM_MODULE_SUB_POWER_DOMAIN_MAX));
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_AUDP);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_AUDP;
s_pm_sleeped_modules &= ~(0x1 << PM_POWER_MODULE_NAME_AUDP);
GLOBAL_INT_RESTORE();
if (s_pm_cp1_auto_power_down_flag)
{
pm_module_check_power_on(PM_POWER_MODULE_NAME_CPU1);
}
if (0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AUDP))
{
return BK_OK;
}
else
{
if (s_pm_mem_auto_power_down_flag)
{
pm_module_check_power_on(PM_POWER_MODULE_NAME_MEM3);
}
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_AUDP, power_state);
}
}
else if ((module == PM_POWER_SUB_MODULE_NAME_VIDP_DMA2D)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_YUVBUF)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_DE)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_LCD)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_ROTT)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL0)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL1)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_H264))
{
GLOBAL_INT_DISABLE();
s_pm_video_pm_state |= 0x1 << (module % (PM_POWER_MODULE_NAME_VIDP * PM_MODULE_SUB_POWER_DOMAIN_MAX));
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_VIDP);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_VIDP;
s_pm_sleeped_modules &= ~(0x1 << PM_POWER_MODULE_NAME_VIDP);
GLOBAL_INT_RESTORE();
if (s_pm_cp1_auto_power_down_flag)
{
pm_module_check_power_on(PM_POWER_MODULE_NAME_CPU1);
}
if (0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_VIDP))
{
// GLOBAL_INT_RESTORE();
return BK_OK;
}
else
{
if (s_pm_mem_auto_power_down_flag)
{
pm_module_check_power_on(PM_POWER_MODULE_NAME_MEM3);
}
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_VIDP, power_state);
}
}
else if ((module == PM_POWER_SUB_MODULE_NAME_PHY_BT)
|| (module == PM_POWER_SUB_MODULE_NAME_PHY_WIFI)
|| (module == PM_POWER_SUB_MODULE_NAME_PHY_RF))
{
GLOBAL_INT_DISABLE();
s_pm_phy_pm_state |= 0x1 << (module % (PM_POWER_MODULE_NAME_PHY * PM_MODULE_SUB_POWER_DOMAIN_MAX));
GLOBAL_INT_RESTORE();
if ((0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_PHY)) && (s_pm_phy_calibration_state == 0x1))
{
if (s_debug_en & 0x2)
os_printf("phy power on already\r\n");
return BK_OK;
}
else
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_PHY, power_state);
if (0x0 == sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_PHY))
{
if(PM_POWER_SUB_MODULE_NAME_PHY_RF != module)
{
#if CONFIG_WIFI_ENABLE
extern void phy_wakeup_reinit(uint8 is_wifi);
phy_wakeup_reinit(module == PM_POWER_SUB_MODULE_NAME_PHY_WIFI);
#else
extern void phy_wakeup_for_bluetooth();
phy_wakeup_for_bluetooth();
#endif
s_pm_is_phy_reinit_flag = true;
GLOBAL_INT_DISABLE();
s_pm_phy_calibration_state = 0x1;
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_PHY);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_PHY;
GLOBAL_INT_RESTORE();
}
else
{
GLOBAL_INT_DISABLE();
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_PHY);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_PHY;
GLOBAL_INT_RESTORE();
}
}
else
{
if (s_debug_en & 0x2)
{
os_printf("phy power on fail 0x%x\r\n", sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_PHY));
}
return BK_FAIL;
}
}
}
else if (module == PM_POWER_MODULE_NAME_BTSP)
{
if (s_pm_mem_auto_power_down_flag)
{
pm_module_check_power_on(PM_POWER_MODULE_NAME_MEM3);
}
sys_drv_module_power_ctrl(module, power_state);
GLOBAL_INT_DISABLE();
s_pm_off_modules &= ~(0x1 << PM_POWER_MODULE_NAME_BTSP);
s_pm_on_modules |= 0x1 << PM_POWER_MODULE_NAME_BTSP;
s_pm_sleeped_modules &= ~(0x1 << PM_POWER_MODULE_NAME_BTSP);
GLOBAL_INT_RESTORE();
}
else
{
sys_drv_module_power_ctrl(module, power_state);
if (module == PM_POWER_MODULE_NAME_PHY) // phy init call this, phy calibration itself
{
s_pm_phy_calibration_state = 0x1;
}
GLOBAL_INT_DISABLE();
s_pm_off_modules &= ~(0x1 << module);
s_pm_on_modules |= 0x1 << module;
GLOBAL_INT_RESTORE();
}
}
else // power off
{
if ( (module == PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART2)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SADC)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_TRNG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_IRDA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_COMSEG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_LA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PM))
{
GLOBAL_INT_DISABLE();
s_pm_bakp_pm_state &= ~(0x1 << (module % (PM_POWER_MODULE_NAME_BAKP * PM_MODULE_SUB_POWER_DOMAIN_MAX)));
if (0x0 == s_pm_bakp_pm_state)
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_BAKP, power_state);
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_BAKP;
s_pm_on_modules &= ~(0x1 << PM_POWER_MODULE_NAME_BAKP);
}
GLOBAL_INT_RESTORE();
}
else if ( (module == PM_POWER_SUB_MODULE_NAME_AHBP_CAN)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_USB)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_ENET)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_SCR)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_LIN))
{
GLOBAL_INT_DISABLE();
s_pm_ahpb_pm_state &= ~(0x1 << (module % (PM_POWER_MODULE_NAME_AHBP * PM_MODULE_SUB_POWER_DOMAIN_MAX)));
if (0x0 == s_pm_ahpb_pm_state)
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_AHBP, power_state);
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_AHBP;
s_pm_on_modules &= ~(0x1 << PM_POWER_MODULE_NAME_AHBP);
}
GLOBAL_INT_RESTORE();
}
else if ((module == PM_POWER_SUB_MODULE_NAME_AUDP_FFT)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_SBC)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_AUDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_I2S))
{
GLOBAL_INT_DISABLE();
s_pm_audio_pm_state &= ~(0x1 << (module % (PM_POWER_MODULE_NAME_AUDP * PM_MODULE_SUB_POWER_DOMAIN_MAX)));
if (0x0 == s_pm_audio_pm_state)
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_AUDP, power_state);
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_AUDP;
s_pm_on_modules &= ~(0x1 << PM_POWER_MODULE_NAME_AUDP);
s_pm_sleeped_modules |= (0x1 << PM_POWER_MODULE_NAME_AUDP);
}
GLOBAL_INT_RESTORE();
}
else if ((module == PM_POWER_SUB_MODULE_NAME_VIDP_DMA2D)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_YUVBUF)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_DE)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_LCD)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_ROTT)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL0)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL1)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_H264))
{
GLOBAL_INT_DISABLE();
s_pm_video_pm_state &= ~(0x1 << (module % (PM_POWER_MODULE_NAME_VIDP * PM_MODULE_SUB_POWER_DOMAIN_MAX)));
if (0x0 == s_pm_video_pm_state)
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_VIDP, power_state);
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_VIDP;
s_pm_on_modules &= ~(0x1 << PM_POWER_MODULE_NAME_VIDP);
s_pm_sleeped_modules |= (0x1 << PM_POWER_MODULE_NAME_VIDP);
}
GLOBAL_INT_RESTORE();
}
else if ((module == PM_POWER_SUB_MODULE_NAME_PHY_BT)
|| (module == PM_POWER_SUB_MODULE_NAME_PHY_WIFI)
|| (module == PM_POWER_SUB_MODULE_NAME_PHY_RF))
{
GLOBAL_INT_DISABLE();
s_pm_phy_pm_state &= ~(0x1 << (module % (PM_POWER_MODULE_NAME_PHY * PM_MODULE_SUB_POWER_DOMAIN_MAX)));
if (0x0 == s_pm_phy_pm_state)
{
sys_drv_module_power_ctrl(PM_POWER_MODULE_NAME_PHY, power_state);
s_pm_phy_calibration_state = 0x0;
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_PHY;
s_pm_on_modules &= ~(0x1 << PM_POWER_MODULE_NAME_PHY);
}
GLOBAL_INT_RESTORE();
}
else if (module == PM_POWER_MODULE_NAME_CPU1)
{
sys_drv_module_power_ctrl(module, power_state);
GLOBAL_INT_DISABLE();
s_pm_off_modules |= 0x1 << module;
s_pm_on_modules &= ~(0x1 << module);
GLOBAL_INT_RESTORE();
#if CONFIG_SYS_CPU0&& (CONFIG_CPU_CNT > 1)
bk_pm_cp1_work_state_set(PM_MAILBOX_COMMUNICATION_INIT);
#endif
}
else
{
if ((module == PM_POWER_MODULE_NAME_VIDP)
|| (module == PM_POWER_MODULE_NAME_AUDP)
|| (module == PM_POWER_MODULE_NAME_PHY))
{
// GLOBAL_INT_RESTORE();
if (s_debug_en & 0x2)
os_printf("module[%d] can not directly power off\r\n", module);
return BK_FAIL;
}
if (s_pm_cp1_auto_power_down_flag)
{
if (module == PM_POWER_MODULE_NAME_CPU1)
{
if (!((s_pm_off_modules & (0x1 << PM_POWER_MODULE_NAME_AUDP)) && (s_pm_off_modules & (0x1 << PM_POWER_MODULE_NAME_VIDP))))
{
// GLOBAL_INT_RESTORE();
if (s_debug_en & 0x2)
os_printf("module[%d] can not directly power off\r\n", module);
return BK_FAIL;
}
}
}
sys_drv_module_power_ctrl(module, power_state);
GLOBAL_INT_DISABLE();
s_pm_off_modules |= 0x1 << module;
s_pm_on_modules &= ~(0x1 << module);
GLOBAL_INT_RESTORE();
}
}
if (s_pm_cp1_auto_power_down_flag)
{
off_modules = (0x1 << PM_POWER_MODULE_NAME_VIDP) | (0x1 << PM_POWER_MODULE_NAME_AUDP);
if ((s_pm_off_modules & off_modules) == off_modules)
{
if (sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_VIDP) && sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AUDP))
{
pm_module_check_power_off(PM_POWER_MODULE_NAME_CPU1);
}
}
}
if (s_debug_en & 0x2)
os_printf("cpu0 vote power 0x%X 0x%X\r\n", s_pm_on_modules, s_pm_off_modules);
return BK_OK;
#endif
}
#if CONFIG_SYS_CPU0
uint32_t bk_pm_low_vol_vote_state_get()
{
return ((s_pm_sleeped_modules & s_pm_enter_low_vol_modules) == s_pm_enter_low_vol_modules);
}
bk_err_t pm_cp1_psram_malloc_count_state_set(uint32_t value)
{
#if (CONFIG_CPU_CNT > 1)
s_pm_cp1_psram_malloc_count_state = value;
#endif
return BK_OK;
}
static bk_err_t pm_cp1_psram_malloc_state_get()
{
#if (CONFIG_CPU_CNT > 1)
s_pm_cp1_psram_malloc_count_state = bk_pm_get_cp1_psram_malloc_count();
#endif
return BK_OK;
}
static bk_err_t pm_psram_malloc_state_and_power_ctrl()
{
#if CONFIG_PSRAM_AS_SYS_MEMORY
uint32_t cp0_psram_malloc_count = 0;
uint32_t cp1_psram_malloc_count = 0;
/*get the cp1 psram malloc count*/
#if (CONFIG_CPU_CNT > 1)
cp1_psram_malloc_count = s_pm_cp1_psram_malloc_count_state;
if (s_debug_en == 64)
{
if(s_pm_cp1_psram_malloc_count_state > 0)
{
os_printf("Attention the CPU1 psram malloc count[%d] > 0\r\n",cp1_psram_malloc_count);
os_printf("The power consumption will get higher, please free them\r\n");
bk_pm_dump_cp1_psram_malloc_info();
}
}
#endif
/*get the cp0 psram malloc count*/
cp0_psram_malloc_count = bk_psram_heap_get_used_count();
if (s_debug_en == 64)
{
if(cp0_psram_malloc_count > 0)
{
os_printf("Attention the CPU0 psram malloc count[%d] > 0\r\n",cp0_psram_malloc_count);
os_printf("The power consumption will get higher, please free them\r\n");
bk_psram_heap_get_used_state();
}
}
if((cp0_psram_malloc_count == 0)&&(cp1_psram_malloc_count == 0))
{
bk_pm_module_vote_psram_ctrl(PM_POWER_PSRAM_MODULE_NAME_AS_MEM,PM_POWER_MODULE_STATE_OFF);
bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM, PM_POWER_MODULE_STATE_OFF);
}
#endif
return BK_OK;
}
#endif
bk_err_t bk_pm_module_vote_sleep_ctrl(pm_sleep_module_name_e module, uint32_t sleep_state, uint32_t sleep_time)
{
#if CONFIG_SYS_CPU1
#if CONFIG_MAILBOX
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
if(module == PM_SLEEP_MODULE_NAME_LOG)
{
return BK_OK;
}
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
bk_pm_cp1_sleep_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_SLEEP_CTRL_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = sleep_state;
mb_cmd.param3 = sleep_time;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
previous_tick = pm_cp1_aon_rtc_counter_get();
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_SEND_CMD_CP0_RESPONSE_TIME_OUT*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_sleep_ctrl_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_sleep_ctrl_state_get())
{
os_printf("cp1 wait cp0 vote sleep[%d] time out\r\n",module);
}
#endif
return BK_OK;
#elif CONFIG_SYS_CPU2
return BK_OK;
#elif CONFIG_SYS_CPU0
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
if (sleep_state == 0x1) // enter sleep
{
if (module == PM_SLEEP_MODULE_NAME_BTSP)
{
s_bt_system_wakeup_param.wifi_bt_wakeup = BT_WAKEUP;
s_pm_wakeup_source |= 0x1 << PM_WAKEUP_SOURCE_INT_SYSTEM_WAKE;
s_bt_system_wakeup_param.sleep_time = ((sleep_time * bk_rtc_get_ms_tick_count()) / 1000) + 1; // bt provide sleep time convent to 32k tick;+1:protect the precision miss
#if CONFIG_AON_RTC
s_bt_need_wakeup_time = bk_aon_rtc_get_current_tick(AON_RTC_ID_1) + s_bt_system_wakeup_param.sleep_time;
#endif
/*set bt wakeup source*/
sys_drv_enable_bt_wakeup_source();
}
else if (module == PM_SLEEP_MODULE_NAME_WIFIP_MAC)
{
// s_wifi_system_wakeup_param.wifi_bt_wakeup = WIFI_WAKEUP;
s_pm_wakeup_source |= 0x1 << PM_WAKEUP_SOURCE_INT_SYSTEM_WAKE;
sys_drv_enable_mac_wakeup_source();
}
else if (module == PM_SLEEP_MODULE_NAME_APP)
{
}
s_pm_sleeped_modules |= 0x1ULL << module;
}
else // exit sleep
{
if (module == PM_SLEEP_MODULE_NAME_BTSP)
{
s_bt_system_wakeup_param.wifi_bt_wakeup = BT_WAKEUP;
s_bt_system_wakeup_param.sleep_time = 0;
s_bt_need_wakeup_time = 0;
/*disable bt wakeup source*/
aon_pmu_drv_clear_wakeup_source(WAKEUP_SOURCE_INT_BT);
// os_printf("bt exit sleep\r\n");
}
else if (module == PM_SLEEP_MODULE_NAME_WIFIP_MAC)
{
/*disable WIFI wakeup source*/
aon_pmu_drv_clear_wakeup_source(WAKEUP_SOURCE_INT_WIFI);
}
else if (module == PM_SLEEP_MODULE_NAME_APP)
{
}
s_pm_sleeped_modules &= ~(0x1 << module);
}
if (s_debug_en & 0x1)
os_printf("pm sleep state 0x%llX 0x%x %d\r\n", s_pm_sleeped_modules, s_pm_on_modules, module);
GLOBAL_INT_RESTORE();
return BK_OK;
#endif
}
bk_err_t bk_pm_sleep_mode_set(pm_sleep_mode_e sleep_mode)
{
s_pm_sleep_mode = sleep_mode;
if (s_pm_sleep_mode == PM_MODE_DEEP_SLEEP)
{
for (uint8_t i = 0; i < PM_DEEPSLEEP_CB_SIZE; i++)
{
if (s_pm_deepsleep_enter_cb_conf[i].cfg.cb != NULL)
{
s_pm_deepsleep_enter_cb_conf[i].cfg.cb(0, s_pm_deepsleep_enter_cb_conf[i].cfg.args);
}
}
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
else if (s_pm_sleep_mode == PM_MODE_SUPER_DEEP_SLEEP)
{
for (uint8_t i = 0; i < PM_SUPERDEEP_CB_SIZE; i++)
{
if (s_pm_superdeep_enter_cb_conf[i].cfg.cb != NULL)
{
// os_printf("%d %d\r\n", i, s_pm_superdeep_enter_cb_conf[i].id);
s_pm_superdeep_enter_cb_conf[i].cfg.cb(0, s_pm_superdeep_enter_cb_conf[i].cfg.args);
}
}
}
#endif
else if (s_pm_sleep_mode == PM_MODE_LOW_VOLTAGE)
{
// to do
}
else
{
}
return BK_OK;
}
bk_err_t bk_pm_wakeup_source_set(pm_wakeup_source_e wakeup_source, void *source_param)
{
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
s_pm_wakeup_source |= 0x1 << wakeup_source;
if (source_param == NULL)
{
GLOBAL_INT_RESTORE();
return BK_OK;
}
switch (wakeup_source)
{
case PM_WAKEUP_SOURCE_INT_GPIO:
break;
case PM_WAKEUP_SOURCE_INT_RTC:
break;
case PM_WAKEUP_SOURCE_INT_SYSTEM_WAKE: // wifi/bt
break;
case PM_WAKEUP_SOURCE_INT_USBPLUG:
break;
case PM_WAKEUP_SOURCE_INT_TOUCHED:
os_memcpy(&s_touch_wakeup_param, (touch_wakeup_param_t *)source_param, sizeof(touch_wakeup_param_t));
break;
default:
break;
}
GLOBAL_INT_RESTORE();
return BK_OK;
}
/*=========================COMMON PM API END========================*/
/*=========================SPECIFIC API START========================*/
uint32_t bk_pm_mcu_pm_state_get()
{
return s_pm_mcu_pm_state;
}
bk_err_t bk_pm_mcu_pm_ctrl(uint32_t power_state)
{
s_pm_mcu_pm_state = power_state;
return BK_OK;
}
void bk_pm_enter_sleep()
{
uint32_t sleep_ticks = 0;
pm_management(sleep_ticks);
}
uint32_t bk_pm_app_auto_vote_state_get()
{
return s_pm_app_auto_vote_enable;
}
bk_err_t bk_pm_app_auto_vote_state_set(uint32_t value)
{
s_pm_app_auto_vote_enable = value;
return BK_OK;
}
uint32_t bk_pm_wakeup_from_lowvol_consume_time_get()
{
return ((s_pm_lowvol_consume_time_exit_wfi * 1000) / bk_rtc_get_ms_tick_count()); // unit: us
}
uint32_t bk_pm_cp1_boot_flag_get()
{
return 0; // s_pm_cp1_boot_ready;
}
uint32_t bk_pm_phy_cali_state_get()
{
return s_pm_phy_calibration_state;
}
bool bk_pm_phy_reinit_flag_get()
{
return s_pm_is_phy_reinit_flag;
}
void bk_pm_phy_reinit_flag_clear()
{
s_pm_is_phy_reinit_flag = false;
}
/*=========================SPECIFIC API END========================*/
/*=========================MODULES POWER CTRL START========================*/
static void pm_check_power_on_module()
{
#if CONFIG_SYS_CPU0
uint32_t off_modules = 0;
#endif
if (!(s_pm_on_modules & ((0x1 << PM_POWER_MODULE_NAME_BTSP)))) // when the module not power on , set the module sleep state
{
s_pm_sleeped_modules |= 0x1 << PM_POWER_MODULE_NAME_BTSP;
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_BTSP;
// os_printf("bt not power on \r\n");
}
if (!(s_pm_on_modules & (0x1 << PM_POWER_MODULE_NAME_WIFIP_MAC))) // when the module not power on , set the module sleep state
{
s_pm_sleeped_modules |= 0x1 << PM_POWER_MODULE_NAME_WIFIP_MAC;
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_WIFIP_MAC;
// os_printf("wifi not power on \r\n");
}
if (!(s_pm_on_modules & (0x1 << PM_POWER_MODULE_NAME_AUDP))) // when the module not power on , set the module sleep state
{
s_pm_sleeped_modules |= 0x1 << PM_POWER_MODULE_NAME_AUDP;
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_AUDP;
// os_printf("audio not power on \r\n");
}
if (!(s_pm_on_modules & (0x1 << PM_POWER_MODULE_NAME_VIDP))) // when the module not power on , set the module sleep state
{
s_pm_sleeped_modules |= 0x1 << PM_POWER_MODULE_NAME_VIDP;
s_pm_off_modules |= 0x1 << PM_POWER_MODULE_NAME_VIDP;
// os_printf("video not power on \r\n");
}
#if CONFIG_SYS_CPU0
if (s_pm_mem_auto_power_down_flag)
{
off_modules = (0x1 << PM_POWER_MODULE_NAME_VIDP) | (0x1 << PM_POWER_MODULE_NAME_AUDP) | (0x1 << PM_POWER_MODULE_NAME_BTSP);
if ((s_pm_off_modules & off_modules) == off_modules)
{
pm_module_check_power_off(PM_POWER_MODULE_NAME_MEM3);
}
}
if (s_pm_cp1_auto_power_down_flag)
{
off_modules = (0x1 << PM_POWER_MODULE_NAME_VIDP) | (0x1 << PM_POWER_MODULE_NAME_AUDP);
if ((s_pm_off_modules & off_modules) == off_modules)
{
#if !CONFIG_SOC_BK7236XX && !CONFIG_SOC_BK7239XX && !CONFIG_SOC_BK7286XX // temp mofify for bk7236
if (sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_VIDP) && sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AUDP))
#endif
{
// pm_module_check_power_off(PM_POWER_MODULE_NAME_CPU1);
}
}
}
#endif
}
void pm_rf_power_ctrl(pm_power_module_name_e module, pm_power_module_state_e power_state)
{
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
if (power_state == PM_POWER_MODULE_STATE_ON)
{
s_pm_rf_on_modules |= 0x1 << module;
}
else
{
s_pm_rf_off_modules |= 0x1 << module;
}
sys_drv_module_RF_power_ctrl(module, power_state);
GLOBAL_INT_RESTORE();
}
void pm_rf_switch(pm_power_module_name_e name)
{
}
int32 bk_pm_module_power_state_get(pm_power_module_name_e module)
{
if ( (module == PM_POWER_SUB_MODULE_NAME_BAKP_TIMER1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_UART2)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_I2C1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SADC)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PWM0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_TRNG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_IRDA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_SDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_COMSEG)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA0)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_DMA1)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_LA)
|| (module == PM_POWER_SUB_MODULE_NAME_BAKP_PM))
{
return sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_BAKP);
}
else if ( (module == PM_POWER_SUB_MODULE_NAME_AHBP_CAN)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_USB)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_PSRAM)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_QSPI1)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_ENET)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_SCR)
|| (module == PM_POWER_SUB_MODULE_NAME_AHBP_LIN))
{
return sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AHBP);
}
else if ((module == PM_POWER_SUB_MODULE_NAME_AUDP_FFT)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_SBC)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_AUDIO)
|| (module == PM_POWER_SUB_MODULE_NAME_AUDP_I2S))
{
return sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_AUDP);
}
else if ((module == PM_POWER_SUB_MODULE_NAME_VIDP_DMA2D)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_YUVBUF)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_EN)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_JPEG_DE)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_LCD)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_ROTT)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL0)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_SCAL1)
|| (module == PM_POWER_SUB_MODULE_NAME_VIDP_H264))
{
return sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_VIDP);
}
else if ((module == PM_POWER_SUB_MODULE_NAME_PHY_BT)
|| (module == PM_POWER_SUB_MODULE_NAME_PHY_WIFI))
{
return sys_drv_module_power_state_get(PM_POWER_MODULE_NAME_PHY);
}
else
{
if (module >= PM_POWER_MODULE_NAME_NONE)
{
os_printf("pm module[%d] not support ,get power state fail %d\r\n", module);
return BK_ERR_NOT_SUPPORT;
}
else
{
return sys_drv_module_power_state_get(module);
}
}
}
#if CONFIG_SYS_CPU0
static void pm_module_check_power_on(pm_power_module_name_e module)
{
if (PM_POWER_MODULE_STATE_OFF == sys_drv_module_power_state_get(module))
{
sys_drv_module_power_ctrl(module, PM_POWER_MODULE_STATE_ON);
if (module == PM_POWER_MODULE_NAME_MEM3)
{
#if CONFIG_SYSTEM_CTRL
#if CONFIG_SYS_CPU0
extern void smem_reset_lastblock(void);
smem_reset_lastblock();
#endif
#endif
}
if (module == PM_POWER_MODULE_NAME_CPU1)
{
#if (CONFIG_SYS_CPU0) && (CONFIG_CPU_CNT > 1)
extern void start_cpu1_core();
start_cpu1_core();
// s_pm_cp1_boot_ready = 0x0;
#endif
}
s_pm_off_modules &= ~(0x1 << module);
s_pm_on_modules |= 0x1 << module;
}
}
static void pm_module_check_power_off(pm_power_module_name_e module)
{
if (PM_POWER_MODULE_STATE_ON == sys_drv_module_power_state_get(module))
{
if (module == PM_POWER_MODULE_NAME_CPU1)
{
#if (CONFIG_SYS_CPU0) && (CONFIG_CPU_CNT > 1)
extern void stop_cpu1_core(void);
stop_cpu1_core();
#endif
}
if (s_debug_en & 0x2)
{
os_printf("pm_module_check_power_off module[%d][%d]\r\n", module, sys_drv_module_power_state_get(module));
}
sys_drv_module_power_ctrl(module, PM_POWER_MODULE_STATE_OFF);
if (module == PM_POWER_MODULE_NAME_CPU1)
{
// s_pm_cp1_boot_ready = 0x0;
}
s_pm_off_modules |= 0x1 << module;
s_pm_on_modules &= ~(0x1 << module);
}
}
uint32_t bk_pm_cp1_auto_power_down_state_get()
{
return s_pm_cp1_auto_power_down_flag;
}
bk_err_t bk_pm_cp1_auto_power_down_state_set(uint32_t value)
{
s_pm_cp1_auto_power_down_flag = value;
return BK_OK;
}
pm_mem_auto_ctrl_e bk_pm_mem_auto_power_down_state_get()
{
return s_pm_mem_auto_power_down_flag;
}
bk_err_t bk_pm_mem_auto_power_down_state_set(pm_mem_auto_ctrl_e value)
{
s_pm_mem_auto_power_down_flag = value;
return BK_OK;
}
#endif
/*=========================MODULES POWER CTRL END========================*/
/*=========================WAKEUP SOURCE CONFIG START========================*/
static void pm_touched_wakeup_low_voltage()
{
sys_drv_touch_wakeup_enable(s_touch_wakeup_param.touch_channel);
}
static void pm_gpio_wakeup_deep_sleep()
{
#if CONFIG_GPIO_WAKEUP_SUPPORT
gpio_enter_low_power((void *)0);
#endif
}
static void pm_rtc_wakeup_deep_sleep()
{
aon_pmu_drv_set_wakeup_source(WAKEUP_SOURCE_INT_RTC);
}
static void pm_touched_wakeup_deep_sleep()
{
}
#if CONFIG_SYS_CPU0
static void pm_deep_sleep_wakeup_source_set()
{
#if CONFIG_SYSTEM_CTRL
uint32_t pmu_state = 0;
if (aon_pmu_drv_reg_get(PMU_REG2) & BIT(BIT_SLEEP_FLAG_DEEP_SLEEP))
{
pmu_state = 0;
pmu_state = aon_pmu_drv_reg_get(PMU_REG0x71);
pmu_state = (pmu_state >> 20) & PM_WAKEUP_SOURCE_MARK;
switch (pmu_state)
{
case 0x1: // gpio
bk_misc_set_reset_reason(RESET_SOURCE_DEEPPS_GPIO);
s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_GPIO;
break;
case 0x2: // rtc
bk_misc_set_reset_reason(RESET_SOURCE_DEEPPS_RTC);
s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_RTC;
break;
case 0x10: // bk7256 use touch and bk7236 use usb
bk_misc_set_reset_reason(RESET_SOURCE_DEEPPS_TOUCH);
s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_TOUCHED;
break;
case 0x20: // touch
bk_misc_set_reset_reason(RESET_SOURCE_DEEPPS_TOUCH);
s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_TOUCHED;
break;
default:
s_pm_exit_deepsleep_wakeup_source = PM_WAKEUP_SOURCE_INT_NONE;
break;
}
#if 0
/*clear the wakeup source*/
pmu_state = 0;
pmu_state = aon_pmu_drv_reg_get(PMU_REG0x43);
pmu_state |= (0x1 << 17);
aon_pmu_drv_reg_set(PMU_REG0x43, pmu_state);
#endif
}
#endif
}
pm_wakeup_source_e bk_pm_deep_sleep_wakeup_source_get()
{
return s_pm_exit_deepsleep_wakeup_source;
}
pm_wakeup_source_e bk_pm_exit_low_vol_wakeup_source_get()
{
return s_pm_exit_low_vol_wakeup_source;
}
bk_err_t bk_pm_exit_low_vol_wakeup_source_set()
{
#if CONFIG_SYSTEM_CTRL
uint32_t pmu_state = 0;
if (aon_pmu_drv_reg_get(PMU_REG2) & BIT(BIT_SLEEP_FLAG_LOW_VOLTAGE))
{
pmu_state = 0;
pmu_state = aon_pmu_drv_reg_get(PMU_REG0x71);
pmu_state = (pmu_state >> 20) & PM_WAKEUP_SOURCE_MARK;
switch (pmu_state)
{
case 0x1: // gpio
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_GPIO;
break;
case 0x2: // rtc
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_RTC;
break;
case 0x4: // WIFI wakeup
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_WIFI;
break;
case 0x8: // bk7256 use usb and bk7236 use BT wakeup
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_BT;
break;
case 0x10: // bk7256 use touch and bk7236 use usb wakeup
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_TOUCHED;
break;
case 0x20: // touch
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_TOUCHED;
break;
default:
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_NONE;
break;
}
}
#endif
return BK_OK;
}
bk_err_t bk_pm_exit_low_vol_wakeup_source_clear()
{
/*clear the wakeup source*/
#if CONFIG_SYSTEM_CTRL
uint32_t pmu_state = 0;
pmu_state = aon_pmu_drv_reg_get(PMU_REG0x43);
pmu_state |= (0x1 << 17);
aon_pmu_drv_reg_set(PMU_REG0x43, pmu_state);
#endif
s_pm_exit_low_vol_wakeup_source = PM_WAKEUP_SOURCE_INT_NONE;
return BK_OK;
}
#endif
/*=========================WAKEUP SOURCE CONFIG END========================*/
/*=========================SLEEP/WAKEUP FUNCTION START========================*/
static void pm_enter_normal_sleep()
{
sys_drv_enter_normal_sleep(0);
}
static void pm_enter_low_voltage()
{
sys_drv_enter_low_voltage();
}
static void pm_enter_deep_sleep()
{
sys_drv_enter_deep_sleep(NULL);
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
static void pm_enter_super_deep_sleep()
{
uint8_t use_super_deep = 1;
bk_misc_set_reset_reason(RESET_SOURCE_SUPER_DEEP);
sys_drv_enter_deep_sleep(&use_super_deep);
}
#endif
static void pm_low_voltage_resource_set()
{
pm_dev_id_e dev_id = 0;
#if CONFIG_SYS_CPU0
pm_psram_malloc_state_and_power_ctrl();
#endif
bk_pm_exit_low_vol_wakeup_source_clear();
for (dev_id = 0; dev_id < PM_DEV_ID_MAX; dev_id++)
{
if (s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].cb != NULL)
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].cb(0, s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].args);
}
}
#if CONFIG_GPIO_WAKEUP_SUPPORT
gpio_enter_low_power((void *)0);
#endif
if (s_pm_wakeup_source & (0x1 << PM_WAKEUP_SOURCE_INT_TOUCHED))
{
pm_touched_wakeup_low_voltage();
}
#if CONFIG_BAKP_POWER_DOMAIN_PM_CONTROL
bk_pm_module_vote_power_ctrl(POWER_SUB_MODULE_NAME_BAKP_PM, PM_POWER_MODULE_STATE_OFF);
#endif
/*flash line mode 4->2 when enter low voltage*/
#if CONFIG_FLASH_ORIGIN_API
flash_set_line_mode(2);
#else
bk_flash_set_line_mode(2);
#endif
}
void pm_low_voltage_bsp_restore(void)
{
/*flash line mode 2->4 when exit low voltage*/
#if CONFIG_FLASH_ORIGIN_API
flash_set_line_mode(flash_get_line_mode());
#else
bk_flash_set_line_mode(bk_flash_get_line_mode());
#endif
#if CONFIG_CKMN
bk_rosc_32k_ckest_prog(32);
#endif
#if CONFIG_INT_WDT
wdt_init();
#endif
bk_pm_exit_low_vol_wakeup_source_set();
}
static void pm_low_voltage_resource_restore()
{
pm_dev_id_e dev_id = 0;
#if CONFIG_BAKP_POWER_DOMAIN_PM_CONTROL
bk_pm_module_vote_power_ctrl(POWER_SUB_MODULE_NAME_BAKP_PM, PM_POWER_MODULE_STATE_ON);
#endif
#if CONFIG_GPIO_WAKEUP_SUPPORT
gpio_exit_low_power((void *)0);
#endif
for (dev_id = 0; dev_id < PM_DEV_ID_MAX; dev_id++)
{
if (s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].cb != NULL)
{
if (dev_id == PM_DEV_ID_MAC)
{
if (bk_pm_exit_low_vol_wakeup_source_get() == PM_WAKEUP_SOURCE_INT_GPIO)
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].cb(0, s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].args);
if (s_debug_en & 0x2)
{
os_printf("wifi exit low vol arg:%d\r\n", s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].args);
}
}
else
{
continue;
}
}
else
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].cb(0, s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].args);
}
}
}
}
static uint32_t pm_low_voltage_process()
{
volatile uint32_t int_level = 0;
uint32_t sleep_tick = 0;
#if CONFIG_AON_RTC
uint32_t entry_tick = 0;
uint32_t exit_tick = 0;
#endif
int_level = rtos_enter_critical();
#if CONFIG_AON_RTC
entry_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
#endif
pm_low_voltage_resource_set();
pm_enter_low_voltage();
pm_low_voltage_resource_restore();
if (s_debug_en & 0x2)
os_printf("low voltage int open before\r\n");
#if CONFIG_AON_RTC
exit_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
sleep_tick = exit_tick - entry_tick;
#endif
rtos_exit_critical(int_level);
if (s_debug_en & 0x2)
os_printf("low voltage int open after 0x%x 0x%x \r\n", /*int_mie,*/ int_level, bk_pm_lp_vol_get());
return sleep_tick;
}
static void pm_deep_sleep_process()
{
// if(s_pm_wakeup_source&(0x1 << PM_WAKEUP_SOURCE_INT_GPIO))
{
pm_gpio_wakeup_deep_sleep();
}
if (s_pm_wakeup_source & (0x1 << PM_WAKEUP_SOURCE_INT_RTC))
{
pm_rtc_wakeup_deep_sleep();
}
if (s_pm_wakeup_source & (0x1 << PM_WAKEUP_SOURCE_INT_TOUCHED))
{
pm_touched_wakeup_deep_sleep();
}
pm_enter_deep_sleep();
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
static void pm_super_deep_sleep_process()
{
uint64_t skip_io = 0;
#if CONFIG_GPIO_RETENTION_SUPPORT
gpio_retention_sync(false);
skip_io = gpio_retention_map_get();
#endif
#if CONFIG_GPIO_WAKEUP_SUPPORT
gpio_hal_switch_to_low_power_status(BIT64(16) | skip_io);
#endif
pm_enter_super_deep_sleep();
}
#endif
static bk_err_t pm_wakeup_from_deepsleep_handle()
{
#if CONFIG_SYSTEM_CTRL
uint32_t pmu_state = 0;
if (aon_pmu_drv_reg_get(PMU_REG2) & BIT(BIT_SLEEP_FLAG_DEEP_SLEEP))
{
pmu_state = 0;
pmu_state = aon_pmu_drv_reg_get(PMU_REG2);
pmu_state &= ~(BIT(BIT_SLEEP_FLAG_DEEP_SLEEP));
aon_pmu_drv_reg_set(PMU_REG2, pmu_state);
}
#endif
return BK_OK;
}
/*=========================SLEEP/WAKEUP FUNCTION END========================*/
/*=========================SLEEP CB REGISTER API START========================*/
static void pm_sleep_cb_push_item(pm_sleep_cb_t cb_arr[], uint8_t *cb_cnt_p, pm_sleep_cb_t cb_item)
{
if (*cb_cnt_p == PM_DEEPSLEEP_CB_SIZE)
{
if (s_debug_en & 0x2)
os_printf("call back function overflow, dev %d regist fail!\r\n", cb_item.id);
if (s_debug_en & 0x1)
{
os_printf("cb functions dump: [ ");
for (uint8_t i = 0; i < PM_DEEPSLEEP_CB_SIZE; i++)
os_printf("%d ", cb_arr[i].id);
os_printf("]\r\n");
}
return;
} else if (cb_arr[*cb_cnt_p].cfg.cb != NULL) {
if (s_debug_en & 0x2)
os_printf("cb functions have overlap warning, dev %d -> %d\r\n", cb_item.id, cb_arr[*cb_cnt_p].id);
}
for (uint8_t i = 0; i < *cb_cnt_p; i++)
{
if (cb_arr[i].id == cb_item.id)
{
cb_arr[i].cfg.cb = cb_item.cfg.cb;
cb_arr[i].cfg.args = cb_item.cfg.args;
return;
}
}
cb_arr[*cb_cnt_p].id = cb_item.id;
cb_arr[*cb_cnt_p].cfg.cb = cb_item.cfg.cb;
cb_arr[*cb_cnt_p].cfg.args = cb_item.cfg.args;
(*cb_cnt_p)++;
}
static void pm_sleep_cb_pop_item(pm_sleep_cb_t cb_arr[], uint8_t *cb_cnt_p, uint8_t item_ind)
{
uint8_t tail_ind = (*cb_cnt_p) - 1;
cb_arr[item_ind].id = cb_arr[tail_ind].id;
cb_arr[item_ind].cfg.cb = cb_arr[tail_ind].cfg.cb;
cb_arr[item_ind].cfg.args = cb_arr[tail_ind].cfg.args;
cb_arr[tail_ind].id = PM_DEV_ID_MAX;
cb_arr[tail_ind].cfg.cb = NULL;
cb_arr[tail_ind].cfg.args = NULL;
(*cb_cnt_p)--;
}
bk_err_t bk_pm_sleep_register_cb(pm_sleep_mode_e sleep_mode, pm_dev_id_e dev_id, pm_cb_conf_t *enter_config, pm_cb_conf_t *exit_config)
{
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
if (sleep_mode == PM_MODE_LOW_VOLTAGE)
{
if (enter_config != NULL)
{
if ((enter_config->cb != NULL) && (dev_id < PM_DEV_ID_MAX))
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].cb = enter_config->cb;
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].args = enter_config->args;
}
}
if (exit_config != NULL)
{
if ((exit_config->cb != NULL) && (dev_id < PM_DEV_ID_MAX))
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].cb = exit_config->cb;
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].args = exit_config->args;
}
}
}
else if (sleep_mode == PM_MODE_DEEP_SLEEP)
{
if (enter_config != NULL)
{
pm_sleep_cb_t cb_item = {dev_id, *enter_config};
// use exit_config to indicate the execution priority when entering sleep
if ((enter_config->cb != NULL) && (exit_config != NULL) && ((pm_cb_priority_e)exit_config->args < PM_CB_PRIORITY_MAX))
{
pm_sleep_cb_push_item(s_pm_deepsleep_enter_cb_conf, &s_pm_deepsleep_enter_cb_cnt[(pm_cb_priority_e)exit_config->args], cb_item);
}
else if ((enter_config->cb != NULL) && (dev_id < PM_DEV_ID_DEFAULT))
{
pm_sleep_cb_push_item(s_pm_deepsleep_enter_cb_conf, &s_pm_deepsleep_enter_cb_cnt[PM_CB_PRIORITY_0], cb_item);
}
else if ((enter_config->cb != NULL) && (dev_id < PM_DEV_ID_MAX))
{
pm_sleep_cb_push_item(s_pm_deepsleep_enter_cb_conf, &s_pm_deepsleep_enter_cb_cnt[PM_CB_PRIORITY_1], cb_item);
}
}
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
else if (sleep_mode == PM_MODE_SUPER_DEEP_SLEEP)
{
if (enter_config != NULL)
{
pm_sleep_cb_t cb_item = {dev_id, *enter_config};
if ((enter_config->cb != NULL) && (dev_id < PM_DEV_ID_DEFAULT))
{
pm_sleep_cb_push_item(s_pm_superdeep_enter_cb_conf, &s_pm_superdeep_enter_cb_cnt[PM_CB_PRIORITY_0], cb_item);
}
else if ((enter_config->cb != NULL) && (dev_id < PM_DEV_ID_MAX))
{
pm_sleep_cb_push_item(s_pm_superdeep_enter_cb_conf, &s_pm_superdeep_enter_cb_cnt[PM_CB_PRIORITY_1], cb_item);
}
}
}
#endif
else
{
os_printf("The sleep mode[%d] not support register call back \r\n", sleep_mode);
}
GLOBAL_INT_RESTORE();
return BK_OK;
}
bk_err_t bk_pm_sleep_unregister_cb(pm_sleep_mode_e sleep_mode, pm_dev_id_e dev_id, bool enter_cb, bool exit_cb)
{
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
if (sleep_mode == PM_MODE_LOW_VOLTAGE)
{
if ((enter_cb == true) && (dev_id < PM_DEV_ID_MAX))
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].cb = NULL;
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_ENTER_LOWVOL_INDEX][dev_id].args = NULL;
}
if (exit_cb == true)
{
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].cb = NULL;
s_pm_lowvol_enter_exit_cb_conf[PM_SLEEP_CB_EXIT_LOWVOL_INDEX][dev_id].args = NULL;
}
}
else if (sleep_mode == PM_MODE_DEEP_SLEEP)
{
if ((enter_cb == true) && (dev_id < PM_DEV_ID_DEFAULT))
{
for (uint8_t i = PM_SLEEP_CB_IND_PRI_0; i < PM_SLEEP_CB_IND_PRI_1; i++)
{
if (s_pm_deepsleep_enter_cb_conf[i].id == dev_id)
{
pm_sleep_cb_pop_item(s_pm_deepsleep_enter_cb_conf, &s_pm_deepsleep_enter_cb_cnt[PM_CB_PRIORITY_0], i);
break;
}
}
}
else if ((enter_cb == true) && (dev_id < PM_DEV_ID_MAX))
{
for (uint8_t i = PM_SLEEP_CB_IND_PRI_1; i < PM_DEEPSLEEP_CB_SIZE; i++)
{
if (s_pm_deepsleep_enter_cb_conf[i].id == dev_id)
{
pm_sleep_cb_pop_item(s_pm_deepsleep_enter_cb_conf, &s_pm_deepsleep_enter_cb_cnt[PM_CB_PRIORITY_1], i);
break;
}
}
}
}
#if CONFIG_PM_SUPER_DEEP_SLEEP
else if (sleep_mode == PM_MODE_SUPER_DEEP_SLEEP)
{
if ((enter_cb == true) && (dev_id < PM_DEV_ID_DEFAULT))
{
for (uint8_t i = PM_SLEEP_CB_IND_PRI_0; i < PM_SLEEP_CB_IND_PRI_1; i++)
{
if (s_pm_superdeep_enter_cb_conf[i].id == dev_id)
{
pm_sleep_cb_pop_item(s_pm_superdeep_enter_cb_conf, &s_pm_superdeep_enter_cb_cnt[PM_CB_PRIORITY_0], i);
break;
}
}
}
else if ((enter_cb == true) && (dev_id < PM_DEV_ID_MAX))
{
for (uint8_t i = PM_SLEEP_CB_IND_PRI_1; i < PM_SUPERDEEP_CB_SIZE; i++)
{
if (s_pm_superdeep_enter_cb_conf[i].id == dev_id)
{
pm_sleep_cb_pop_item(s_pm_superdeep_enter_cb_conf, &s_pm_superdeep_enter_cb_cnt[PM_CB_PRIORITY_1], i);
break;
}
}
}
}
#endif
else
{
os_printf("The sleep mode[%d] not support unregister call back \r\n", sleep_mode);
}
GLOBAL_INT_RESTORE();
return BK_OK;
}
bk_err_t bk_pm_light_sleep_register_cb(pm_cb_conf_t *enter_config, pm_cb_conf_t *exit_config)
{
#if !defined(CONFIG_PM_LIGHT_SLEEP)
return BK_ERR_NOT_SUPPORT;
#else
if (enter_config != NULL)
{
s_pm_light_sleep_enter_cb_conf.cb = enter_config->cb;
s_pm_light_sleep_enter_cb_conf.args = enter_config->args;
}
if (exit_config != NULL)
{
s_pm_light_sleep_exit_cb_conf.cb = exit_config->cb;
s_pm_light_sleep_exit_cb_conf.args = exit_config->args;
}
return BK_OK;
#endif
}
bk_err_t bk_pm_light_sleep_unregister_cb(bool enter_cb, bool exit_cb)
{
#if !defined(CONFIG_PM_LIGHT_SLEEP)
return BK_ERR_NOT_SUPPORT;
#else
if (enter_cb)
{
s_pm_light_sleep_enter_cb_conf.cb = NULL;
}
if (exit_cb)
{
s_pm_light_sleep_exit_cb_conf.cb = NULL;
}
return BK_OK;
#endif
}
/*=========================SLEEP CB REGISTER API END========================*/
/*=========================POWER/VOLTAGE CTRL START========================*/
bk_err_t bk_pm_external_ldo_ctrl(uint32_t value)
{
uint32_t i = 0;
uint32_t gpio_ctrl_ldo_output_high_map[] = GPIO_CTRL_LDO_OUTPUT_HIGH_MAP;
uint32_t gpio_ctrl_ldo_output_low_map[] = GPIO_CTRL_LDO_OUTPUT_LOW_MAP;
if (value == 0x1) // output higt
{
for (i = 0; i < sizeof(gpio_ctrl_ldo_output_high_map) / sizeof(uint32_t); i++)
{
bk_gpio_enable_output(gpio_ctrl_ldo_output_high_map[i]);
bk_gpio_set_output_high(gpio_ctrl_ldo_output_high_map[i]);
}
}
else if (value == 0x0) // output low
{
for (i = 0; i < sizeof(gpio_ctrl_ldo_output_low_map) / sizeof(uint32_t); i++)
{
bk_gpio_enable_output(gpio_ctrl_ldo_output_high_map[i]);
bk_gpio_set_output_low(gpio_ctrl_ldo_output_low_map[i]);
}
}
else
{
}
return BK_OK;
}
uint32_t bk_pm_lp_vol_get()
{
return sys_drv_lp_vol_get();
}
int bk_pm_lp_vol_set(uint32_t value)
{
sys_drv_lp_vol_set(value);
return BK_OK;
}
uint32_t bk_pm_rf_tx_vol_get()
{
return sys_drv_rf_tx_vol_get();
}
int bk_pm_rf_tx_vol_set(uint32_t value)
{
sys_drv_rf_tx_vol_set(value);
return BK_OK;
}
uint32_t bk_pm_rf_rx_vol_get()
{
return sys_drv_rf_rx_vol_get();
}
int bk_pm_rf_rx_vol_set(uint32_t value)
{
sys_drv_rf_rx_vol_set(value);
return BK_OK;
}
/*=========================POWER/VOLTAGE CTRL END========================*/
/*=========================CLK/FREQ CTRL START========================*/
bk_err_t pm_core_bus_clock_ctrl(uint32_t cksel_core, uint32_t ckdiv_core, uint32_t ckdiv_bus, uint32_t ckdiv_cpu0, uint32_t ckdiv_cpu1)
{
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
sys_drv_core_bus_clock_ctrl(cksel_core, ckdiv_core, ckdiv_bus, ckdiv_cpu0, ckdiv_cpu1);
GLOBAL_INT_RESTORE();
return BK_OK;
}
pm_cpu_freq_e bk_pm_current_max_cpu_freq_get()
{
return s_pm_current_cpu_freq;
}
pm_cpu_freq_e bk_pm_module_current_cpu_freq_get(pm_dev_id_e module)
{
return s_pm_cpu_freq[module];
}
bk_err_t bk_pm_module_vote_cpu_freq(pm_dev_id_e module, pm_cpu_freq_e cpu_freq)
{
#if CONFIG_SYS_CPU1
#if CONFIG_MAILBOX
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
bk_pm_cp1_cpu_freq_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_CPU_FREQ_CTRL_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = cpu_freq;
mb_cmd.param3 = 0;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
previous_tick = pm_cp1_aon_rtc_counter_get();
current_tick = previous_tick;
os_printf("cp1 vote freq begin [%lld]\r\n",previous_tick);
while((current_tick - previous_tick) < (PM_SEND_CMD_CP0_RESPONSE_TIME_OUT*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_cpu_freq_ctrl_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_cpu_freq_ctrl_state_get())
{
os_printf("cp1 vote freq[%d] time out\r\n",module);
}
os_printf("cp1 vote freq end [%lld]\r\n",current_tick);
if(s_debug_en&0x2)
os_printf("cpu1 vote cpu freq \r\n");
#endif
return BK_OK;
#else
bk_err_t ret = BK_OK;
uint32_t i = 0;
uint32_t freq_max = 0;
uint32_t freq_max_index = 0;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
/*save the cpu freq first*/
if (PM_CPU_FRQ_DEFAULT == cpu_freq)
{
cpu_freq = PM_CPU_FRQ_26M; // it will use the PM_DEV_ID_DEFAULT vote cpu frequency
}
s_pm_cpu_freq[module] = (uint8_t)cpu_freq;
/*get the max cpu freq*/
freq_max = s_pm_cpu_freq[0];
for (i = 1; i < PM_DEV_ID_MAX; i++)
{
if (freq_max < s_pm_cpu_freq[i])
{
freq_max = s_pm_cpu_freq[i];
freq_max_index = i;
}
}
/*updete the current cpu frequency*/
if (s_pm_current_cpu_freq == freq_max)
{
GLOBAL_INT_RESTORE();
return BK_OK;
}
else
{
ret = sys_drv_switch_cpu_bus_freq(freq_max);
}
if (ret == BK_OK)
s_pm_current_cpu_freq = freq_max;
GLOBAL_INT_RESTORE();
if (ret != BK_OK)
{
os_printf("cpu0 switch cpu freq error\r\n");
return ret;
}
if (s_debug_en & 0x2)
os_printf("cpu0 switch cpu freq %d %d\r\n", freq_max, freq_max_index);
return BK_OK;
#endif
}
bk_err_t bk_pm_clock_ctrl(pm_dev_clk_e module, pm_dev_clk_pwr_e clock_state)
{
#if CONFIG_SYS_CPU1
#if CONFIG_MAILBOX
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
bk_pm_cp1_clk_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_CLK_CTRL_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = clock_state;
mb_cmd.param3 = 0;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
previous_tick = pm_cp1_aon_rtc_counter_get();
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_SEND_CMD_CP0_RESPONSE_TIME_OUT*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_clk_ctrl_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_clk_ctrl_state_get())
{
os_printf("cp1 vote freq[%d] time out\r\n",module);
}
#endif
return BK_OK;
#else
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
sys_drv_dev_clk_pwr_up(module, clock_state);
GLOBAL_INT_RESTORE();
return BK_OK;
#endif
}
pm_lpo_src_e bk_pm_lpo_src_get()
{
return (pm_lpo_src_e)aon_pmu_drv_lpo_src_get();
}
bk_err_t bk_pm_lpo_src_set(pm_lpo_src_e lpo_src)
{
aon_pmu_drv_lpo_src_set((uint32_t)lpo_src);
return BK_OK;
}
bk_err_t bk_pm_rosc_calibration(pm_rosc_cali_mode_e rosc_cali_mode, uint32_t cali_interval)
{
bk_err_t ret = BK_OK;
ret = sys_drv_rosc_calibration(rosc_cali_mode, cali_interval);
if (ret != BK_OK)
{
os_printf("set rosc calibration parameter error %d %d \r\n", rosc_cali_mode, cali_interval);
return ret;
}
return BK_OK;
}
bk_err_t pm_clk_32k_source_notify_cb(void)
{
bk_err_t ret;
ret = rtos_set_semaphore(&s_sync_sema);
return ret;
}
bk_err_t pm_extern32k_register_cb(pm_cb_extern32k_cfg_t *cfg)
{
if (cfg == NULL)
return BK_FAIL;
s_pm_cb_module_cfg.cfg[cfg->cb_module].cb_func = cfg->cb_func;
return BK_OK;
}
bk_err_t pm_extern32k_unregister_cb(pm_cb_extern32k_cfg_t *cfg)
{
if (cfg == NULL)
return BK_FAIL;
s_pm_cb_module_cfg.cfg[cfg->cb_module].cb_func = NULL;
return BK_OK;
}
bk_err_t pm_extern32k_cb_exec(pm_sw_step_e sw_step, pm_lpo_src_e lpo_src)
{
int i;
s_pm_cb_module_cfg.module_count = 0;
for (i = 0; i < PM_32K_MODULE_MAX; i++)
{
if (s_pm_cb_module_cfg.cfg[i].cb_func)
{
/*call cb and register notify callback*/
s_pm_cb_module_cfg.module_count++;
s_pm_cb_module_cfg.cfg[i].cb_func(sw_step, lpo_src, pm_clk_32k_source_notify_cb);
}
}
return BK_OK;
}
bk_err_t pm_clk_32k_source_switch(pm_lpo_src_e lpo_src)
{
#if CONFIG_EXTERN_32K_PIN_MULT
pm_lpo_src_e clk_src;
bk_err_t ret;
uint32_t count;
clk_src = bk_clk_32k_customer_config_get();
if (s_debug_en & 0x2)
{
os_printf("customer set clk %d\r\n", clk_src);
}
if (clk_src != PM_LPO_SRC_X32K)
{
return BK_OK;
}
clk_src = bk_pm_lpo_src_get();
if (s_debug_en & 0x2)
{
os_printf("current clk %d,set clk %d\r\n", clk_src, lpo_src);
}
if (clk_src == lpo_src)
{
return BK_OK;
}
if (NULL == s_sync_sema)
{
rtos_init_semaphore(&s_sync_sema, PM_32K_MODULE_MAX);
}
/*when close DVP,wait for the external clock to stabilize*/
if (lpo_src == PM_LPO_SRC_X32K)
{
aon_pmu_drv_lpo_src_extern32k_enable();
rtos_delay_milliseconds(SWITCH_32K_DELAY);
}
/*Before clock switch,execute BTWF callback and wait BTWF notify*/
pm_extern32k_cb_exec(PM_32K_STEP_BEGIN, lpo_src);
count = s_pm_cb_module_cfg.module_count;
while (count)
{
/*Wait for the BTWF clock switch to complete*/
ret = rtos_get_semaphore(&s_sync_sema, SWITCH_32K_WAIT);
if (ret < 0)
{
os_printf(" ERR: wait sema timeout\r\n");
rtos_deinit_semaphore(&s_sync_sema);
return BK_FAIL;
}
count--;
}
/*switch 32k source*/
bk_pm_lpo_src_set(lpo_src);
/*after clock switch,execute BTWF callback and wait BTWF notify*/
pm_extern32k_cb_exec(PM_32K_STEP_FINISH, lpo_src);
rtos_deinit_semaphore(&s_sync_sema);
#endif
return BK_OK;
}
/*=========================CLK/FREQ CTRL END========================*/
/*=========================DEBUG/TEST CTRL START========================*/
#if PM_DEBUG
#define AON_GPIO_BASE (0x44000400)
void TOGGLE_GPIO18()
{
uint32_t param = 0;
param = 0x2;
REG_WRITE(AON_GPIO_BASE + 0x12 * 4, param);
param = 0x0;
REG_WRITE(AON_GPIO_BASE + 0x12 * 4, param);
}
#endif
uint32_t pm_debug_mode()
{
return s_debug_en;
}
bk_err_t pm_debug_module_state()
{
#if CONFIG_SYS_CPU0
if(s_pm_video_pm_state > 0)
{
os_printf("Attention the video not power down[modulue:0x%x]\r\n",s_pm_video_pm_state);
}
if(s_pm_audio_pm_state > 0)
{
os_printf("Attention the audio not power down[modulue:0x%x]\r\n",s_pm_audio_pm_state);
}
if(!bk_pm_module_power_state_get(PM_POWER_MODULE_NAME_CPU1))
{
os_printf("Attention the cpu1 not power down[state:0x%x]\r\n",bk_pm_module_power_state_get(PM_POWER_MODULE_NAME_CPU1));
}
if(!(REG_READ(PM_DEBUG_SYS_REG_BASE+0x6*4)&0x2))
{
os_printf("Attention the cpu2 not power down[state:0x%x]\r\n",REG_READ(PM_DEBUG_SYS_REG_BASE+0x6*4));
}
#if CONFIG_PSRAM_AS_SYS_MEMORY
uint32_t cp0_psram_malloc_count = 0;
/*get the cp1 psram malloc count*/
#if (CONFIG_CPU_CNT > 1)
uint32_t cp1_psram_malloc_count = s_pm_cp1_psram_malloc_count_state;
if(cp1_psram_malloc_count > 0)
{
os_printf("Attention the CPU1 psram malloc count[%d] > 0\r\n",cp1_psram_malloc_count);
os_printf("The power consumption will get higher, please free them\r\n");
bk_pm_dump_cp1_psram_malloc_info();
}
#endif
/*get the cp0 psram malloc count*/
cp0_psram_malloc_count = bk_psram_heap_get_used_count();
if(cp0_psram_malloc_count > 0)
{
os_printf("Attention the CPU0 psram malloc count[%d] > 0\r\n",cp0_psram_malloc_count);
os_printf("The power consumption will get higher, please free them\r\n");
bk_psram_heap_get_used_state();
}
#endif
#endif
return BK_OK;
}
void pm_debug_ctrl(uint32_t debug_en)
{
s_debug_en = debug_en;
#if CONFIG_SYS_CPU0
if(debug_en == PM_DEBUG_CTRL_STATE)
{
os_printf("pm video and audio state:0x%x 0x%x\r\n",s_pm_video_pm_state,s_pm_audio_pm_state);
os_printf("pm ahpb and bakp state:0x%x 0x%x\r\n",s_pm_ahpb_pm_state,s_pm_bakp_pm_state);
os_printf("pm low vol[module:0x%llx] [need module:0x%llx]\r\n",s_pm_sleeped_modules,s_pm_enter_low_vol_modules);
os_printf("pm deepsleep[module:0x%x][need module:0x%x]\r\n",s_pm_off_modules,s_pm_enter_deep_sleep_modules);
os_printf("pm power and pmu state[0x%x][0x%x]\r\n",REG_READ(PM_DEBUG_SYS_REG_BASE+0x10*4),REG_READ(PM_DEBUG_PMU_REG_BASE+0x41*4));
if(s_pm_ahpb_pm_state > 0)
{
os_printf("Attention the ahbp not power down[modulue:0x%x]\r\n",s_pm_ahpb_pm_state);
}
if(s_pm_bakp_pm_state > 0)
{
os_printf("Attention the bakp not power down[modulue:0x%x]\r\n",s_pm_bakp_pm_state);
}
pm_cp1_psram_malloc_state_get();
pm_debug_module_state();
}
#endif
}
/*=========================DEBUG/TEST CTRL END========================*/