2025-10-10 16:07:00 +08:00

965 lines
26 KiB
C
Executable File

// Copyright 2020-2021 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 <common/bk_include.h>
#include <driver/pwr_clk.h>
#if CONFIG_MAILBOX
#include <driver/mailbox_channel.h>
#endif
#include <modules/pm.h>
#include "sys_driver.h"
#if CONFIG_PSRAM
#include <driver/psram.h>
#endif
#include <os/mem.h>
#include "sys_types.h"
#include <driver/aon_rtc.h>
#include <os/os.h>
#include <driver/psram.h>
#include <components/system.h>
#include "bk_pm_internal_api.h"
#include <common/bk_kernel_err.h>
#include "aon_pmu_hal.h"
#include "wdt_driver.h"
/*=====================DEFINE SECTION START=====================*/
#define PM_SEND_CMD_CP1_RESPONSE_TIEM (100) //100ms
#define PM_BOOT_CP1_WAITING_TIEM (500) // 0.5s
#define PM_CP1_RECOVERY_DEFAULT_VALUE (0xFFFFFFFFFFFFFFFF)
#define PM_OPEN_CP1_TIMEOUT (20000) //20s
#define PM_SEMA_WAIT_FOREVER (0xFFFFFFFF) /*Wait Forever*/
#define PM_BOOT_CP1_TRY_COUNT (3)
#define PWR_TAG "PWR"
#define PWR_LOGI(...) BK_LOGI(SOC_TAG, ##__VA_ARGS__)
#define PWR_LOGW(...) BK_LOGW(SOC_TAG, ##__VA_ARGS__)
#define PWR_LOGE(...) BK_LOGE(SOC_TAG, ##__VA_ARGS__)
#define PWR_LOGD(...) BK_LOGD(SOC_TAG, ##__VA_ARGS__)
/*=====================DEFINE SECTION END=====================*/
/*=====================VARIABLE SECTION START=================*/
#if CONFIG_SYS_CPU1
static volatile pm_mailbox_communication_state_e s_pm_cp1_pwr_finish = 0;
static volatile pm_mailbox_communication_state_e s_pm_cp1_clk_finish = 0;
static volatile pm_mailbox_communication_state_e s_pm_cp1_sleep_finish = 0;
static volatile pm_mailbox_communication_state_e s_pm_cp1_cpu_freq_finish = 0;
static volatile pm_mailbox_communication_state_e s_pm_cp1_init = 0;
static volatile pm_mailbox_communication_state_e s_pm_external_ldo_ctrl = 0;
static volatile pm_mailbox_communication_state_e s_pm_psram_power_ctrl = 0;
#elif CONFIG_SYS_CPU0
static volatile pm_mailbox_communication_state_e s_pm_cp1_boot_ready = 0;
static volatile pm_mailbox_communication_state_e s_pm_cp1_psram_malloc_state = 0;
static volatile uint32_t s_pm_cp1_psram_malloc_count = 0;
static volatile uint64_t s_pm_cp1_module_recovery_state = PM_CP1_RECOVERY_DEFAULT_VALUE;
#if (CONFIG_CPU_CNT > 1)
static beken_semaphore_t s_sync_cp1_open_sema = NULL;
#endif
static volatile uint32_t s_pm_cp1_closing = 0;
static volatile uint32_t s_pm_cp1_sema_count = 0;
#else
static volatile pm_mailbox_communication_state_e s_pm_cp1_boot_ready = 0;
#endif
static volatile uint32_t s_pm_cp1_boot_try_count = 0;
/*=====================VARIABLE SECTION END=================*/
/*================FUNCTION DECLARATION SECTION START========*/
#if CONFIG_SYS_CPU1 && CONFIG_MAILBOX
static void pm_cp1_mailbox_init();
bk_err_t pm_cp1_mailbox_response(uint32_t cmd, int ret);
bk_err_t bk_pm_cp1_ctrl_state_set(pm_mailbox_communication_state_e state);
pm_mailbox_communication_state_e bk_pm_cp1_ctrl_state_get();
static void pm_cp1_mailbox_send_data(uint32_t cmd, uint32_t param1,uint32_t param2,uint32_t param3);
#endif
#if CONFIG_SYS_CPU0 && (CONFIG_CPU_CNT > 1)
#if CONFIG_MAILBOX
static void pm_cp0_mailbox_init();
#endif
static void pm_module_shutdown_cpu1(pm_power_module_name_e module);
bk_err_t bk_pm_cp1_recovery_module_state_ctrl(pm_cp1_prepare_close_module_name_e module,pm_cp1_module_recovery_state_e state);
#endif
/*================FUNCTION DECLARATION SECTION END========*/
pm_lpo_src_e bk_clk_32k_customer_config_get(void)
{
#if CONFIG_LPO_MP_A_FORCE_USE_EXT32K
uint32_t chip_id = aon_pmu_hal_get_chipid();
if ((chip_id & PM_CHIP_ID_MASK) == (PM_CHIP_ID_MP_A & PM_CHIP_ID_MASK))
{
return PM_LPO_SRC_X32K;
}
else
{
#if CONFIG_EXTERN_32K
return PM_LPO_SRC_X32K;
#elif CONFIG_LPO_SRC_26M32K
return PM_LPO_SRC_DIVD;
#else
return PM_LPO_SRC_ROSC;
#endif
}
#else
#if CONFIG_EXTERN_32K
return PM_LPO_SRC_X32K;
#elif CONFIG_LPO_SRC_26M32K
return PM_LPO_SRC_DIVD;
#else
return PM_LPO_SRC_ROSC;
#endif
#endif
return PM_LPO_SRC_ROSC;
}
bk_err_t bk_pm_mailbox_init()
{
#if CONFIG_SYS_CPU1
/*cp1 mailbox init*/
#if CONFIG_MAILBOX
pm_cp1_mailbox_init();
#endif
#endif
#if CONFIG_SYS_CPU0
/*cp0 mailbox init*/
#if CONFIG_MAILBOX && (CONFIG_CPU_CNT > 1)
pm_cp0_mailbox_init();
#endif //CONFIG_MAILBOX
#endif
return BK_OK;
}
#if CONFIG_SYS_CPU1
#if CONFIG_MAILBOX
bk_err_t bk_pm_cp1_boot_ok_response_set()
{
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);
}
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_pwr_ctrl_state_get()
{
return s_pm_cp1_pwr_finish;
}
bk_err_t bk_pm_cp1_pwr_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_pwr_finish = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_clk_ctrl_state_get()
{
return s_pm_cp1_clk_finish;
}
bk_err_t bk_pm_cp1_clk_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_clk_finish = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_sleep_ctrl_state_get()
{
return s_pm_cp1_sleep_finish;
}
bk_err_t bk_pm_cp1_sleep_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_sleep_finish = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_cpu_freq_ctrl_state_get()
{
return s_pm_cp1_cpu_freq_finish;
}
bk_err_t bk_pm_cp1_cpu_freq_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_cpu_freq_finish = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_external_ldo_ctrl_state_get()
{
return s_pm_external_ldo_ctrl;
}
bk_err_t bk_pm_cp1_external_ldo_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_external_ldo_ctrl = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_psram_power_state_get()
{
return s_pm_psram_power_ctrl;
}
bk_err_t bk_pm_cp1_psram_power_state_set(pm_mailbox_communication_state_e state)
{
s_pm_psram_power_ctrl = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp1_ctrl_state_get()
{
return s_pm_cp1_init;
}
bk_err_t bk_pm_cp1_ctrl_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_init = state;
return BK_OK;
}
bk_err_t bk_pm_cp1_recovery_response(uint32_t cmd, pm_cp1_prepare_close_module_name_e module_name,pm_cp1_module_recovery_state_e state)
{
pm_cp1_mailbox_send_data(cmd,module_name,state,0);
return BK_OK;
}
static void pm_cp1_mailbox_send_data(uint32_t cmd, uint32_t param1,uint32_t param2,uint32_t param3)
{
bk_err_t ret = BK_OK;
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
mb_cmd.hdr.cmd = cmd;
mb_cmd.param1 = param1;
mb_cmd.param2 = param2;
mb_cmd.param3 = param3;
ret = mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
os_printf("cp1 send data %d\r\n",ret);
}
bk_err_t pm_cp1_mailbox_response(uint32_t cmd, int ret)
{
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
mb_cmd.hdr.cmd = cmd;
mb_cmd.param1 = ret;
mb_cmd.param2 = 0;
mb_cmd.param3 = 0;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
return BK_OK;
}
static void pm_cp1_mailbox_tx_cmpl_isr(int *pm_mb, mb_chnl_ack_t *cmd_buf)
{
}
static void pm_cp1_mailbox_rx_isr(int *pm_mb, mb_chnl_cmd_t *cmd_buf)
{
bk_err_t ret = BK_OK;
uint32_t used_count;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
switch(cmd_buf->hdr.cmd) {
case PM_POWER_CTRL_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_cp1_pwr_finish = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_CLK_CTRL_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_cp1_clk_finish = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_SLEEP_CTRL_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_cp1_sleep_finish = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_CPU_FREQ_CTRL_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_cp1_cpu_freq_finish = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_CTRL_EXTERNAL_LDO_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_external_ldo_ctrl = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_CTRL_PSRAM_POWER_CMD:
if(cmd_buf->param1 == BK_OK)
{
s_pm_psram_power_ctrl = PM_MAILBOX_COMMUNICATION_FINISH;
}
else
{
ret = BK_FAIL;
}
break;
case PM_CP1_PSRAM_MALLOC_STATE_CMD:
used_count = bk_psram_heap_get_used_count();
pm_cp1_mailbox_send_data(PM_CP1_PSRAM_MALLOC_STATE_CMD,0x1,used_count,0);
//os_printf("cp1 bk_psram_heap_get_used_count[%d]\r\n", bk_psram_heap_get_used_count());
break;
case PM_CP1_DUMP_PSRAM_MALLOC_INFO_CMD:
bk_psram_heap_get_used_state();
break;
case PM_CP1_RECOVERY_CMD:
stop_cpu1_handle_notifications();
bk_pm_cp1_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
break;
default:
break;
}
GLOBAL_INT_RESTORE();
if(ret != BK_OK)
{
os_printf("cp1 resps:cp0 rev msg error\r\n");
}
//if(pm_debug_mode()&0x2)
{
if(cmd_buf->hdr.cmd != PM_CP1_PSRAM_MALLOC_STATE_CMD)
{
os_printf("cp1_mb_rx_isr %d %d %d\r\n",cmd_buf->hdr.cmd,cmd_buf->param1,cmd_buf->param2);
}
}
}
static void pm_cp1_mailbox_tx_isr(int *pm_mb)
{
}
static void pm_cp1_mailbox_init()
{
mb_chnl_open(MB_CHNL_PWC, NULL);
if (pm_cp1_mailbox_rx_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_RX_ISR, pm_cp1_mailbox_rx_isr);
if (pm_cp1_mailbox_tx_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_TX_ISR, pm_cp1_mailbox_tx_isr);
if (pm_cp1_mailbox_tx_cmpl_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_TX_CMPL_ISR, pm_cp1_mailbox_tx_cmpl_isr);
}
#endif //CONFIG_MAILBOX
#endif//CONFIG_SYS_CPU1
#if CONFIG_SYS_CPU0 && (CONFIG_CPU_CNT > 1)
pm_mailbox_communication_state_e bk_pm_cp1_work_state_get()
{
return s_pm_cp1_boot_ready;
}
bk_err_t bk_pm_cp1_work_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_boot_ready = state;
return BK_OK;
}
pm_mailbox_communication_state_e bk_pm_cp0_psram_malloc_state_get()
{
return s_pm_cp1_psram_malloc_state;
}
bk_err_t bk_pm_cp0_psram_malloc_state_set(pm_mailbox_communication_state_e state)
{
s_pm_cp1_psram_malloc_state = state;
return BK_OK;
}
#if CONFIG_MAILBOX
static void pm_cp0_mailbox_send_data(uint32_t cmd, uint32_t param1,uint32_t param2,uint32_t param3)
{
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
mb_cmd.hdr.cmd = cmd;
mb_cmd.param1 = param1;
mb_cmd.param2 = param2;
mb_cmd.param3 = param3;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
}
static void pm_cp0_mailbox_response(uint32_t cmd, int ret)
{
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
mb_cmd.hdr.cmd = cmd;
mb_cmd.param1 = ret;
mb_cmd.param2 = 0;
mb_cmd.param3 = 0;
mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
}
static void pm_cp0_mailbox_tx_cmpl_isr(int *pm_mb, mb_chnl_ack_t *cmd_buf)
{
}
static void pm_cp0_mailbox_rx_isr(int *pm_mb, mb_chnl_cmd_t *cmd_buf)
{
bk_err_t ret = BK_OK;
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
switch(cmd_buf->hdr.cmd) {
case PM_POWER_CTRL_CMD:
ret = bk_pm_module_vote_power_ctrl(cmd_buf->param1,cmd_buf->param2);
pm_cp0_mailbox_response(PM_POWER_CTRL_CMD,ret);
break;
case PM_CLK_CTRL_CMD:
ret = bk_pm_clock_ctrl(cmd_buf->param1,cmd_buf->param2);
pm_cp0_mailbox_response(PM_CLK_CTRL_CMD,ret);
break;
case PM_SLEEP_CTRL_CMD:
ret = bk_pm_module_vote_sleep_ctrl(cmd_buf->param1,cmd_buf->param2,cmd_buf->param3);
pm_cp0_mailbox_response(PM_SLEEP_CTRL_CMD,ret);
break;
case PM_CPU_FREQ_CTRL_CMD:
ret = bk_pm_module_vote_cpu_freq(cmd_buf->param1,cmd_buf->param2);
pm_cp0_mailbox_response(PM_CPU_FREQ_CTRL_CMD,ret);
break;
case PM_CTRL_EXTERNAL_LDO_CMD:
ret = bk_pm_module_vote_ctrl_external_ldo(cmd_buf->param1,cmd_buf->param2,cmd_buf->param3);
pm_cp0_mailbox_response(PM_CTRL_EXTERNAL_LDO_CMD,ret);
break;
case PM_CTRL_PSRAM_POWER_CMD:
ret = bk_pm_module_vote_psram_ctrl(cmd_buf->param1,cmd_buf->param2);
pm_cp0_mailbox_response(PM_CTRL_PSRAM_POWER_CMD,ret);
break;
case PM_CPU1_BOOT_READY_CMD:
if(cmd_buf->param1 == 0x1)
{
s_pm_cp1_boot_ready = PM_MAILBOX_COMMUNICATION_FINISH;
}
//if(pm_debug_mode()&0x2)//for temp debug
os_printf("cpu0 receive the cpu1 boot success event [%d]\r\n",cmd_buf->param1);
break;
case PM_CP1_PSRAM_MALLOC_STATE_CMD:
if(cmd_buf->param1 == 0x1)
{
bk_pm_cp0_psram_malloc_state_set(PM_MAILBOX_COMMUNICATION_FINISH);
s_pm_cp1_psram_malloc_count = cmd_buf->param2;
}
break;
case PM_CP1_RECOVERY_CMD:
bk_pm_cp1_recovery_module_state_ctrl(cmd_buf->param1,cmd_buf->param2);
//os_printf("pm_cp0_mb_rx_isr CP1_RECOV_CMD\r\n");
break;
default:
break;
}
GLOBAL_INT_RESTORE();
if(ret != BK_OK)
{
os_printf("cp0 handle cp1 message error\r\n");
}
//if(pm_debug_mode()&0x2)
{
if(cmd_buf->hdr.cmd != PM_CP1_PSRAM_MALLOC_STATE_CMD)
{
os_printf("cp0_mb_rx_isr %d %d %d %d %d\r\n",cmd_buf->hdr.cmd,cmd_buf->param1,cmd_buf->param2,cmd_buf->param3,ret);
}
}
}
static void pm_cp0_mailbox_tx_isr(int *pm_mb)
{
}
static void pm_cp0_mailbox_init()
{
mb_chnl_open(MB_CHNL_PWC, NULL);
if (pm_cp0_mailbox_rx_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_RX_ISR, pm_cp0_mailbox_rx_isr);
if (pm_cp0_mailbox_tx_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_TX_ISR, pm_cp0_mailbox_tx_isr);
if (pm_cp0_mailbox_tx_cmpl_isr != NULL)
mb_chnl_ctrl(MB_CHNL_PWC, MB_CHNL_SET_TX_CMPL_ISR, pm_cp0_mailbox_tx_cmpl_isr);
}
#endif //CONFIG_MAILBOX
#endif //CONFIG_SYS_CPU0 && (CONFIG_CPU_CNT > 1)
#if CONFIG_SYS_CPU0&& (CONFIG_CPU_CNT > 1)
static uint32_t s_pm_cp1_ctrl_state = 0;
extern void start_cpu1_core(void);
extern void stop_cpu1_core(void);
bk_err_t bk_pm_cp1_recovery_module_state_ctrl(pm_cp1_prepare_close_module_name_e module,pm_cp1_module_recovery_state_e state)
{
if(state == PM_CP1_MODULE_RECOVERY_STATE_INIT)
{
s_pm_cp1_module_recovery_state &= ~(0x1ULL << module);
}
else
{
s_pm_cp1_module_recovery_state |= (0x1ULL << module);
}
os_printf("cp1 rev 0x%llx %d %d %d\r\n",s_pm_cp1_module_recovery_state,bk_pm_cp1_work_state_get(),bk_pm_cp1_recovery_all_state_get(),s_pm_cp1_ctrl_state);
if(bk_pm_cp1_recovery_all_state_get())
{
bk_pm_module_check_cp1_shutdown();
}
return BK_OK;
}
bool bk_pm_cp1_recovery_all_state_get()
{
bool cp1_all_module_recovery = false;
if(bk_pm_cp1_work_state_get())
{
cp1_all_module_recovery = (s_pm_cp1_module_recovery_state == PM_CP1_RECOVERY_DEFAULT_VALUE);
}
return cp1_all_module_recovery;
}
static void pm_module_bootup_cpu1(pm_power_module_name_e module)
{
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
if(PM_POWER_MODULE_STATE_OFF == sys_drv_module_power_state_get(module))
{
if(module == PM_POWER_MODULE_NAME_CPU1)
{
boot_cp1:
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_CPU1, 0, 0);
bk_pm_module_vote_power_ctrl(PM_POWER_MODULE_NAME_CPU1, PM_POWER_MODULE_STATE_ON);
#if defined(RECV_CMD_LOG_FROM_MBOX)
void reset_forward_log_status(void);
// reset cpu1's log transfer status on cpu0.
reset_forward_log_status();
#endif
start_cpu1_core();
previous_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_BOOT_CP1_WAITING_TIEM*AON_RTC_MS_TICK_CNT))
{
if (bk_pm_cp1_work_state_get()) // wait the cp1 response
{
break;
}
current_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
}
if(!bk_pm_cp1_work_state_get())
{
os_printf("cp0 boot cp1[%d] time out, boot cp1 fail!!!\r\n",s_pm_cp1_boot_try_count);
/*Reset psram*/
bk_pm_module_vote_psram_ctrl(PM_POWER_PSRAM_MODULE_NAME_MEDIA, PM_POWER_MODULE_STATE_OFF);
bk_pm_module_vote_psram_ctrl(PM_POWER_PSRAM_MODULE_NAME_MEDIA, PM_POWER_MODULE_STATE_ON);
s_pm_cp1_boot_try_count++;
if(s_pm_cp1_boot_try_count < PM_BOOT_CP1_TRY_COUNT)
{
goto boot_cp1;
}
if(s_pm_cp1_boot_try_count == PM_BOOT_CP1_TRY_COUNT)
{
bk_wdt_force_reboot();//try 3 times, if fail ,reboot.
}
}
}
}
}
bk_err_t bk_pm_module_check_cp1_shutdown()
{
if(0x0 == s_pm_cp1_ctrl_state)
{
pm_module_shutdown_cpu1(PM_POWER_MODULE_NAME_CPU1);
}
return BK_OK;
}
static void pm_module_shutdown_cpu1(pm_power_module_name_e module)
{
bk_err_t ret = BK_OK;
GLOBAL_INT_DECLARATION();
if(PM_POWER_MODULE_STATE_ON == sys_drv_module_power_state_get(module))
{
if(module == PM_POWER_MODULE_NAME_CPU1)
{
stop_cpu1_core();
bk_pm_module_vote_psram_ctrl(PM_POWER_PSRAM_MODULE_NAME_MEDIA, PM_POWER_MODULE_STATE_OFF);
bk_pm_module_vote_power_ctrl(PM_POWER_MODULE_NAME_CPU1, PM_POWER_MODULE_STATE_OFF);
bk_pm_module_vote_cpu_freq(PM_DEV_ID_CPU1,PM_CPU_FRQ_DEFAULT);
GLOBAL_INT_DISABLE();
s_pm_cp1_boot_ready = 0;
s_pm_cp1_closing = 0;
s_pm_cp1_boot_try_count = 0;
GLOBAL_INT_RESTORE();
ret = rtos_set_semaphore(&s_sync_cp1_open_sema);
if(s_pm_cp1_sema_count == 0)
{
rtos_deinit_semaphore(&s_sync_cp1_open_sema);
}
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_CPU1, 1, 0);
os_printf("Shutdown_cp1[%d][%d][%d]\r\n",s_pm_cp1_closing,ret,s_pm_cp1_sema_count);
}
}
}
bk_err_t bk_pm_module_vote_boot_cp1_ctrl(pm_boot_cp1_module_name_e module,pm_power_module_state_e power_state)
{
bk_err_t ret = BK_OK;
GLOBAL_INT_DECLARATION();
os_printf("boot_cp1 %d %d 0x%x [%d][0x%x]E_1\r\n",module, power_state,s_pm_cp1_ctrl_state,s_pm_cp1_closing,&s_sync_cp1_open_sema);
if (NULL == s_sync_cp1_open_sema)
{
rtos_init_semaphore(&s_sync_cp1_open_sema, 1);
}
if(s_pm_cp1_closing)
{
GLOBAL_INT_DISABLE();
s_pm_cp1_sema_count++;
GLOBAL_INT_RESTORE();
os_printf("boot_cp1 get sema[%d][0x%x]\r\n",s_pm_cp1_sema_count,&s_sync_cp1_open_sema);
/*add protect:init again when the s_sync_cp1_open_sema free*/
if (NULL == s_sync_cp1_open_sema)
{
rtos_init_semaphore(&s_sync_cp1_open_sema, 1);
}
ret = rtos_get_semaphore(&s_sync_cp1_open_sema, PM_OPEN_CP1_TIMEOUT);
GLOBAL_INT_DISABLE();
s_pm_cp1_sema_count--;
GLOBAL_INT_RESTORE();
if(ret == kTimeoutErr)
{
os_printf("boot_cp1[%d]0x%llx %d %d %d\r\n",ret,s_pm_cp1_module_recovery_state,bk_pm_cp1_work_state_get(),bk_pm_cp1_recovery_all_state_get(),s_pm_cp1_ctrl_state);
if(bk_pm_cp1_recovery_all_state_get())
{
bk_pm_module_check_cp1_shutdown();
}
}
}
os_printf("boot_cp1 %d %d 0x%x [%d]E_2\r\n",module, power_state,s_pm_cp1_ctrl_state,ret);
if(power_state == PM_POWER_MODULE_STATE_ON)//power on
{
bk_pm_module_vote_cpu_freq(PM_DEV_ID_CPU1,PM_CPU_FRQ_480M);
bk_pm_module_vote_psram_ctrl(PM_POWER_PSRAM_MODULE_NAME_MEDIA, PM_POWER_MODULE_STATE_ON);
GLOBAL_INT_DISABLE();
s_pm_cp1_ctrl_state |= 0x1 << (module);
GLOBAL_INT_RESTORE();
pm_module_bootup_cpu1(PM_POWER_MODULE_NAME_CPU1);
}
else //power down
{
if(s_pm_cp1_ctrl_state&(0x1 << (module)))
{
GLOBAL_INT_DISABLE();
s_pm_cp1_ctrl_state &= ~(0x1 << (module));
GLOBAL_INT_RESTORE();
if(0x0 == s_pm_cp1_ctrl_state)
{
s_pm_cp1_closing = 1;
os_printf("boot_cp1 %d %d close 0x%llx %d\r\n",module, power_state,s_pm_cp1_module_recovery_state,s_pm_cp1_boot_ready);
pm_cp0_mailbox_send_data(PM_CP1_RECOVERY_CMD,0,0,0);
//pm_module_shutdown_cpu1(PM_POWER_MODULE_NAME_CPU1);
}
}
}
return BK_OK;
}
/*Get the cp1 heap malloc count*/
uint32_t bk_pm_get_cp1_psram_malloc_count()
{
uint64_t previous_tick = 0;
uint64_t current_tick = 0;
if(s_pm_cp1_boot_ready)
{
s_pm_cp1_psram_malloc_count = 0;
bk_pm_cp0_psram_malloc_state_set(PM_MAILBOX_COMMUNICATION_INIT);
pm_cp0_mailbox_send_data(PM_CP1_PSRAM_MALLOC_STATE_CMD,0,0,0);
previous_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_SEND_CMD_CP1_RESPONSE_TIEM*AON_RTC_MS_TICK_CNT))
{
if (bk_pm_cp0_psram_malloc_state_get()) // wait the cp1 response
{
break;
}
current_tick = bk_aon_rtc_get_current_tick(AON_RTC_ID_1);
}
if(!bk_pm_cp0_psram_malloc_state_get())
{
os_printf("cp0 get the psram malloc state time out > 100ms\r\n");
}
return s_pm_cp1_psram_malloc_count;
}
else
{
return 0;
}
}
/*trigger the cp1 heap malloc dump*/
bk_err_t bk_pm_dump_cp1_psram_malloc_info()
{
if(s_pm_cp1_boot_ready)
{
pm_cp0_mailbox_send_data(PM_CP1_DUMP_PSRAM_MALLOC_INFO_CMD,0,0,0);
}
return BK_OK;
}
#endif
#if CONFIG_SYS_CPU0 && (CONFIG_CPU_CNT > 2)
static volatile pm_mailbox_communication_state_e s_pm_cp2_boot_ready = 0;
static uint32_t s_pm_cp2_ctrl_state = 0;
extern void start_cpu2_core(void);
extern void stop_cpu2_core(void);
static void pm_module_bootup_cpu2(pm_power_module_name_e module)
{
if(PM_POWER_MODULE_STATE_OFF == sys_drv_module_power_state_get(module))
{
if(module == PM_POWER_MODULE_NAME_CPU2)
{
bk_pm_module_vote_power_ctrl(PM_POWER_MODULE_NAME_CPU2, PM_POWER_MODULE_STATE_ON);
start_cpu2_core();
//while(!s_pm_cp2_boot_ready);
}
}
}
static void pm_module_shutdown_cpu2(pm_power_module_name_e module)
{
GLOBAL_INT_DECLARATION();
if(PM_POWER_MODULE_STATE_ON == sys_drv_module_power_state_get(module))
{
if(module == PM_POWER_MODULE_NAME_CPU2)
{
stop_cpu2_core();
bk_pm_module_vote_power_ctrl(PM_POWER_MODULE_NAME_CPU2, PM_POWER_MODULE_STATE_OFF);
GLOBAL_INT_DISABLE();
s_pm_cp2_boot_ready = 0;
GLOBAL_INT_RESTORE();
}
}
}
bk_err_t bk_pm_module_vote_boot_cp2_ctrl(pm_boot_cp2_module_name_e module,pm_power_module_state_e power_state)
{
GLOBAL_INT_DECLARATION();
if(power_state == PM_POWER_MODULE_STATE_ON)//power on
{
GLOBAL_INT_DISABLE();
s_pm_cp2_ctrl_state |= 0x1 << (module);
GLOBAL_INT_RESTORE();
pm_module_bootup_cpu2(PM_POWER_MODULE_NAME_CPU2);
}
else //power down
{
GLOBAL_INT_DISABLE();
s_pm_cp2_ctrl_state &= ~(0x1 << (module));
GLOBAL_INT_RESTORE();
if(0x0 == s_pm_cp2_ctrl_state)
{
pm_module_shutdown_cpu2(PM_POWER_MODULE_NAME_CPU2);
}
}
return BK_OK;
}
#endif
#if CONFIG_SYS_CPU0
#if CONFIG_PSRAM
static uint32_t s_pm_psram_ctrl_state = 0;
#endif
static bk_err_t pm_psram_power_ctrl(pm_power_psram_module_name_e module,pm_power_module_state_e power_state)
{
#if CONFIG_PSRAM
bk_err_t ret = BK_OK;
GLOBAL_INT_DECLARATION();
//os_printf("%s %d %d 0x%x\r\n",__func__, module, power_state,s_pm_psram_ctrl_state);
if(power_state == PM_POWER_MODULE_STATE_ON)//power on
{
GLOBAL_INT_DISABLE();
s_pm_psram_ctrl_state |= 0x1 << (module);
GLOBAL_INT_RESTORE();
ret = bk_psram_init();
if(ret != BK_OK)
{
PWR_LOGE("Psram_I err0:%d",ret);
bk_psram_deinit();
ret = bk_psram_init();
if(ret != BK_OK)
{
PWR_LOGE("Psram_I err1:%d",ret);
bk_psram_deinit();
ret = bk_psram_init();
if(ret != BK_OK)
{
PWR_LOGE("Psram_I err2:%d",ret);
bk_wdt_force_reboot();//try 3 times, if fail ,reboot.
}
}
}
}
else //power down
{
if(s_pm_psram_ctrl_state&(0x1 << (module)))
{
GLOBAL_INT_DISABLE();
s_pm_psram_ctrl_state &= ~(0x1 << (module));
GLOBAL_INT_RESTORE();
if(0x0 == s_pm_psram_ctrl_state)
{
bk_psram_deinit();
}
}
}
#endif
return BK_OK;
}
bk_err_t pm_debug_pwr_clk_state()
{
#if CONFIG_SYS_CPU0
#if CONFIG_PSRAM
os_printf("pm_psram:0x%x 0x%x\r\n",s_pm_psram_ctrl_state,bk_psram_heap_init_flag_get());
#endif
#if (CONFIG_CPU_CNT > 1)
os_printf("pm_cp1_ctr:0x%x \r\n",s_pm_cp1_ctrl_state);
#endif
os_printf("pm_cp1_boot_ready:0x%x 0x%x\r\n",s_pm_cp1_boot_ready,s_pm_cp1_module_recovery_state);
#endif
return BK_OK;
}
#endif
bk_err_t bk_pm_module_vote_psram_ctrl(pm_power_psram_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;
bk_err_t ret = BK_OK;
mb_chnl_cmd_t mb_cmd = {0};
GLOBAL_INT_DECLARATION();
GLOBAL_INT_DISABLE();
bk_pm_cp1_psram_power_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_CTRL_PSRAM_POWER_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = power_state;
ret = mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
GLOBAL_INT_RESTORE();
os_printf("cp1 vote psram_P B:%d\r\n",ret);
while(ret != BK_OK)
{
ret = mb_chnl_write(MB_CHNL_PWC, &mb_cmd);
rtos_delay_milliseconds(4);
}
previous_tick = pm_cp1_aon_rtc_counter_get();
current_tick = previous_tick;
while((current_tick - previous_tick) < (PM_SEND_CMD_CP1_RESPONSE_TIEM*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_psram_power_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_psram_power_state_get())
{
os_printf("cp1 get psram sta timeout\r\n");
}
os_printf("cp1 vote psram_P E\r\n");
#endif
return BK_OK;
#elif CONFIG_SYS_CPU0
pm_psram_power_ctrl(module,power_state);
return BK_OK;
#else
return BK_OK;
#endif
}
bk_err_t bk_pm_module_vote_ctrl_external_ldo(gpio_ctrl_ldo_module_e module,gpio_id_t gpio_id,gpio_output_state_e value)
{
#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_external_ldo_ctrl_state_set(PM_MAILBOX_COMMUNICATION_INIT);
mb_cmd.hdr.cmd = PM_CTRL_EXTERNAL_LDO_CMD;
mb_cmd.param1 = module;
mb_cmd.param2 = gpio_id;
mb_cmd.param3 = value;
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_BOOT_CP1_WAITING_TIEM*PM_AON_RTC_DEFAULT_TICK_COUNT))
{
if (bk_pm_cp1_external_ldo_ctrl_state_get()) // wait the cp0 response
{
break;
}
current_tick = pm_cp1_aon_rtc_counter_get();
}
if(!bk_pm_cp1_external_ldo_ctrl_state_get())
{
os_printf("cp1 ctr extLdo timeout\r\n");
}
os_printf("cp1 vote ctr_extLdo\r\n");
#endif
return BK_OK;
#elif CONFIG_SYS_CPU0
bk_gpio_ctrl_external_ldo(module,gpio_id,value);
return BK_OK;
#else
return BK_OK;
#endif
}