diff options
author | Alexei Fedorov <Alexei.Fedorov@arm.com> | 2019-04-26 12:07:07 +0100 |
---|---|---|
committer | Soby Mathew <soby.mathew@arm.com> | 2019-05-03 09:27:46 +0000 |
commit | ccd4d475ea8681464df8a3e7f55e902a0707c7e2 (patch) | |
tree | 022f499184ebb6b8dd084ed5fc9cfeca0033b7db /drivers/arm | |
parent | 8917380a1eba4f7a499a4a51b75a0488a683d2c0 (diff) |
SMMUv3: refactor the driver code
This patch is a preparation for the subsequent changes in
SMMUv3 driver. It introduces a new "smmuv3_poll" function
and replaces inline functions for accessing SMMU registers
with mmio read/write operations. Also the infinite loop
for the poll has been replaced with a counter based timeout.
Change-Id: I7a0547beb1509601f253e126b1a7a6ab3b0307e7
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
Diffstat (limited to 'drivers/arm')
-rw-r--r-- | drivers/arm/smmu/smmu_v3.c | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c index 004e81e3..ab2eb2be 100644 --- a/drivers/arm/smmu/smmu_v3.c +++ b/drivers/arm/smmu/smmu_v3.c @@ -1,60 +1,55 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <common/debug.h> #include <cdefs.h> -#include <stdbool.h> - #include <drivers/arm/smmu_v3.h> #include <lib/mmio.h> -static inline uint32_t __init smmuv3_read_s_idr1(uintptr_t base) -{ - return mmio_read_32(base + SMMU_S_IDR1); -} +/* SMMU poll number of retries */ +#define SMMU_POLL_RETRY 1000000 -static inline uint32_t __init smmuv3_read_s_init(uintptr_t base) +static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask, + uint32_t value) { - return mmio_read_32(base + SMMU_S_INIT); -} - -static inline void __init smmuv3_write_s_init(uintptr_t base, uint32_t value) -{ - mmio_write_32(base + SMMU_S_INIT, value); -} - -/* Test for pending invalidate */ -static inline bool smmuv3_inval_pending(uintptr_t base) -{ - return (smmuv3_read_s_init(base) & SMMU_S_INIT_INV_ALL_MASK) != 0U; + uint32_t reg_val, retries = SMMU_POLL_RETRY; + + do { + reg_val = mmio_read_32(smmu_reg); + if ((reg_val & mask) == value) + return 0; + } while (--retries != 0U); + + ERROR("Failed to poll SMMUv3 register @%p\n", (void *)smmu_reg); + ERROR("Read value 0x%x, expected 0x%x\n", reg_val, + value == 0U ? reg_val & ~mask : reg_val | mask); + return -1; } /* * Initialize the SMMU by invalidating all secure caches and TLBs. - * - * Returns 0 on success, and -1 on failure. + * Abort all incoming transactions in order to implement a default + * deny policy on reset */ int __init smmuv3_init(uintptr_t smmu_base) { - uint32_t idr1_reg; - /* * Invalidation of secure caches and TLBs is required only if the SMMU * supports secure state. If not, it's implementation defined as to how * SMMU_S_INIT register is accessed. */ - idr1_reg = smmuv3_read_s_idr1(smmu_base); - if (((idr1_reg >> SMMU_S_IDR1_SECURE_IMPL_SHIFT) & - SMMU_S_IDR1_SECURE_IMPL_MASK) == 0U) { - return -1; - } + if ((mmio_read_32(smmu_base + SMMU_S_IDR1) & + SMMU_S_IDR1_SECURE_IMPL) != 0U) { - /* Initiate invalidation, and wait for it to finish */ - smmuv3_write_s_init(smmu_base, SMMU_S_INIT_INV_ALL_MASK); - while (smmuv3_inval_pending(smmu_base)) - ; + /* Initiate invalidation */ + mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL); + /* Wait for global invalidation operation to finish */ + return smmuv3_poll(smmu_base + SMMU_S_INIT, + SMMU_S_INIT_INV_ALL, 0U); + } return 0; } |