summaryrefslogtreecommitdiff
path: root/plat/nvidia
diff options
context:
space:
mode:
authorVignesh Radhakrishnan <vigneshr@nvidia.com>2017-03-03 10:58:05 -0800
committerVarun Wadekar <vwadekar@nvidia.com>2017-04-13 14:18:42 -0700
commita9e0260c7727a48aef7573503021b9f4fa11e329 (patch)
tree6188566e2a470aa96f66f964c393f3b98b53d048 /plat/nvidia
parent62bfc44b3f78c1ee52a88b2dcb3093ced6a17f7f (diff)
Tegra: Add support for fake system suspend
This patch adds support for fake system suspend (SC7). This is a debug mode, to ensure that a different code path is executed for cases like pre-silicon development, where a full-fledged SC7 is not possible in early stages. This particular patch ensures that, if fake system suspend is enabled (denoted by tegra_fake_system_suspend variable having a non-zero value), instead of calling WFI, a request for a warm reset is made for starting the SC7 exit procedure. This ensures that the code path of kernel->ATF and back to kernel is executed without depending on other components involved in SC7 code path. Additionally, this patch also adds support for SMC call from kernel, enabling fake system suspend mode. Signed-off-by: Vignesh Radhakrishnan <vigneshr@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'plat/nvidia')
-rw-r--r--plat/nvidia/tegra/common/tegra_pm.c33
-rw-r--r--plat/nvidia/tegra/common/tegra_sip_calls.c30
-rw-r--r--plat/nvidia/tegra/include/tegra_private.h2
3 files changed, 60 insertions, 5 deletions
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 5376d523..d6329268 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -49,6 +49,14 @@ extern uint64_t tegra_sec_entry_point;
extern uint64_t tegra_console_base;
/*
+ * tegra_fake_system_suspend acts as a boolean var controlling whether
+ * we are going to take fake system suspend code or normal system suspend code
+ * path. This variable is set inside the sip call handlers,when the kernel
+ * requests a SIP call to set the suspend debug flags.
+ */
+uint8_t tegra_fake_system_suspend;
+
+/*
* The following platform setup functions are weakly defined. They
* provide typical implementations that will be overridden by a SoC.
*/
@@ -182,14 +190,31 @@ void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
__dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t
*target_state)
{
+ uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+ uint64_t rmr_el3 = 0;
+
/* call the chip's power down handler */
tegra_soc_pwr_domain_power_down_wfi(target_state);
- /* enter power down state */
- wfi();
+ /*
+ * If we are in fake system suspend mode, ensure we start doing
+ * procedures that help in looping back towards system suspend exit
+ * instead of calling WFI by requesting a warm reset.
+ * Else, just call WFI to enter low power state.
+ */
+ if ((tegra_fake_system_suspend != 0U) &&
+ (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) {
+
+ /* warm reboot */
+ rmr_el3 = read_rmr_el3();
+ write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU);
+
+ } else {
+ /* enter power down state */
+ wfi();
+ }
/* we can never reach here */
- ERROR("%s: operation not handled.\n", __func__);
panic();
}
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index 4dd43532..b01dcb0c 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -37,6 +37,7 @@
#include <memctrl.h>
#include <runtime_svc.h>
#include <tegra_private.h>
+#include <tegra_platform.h>
/*******************************************************************************
* Common Tegra SiP SMCs
@@ -44,6 +45,13 @@
#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
#define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005
#define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006
+#define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND 0xC2000007
+
+/*******************************************************************************
+ * Fake system suspend mode control var
+ ******************************************************************************/
+extern uint8_t tegra_fake_system_suspend;
+
/*******************************************************************************
* SoC specific SiP handler
@@ -144,6 +152,26 @@ uint64_t tegra_sip_handler(uint32_t smc_fid,
SMC_RET0(handle);
break;
+ case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND:
+ /*
+ * System suspend fake mode is set if we are on VDK and we make
+ * a debug SIP call. This mode ensures that we excercise debug
+ * path instead of the regular code path to suit the pre-silicon
+ * platform needs. These include replacing the call to WFI by
+ * a warm reset request.
+ */
+ if (tegra_platform_is_emulation() != 0U) {
+
+ tegra_fake_system_suspend = 1;
+ SMC_RET1(handle, 0);
+ }
+
+ /*
+ * We return to the external world as if this SIP is not
+ * implemented in case, we are not running on VDK.
+ */
+ break;
+
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index 39006f6f..edd1f65d 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -103,6 +103,8 @@ void tegra_security_setup(void);
void tegra_security_setup_videomem(uintptr_t base, uint64_t size);
/* Declarations for tegra_pm.c */
+extern uint8_t tegra_fake_system_suspend;
+
void tegra_pm_system_suspend_entry(void);
void tegra_pm_system_suspend_exit(void);
int tegra_system_suspended(void);