diff options
-rw-r--r-- | arch/arm/mach-socfpga/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/ccu_ncore3.c | 64 |
2 files changed, 65 insertions, 0 deletions
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 7e37ccae0fb..cccba711305 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -65,6 +65,7 @@ obj-y += reset_manager_s10.o obj-y += wrap_handoff_soc64.o obj-y += wrap_pll_config_soc64.o obj-y += altera-sysmgr.o +obj-y += ccu_ncore3.o endif ifdef CONFIG_TARGET_SOCFPGA_N5X diff --git a/arch/arm/mach-socfpga/ccu_ncore3.c b/arch/arm/mach-socfpga/ccu_ncore3.c new file mode 100644 index 00000000000..a399aedcd10 --- /dev/null +++ b/arch/arm/mach-socfpga/ccu_ncore3.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2025 Altera Corporation <www.altera.com> + * + */ +#include <wait_bit.h> +#include <asm/arch/base_addr_soc64.h> +#include <linux/bitfield.h> + +#define CCU_DMI0_DMIUSMCTCR SOCFPGA_CCU_ADDRESS + 0x7300 +#define CCU_DMI0_DMIUSMCMCR SOCFPGA_CCU_ADDRESS + 0x7340 +#define CCU_DMI0_DMIUSMCMAR SOCFPGA_CCU_ADDRESS + 0x7344 +#define CCU_DMI0_DMIUSMCMCR_MNTOP GENMASK(3, 0) +#define MAX_DISTRIBUTED_MEM_INTERFACE 2 +#define FLUSH_ALL_ENTRIES 0x4 +#define CCU_DMI0_DMIUSMCMCR_ARRAY_ID GENMASK(21, 16) +#define ARRAY_ID_TAG 0x0 +#define ARRAY_ID_DATA 0x1 +#define CACHE_OPERATION_DONE BIT(0) +#define TIMEOUT_200MS 200 + +int __asm_flush_l3_dcache(void) +{ + int i; + int ret = 0; + + /* Flushing all entries in CCU system memory cache */ + for (i = 0; i < MAX_DISTRIBUTED_MEM_INTERFACE; i++) { + /* + * Skipping if the system memory cache is not enabled for + * particular DMI + */ + if (!readl((uintptr_t)(CCU_DMI0_DMIUSMCTCR + (i * 0x1000)))) + continue; + + writel(FIELD_PREP(CCU_DMI0_DMIUSMCMCR_MNTOP, FLUSH_ALL_ENTRIES) | + FIELD_PREP(CCU_DMI0_DMIUSMCMCR_ARRAY_ID, ARRAY_ID_TAG), + (uintptr_t)(CCU_DMI0_DMIUSMCMCR + (i * 0x1000))); + + /* Wait for cache maintenance operation done */ + ret = wait_for_bit_le32((const void *)(uintptr_t)(CCU_DMI0_DMIUSMCMAR + + (i * 0x1000)), CACHE_OPERATION_DONE, false, TIMEOUT_200MS, + false); + if (ret) { + debug("%s: Timeout while waiting for flushing tag in DMI%d done\n", + __func__, i); + return ret; + } + + writel(FIELD_PREP(CCU_DMI0_DMIUSMCMCR_MNTOP, FLUSH_ALL_ENTRIES) | + FIELD_PREP(CCU_DMI0_DMIUSMCMCR_ARRAY_ID, ARRAY_ID_DATA), + (uintptr_t)(CCU_DMI0_DMIUSMCMCR + (i * 0x1000))); + + /* Wait for cache maintenance operation done */ + ret = wait_for_bit_le32((const void *)(uintptr_t)(CCU_DMI0_DMIUSMCMAR + + (i * 0x1000)), CACHE_OPERATION_DONE, false, TIMEOUT_200MS, + false); + if (ret) + debug("%s: Timeout waiting for flushing data in DMI%d done\n", + __func__, i); + } + + return ret; +} |