1765 lines
50 KiB
C
1765 lines
50 KiB
C
/**
|
|
* @file sdrv_smc.c
|
|
* @brief Sdrv SMC driver source.
|
|
*
|
|
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <reg.h>
|
|
#include <regs_base.h>
|
|
#include <param.h>
|
|
#include <sdrv_smc.h>
|
|
#include "sdrv_smc_reg.h"
|
|
|
|
#define GET_COM_IRQ_MASK_BASE(m, n) (COM_IRQ_MASK_##m##_OFF(n))
|
|
|
|
#define SMC_WAIT_TIME 500000u
|
|
|
|
static sdrv_smc_t g_default_smc_ctrl = {
|
|
.base = APB_SMC_BASE,
|
|
};
|
|
|
|
static inline uint32_t sdrv_smc_readl(uint32_t base, uint32_t offset)
|
|
{
|
|
return readl(base + offset);
|
|
}
|
|
|
|
static inline void sdrv_smc_writel(uint32_t base, uint32_t offset, uint32_t value)
|
|
{
|
|
writel(value, base + offset);
|
|
}
|
|
|
|
static inline uint32_t sdrv_smc_lp_ctl_addr(sdrv_smc_power_switch_e ps)
|
|
{
|
|
#if CONFIG_E3 || CONFIG_D3
|
|
return (ps < SDRV_SMC_POWER_SWITCH_AP_DISP) ? SAF_LP_CTL_OFF(ps) : AP_LP_CTL_OFF(0);
|
|
#endif
|
|
|
|
#if CONFIG_E3L || CONFIG_D3L
|
|
return SAF_LP_CTL_OFF(ps);
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t sdrv_smc_lp_ctl_dly_addr(sdrv_smc_power_switch_e ps)
|
|
{
|
|
#if CONFIG_E3 || CONFIG_D3
|
|
return (ps < SDRV_SMC_POWER_SWITCH_AP_DISP) ? SAF_LP_DLY_CTL_OFF(ps) : AP_LP_DLY_CTL_OFF(0);
|
|
#endif
|
|
|
|
#if CONFIG_E3L || CONFIG_D3L
|
|
return SAF_LP_DLY_CTL_OFF(ps);
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t sdrv_smc_ram_lp_ctl_addr(sdrv_smc_ram_e ram)
|
|
{
|
|
#if CONFIG_E3 || CONFIG_D3
|
|
return (ram < SDRV_SMC_RAM_AP) ? SAF_RAM_LP_CTL_OFF(ram) : AP_RAM_LP_CTL_OFF((ram - SDRV_SMC_RAM_AP));
|
|
#endif
|
|
|
|
#if CONFIG_E3L || CONFIG_D3L
|
|
return SAF_RAM_LP_CTL_OFF(ram);
|
|
#endif
|
|
}
|
|
|
|
static void sdrv_smc_core_irq_mask(uint32_t base, sdrv_smc_core_e core, uint16_t mask)
|
|
{
|
|
uint32_t v = sdrv_smc_readl(base, CORE_IRQ_MASK_OFF(core));
|
|
v |= mask;
|
|
sdrv_smc_writel(base, CORE_IRQ_MASK_OFF(core), v);
|
|
}
|
|
|
|
static void sdrv_smc_core_irq_unmask(uint32_t base, sdrv_smc_core_e core, uint16_t unmask)
|
|
{
|
|
uint32_t v = sdrv_smc_readl(base, CORE_IRQ_MASK_OFF(core));
|
|
v &= ~unmask;
|
|
sdrv_smc_writel(base, CORE_IRQ_MASK_OFF(core), v);
|
|
}
|
|
|
|
static uint32_t sdrv_smc_get_common_irq_mask_offset(sdrv_smc_core_e core,
|
|
uint32_t group)
|
|
{
|
|
uint32_t offset;
|
|
|
|
switch (group) {
|
|
case 0:
|
|
offset = GET_COM_IRQ_MASK_BASE(0, core);
|
|
break;
|
|
|
|
case 1:
|
|
offset = GET_COM_IRQ_MASK_BASE(1, core);
|
|
break;
|
|
|
|
case 2:
|
|
offset = GET_COM_IRQ_MASK_BASE(2, core);
|
|
break;
|
|
|
|
case 3:
|
|
offset = GET_COM_IRQ_MASK_BASE(3, core);
|
|
break;
|
|
|
|
case 4:
|
|
offset = GET_COM_IRQ_MASK_BASE(4, core);
|
|
break;
|
|
|
|
case 5:
|
|
offset = GET_COM_IRQ_MASK_BASE(5, core);
|
|
break;
|
|
|
|
case 6:
|
|
offset = GET_COM_IRQ_MASK_BASE(6, core);
|
|
break;
|
|
|
|
case 7:
|
|
offset = GET_COM_IRQ_MASK_BASE(7, core);
|
|
break;
|
|
|
|
default:
|
|
offset = 0;
|
|
break;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
static void sdrv_smc_common_irq_mask(uint32_t base, sdrv_smc_core_e core, uint32_t group,
|
|
uint32_t mask)
|
|
{
|
|
uint32_t v, offset;
|
|
|
|
offset = sdrv_smc_get_common_irq_mask_offset(core, group);
|
|
|
|
v = sdrv_smc_readl(base, offset);
|
|
v |= mask;
|
|
sdrv_smc_writel(base, offset, v);
|
|
}
|
|
|
|
static void sdrv_smc_common_irq_unmask(uint32_t base, sdrv_smc_core_e core, uint32_t group,
|
|
uint32_t unmask)
|
|
{
|
|
uint32_t v, offset;
|
|
|
|
offset = sdrv_smc_get_common_irq_mask_offset(core, group);
|
|
|
|
v = sdrv_smc_readl(base, offset);
|
|
v &= ~unmask;
|
|
sdrv_smc_writel(base, offset, v);
|
|
}
|
|
|
|
static void sdrv_smc_clear_core_interrupt_monitor(uint32_t base, sdrv_smc_core_e core,
|
|
uint16_t clear_bitmap)
|
|
{
|
|
uint32_t v = sdrv_smc_readl(base, CORE_IRQ_MON_OFF(core));
|
|
v &= ~clear_bitmap;
|
|
sdrv_smc_writel(base, CORE_IRQ_MON_OFF(core), v);
|
|
}
|
|
|
|
static void sdrv_smc_clear_common_interrupt_monitor(uint32_t base, uint32_t grp,
|
|
uint32_t clear_bitmap)
|
|
{
|
|
if (grp < 8) {
|
|
uint32_t offset = COM_IRQ_MON_0_OFF + grp * 0x4;
|
|
uint32_t v = sdrv_smc_readl(base, offset);
|
|
|
|
v &= ~clear_bitmap;
|
|
sdrv_smc_writel(base, offset, v);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config Safety/AP domain global control setting.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] config global control setting.
|
|
*/
|
|
status_t sdrv_smc_ctrl_global_control_config(sdrv_smc_t *smc_ctrl, sdrv_smc_global_control_t *config)
|
|
{
|
|
uint32_t base, v;
|
|
|
|
sdrv_smc_ctrl_set_primary_core(smc_ctrl, SDRV_SMC_SAF, config->saf_pri_core);
|
|
sdrv_smc_ctrl_set_primary_core(smc_ctrl, SDRV_SMC_AP, config->ap_pri_core);
|
|
sdrv_smc_ctrl_ap_domain_handshake(smc_ctrl, !config->ap_off_en);
|
|
|
|
base = (uint32_t)smc_ctrl->base;
|
|
v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
|
|
if (config->lp_align_saf_en) {
|
|
v |= BM_AP_GLB_CTL_LP_ALIGN2SAF;
|
|
}
|
|
else {
|
|
v &= ~BM_AP_GLB_CTL_LP_ALIGN2SAF;
|
|
}
|
|
|
|
if (config->wkup_align_saf_en) {
|
|
v |= BM_AP_GLB_CTL_WKUP_ALIGN2SAF;
|
|
}
|
|
else {
|
|
v &= ~BM_AP_GLB_CTL_WKUP_ALIGN2SAF;
|
|
}
|
|
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set primary core id for a power domain.
|
|
*
|
|
* This function sets primary core id for a domain. Only the primary CPU of
|
|
* one domain can configure SMC registers of this domain.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] domain Safety or AP domain
|
|
* @param [in] id core id
|
|
*/
|
|
status_t sdrv_smc_ctrl_set_primary_core(sdrv_smc_t *smc_ctrl, sdrv_smc_domain_e domain, sdrv_smc_core_e id)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (domain == SDRV_SMC_SAF) {
|
|
uint32_t v = sdrv_smc_readl(base, SAF_GLB_CTL_OFF);
|
|
v &= ~FM_SAF_GLB_CTL_PRI_CORE;
|
|
v |= FV_SAF_GLB_CTL_PRI_CORE(id);
|
|
sdrv_smc_writel(base, SAF_GLB_CTL_OFF, v);
|
|
} else if (domain == SDRV_SMC_AP) {
|
|
uint32_t v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
v &= ~FM_AP_GLB_CTL_PRI_CORE;
|
|
v |= FV_AP_GLB_CTL_PRI_CORE(id);
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set low power mode for specific domain.
|
|
*
|
|
* This function sets the low power mode of specific domain. The domain will
|
|
* enter required low power mode after its primary CPU and all CPUs belongs
|
|
* to this domain enters WFI.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] domain Safety or AP domain
|
|
* @param [in] mode Sleep or hibernate after primary CPU WFI
|
|
*/
|
|
status_t sdrv_smc_ctrl_set_lowpower_mode(sdrv_smc_t *smc_ctrl, sdrv_smc_domain_e domain, sdrv_smc_mode_e mode)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (domain == SDRV_SMC_SAF) {
|
|
uint32_t v = sdrv_smc_readl(base, SAF_GLB_CTL_OFF);
|
|
v &= ~BM_SAF_GLB_CTL_LP_MODE;
|
|
if (mode == SDRV_SMC_HIBERNATE) {
|
|
v |= BM_SAF_GLB_CTL_LP_MODE;
|
|
}
|
|
sdrv_smc_writel(base, SAF_GLB_CTL_OFF, v);
|
|
} else if (domain == SDRV_SMC_AP) {
|
|
uint32_t v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
v &= ~BM_AP_GLB_CTL_LP_MODE;
|
|
if (mode == SDRV_SMC_HIBERNATE) {
|
|
v |= BM_AP_GLB_CTL_LP_MODE;
|
|
}
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Enable or disable low power for specific domain
|
|
*
|
|
* This function enable or disable low power mode for a domain. If enabled, when all
|
|
* CPUs enter wfi, SMC will start low power procedure.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] domain safety or ap domain
|
|
* @param [in] enable true/false
|
|
*/
|
|
status_t sdrv_smc_ctrl_lowpower_enable(sdrv_smc_t *smc_ctrl, sdrv_smc_domain_e domain, bool enable)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (domain == SDRV_SMC_SAF) {
|
|
uint32_t v = sdrv_smc_readl(base, SAF_GLB_CTL_OFF);
|
|
v &= ~BM_SAF_GLB_CTL_WFI_DIS;
|
|
if (!enable) {
|
|
v |= BM_SAF_GLB_CTL_WFI_DIS;
|
|
}
|
|
sdrv_smc_writel(base, SAF_GLB_CTL_OFF, v);
|
|
} else if (domain == SDRV_SMC_AP) {
|
|
uint32_t v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
v &= ~BM_AP_GLB_CTL_WFI_DIS;
|
|
if (!enable) {
|
|
v |= BM_AP_GLB_CTL_WFI_DIS;
|
|
}
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Control power switchs in low power mode.
|
|
*
|
|
* This function configures power switch states (on or off) in domain
|
|
* low power mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] mode The SMC low power mode to configure the switch for.
|
|
* @param [in] power_down_enable True to turn off the switch in low power
|
|
* mode. False to leave the power switch on in lower power mode.
|
|
*/
|
|
status_t sdrv_smc_ctrl_power_switch_config(sdrv_smc_t *smc_ctrl, sdrv_smc_power_switch_e power_switch,
|
|
sdrv_smc_mode_e mode, bool power_down_enable)
|
|
{
|
|
uint32_t offset;
|
|
uint32_t v;
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
offset = sdrv_smc_lp_ctl_addr(power_switch);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
if (power_down_enable) {
|
|
if (mode == SDRV_SMC_HIBERNATE) {
|
|
v |= BM_SAF_LP_CTL_HIB_PD_EN;
|
|
} else {
|
|
v |= BM_SAF_LP_CTL_SLP_PD_EN;
|
|
}
|
|
} else {
|
|
if (mode == SDRV_SMC_HIBERNATE) {
|
|
v &= ~BM_SAF_LP_CTL_HIB_PD_EN;
|
|
} else {
|
|
v &= ~BM_SAF_LP_CTL_SLP_PD_EN;
|
|
}
|
|
}
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config Power switch in low power delay control.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] iso_en isolation enable delay between LP process start to X_iso_en pose.
|
|
* @param [in] pg power gate delay between X_iso_en pose to X_pwr_gate pose.
|
|
* @param [in] po power on delay between RUN process start to X_pwr_gate nege.
|
|
* @param [in] iso_dis isolation disable delay between X_pwr_gate nege to X_iso_en_nege.
|
|
*/
|
|
status_t sdrv_smc_ctrl_power_switch_delay_config(sdrv_smc_t *smc_ctrl, sdrv_smc_power_switch_e power_switch,
|
|
uint32_t iso_en, uint32_t pg, uint32_t po, uint32_t iso_dis)
|
|
{
|
|
uint32_t offset;
|
|
volatile uint32_t v;
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
offset = sdrv_smc_lp_ctl_dly_addr(power_switch);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
v &= ~FM_SAF_LP_DLY_CTL_ISO_EN;
|
|
v &= ~FM_SAF_LP_DLY_CTL_PG;
|
|
v &= ~FM_SAF_LP_DLY_CTL_PO;
|
|
v &= ~FM_SAF_LP_DLY_CTL_ISO_DIS;
|
|
|
|
v |= FV_SAF_LP_DLY_CTL_ISO_EN(iso_en);
|
|
v |= FV_SAF_LP_DLY_CTL_PG(pg);
|
|
v |= FV_SAF_LP_DLY_CTL_PO(po);
|
|
v |= FV_SAF_LP_DLY_CTL_ISO_DIS(iso_dis);
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Configure low power modes for core RAM
|
|
*
|
|
* This function configures low power modes for core RAMs, i.e, module interal
|
|
* RAM, CPU cache and TCM, in SMC sleep or hibernate modes.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] ram RAM type.
|
|
* @param [in] mode The SMC low power mode to configure RAM mode for.
|
|
* @param [in] ram_mode RAM mode in SMC low power mode. Possible values are:
|
|
* SDRV_SMC_CHIP_ENABLE
|
|
* SDRV_SMC_SELECTIVE_PRECHARGE
|
|
* SDRV_SMC_RETENTION_1
|
|
* SDRV_SMC_RETENTION_2
|
|
* SDRV_SMC_POWER_DOWN
|
|
*/
|
|
status_t sdrv_smc_ctrl_ram_lowpower_config(sdrv_smc_t *smc_ctrl, sdrv_smc_ram_e ram, sdrv_smc_mode_e mode,
|
|
uint32_t ram_mode)
|
|
{
|
|
uint32_t offset;
|
|
uint32_t v;
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
offset = sdrv_smc_ram_lp_ctl_addr(ram);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
if (mode == SDRV_SMC_SLEEP) {
|
|
v &= ~BM_SAF_RAM_LP_CTL_SLP_RAM_PD_EN;
|
|
|
|
if (ram_mode != SDRV_SMC_CHIP_ENABLE) {
|
|
v |= BM_SAF_RAM_LP_CTL_SLP_RAM_PD_EN;
|
|
}
|
|
|
|
v &= ~FM_SAF_RAM_LP_CTL_SLP_RAM_LP_SETTING;
|
|
v |= FV_SAF_RAM_LP_CTL_SLP_RAM_LP_SETTING(ram_mode);
|
|
} else if (mode == SDRV_SMC_HIBERNATE) {
|
|
v &= ~BM_SAF_RAM_LP_CTL_HIB_RAM_PD_EN;
|
|
|
|
if (ram_mode != SDRV_SMC_CHIP_ENABLE) {
|
|
v |= BM_SAF_RAM_LP_CTL_HIB_RAM_PD_EN;
|
|
}
|
|
|
|
v &= ~FM_SAF_RAM_LP_CTL_HIB_RAM_LP_SETTING;
|
|
v |= FV_SAF_RAM_LP_CTL_HIB_RAM_LP_SETTING(ram_mode);
|
|
}
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC Saf or AP domain tiemout setting.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] domain SDRV_SMC_SAF or SDRV_SMC_AP.
|
|
* @param [in] config domain timeout setting.
|
|
*/
|
|
status_t sdrv_smc_ctrl_domain_timeout_config(sdrv_smc_t *smc_ctrl, sdrv_smc_domain_e domain,
|
|
sdrv_smc_domain_timeout_t *config)
|
|
{
|
|
uint32_t offset;
|
|
volatile uint32_t v;
|
|
uint32_t base;
|
|
|
|
base = (uint32_t)smc_ctrl->base;
|
|
offset = (domain == SDRV_SMC_SAF) ? SAF_TIMEOUT_OFF : AP_TIMEOUT_OFF;
|
|
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
if (config->wkup_en) {
|
|
v |= BM_SAF_TIMEOUT_WKUP_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SAF_TIMEOUT_WKUP_EN;
|
|
}
|
|
|
|
if (config->wdt_en) {
|
|
v |= BM_SAF_TIMEOUT_WDT_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SAF_TIMEOUT_WDT_EN;
|
|
}
|
|
|
|
v &= ~FM_SAF_TIMEOUT_CKGEN_HK;
|
|
v &= ~FM_SAF_TIMEOUT_RSTGEN_HK;
|
|
v &= ~FM_SAF_TIMEOUT_MODE_REQ_TRANS;
|
|
|
|
v |= FV_SAF_TIMEOUT_CKGEN_HK(config->ckgen_hk);
|
|
v |= FV_SAF_TIMEOUT_RSTGEN_HK(config->rstgen_hk);
|
|
v |= FV_SAF_TIMEOUT_MODE_REQ_TRANS(config->mode_req_trans);
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC Saf or AP domain misc.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] domain SDRV_SMC_SAF or SDRV_SMC_AP.
|
|
* @param [in] lp_trans_req LP mode transition request.
|
|
* @param [in] irq_mask_dly Interrupt mask delay.
|
|
* @param [in] ill_trans_wkup_en Swm illegal transfer wakeup enable.
|
|
*/
|
|
status_t sdrv_smc_ctrl_domain_misc_config(sdrv_smc_t *smc_ctrl, sdrv_smc_domain_e domain,
|
|
bool lp_trans_req, uint32_t irq_mask_dly, bool ill_trans_wkup_en)
|
|
{
|
|
uint32_t offset;
|
|
volatile uint32_t v;
|
|
uint32_t base;
|
|
|
|
base = (uint32_t)smc_ctrl->base;
|
|
offset = (domain == SDRV_SMC_SAF) ? SAF_MISC_OFF : AP_MISC_OFF;
|
|
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
v &= ~BM_SAF_MISC_LP_TRANS_REQ;
|
|
v &= ~FM_SAF_MISC_IRQ_MASK_DLY;
|
|
v &= ~BM_SAF_MISC_ILL_TRANS_WKUP_EN;
|
|
|
|
if (lp_trans_req) {
|
|
v |= BM_SAF_MISC_LP_TRANS_REQ;
|
|
}
|
|
|
|
if (ill_trans_wkup_en) {
|
|
v |= BM_SAF_MISC_ILL_TRANS_WKUP_EN;
|
|
}
|
|
|
|
v |= FV_SAF_MISC_IRQ_MASK_DLY(irq_mask_dly);
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief AP domain smc config
|
|
*
|
|
* This function configures whether AP power state has impacts to the
|
|
* SMC state machine.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] ap_bitmap OR'ed value of the following macros:
|
|
* SDRV_SMC_IGNORE_AP
|
|
* SDRV_SMC_AP_LP_ALIGN_SAF
|
|
* SDRV_SMC_AP_WK_ALIGN_SAF
|
|
*/
|
|
status_t sdrv_smc_ctrl_ap_domain_config(sdrv_smc_t *smc_ctrl, uint32_t ap_bitmap)
|
|
{
|
|
uint32_t v;
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
v &= ~BM_AP_GLB_CTL_LP_ALIGN2SAF;
|
|
v &= ~BM_AP_GLB_CTL_WKUP_ALIGN2SAF;
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
|
|
if (ap_bitmap & SDRV_SMC_IGNORE_AP) {
|
|
v = sdrv_smc_readl(base, SOC_GLB_CTL_OFF);
|
|
v |= BM_SOC_GLB_CTL_AP_OFF;
|
|
sdrv_smc_writel(base, SOC_GLB_CTL_OFF, v);
|
|
} else {
|
|
v = sdrv_smc_readl(base, SOC_GLB_CTL_OFF);
|
|
v &= ~BM_SOC_GLB_CTL_AP_OFF;
|
|
sdrv_smc_writel(base, SOC_GLB_CTL_OFF, v);
|
|
|
|
v = sdrv_smc_readl(base, AP_GLB_CTL_OFF);
|
|
|
|
if (ap_bitmap & SDRV_SMC_AP_LP_ALIGN_SAF) {
|
|
v |= BM_AP_GLB_CTL_LP_ALIGN2SAF;
|
|
}
|
|
|
|
if (ap_bitmap & SDRV_SMC_AP_WK_ALIGN_SAF) {
|
|
v |= BM_AP_GLB_CTL_WKUP_ALIGN2SAF;
|
|
}
|
|
|
|
sdrv_smc_writel(base, AP_GLB_CTL_OFF, v);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Configure RC oscillator state in hibernate mode.
|
|
*
|
|
* This function configures on chip 24M RC oscillator state in SMC
|
|
* hibernate mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] enable True to enable the RC oscillator in hibernate mode.
|
|
* False to turn off the oscillator in hibernate mode.
|
|
*/
|
|
status_t sdrv_smc_ctrl_rc24m_hibernate_enable(sdrv_smc_t *smc_ctrl, bool enable)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_HIB_RC_DIS_OFF);
|
|
|
|
if (enable) {
|
|
v &= ~BM_SOC_HIB_RC_DIS_RC_DIS_EN;
|
|
} else {
|
|
v |= BM_SOC_HIB_RC_DIS_RC_DIS_EN;
|
|
}
|
|
|
|
sdrv_smc_writel(base, SOC_HIB_RC_DIS_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set pre-divider number for 24M and 32K clock.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] div_32k pre div number for clk32k.
|
|
* @param [in] div_24m pre div number for clk24m.
|
|
*/
|
|
status_t sdrv_smc_ctrl_pre_divider_config(sdrv_smc_t *smc_ctrl, uint16_t div_32k, uint8_t div_24m)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_PRE_DIV_OFF);
|
|
|
|
v &= ~FM_SOC_PRE_DIV_DIV_NUM_32K;
|
|
v &= ~FM_SOC_PRE_DIV_DIV_NUM_24M;
|
|
|
|
v |= FV_SOC_PRE_DIV_DIV_NUM_32K(div_32k);
|
|
v |= FV_SOC_PRE_DIV_DIV_NUM_24M(div_24m);
|
|
|
|
sdrv_smc_writel(base, SOC_PRE_DIV_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set soc swm timeout setting.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] config soc timeout settings.
|
|
*/
|
|
status_t sdrv_smc_ctrl_soc_swm_timeout_config(sdrv_smc_t *smc_ctrl, sdrv_smc_soc_timeout_t *config)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_SWM_TIMEOUT_OFF);
|
|
|
|
if (config->wkup_en) {
|
|
v |= BM_SOC_SWM_TIMEOUT_WKUP_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_SWM_TIMEOUT_WKUP_EN;
|
|
}
|
|
|
|
if (config->wdt_en) {
|
|
v |= BM_SOC_SWM_TIMEOUT_WDT_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_SWM_TIMEOUT_WDT_EN;
|
|
}
|
|
|
|
v &= ~FM_SOC_SWM_TIMEOUT_PMU_HK;
|
|
v |= FV_SOC_SWM_TIMEOUT_PMU_HK(config->pmu_hk);
|
|
|
|
sdrv_smc_writel(base, SOC_SWM_TIMEOUT_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set soc wakeup control setting.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] config soc wakeup control settings.
|
|
*/
|
|
status_t sdrv_smc_ctrl_soc_wakeup_control_config(sdrv_smc_t *smc_ctrl, sdrv_smc_soc_wakeup_ctrl_t *config)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_WKUP_CTL_OFF);
|
|
|
|
if (config->lp2wkup_tout_wkup_en) {
|
|
v |= BM_SOC_WKUP_CTL_LP2WKUP_TOUT_WKUP_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_WKUP_CTL_LP2WKUP_TOUT_WKUP_EN;
|
|
}
|
|
|
|
if (config->lp2wkup_wdt_en) {
|
|
v |= BM_SOC_WKUP_CTL_LP2WKUP_WDT_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_WKUP_CTL_LP2WKUP_WDT_EN;
|
|
}
|
|
|
|
v &= ~FM_SOC_WKUP_CTL_LP2WKUP_VAL;
|
|
v |= FV_SOC_WKUP_CTL_LP2WKUP_VAL(config->lp2wkup_val);
|
|
|
|
if (config->wkup_wdt_en) {
|
|
v |= BM_SOC_WKUP_CTL_WKUP_WDT_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_WKUP_CTL_WKUP_WDT_EN;
|
|
}
|
|
|
|
if (config->wkup_done_src_sel) {
|
|
v |= BM_SOC_WKUP_CTL_WKUP_DONE_SRC_SEL;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_WKUP_CTL_WKUP_DONE_SRC_SEL;
|
|
}
|
|
|
|
sdrv_smc_writel(base, SOC_WKUP_CTL_OFF, v);
|
|
|
|
v = sdrv_smc_readl(base, SOC_WKUP_TIMEOUT_OFF);
|
|
|
|
v &= ~FM_SOC_WKUP_TIMEOUT_WKUP_ACK;
|
|
v &= ~FM_SOC_WKUP_TIMEOUT_SOC_RUN;
|
|
v |= FV_SOC_WKUP_TIMEOUT_WKUP_ACK(config->wkup_ack_val);
|
|
v |= FV_SOC_WKUP_TIMEOUT_SOC_RUN(config->soc_run_val);
|
|
|
|
sdrv_smc_writel(base, SOC_WKUP_TIMEOUT_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear all core wakeup acknowledge.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
*/
|
|
status_t sdrv_smc_ctrl_clear_core_wakeup_ack(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_WKUP_CTL_OFF);
|
|
v &= ~FM_SOC_WKUP_CTL_SW_WKUP_ACK;
|
|
sdrv_smc_writel(base, SOC_WKUP_CTL_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set core wakeup acknowledge.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] ack bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_ctrl_set_core_wakeup_ack(sdrv_smc_t *smc_ctrl, uint32_t ack)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_WKUP_CTL_OFF);
|
|
v |= FV_SOC_WKUP_CTL_SW_WKUP_ACK(ack);
|
|
sdrv_smc_writel(base, SOC_WKUP_CTL_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set wakeup core irq enable or disable.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] err_wkup smc error wakeup core irq enable
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
* @param [in] bk_wkup smc wakeup core irq enable
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_ctrl_core_wakeup_irq_config(sdrv_smc_t *smc_ctrl, uint32_t err_wkup, uint32_t bk_wkup)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SMC_WKUP_IRQ_OFF);
|
|
v &= ~FM_SMC_WKUP_IRQ_BK_WKUP_EN;
|
|
v &= ~FM_SMC_WKUP_IRQ_ERR_WKUP_EN;
|
|
v |= FV_SMC_WKUP_IRQ_ERR_WKUP_EN(err_wkup);
|
|
v |= FV_SMC_WKUP_IRQ_BK_WKUP_EN(bk_wkup);
|
|
sdrv_smc_writel(base, SMC_WKUP_IRQ_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get wakeup core irq status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @return uint32_t bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
uint32_t sdrv_smc_ctrl_get_core_wakeup_irq_status(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SMC_WKUP_IRQ_OFF);
|
|
|
|
return GFV_SMC_WKUP_IRQ_WKUP_IRQ_STA(v);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear wakeup core irq status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] clr clear status bit.
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_ctrl_clear_core_wakeup_irq_status(sdrv_smc_t *smc_ctrl, uint32_t clr)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SMC_WKUP_IRQ_OFF);
|
|
v |= FV_SMC_WKUP_IRQ_WKUP_CLR(clr);
|
|
sdrv_smc_writel(base, SMC_WKUP_IRQ_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config SOC misc.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] ill_trans_wkup_en Swm illegal transfer wakeup enable.
|
|
*/
|
|
status_t sdrv_smc_ctrl_soc_misc_config(sdrv_smc_t *smc_ctrl, bool ill_trans_wkup_en)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SOC_MISC_OFF);
|
|
|
|
if (ill_trans_wkup_en) {
|
|
v |= BM_SOC_MISC_ILL_TRANS_WKUP_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SOC_MISC_ILL_TRANS_WKUP_EN;
|
|
}
|
|
|
|
sdrv_smc_writel(base, SOC_MISC_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC misc.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] lpbk_force_check_en lpbk force check enable, loopback wdt div number check without req/ack active.
|
|
* @param [in] permission_err_en enable for permission error as apbslverr.
|
|
*/
|
|
status_t sdrv_smc_ctrl_smc_misc_config(sdrv_smc_t *smc_ctrl, bool lpbk_force_check_en, bool permission_err_en)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
|
|
v = sdrv_smc_readl(base, SMC_MISC_OFF);
|
|
|
|
if (lpbk_force_check_en) {
|
|
v |= (0x1U << 1);
|
|
}
|
|
else {
|
|
v &= ~(0x1U << 1);
|
|
}
|
|
|
|
if (permission_err_en) {
|
|
v |= (0x1U << 0);
|
|
}
|
|
else {
|
|
v &= ~(0x1U << 0);
|
|
}
|
|
|
|
sdrv_smc_writel(base, SMC_MISC_OFF, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC handshake with other module.
|
|
*
|
|
* This function trigger SMC handshake with other module, after handshake
|
|
* successful, that module will in low power mode, it will use configuration
|
|
* in low power mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] handshake module to handshake
|
|
* @param [in] smc_swm system work mode, can be following macro:
|
|
* SDRV_SMC_SWM_RUN
|
|
* SDRV_SMC_SWM_SLP
|
|
* SDRV_SMC_SWM_HIB
|
|
* SDRV_SMC_SWM_RTC
|
|
*/
|
|
status_t sdrv_smc_ctrl_trigger_software_handshake(sdrv_smc_t *smc_ctrl, sdrv_smc_handshake_e handshake,
|
|
uint32_t smc_swm)
|
|
{
|
|
volatile uint32_t timeout = SMC_WAIT_TIME;
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t bit_s = handshake * 5;
|
|
uint32_t v = 0;
|
|
|
|
sdrv_smc_writel(base, SMC_SW_SWM_OFF, 0);
|
|
|
|
v |= ((smc_swm & 0x3) << (bit_s + 2));
|
|
v |= (0x3 << bit_s);
|
|
|
|
sdrv_smc_writel(base, SMC_SW_SWM_OFF, v);
|
|
|
|
v = sdrv_smc_readl(base, SMC_SW_SWM_OFF);
|
|
while ((!(v & (0x1 << (bit_s + 4)))) && (0u != timeout)) {
|
|
v = sdrv_smc_readl(base, SMC_SW_SWM_OFF);
|
|
timeout--;
|
|
}
|
|
|
|
sdrv_smc_writel(base, SMC_SW_SWM_OFF, 0);
|
|
|
|
return (0u != timeout) ? SDRV_STATUS_OK : SDRV_STATUS_TIMEOUT;
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC control power switch in run mode.
|
|
*
|
|
* This function can software override power switch value.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] power_down_enable True to turn off the switch,
|
|
* False to turn on the switch.
|
|
*/
|
|
status_t sdrv_smc_ctrl_trigger_software_power_switch(sdrv_smc_t *smc_ctrl,
|
|
sdrv_smc_power_switch_e power_switch, bool power_down_enable)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
volatile uint32_t v;
|
|
uint32_t offset;
|
|
|
|
offset = sdrv_smc_lp_ctl_addr(power_switch);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
if (power_down_enable) {
|
|
v |= BM_SAF_LP_CTL_SW_PD_EN;
|
|
sdrv_smc_writel(base, offset, v);
|
|
v |= BM_SAF_LP_CTL_SW_ISO_EN;
|
|
sdrv_smc_writel(base, offset, v);
|
|
v |= BM_SAF_LP_CTL_SW_PWR_GATE;
|
|
sdrv_smc_writel(base, offset, v);
|
|
} else {
|
|
v &= ~BM_SAF_LP_CTL_SW_PWR_GATE;
|
|
sdrv_smc_writel(base, offset, v);
|
|
v &= ~BM_SAF_LP_CTL_SW_ISO_EN;
|
|
sdrv_smc_writel(base, offset, v);
|
|
v &= ~BM_SAF_LP_CTL_SW_PD_EN;
|
|
sdrv_smc_writel(base, offset, v);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get power switch software power gate status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] power_switch The power switch to read.
|
|
* @return Power gate status.
|
|
*/
|
|
bool sdrv_smc_ctrl_software_power_switch_gate_status(sdrv_smc_t *smc_ctrl, sdrv_smc_power_switch_e power_switch)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t v;
|
|
uint32_t offset;
|
|
|
|
offset = sdrv_smc_lp_ctl_addr(power_switch);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
return (v & BM_SAF_LP_CTL_SW_PWR_GATE) == BM_SAF_LP_CTL_SW_PWR_GATE;
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC control core ram power down in run mode.
|
|
*
|
|
* This function can software override core ram power down value.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] ram RAM type.
|
|
* @param [in] ram_mode RAM mode override by software. Possible values are:
|
|
* SDRV_SMC_CHIP_ENABLE
|
|
* SDRV_SMC_SELECTIVE_PRECHARGE
|
|
* SDRV_SMC_RETENTION_1
|
|
* SDRV_SMC_RETENTION_2
|
|
* SDRV_SMC_POWER_DOWN
|
|
*/
|
|
status_t sdrv_smc_ctrl_trigger_software_ram_lowpower(sdrv_smc_t *smc_ctrl, sdrv_smc_ram_e ram,
|
|
uint32_t ram_mode)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
uint32_t offset;
|
|
uint32_t v;
|
|
|
|
offset = sdrv_smc_ram_lp_ctl_addr(ram);
|
|
v = sdrv_smc_readl(base, offset);
|
|
|
|
v &= ~FM_SAF_RAM_LP_CTL_SW_RAM_LP_SETTING;
|
|
v |= FV_SAF_RAM_LP_CTL_SW_RAM_LP_SETTING(ram_mode);
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
if (ram_mode != SDRV_SMC_CHIP_ENABLE) {
|
|
v |= BM_SAF_RAM_LP_CTL_SW_RAM_PD_EN;
|
|
}
|
|
else {
|
|
v &= ~BM_SAF_RAM_LP_CTL_SW_RAM_PD_EN;
|
|
}
|
|
|
|
sdrv_smc_writel(base, offset, v);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get SWM status monitor register.
|
|
*
|
|
* This function get SOC/SAF/AP system work mode, futhermode,
|
|
* get SAF/AP internal system work mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @return uint32_t
|
|
* 0x1 Run, 0x2 Sleep, 0x4 Hibernate
|
|
* bit[3:0]-SAF_SWM, bit[7:4]-AP_SWM, bit[11:8]-SOC_SWM
|
|
* 0x1 Run, 0x2 LP Proc, 0x4 Run Proc, 0x8 LP
|
|
* bit[20:16]-SAF_INTER_SWM, bit[25:21]-AP_INTER_SWM
|
|
*/
|
|
uint32_t sdrv_smc_ctrl_status_monitor(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
return sdrv_smc_readl(base, SWM_MON_OFF);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear SMC timeout and illegal transition error status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
*/
|
|
status_t sdrv_smc_ctrl_clear_timeout_illegal_status(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
sdrv_smc_writel(base, SMC_TOUT_STA_OFF, 0);
|
|
sdrv_smc_writel(base, SMC_ILL_TRANS_STA_OFF, 0);
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get SMC timeout event monitor status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_ctrl_timeout_status_monitor(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
return sdrv_smc_readl(base, SMC_TOUT_STA_OFF);
|
|
}
|
|
|
|
/**
|
|
* @brief Get SMC illegal transition event monitor status.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_ctrl_illegal_status_monitor(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
return sdrv_smc_readl(base, SMC_ILL_TRANS_STA_OFF);
|
|
}
|
|
|
|
/**
|
|
* @brief Mask all interrupt for SMC.
|
|
*
|
|
* This function mask all interrupt source in low power mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
*/
|
|
status_t sdrv_smc_ctrl_all_wakeup_interrupt_disable(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
for (uint32_t core = 0; core <= SDRV_SMC_CORE_SX1; core++) {
|
|
sdrv_smc_core_irq_mask(base, (sdrv_smc_core_e)core, 0xFFFF);
|
|
|
|
for (uint32_t grp = 0; grp < 8; grp++) {
|
|
sdrv_smc_common_irq_mask(base, (sdrv_smc_core_e)core, grp, 0xFFFFFFFF);
|
|
}
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Enable wakeup interrupt for specific core.
|
|
*
|
|
* This function enable interrupt to wakeup specific core in low power mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_ctrl_wakeup_interrupt_enable(sdrv_smc_t *smc_ctrl, sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (irq_num < (256 + 16)) {
|
|
if (irq_num < 16) {
|
|
sdrv_smc_core_irq_unmask(base, core, 0x1U << irq_num);
|
|
} else {
|
|
irq_num -= 16;
|
|
sdrv_smc_common_irq_unmask(base, core, irq_num / 32,
|
|
0x1U << (irq_num % 32));
|
|
}
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable wakeup interrupt for specific core.
|
|
*
|
|
* This function disable interrupt to wakeup specific core in low power mode.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_ctrl_wakeup_interrupt_disable(sdrv_smc_t *smc_ctrl, sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (irq_num < (256 + 16)) {
|
|
if (irq_num < 16) {
|
|
sdrv_smc_core_irq_mask(base, core, 0x1U << irq_num);
|
|
} else {
|
|
irq_num -= 16;
|
|
sdrv_smc_common_irq_mask(base, core, irq_num / 32,
|
|
0x1U << (irq_num % 32));
|
|
}
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear all interrupt monitor register status.
|
|
*
|
|
* This function will clear all interrupt status in interrupt monitor register.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
*/
|
|
status_t sdrv_smc_ctrl_all_interrupt_monitor_clear(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
for (uint32_t core = 0; core <= SDRV_SMC_CORE_SX1; core++) {
|
|
sdrv_smc_clear_core_interrupt_monitor(base, (sdrv_smc_core_e)core, 0xFFFF);
|
|
}
|
|
|
|
for (uint32_t grp = 0; grp < 8; grp++) {
|
|
sdrv_smc_clear_common_interrupt_monitor(base, grp, 0xFFFFFFFF);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific core interrupt status in interrupt monitor register.
|
|
*
|
|
* This function get the interrupt status for specific core.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
* @return true represents irq occurs, false represents no interrupt occurs.
|
|
*/
|
|
bool sdrv_smc_ctrl_interrupt_monitor_status(sdrv_smc_t *smc_ctrl, sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (irq_num < (256 + 16)) {
|
|
uint32_t v;
|
|
|
|
if (irq_num < 16) {
|
|
v = sdrv_smc_readl(base, CORE_IRQ_MON_OFF(core));
|
|
return !!(v & (0x1U << irq_num));
|
|
} else {
|
|
irq_num -= 16;
|
|
v = sdrv_smc_readl(base, COM_IRQ_MON_0_OFF + (irq_num / 32) * 0x4);
|
|
return !!(v & (0x1U << (irq_num % 32)));
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific core interrupt status in interrupt monitor register.
|
|
*
|
|
* This function clear the interrupt status for specific core.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_ctrl_clear_interrupt_monitor_status(sdrv_smc_t *smc_ctrl, sdrv_smc_core_e core,
|
|
uint32_t irq_num)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (irq_num < (256 + 16)) {
|
|
if (irq_num < 16) {
|
|
sdrv_smc_clear_core_interrupt_monitor(base, core, 0x1U << irq_num);
|
|
} else {
|
|
irq_num -= 16;
|
|
sdrv_smc_clear_common_interrupt_monitor(base, irq_num / 32,
|
|
0x1U << (irq_num % 32));
|
|
}
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief This function record monitor interrupt status when exit WFI.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
*/
|
|
status_t sdrv_smc_ctrl_record_interrupt_monitor_status(sdrv_smc_t *smc_ctrl)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(smc_ctrl->core_irq_status); i++) {
|
|
smc_ctrl->core_irq_status[i] = sdrv_smc_readl(base, CORE_IRQ_MON_OFF(i));
|
|
}
|
|
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(smc_ctrl->group_irq_status); i++) {
|
|
smc_ctrl->group_irq_status[i] = sdrv_smc_readl(base, COM_IRQ_MON_0_OFF + i * 0x4);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC whether handshake with AP domain.
|
|
*
|
|
* This function config SMC ignore AP domain.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance
|
|
* @param [in] enable true represents SMC will handshake with AP,
|
|
* false represents SMC will not handshake with AP.
|
|
*/
|
|
status_t sdrv_smc_ctrl_ap_domain_handshake(sdrv_smc_t *smc_ctrl, bool enable)
|
|
{
|
|
uint32_t base = (uint32_t)smc_ctrl->base;
|
|
|
|
if (enable) {
|
|
sdrv_smc_writel(base, SOC_GLB_CTL_OFF, 0);
|
|
} else {
|
|
sdrv_smc_writel(base, SOC_GLB_CTL_OFF, 1);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Debug for SMC status.
|
|
*
|
|
* This function choose a debug output type, and return the debug value.
|
|
*
|
|
* @param [in] smc_ctrl SMC controller instance.
|
|
* @param [in] dbg_mux mux defined in sdrv_smc_debug_mux_e.
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_ctrl_debug_monitor(sdrv_smc_t *smc_ctrl, sdrv_smc_debug_mux_e dbg_mux)
|
|
{
|
|
uint32_t ret;
|
|
uint32_t base;
|
|
|
|
base = (uint32_t)smc_ctrl->base;
|
|
|
|
sdrv_smc_writel(base, SMC_DBG_SEL_OFF, FV_SMC_DBG_SEL_SEL(dbg_mux));
|
|
|
|
ret = sdrv_smc_readl(base, SMC_DBG_MON_OFF);
|
|
|
|
sdrv_smc_writel(base, SMC_DBG_SEL_OFF, 0x0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Config Safety/AP domain global control setting.
|
|
*
|
|
* @param [in] config global control setting.
|
|
*/
|
|
status_t sdrv_smc_global_control_config(sdrv_smc_global_control_t *config)
|
|
{
|
|
return sdrv_smc_ctrl_global_control_config(&g_default_smc_ctrl, config);
|
|
}
|
|
|
|
/**
|
|
* @brief Set primary core id for a power domain.
|
|
*
|
|
* This function sets primary core id for a domain. Only the primary CPU of
|
|
* one domain can configure SMC registers of this domain.
|
|
*
|
|
* @param [in] domain Safety or AP domain
|
|
* @param [in] id core id
|
|
*/
|
|
status_t sdrv_smc_set_primary_core(sdrv_smc_domain_e domain, sdrv_smc_core_e id)
|
|
{
|
|
return sdrv_smc_ctrl_set_primary_core(&g_default_smc_ctrl, domain, id);
|
|
}
|
|
|
|
/**
|
|
* @brief Set low power mode for specific domain.
|
|
*
|
|
* This function sets the low power mode of specific domain. The domain will
|
|
* enter required low power mode after its primary CPU and all CPUs belongs
|
|
* to this domain enters WFI.
|
|
*
|
|
* @param [in] domain Safety or AP domain
|
|
* @param [in] mode Sleep or hibernate after primary CPU WFI
|
|
*/
|
|
status_t sdrv_smc_set_lowpower_mode(sdrv_smc_domain_e domain, sdrv_smc_mode_e mode)
|
|
{
|
|
return sdrv_smc_ctrl_set_lowpower_mode(&g_default_smc_ctrl, domain, mode);
|
|
}
|
|
|
|
/**
|
|
* @brief Enable or disable low power for specific domain
|
|
*
|
|
* This function enable or disable low power mode for a domain. If enabled, when all
|
|
* CPUs enter wfi, SMC will start low power procedure.
|
|
*
|
|
* @param [in] domain safety or ap domain
|
|
* @param [in] enable true/false
|
|
*/
|
|
status_t sdrv_smc_lowpower_enable(sdrv_smc_domain_e domain, bool enable)
|
|
{
|
|
return sdrv_smc_ctrl_lowpower_enable(&g_default_smc_ctrl, domain, enable);
|
|
}
|
|
|
|
/**
|
|
* @brief Control power switchs in low power mode.
|
|
*
|
|
* This function configures power switch states (on or off) in domain
|
|
* low power mode.
|
|
*
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] mode The SMC low power mode to configure the switch for.
|
|
* @param [in] power_down_enable True to turn off the switch in low power
|
|
* mode. False to leave the power switch on in lower power mode.
|
|
*/
|
|
status_t sdrv_smc_power_switch_config(sdrv_smc_power_switch_e power_switch,
|
|
sdrv_smc_mode_e mode, bool power_down_enable)
|
|
{
|
|
return sdrv_smc_ctrl_power_switch_config(&g_default_smc_ctrl, power_switch, mode, power_down_enable);
|
|
}
|
|
|
|
/**
|
|
* @brief Config Power switch in low power delay control.
|
|
*
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] iso_en isolation enable delay between LP process start to X_iso_en pose.
|
|
* @param [in] pg power gate delay between X_iso_en pose to X_pwr_gate pose.
|
|
* @param [in] po power on delay between RUN process start to X_pwr_gate nege.
|
|
* @param [in] iso_dis isolation disable delay between X_pwr_gate nege to X_iso_en_nege.
|
|
*/
|
|
status_t sdrv_smc_power_switch_delay_config(sdrv_smc_power_switch_e power_switch,
|
|
uint32_t iso_en, uint32_t pg, uint32_t po, uint32_t iso_dis)
|
|
{
|
|
return sdrv_smc_ctrl_power_switch_delay_config(&g_default_smc_ctrl, power_switch, iso_en, pg, po, iso_dis);
|
|
}
|
|
|
|
/**
|
|
* @brief Configure low power modes for core RAM
|
|
*
|
|
* This function configures low power modes for core RAMs, i.e, module interal
|
|
* RAM, CPU cache and TCM, in SMC sleep or hibernate modes.
|
|
*
|
|
* @param [in] ram RAM type.
|
|
* @param [in] mode The SMC low power mode to configure RAM mode for.
|
|
* @param [in] ram_mode RAM mode in SMC low power mode. Possible values are:
|
|
* SDRV_SMC_CHIP_ENABLE
|
|
* SDRV_SMC_SELECTIVE_PRECHARGE
|
|
* SDRV_SMC_RETENTION_1
|
|
* SDRV_SMC_RETENTION_2
|
|
* SDRV_SMC_POWER_DOWN
|
|
*/
|
|
status_t sdrv_smc_ram_lowpower_config(sdrv_smc_ram_e ram, sdrv_smc_mode_e mode,
|
|
uint32_t ram_mode)
|
|
{
|
|
return sdrv_smc_ctrl_ram_lowpower_config(&g_default_smc_ctrl, ram, mode, ram_mode);
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC Saf or AP domain misc.
|
|
*
|
|
* @param [in] domain SDRV_SMC_SAF or SDRV_SMC_AP.
|
|
* @param [in] lp_trans_req LP mode transition request.
|
|
* @param [in] irq_mask_dly Interrupt mask delay.
|
|
* @param [in] ill_trans_wkup_en Swm illegal transfer wakeup enable.
|
|
*/
|
|
status_t sdrv_smc_domain_misc_config(sdrv_smc_domain_e domain,
|
|
bool lp_trans_req, uint32_t irq_mask_dly, bool ill_trans_wkup_en)
|
|
{
|
|
return sdrv_smc_ctrl_domain_misc_config(&g_default_smc_ctrl, domain, lp_trans_req, irq_mask_dly, ill_trans_wkup_en);
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC Saf or AP domain timeout setting.
|
|
*
|
|
* @param [in] domain SDRV_SMC_SAF or SDRV_SMC_AP.
|
|
* @param [in] config domain timeout setting config.
|
|
*/
|
|
status_t sdrv_smc_domain_timeout_config(sdrv_smc_domain_e domain, sdrv_smc_domain_timeout_t *config)
|
|
{
|
|
return sdrv_smc_ctrl_domain_timeout_config(&g_default_smc_ctrl, domain, config);
|
|
}
|
|
|
|
/**
|
|
* @brief AP domain smc config
|
|
*
|
|
* This function configures whether AP power state has impacts to the
|
|
* SMC state machine.
|
|
*
|
|
* @param [in] ap_bitmap OR'ed value of the following macros:
|
|
* SDRV_SMC_IGNORE_AP
|
|
* SDRV_SMC_AP_LP_ALIGN_SAF
|
|
* SDRV_SMC_AP_WK_ALIGN_SAF
|
|
*/
|
|
status_t sdrv_smc_ap_domain_config(uint32_t ap_bitmap)
|
|
{
|
|
return sdrv_smc_ctrl_ap_domain_config(&g_default_smc_ctrl, ap_bitmap);
|
|
}
|
|
|
|
/**
|
|
* @brief Configure RC oscillator state in hibernate mode.
|
|
*
|
|
* This function configures on chip 24M RC oscillator state in SMC
|
|
* hibernate mode.
|
|
*
|
|
* @param [in] enable True to enable the RC oscillator in hibernate mode.
|
|
* False to turn off the oscillator in hibernate mode.
|
|
*/
|
|
status_t sdrv_smc_rc24m_hibernate_enable(bool enable)
|
|
{
|
|
return sdrv_smc_ctrl_rc24m_hibernate_enable(&g_default_smc_ctrl, enable);
|
|
}
|
|
|
|
/**
|
|
* @brief Set pre-divider number for 24M and 32K clock.
|
|
*
|
|
* @param [in] div_32k pre div number for clk32k.
|
|
* @param [in] div_24m pre div number for clk24m.
|
|
*/
|
|
status_t sdrv_smc_pre_divider_config(uint16_t div_32k, uint8_t div_24m)
|
|
{
|
|
return sdrv_smc_ctrl_pre_divider_config(&g_default_smc_ctrl, div_32k, div_24m);
|
|
}
|
|
|
|
/**
|
|
* @brief Set soc swm timeout setting.
|
|
*
|
|
* @param [in] config soc timeout settings.
|
|
*/
|
|
status_t sdrv_smc_soc_swm_timeout_config(sdrv_smc_soc_timeout_t *config)
|
|
{
|
|
return sdrv_smc_ctrl_soc_swm_timeout_config(&g_default_smc_ctrl, config);
|
|
}
|
|
|
|
/**
|
|
* @brief Set soc wakeup control setting.
|
|
*
|
|
* @param [in] config soc wakeup control settings.
|
|
*/
|
|
status_t sdrv_smc_soc_wakeup_control_config(sdrv_smc_soc_wakeup_ctrl_t *config)
|
|
{
|
|
return sdrv_smc_ctrl_soc_wakeup_control_config(&g_default_smc_ctrl, config);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear all core wakeup acknowledge.
|
|
*
|
|
*/
|
|
status_t sdrv_smc_clear_core_wakeup_ack(void)
|
|
{
|
|
return sdrv_smc_ctrl_clear_core_wakeup_ack(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Set core wakeup acknowledge.
|
|
*
|
|
* @param [in] ack bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_set_core_wakeup_ack(uint32_t ack)
|
|
{
|
|
return sdrv_smc_ctrl_set_core_wakeup_ack(&g_default_smc_ctrl, ack);
|
|
}
|
|
|
|
/**
|
|
* @brief Set wakeup core irq enable or disable.
|
|
*
|
|
* @param [in] err_wkup smc error wakeup core irq enable
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
* @param [in] bk_wkup smc wakeup core irq enable
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_core_wakeup_irq_config(uint32_t err_wkup, uint32_t bk_wkup)
|
|
{
|
|
return sdrv_smc_ctrl_core_wakeup_irq_config(&g_default_smc_ctrl, err_wkup, bk_wkup);
|
|
}
|
|
|
|
/**
|
|
* @brief Get wakeup core irq status.
|
|
*
|
|
* @return uint32_t bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
uint32_t sdrv_smc_get_core_wakeup_irq_status(void)
|
|
{
|
|
return sdrv_smc_ctrl_get_core_wakeup_irq_status(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear wakeup core irq status.
|
|
*
|
|
* @param [in] clr clear status bit.
|
|
* bit0:cr5_saf, bit1:cr5_sp0, bit2:cr5_sp1, bit3:cr5_sx0, bit4:cr5_sx1
|
|
*/
|
|
status_t sdrv_smc_clear_core_wakeup_irq_status(uint32_t clr)
|
|
{
|
|
return sdrv_smc_ctrl_clear_core_wakeup_irq_status(&g_default_smc_ctrl, clr);
|
|
}
|
|
|
|
/**
|
|
* @brief Config SOC misc.
|
|
*
|
|
* @param [in] ill_trans_wkup_en Swm illegal transfer wakeup enable.
|
|
*/
|
|
status_t sdrv_smc_soc_misc_config(bool ill_trans_wkup_en)
|
|
{
|
|
return sdrv_smc_ctrl_soc_misc_config(&g_default_smc_ctrl, ill_trans_wkup_en);
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC misc.
|
|
*
|
|
* @param [in] lpbk_force_check_en lpbk force check enable, loopback wdt div number check without req/ack active.
|
|
* @param [in] permission_err_en enable for permission error as apbslverr.
|
|
*/
|
|
status_t sdrv_smc_smc_misc_config(bool lpbk_force_check_en, bool permission_err_en)
|
|
{
|
|
return sdrv_smc_ctrl_smc_misc_config(&g_default_smc_ctrl, lpbk_force_check_en, permission_err_en);
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC handshake with other module.
|
|
*
|
|
* This function trigger SMC handshake with other module, after handshake
|
|
* successful, that module will in low power mode, it will use configuration
|
|
* in low power mode.
|
|
*
|
|
* @param [in] handshake module to handshake
|
|
* @param [in] smc_swm system work mode, can be following macro:
|
|
* SDRV_SMC_SWM_RUN
|
|
* SDRV_SMC_SWM_SLP
|
|
* SDRV_SMC_SWM_HIB
|
|
* SDRV_SMC_SWM_RTC
|
|
*/
|
|
status_t sdrv_smc_trigger_software_handshake(sdrv_smc_handshake_e handshake,
|
|
uint32_t smc_swm)
|
|
{
|
|
return sdrv_smc_ctrl_trigger_software_handshake(&g_default_smc_ctrl, handshake, smc_swm);
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC control power switch in run mode.
|
|
*
|
|
* This function can software override power switch value.
|
|
*
|
|
* @param [in] power_switch The power switch to configure.
|
|
* @param [in] power_down_enable True to turn off the switch,
|
|
* False to turn on the switch.
|
|
*/
|
|
status_t sdrv_smc_trigger_software_power_switch(
|
|
sdrv_smc_power_switch_e power_switch, bool power_down_enable)
|
|
{
|
|
return sdrv_smc_ctrl_trigger_software_power_switch(&g_default_smc_ctrl, power_switch, power_down_enable);
|
|
}
|
|
|
|
/**
|
|
* @brief Get power switch software power gate status.
|
|
*
|
|
* @param [in] power_switch The power switch to read.
|
|
* @return Power gate status.
|
|
*/
|
|
bool sdrv_smc_software_power_switch_gate_status(sdrv_smc_power_switch_e power_switch)
|
|
{
|
|
return sdrv_smc_ctrl_software_power_switch_gate_status(&g_default_smc_ctrl, power_switch);
|
|
}
|
|
|
|
/**
|
|
* @brief Software trigger SMC control core ram power down in run mode.
|
|
*
|
|
* This function can software override core ram power down value.
|
|
*
|
|
* @param [in] ram RAM type.
|
|
* @param [in] ram_mode RAM mode override by software. Possible values are:
|
|
* SDRV_SMC_CHIP_ENABLE
|
|
* SDRV_SMC_SELECTIVE_PRECHARGE
|
|
* SDRV_SMC_RETENTION_1
|
|
* SDRV_SMC_RETENTION_2
|
|
* SDRV_SMC_POWER_DOWN
|
|
*/
|
|
status_t sdrv_smc_trigger_software_ram_lowpower(sdrv_smc_ram_e ram,
|
|
uint32_t ram_mode)
|
|
{
|
|
return sdrv_smc_ctrl_trigger_software_ram_lowpower(&g_default_smc_ctrl, ram, ram_mode);
|
|
}
|
|
|
|
/**
|
|
* @brief Get SWM status monitor register.
|
|
*
|
|
* This function get SOC/SAF/AP system work mode, futhermode,
|
|
* get SAF/AP internal system work mode.
|
|
*
|
|
* @return uint32_t
|
|
* 0x1 Run, 0x2 Sleep, 0x4 Hibernate
|
|
* bit[3:0]-SAF_SWM, bit[7:4]-AP_SWM, bit[11:8]-SOC_SWM
|
|
* 0x1 Run, 0x2 LP Proc, 0x4 Run Proc, 0x8 LP
|
|
* bit[20:16]-SAF_INTER_SWM, bit[25:21]-AP_INTER_SWM
|
|
*/
|
|
uint32_t sdrv_smc_status_monitor(void)
|
|
{
|
|
return sdrv_smc_ctrl_status_monitor(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear SMC timeout and illegal transition error status.
|
|
*/
|
|
status_t sdrv_smc_clear_timeout_illegal_status(void)
|
|
{
|
|
return sdrv_smc_ctrl_clear_timeout_illegal_status(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Get SMC timeout event monitor status.
|
|
*
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_timeout_status_monitor(void)
|
|
{
|
|
return sdrv_smc_ctrl_timeout_status_monitor(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Get SMC illegal transition event monitor status.
|
|
*
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_illegal_status_monitor(void)
|
|
{
|
|
return sdrv_smc_ctrl_illegal_status_monitor(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Mask all interrupt for SMC.
|
|
*
|
|
* This function mask all interrupt source in low power mode.
|
|
*/
|
|
status_t sdrv_smc_all_wakeup_interrupt_disable(void)
|
|
{
|
|
return sdrv_smc_ctrl_all_wakeup_interrupt_disable(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Enable wakeup interrupt for specific core.
|
|
*
|
|
* This function enable interrupt to wakeup specific core in low power mode.
|
|
*
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_wakeup_interrupt_enable(sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
return sdrv_smc_ctrl_wakeup_interrupt_enable(&g_default_smc_ctrl, core, irq_num);
|
|
}
|
|
|
|
/**
|
|
* @brief Disable wakeup interrupt for specific core.
|
|
*
|
|
* This function disable interrupt to wakeup specific core in low power mode.
|
|
*
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_wakeup_interrupt_disable(sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
return sdrv_smc_ctrl_wakeup_interrupt_disable(&g_default_smc_ctrl, core, irq_num);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear all interrupt monitor register status.
|
|
*
|
|
* This function will clear all interrupt status in interrupt monitor register.
|
|
*/
|
|
status_t sdrv_smc_all_interrupt_monitor_clear(void)
|
|
{
|
|
return sdrv_smc_ctrl_all_interrupt_monitor_clear(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific core interrupt status in interrupt monitor register.
|
|
*
|
|
* This function get the interrupt status for specific core.
|
|
*
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
* @return true represents irq occurs, false represents no interrupt occurs.
|
|
*/
|
|
bool sdrv_smc_interrupt_monitor_status(sdrv_smc_core_e core, uint32_t irq_num)
|
|
{
|
|
return sdrv_smc_ctrl_interrupt_monitor_status(&g_default_smc_ctrl, core, irq_num);
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific core interrupt status in interrupt monitor register.
|
|
*
|
|
* This function clear the interrupt status for specific core.
|
|
*
|
|
* @param [in] core core id
|
|
* @param [in] irq_num irq number
|
|
*/
|
|
status_t sdrv_smc_clear_interrupt_monitor_status(sdrv_smc_core_e core,
|
|
uint32_t irq_num)
|
|
{
|
|
return sdrv_smc_ctrl_clear_interrupt_monitor_status(&g_default_smc_ctrl, core, irq_num);
|
|
}
|
|
|
|
/**
|
|
* @brief This function record monitor interrupt status when exit WFI.
|
|
*
|
|
*/
|
|
status_t sdrv_smc_record_interrupt_monitor_status(void)
|
|
{
|
|
return sdrv_smc_ctrl_record_interrupt_monitor_status(&g_default_smc_ctrl);
|
|
}
|
|
|
|
/**
|
|
* @brief Config SMC whether handshake with AP domain.
|
|
*
|
|
* This function config SMC ignore AP domain.
|
|
*
|
|
* @param [in] enable true represents SMC will handshake with AP,
|
|
* false represents SMC will not handshake with AP.
|
|
*/
|
|
status_t sdrv_smc_ap_domain_handshake(bool enable)
|
|
{
|
|
return sdrv_smc_ctrl_ap_domain_handshake(&g_default_smc_ctrl, enable);
|
|
}
|
|
|
|
/**
|
|
* @brief Debug for SMC status.
|
|
*
|
|
* This function choose a debug output type, and return the debug value.
|
|
*
|
|
* @param [in] dbg_mux mux defined in sdrv_smc_debug_mux_e.
|
|
* @return uint32_t
|
|
*/
|
|
uint32_t sdrv_smc_debug_monitor(sdrv_smc_debug_mux_e dbg_mux)
|
|
{
|
|
return sdrv_smc_ctrl_debug_monitor(&g_default_smc_ctrl, dbg_mux);
|
|
}
|