diff options
author | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-05-26 14:15:40 +0100 |
---|---|---|
committer | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2017-08-01 14:33:47 +0100 |
commit | 1154586b71c1e0453076a50638f00d4499eb22b0 (patch) | |
tree | 46e9875d39a00bedbb07f575d5e9a28e707a6460 /drivers/arm | |
parent | e33fd44548e41bcfa7bf697a36653e19e410e6c6 (diff) |
Add SMMUv3 driver
The driver has only one API: to initialize an SMMUv3 device. This
operates on a device that implements secure state, by invalidating
secure caches and TLBs.
Change-Id: Ief32800419ddf0f1fe38c8f0da8f5ba75c72c826
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Diffstat (limited to 'drivers/arm')
-rw-r--r-- | drivers/arm/smmu/smmu_v3.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c new file mode 100644 index 00000000..cfe8c2a4 --- /dev/null +++ b/drivers/arm/smmu/smmu_v3.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <mmio.h> +#include <smmu_v3.h> + +/* Test for pending invalidate */ +#define INVAL_PENDING(base) \ + smmuv3_read_s_init(base) & SMMU_S_INIT_INV_ALL_MASK + +static inline uint32_t smmuv3_read_s_idr1(uintptr_t base) +{ + return mmio_read_32(base + SMMU_S_IDR1); +} + +static inline uint32_t smmuv3_read_s_init(uintptr_t base) +{ + return mmio_read_32(base + SMMU_S_INIT); +} + +static inline void smmuv3_write_s_init(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SMMU_S_INIT, value); +} + +/* + * Initialize the SMMU by invalidating all secure caches and TLBs. + * + * Returns 0 on success, and -1 on failure. + */ +int 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)) { + return -1; + } + + /* Initiate invalidation, and wait for it to finish */ + smmuv3_write_s_init(smmu_base, SMMU_S_INIT_INV_ALL_MASK); + while (INVAL_PENDING(smmu_base)) + ; + + return 0; +} |