
From: Tien Fong Chee tien.fong.chee@intel.com
set/way instructions "dc cisw" ehich is used by the "dcache flush" command only flushing CPU data caches from L1 -> L2 -> L3 to system memory cache in cache coherency unit, hence this patch enables data flush from system memory cache of CCU into DDR memory.
Signed-off-by: Tien Fong Chee tien.fong.chee@intel.com --- arch/arm/mach-socfpga/Makefile | 1 + arch/arm/mach-socfpga/ccu_ncore3.c | 64 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 arch/arm/mach-socfpga/ccu_ncore3.c
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index e0ada69dd5a..32b3e7a57e2 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -65,6 +65,7 @@ obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o obj-y += wrap_handoff_soc64.o obj-y += wrap_pll_config_soc64.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..18667131eb9 --- /dev/null +++ b/arch/arm/mach-socfpga/ccu_ncore3.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Intel Corporation <www.intel.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; +}