Tegra: read-modify-write ACTLR_ELx registers
This patch changes direct writes to ACTLR_ELx registers to use
read-modify-write instead.
Change-Id: I6e0eaa6974583f3035cb3724088f3f1c849da229
Signed-off-by: Steven Kao <skao@nvidia.com>
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 2bf9a22..4bf1a9d 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -18,16 +18,21 @@
/*******************************************************************************
* Implementation defined ACTLR_EL3 bit definitions
******************************************************************************/
-#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
-#define ACTLR_EL3_L2ECTLR_BIT (1 << 5)
-#define ACTLR_EL3_L2CTLR_BIT (1 << 4)
-#define ACTLR_EL3_CPUECTLR_BIT (1 << 1)
-#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+#define ACTLR_EL3_L2ACTLR_BIT (U(1) << 6)
+#define ACTLR_EL3_L2ECTLR_BIT (U(1) << 5)
+#define ACTLR_EL3_L2CTLR_BIT (U(1) << 4)
+#define ACTLR_EL3_CPUECTLR_BIT (U(1) << 1)
+#define ACTLR_EL3_CPUACTLR_BIT (U(1) << 0)
+#define ACTLR_EL3_ENABLE_ALL_MASK (ACTLR_EL3_L2ACTLR_BIT | \
+ ACTLR_EL3_L2ECTLR_BIT | \
+ ACTLR_EL3_L2CTLR_BIT | \
+ ACTLR_EL3_CPUECTLR_BIT | \
+ ACTLR_EL3_CPUACTLR_BIT)
#define ACTLR_EL3_ENABLE_ALL_ACCESS (ACTLR_EL3_L2ACTLR_BIT | \
- ACTLR_EL3_L2ECTLR_BIT | \
- ACTLR_EL3_L2CTLR_BIT | \
- ACTLR_EL3_CPUECTLR_BIT | \
- ACTLR_EL3_CPUACTLR_BIT)
+ ACTLR_EL3_L2ECTLR_BIT | \
+ ACTLR_EL3_L2CTLR_BIT | \
+ ACTLR_EL3_CPUECTLR_BIT | \
+ ACTLR_EL3_CPUACTLR_BIT)
/* Global functions */
.globl plat_is_my_cpu_primary
@@ -87,8 +92,17 @@
* Enable L2 and CPU ECTLR RW access from non-secure world
* -------------------------------------------------------
*/
- mov x0, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ mrs x0, actlr_el3
+ mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
+ bic x0, x0, x1
+ mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
msr actlr_el3, x0
+ mrs x0, actlr_el2
+ mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
+ bic x0, x0, x1
+ mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
msr actlr_el2, x0
isb
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index ff1bd50..c7636f6 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -23,6 +23,16 @@
#define TEGRA_DRAM_END ULL(0x27FFFFFFF)
/*******************************************************************************
+ * Implementation defined ACTLR_EL1 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL1_PMSTATE_MASK (ULL(0xF) << 0)
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL2 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL2_PMSTATE_MASK (ULL(0xF) << 0)
+
+/*******************************************************************************
* Struct for parameters received from BL2
******************************************************************************/
typedef struct plat_params_from_bl2 {
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
index 7226120..bd3f46f 100644
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
@@ -98,19 +98,24 @@
int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
+ uint64_t val;
+
tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
/* Disable DCO operations */
denver_disable_dco();
/* Power down the CPU */
- write_actlr_el1(DENVER_CPU_STATE_POWER_DOWN);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | DENVER_CPU_STATE_POWER_DOWN);
return PSCI_E_SUCCESS;
}
int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
+ uint64_t val;
+
#if ENABLE_ASSERTIONS
int cpu = read_mpidr() & MPIDR_CPU_MASK;
@@ -128,7 +133,8 @@
denver_disable_dco();
/* Program the suspend state ID */
- write_actlr_el1(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
return PSCI_E_SUCCESS;
}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
index 44ee8fb..1e41cb7 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
@@ -14,10 +14,12 @@
#include <mce_private.h>
#include <t18x_ari.h>
+#include <tegra_private.h>
int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
{
int32_t ret = 0;
+ uint64_t val = 0ULL;
(void)ari_base;
@@ -31,7 +33,8 @@
nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
/* set the core cstate */
- write_actlr_el1(state);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | (uint64_t)state);
}
return ret;