Commit 7eaf040a authored by Varun Wadekar's avatar Varun Wadekar
Browse files

Tegra186: implement quasi power off (SC8) state



This patch adds support for the SC8 system power off state. This
state keeps the sensor subsystem powered ON while powering down
the remaining parts of the SoC. The CPUs and DRAM are powered down
as part of this state entry and perform a cold boot when exiting SC8.

Change-Id: Iba65c661a7fe077a0d696f114bab3b4595e19a0d
Signed-off-by: default avatarVarun Wadekar <vwadekar@nvidia.com>
parent 1f586a71
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#include <t18x_ari.h> #include <t18x_ari.h>
#include <tegra_private.h> #include <tegra_private.h>
extern void prepare_cpu_pwr_dwn(void);
/* state id mask */ /* state id mask */
#define TEGRA186_STATE_ID_MASK 0xF #define TEGRA186_STATE_ID_MASK 0xF
/* constants to get power state's wake time */ /* constants to get power state's wake time */
...@@ -49,6 +51,9 @@ ...@@ -49,6 +51,9 @@
static unsigned int wake_time[PLATFORM_CORE_COUNT]; static unsigned int wake_time[PLATFORM_CORE_COUNT];
/* System power down state */
uint32_t tegra186_system_powerdn_state = TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF;
int32_t tegra_soc_validate_power_state(unsigned int power_state, int32_t tegra_soc_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state) psci_power_state_t *req_state)
{ {
...@@ -162,7 +167,53 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) ...@@ -162,7 +167,53 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
__dead2 void tegra_soc_prepare_system_off(void) __dead2 void tegra_soc_prepare_system_off(void)
{ {
mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); cpu_context_t *ctx = cm_get_context(NON_SECURE);
gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
uint32_t val;
if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) {
/* power off the entire system */
mce_enter_ccplex_state(tegra186_system_powerdn_state);
} else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) {
/* loop until other CPUs power down */
do {
val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED,
TEGRA_ARI_CORE_C7,
MCE_CORE_SLEEP_TIME_INFINITE,
0);
} while (val == 0);
/* Prepare for quasi power down */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 1);
write_ctx_reg(gp_regs, CTX_GPREG_X5, 0);
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1);
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO,
TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC8);
/* Enter quasi power down state */
(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
/* disable GICC */
tegra_gic_cpuif_deactivate();
/* power down core */
prepare_cpu_pwr_dwn();
} else {
ERROR("%s: unsupported power down state (%d)\n", __func__,
tegra186_system_powerdn_state);
}
wfi();
/* wait for the system to power down */
for (;;) {
;
}
} }
int tegra_soc_prepare_system_reset(void) int tegra_soc_prepare_system_reset(void)
......
...@@ -41,10 +41,13 @@ ...@@ -41,10 +41,13 @@
#include <t18x_ari.h> #include <t18x_ari.h>
#include <tegra_private.h> #include <tegra_private.h>
extern uint32_t tegra186_system_powerdn_state;
/******************************************************************************* /*******************************************************************************
* Tegra186 SiP SMCs * Tegra186 SiP SMCs
******************************************************************************/ ******************************************************************************/
#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
#define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE 0x82FFFE01
#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0x82FFFF00 #define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0x82FFFF00
#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0x82FFFF01 #define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0x82FFFF01
#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0x82FFFF02 #define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0x82FFFF02
...@@ -133,6 +136,33 @@ int plat_sip_handler(uint32_t smc_fid, ...@@ -133,6 +136,33 @@ int plat_sip_handler(uint32_t smc_fid,
return 0; return 0;
case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE:
/* clean up the high bits */
x1 = (uint32_t)x1;
/*
* SC8 is a special Tegra186 system state where the CPUs and
* DRAM are powered down but the other subsystem is still
* alive.
*/
if ((x1 == TEGRA_ARI_SYSTEM_SC8) ||
(x1 == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF)) {
tegra186_system_powerdn_state = x1;
flush_dcache_range(
(uintptr_t)&tegra186_system_powerdn_state,
sizeof(tegra186_system_powerdn_state));
} else {
ERROR("%s: unhandled powerdn state (%d)\n", __func__,
(uint32_t)x1);
return -ENOTSUP;
}
return 0;
default: default:
break; break;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment