From 8cc972421faf02cfdd4fea1a21fabe6e9d96e2a3 Mon Sep 17 00:00:00 2001 From: Olivier Deprez Date: Tue, 7 Jan 2025 17:27:05 +0100 Subject: [PATCH] fix(smmu): set root port CR0 GPCEN before ACCESSEN In the SMMU root port programming model, changing both SMMU_ROOT_CR0.GPCEN and ACCESSEN bits in the same MMIO write operation is permitted by the architecture but left to the SMMU IP implementation to determine the order of completing one or the other operation. Enforce more determinism by setting CR0.GPCEN, wait for CR0ACK.GPCEN completion, then setting CR0.ACCESSEN and wait for CR0ACK.ACCESSEN completion. Signed-off-by: Olivier Deprez Change-Id: I36ba5fbc13d06c6243226008d18a2d57477b0d28 --- drivers/arm/smmu/smmu_v3.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c index ef04c4d6c..adca4fd4b 100644 --- a/drivers/arm/smmu/smmu_v3.c +++ b/drivers/arm/smmu/smmu_v3.c @@ -124,22 +124,35 @@ int __init smmuv3_init(uintptr_t smmu_base) gptbr_el3 << 12); /* - * ACCESSEN=1: SMMU- and client-originated accesses are - * not terminated by this mechanism. * GPCEN=1: All clients and SMMU-originated accesses, * except GPT-walks, are subject to GPC. + * + * It is recommended to set GPCEN and wait for completion + * prior to setting ACCESSEN. + */ + mmio_setbits_32(smmu_base + SMMU_ROOT_CR0, + SMMU_ROOT_CR0_GPCEN); + + /* Poll for GPCEN ack bit. */ + if (smmuv3_poll(smmu_base + SMMU_ROOT_CR0ACK, + SMMU_ROOT_CR0_GPCEN, + SMMU_ROOT_CR0_GPCEN) != 0) { + WARN("Failed enabling SMMU GPC.\n"); + } + + /* + * ACCESSEN=1: SMMU- and client-originated accesses are + * not terminated by this mechanism. */ mmio_setbits_32(smmu_base + SMMU_ROOT_CR0, SMMU_ROOT_CR0_GPCEN | SMMU_ROOT_CR0_ACCESSEN); - /* Poll for ACCESSEN and GPCEN ack bits. */ + /* Poll for ACCESSEN ack bit. */ if (smmuv3_poll(smmu_base + SMMU_ROOT_CR0ACK, - SMMU_ROOT_CR0_GPCEN | SMMU_ROOT_CR0_ACCESSEN, - SMMU_ROOT_CR0_GPCEN | SMMU_ROOT_CR0_ACCESSEN) != 0) { - WARN("Failed enabling SMMU GPC.\n"); + WARN("Failed enabling SMMU ACCESS.\n"); /* * Do not return in error, but fall back to