From 75516c3eb021e91e37e4d3115a0bbab143ddd2ff Mon Sep 17 00:00:00 2001
From: Steven Kao <skao@nvidia.com>
Date: Wed, 14 Jun 2017 14:02:23 +0800
Subject: [PATCH] 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>
---
 .../tegra/common/aarch64/tegra_helpers.S      | 34 +++++++++++++------
 plat/nvidia/tegra/include/tegra_private.h     | 10 ++++++
 .../tegra/soc/t132/plat_psci_handlers.c       | 10 ++++--
 plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c  |  5 ++-
 4 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 2bf9a225d..4bf1a9df4 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 ff1bd50d9..c7636f61d 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -22,6 +22,16 @@
 #define TEGRA_DRAM_BASE		ULL(0x80000000)
 #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
  ******************************************************************************/
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
index 7226120b0..bd3f46fcc 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_on_finish(const psci_power_state_t *target_state)
 
 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 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 	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 44ee8fbf6..1e41cb785 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 @@ int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
 		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;
-- 
GitLab