summaryrefslogtreecommitdiff
path: root/plat/nvidia
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2017-04-21 17:43:19 +0100
committerGitHub <noreply@github.com>2017-04-21 17:43:19 +0100
commit3fb340a2b45740d7233490ac9801d530403529e7 (patch)
treefb97e2afcbefdb1629664498e402795a454dac36 /plat/nvidia
parent484acce376e63b228befb06f3d10d0caf7067091 (diff)
parent63ac1a2a791a1eccebe508ec8d6b88888f075a52 (diff)
Merge pull request #912 from vwadekar/tegra-smmu-ctx-save-robust
Tegra: smmu: make the context save sequence robust
Diffstat (limited to 'plat/nvidia')
-rw-r--r--plat/nvidia/tegra/common/drivers/smmu/smmu.c22
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_psci_handlers.c12
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_trampoline.S2
3 files changed, 25 insertions, 11 deletions
diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
index e8b0d0b4..a985532c 100644
--- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c
+++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
@@ -87,7 +87,7 @@ static void tegra_smmu_write_32(uint32_t smmu_id,
*/
void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
{
- uint32_t i;
+ uint32_t i, num_entries = 0;
smmu_regs_t *smmu_ctx_regs;
#if DEBUG
plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
@@ -110,13 +110,29 @@ void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
smmu_ctx_regs = plat_get_smmu_ctx();
assert(smmu_ctx_regs);
+ /*
+ * smmu_ctx_regs[0].val contains the size of the context table minus
+ * the last entry. Sanity check the table size before we start with
+ * the context save operation.
+ */
+ while (smmu_ctx_regs[num_entries].val != 0xFFFFFFFFU) {
+ num_entries++;
+ }
+
+ /* panic if the sizes do not match */
+ if (num_entries != smmu_ctx_regs[0].val)
+ panic();
+
/* save SMMU register values */
- for (i = 1; i < smmu_ctx_regs[0].val; i++)
+ for (i = 1; i < num_entries; i++)
smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
+ /* increment by 1 to take care of the last entry */
+ num_entries++;
+
/* Save SMMU config settings */
memcpy16((void *)(uintptr_t)smmu_ctx_addr, (void *)smmu_ctx_regs,
- sizeof(smmu_regs_t));
+ (sizeof(smmu_regs_t) * num_entries));
/* save the SMMU table address */
mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_LO,
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 66a5999a..9790b817 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -46,11 +46,8 @@
extern void prepare_cpu_pwr_dwn(void);
extern void tegra186_cpu_reset_handler(void);
-extern uint32_t __tegra186_cpu_reset_handler_data,
- __tegra186_cpu_reset_handler_end;
-
-/* TZDRAM offset for saving SMMU context */
-#define TEGRA186_SMMU_CTX_OFFSET 16
+extern uint32_t __tegra186_cpu_reset_handler_end,
+ __tegra186_smmu_context;
/* state id mask */
#define TEGRA186_STATE_ID_MASK 0xF
@@ -151,9 +148,8 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
/* save SMMU context to TZDRAM */
smmu_ctx_base = params_from_bl2->tzdram_base +
- ((uintptr_t)&__tegra186_cpu_reset_handler_data -
- (uintptr_t)tegra186_cpu_reset_handler) +
- TEGRA186_SMMU_CTX_OFFSET;
+ ((uintptr_t)&__tegra186_smmu_context -
+ (uintptr_t)tegra186_cpu_reset_handler);
tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
/* Prepare for system suspend */
diff --git a/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
index 21393d9b..ba696f39 100644
--- a/plat/nvidia/tegra/soc/t186/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
@@ -94,6 +94,8 @@ endfunc tegra186_cpu_reset_handler
__tegra186_cpu_reset_handler_data:
.quad tegra_secure_entrypoint
.quad __BL31_END__ - BL31_BASE
+ .globl __tegra186_smmu_context
+__tegra186_smmu_context:
.rept TEGRA186_SMMU_CTX_SIZE
.quad 0
.endr