diff options
author | andy.hu <andy.hu@starfivetech.com> | 2024-01-11 13:52:28 +0300 |
---|---|---|
committer | andy.hu <andy.hu@starfivetech.com> | 2024-01-11 13:52:28 +0300 |
commit | 9b2efce7988d0e202f00c1efd9c305ca63ccf85c (patch) | |
tree | 0998b48718291357dc95314bf19a80e138935e70 | |
parent | fa86f41550a08f2c087b488fdedba4f64e0a3d16 (diff) | |
parent | e729b64bb83be8fc0d03f81673278f2d78fa4748 (diff) | |
download | linux-9b2efce7988d0e202f00c1efd9c305ca63ccf85c.tar.xz |
Merge branch 'CR_8959_linux6.1_Implement_new_flush_L2_cache_method_Windsome.Zeng' into 'jh7110-6.1.y-devel'
CR 8959 Implement a new method to flush the entire L2 cache
See merge request sdk/linux!1007
-rwxr-xr-x | arch/riscv/boot/dts/starfive/jh7110.dtsi | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/verisilicon/vs_dc.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/verisilicon/vs_dc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/verisilicon/vs_plane.h | 3 | ||||
-rw-r--r-- | drivers/soc/sifive/sifive_ccache.c | 103 | ||||
-rw-r--r-- | include/soc/sifive/sifive_ccache.h | 1 |
6 files changed, 98 insertions, 22 deletions
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi index 19928efe3b1a..845d34aa373c 100755 --- a/arch/riscv/boot/dts/starfive/jh7110.dtsi +++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi @@ -281,7 +281,7 @@ cachectrl: cache-controller@2010000 { compatible = "sifive,fu740-c000-ccache", "cache"; - reg = <0x0 0x2010000 0x0 0x4000 0x0 0x8000000 0x0 0x2000000>; + reg = <0x0 0x2010000 0x0 0x4000 0x0 0x8000000 0x0 0x2000000 0x0 0xa000000 0x0 0x2000000>; reg-names = "control", "sideband"; interrupts = <1 3 4 2>; cache-block-size = <64>; diff --git a/drivers/gpu/drm/verisilicon/vs_dc.c b/drivers/gpu/drm/verisilicon/vs_dc.c index 2fce762256c9..bbc64584a324 100644 --- a/drivers/gpu/drm/verisilicon/vs_dc.c +++ b/drivers/gpu/drm/verisilicon/vs_dc.c @@ -959,12 +959,7 @@ static void update_fb(struct vs_plane *plane, u8 display_id, update_swizzle(drm_fb->format->format, fb); update_watermark(plane_state->watermark, fb); - sifive_l2_flush64_range(fb->y_address, fb->height * fb->y_stride); - if (fb->u_address) - sifive_l2_flush64_range(fb->u_address, fb->height * fb->u_stride); - if (fb->v_address) - sifive_l2_flush64_range(fb->v_address, fb->height * fb->v_stride); - + sifive_ccache_flush_entire(); plane_state->status.tile_mode = fb->tile_mode; } @@ -1288,7 +1283,7 @@ static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, cursor.enable = true; if (cursor.address != pre_address) { - sifive_l2_flush64_range(cursor.address, ((cursor.size == CURSOR_SIZE_32X32) ? + sifive_ccache_flush_range(cursor.address, ((cursor.size == CURSOR_SIZE_32X32) ? CURSOR_MEM_SIZE_32X32 : CURSOR_MEM_SIZE_64X64)); pre_address = cursor.address; } diff --git a/drivers/gpu/drm/verisilicon/vs_dc.h b/drivers/gpu/drm/verisilicon/vs_dc.h index d45c3dae4e91..8e18bd7e7f5b 100644 --- a/drivers/gpu/drm/verisilicon/vs_dc.h +++ b/drivers/gpu/drm/verisilicon/vs_dc.h @@ -8,6 +8,7 @@ #include <linux/version.h> #include <linux/mm_types.h> +#include <soc/sifive/sifive_ccache.h> #include <drm/drm_modes.h> #if KERNEL_VERSION(5, 5, 0) > LINUX_VERSION_CODE @@ -79,7 +80,6 @@ struct vs_dc { }; extern struct platform_driver dc_platform_driver; -extern void sifive_l2_flush64_range(unsigned long start, unsigned long len); void vs_dc_update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane, struct drm_plane *drm_plane, diff --git a/drivers/gpu/drm/verisilicon/vs_plane.h b/drivers/gpu/drm/verisilicon/vs_plane.h index f613c1b2c3a3..38873d2cfadf 100644 --- a/drivers/gpu/drm/verisilicon/vs_plane.h +++ b/drivers/gpu/drm/verisilicon/vs_plane.h @@ -8,6 +8,7 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_fourcc.h> +#include <soc/sifive/sifive_ccache.h> #include "vs_type.h" #include "vs_fb.h" @@ -76,6 +77,4 @@ to_vs_plane_state(struct drm_plane_state *state) return container_of(state, struct vs_plane_state, base); } -extern void sifive_l2_flush64_range(unsigned long start, unsigned long len); - #endif /* __VS_PLANE_H__ */ diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c index 31e9977d24ba..4a289fd548ab 100644 --- a/drivers/soc/sifive/sifive_ccache.c +++ b/drivers/soc/sifive/sifive_ccache.c @@ -46,17 +46,29 @@ #define SIFIVE_CCACHE_FLUSH64 0x200 #define SIFIVE_CCACHE_FLUSH32 0x240 +#define SIFIVE_L2_WAYMASK_BASE 0x800 +#define SIFIVE_L2_MAX_MASTER_ID 32 + #define SIFIVE_CCACHE_WAYENABLE 0x08 #define SIFIVE_CCACHE_ECCINJECTERR 0x40 #define SIFIVE_CCACHE_MAX_ECCINTR 4 -#define SIFIVE_CCACHE_LINE_SIZE 64 +#define SIFIVE_L2_DEFAULT_WAY_MASK 0xffff static void __iomem *ccache_base; static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR]; static struct riscv_cacheinfo_ops ccache_cache_ops; static int level; +static u32 flush_line_len; +static u32 cache_size; +static u32 cache_size_per_way; +static u32 cache_max_line; +static u32 cache_ways_per_bank; +static u32 cache_size_per_block; +static u32 cache_max_enabled_way; +static void __iomem *l2_zero_device_base; + enum { DIR_CORR = 0, DATA_CORR, @@ -101,14 +113,25 @@ static void ccache_config_read(void) u32 cfg; cfg = readl(ccache_base + SIFIVE_CCACHE_CONFIG); - pr_info("%llu banks, %llu ways, sets/bank=%llu, bytes/block=%llu\n", + cache_ways_per_bank = FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS_MASK, cfg); + cache_size_per_block = BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_BLKS_MASK, cfg)); + flush_line_len = cache_size_per_block; + cache_size_per_way = cache_size / cache_ways_per_bank; + cache_max_line = cache_size_per_way / flush_line_len - 1; + + pr_info("%llu banks, %u ways, sets/bank=%llu, bytes/block=%u\n", FIELD_GET(SIFIVE_CCACHE_CONFIG_BANK_MASK, cfg), - FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS_MASK, cfg), + cache_ways_per_bank, BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_SETS_MASK, cfg)), - BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_BLKS_MASK, cfg))); + cache_size_per_block); - cfg = readl(ccache_base + SIFIVE_CCACHE_WAYENABLE); - pr_info("Index of the largest way enabled: %u\n", cfg); + pr_info("max_line=%u, %u bytes/line, %u bytes/way\n", + cache_max_line, + flush_line_len, + cache_size_per_way); + + cache_max_enabled_way = readl(ccache_base + SIFIVE_CCACHE_WAYENABLE); + pr_info("Index of the largest way enabled: %u\n", cache_max_enabled_way); } static const struct of_device_id sifive_ccache_ids[] = { @@ -136,6 +159,52 @@ EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier); static phys_addr_t uncached_offset; DEFINE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key); +static void sifive_ccache_flush_range_by_way_index(u32 start_index, u32 end_index) +{ + u32 way, master; + u32 index; + u64 way_mask; + void __iomem *line_addr, *addr; + + mb(); + way_mask = 1; + line_addr = l2_zero_device_base + start_index * flush_line_len; + for (way = 0; way <= cache_max_enabled_way; ++way) { + addr = ccache_base + SIFIVE_L2_WAYMASK_BASE; + for (master = 0; master < SIFIVE_L2_MAX_MASTER_ID; ++master) { + writeq_relaxed(way_mask, addr); + addr += 8; + } + + addr = line_addr; + for (index = start_index; index <= end_index; ++index) { +#ifdef CONFIG_32BIT + writel_relaxed(0, addr); +#else + writeq_relaxed(0, addr); +#endif + addr += flush_line_len; + } + + way_mask <<= 1; + line_addr += cache_size_per_way; + mb(); + } + + addr = ccache_base + SIFIVE_L2_WAYMASK_BASE; + for (master = 0; master < SIFIVE_L2_MAX_MASTER_ID; ++master) { + writeq_relaxed(SIFIVE_L2_DEFAULT_WAY_MASK, addr); + addr += 8; + } + mb(); +} + +void sifive_ccache_flush_entire(void) +{ + sifive_ccache_flush_range_by_way_index(0, cache_max_line); +} +EXPORT_SYMBOL_GPL(sifive_ccache_flush_entire); + void sifive_ccache_flush_range(phys_addr_t start, size_t len) { phys_addr_t end = start + len; @@ -145,8 +214,8 @@ void sifive_ccache_flush_range(phys_addr_t start, size_t len) return; mb(); - for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end; - line += SIFIVE_CCACHE_LINE_SIZE) { + for (line = ALIGN_DOWN(start, flush_line_len); line < end; + line += flush_line_len) { #ifdef CONFIG_32BIT writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32); #else @@ -282,6 +351,18 @@ static int __init sifive_ccache_init(void) goto err_node_put; } + if (of_address_to_resource(np, 2, &res)) + return -ENODEV; + + l2_zero_device_base = ioremap(res.start, resource_size(&res)); + if (!l2_zero_device_base) + return -ENOMEM; + + if (of_property_read_u32(np, "cache-size", &cache_size)) { + pr_err("L2CACHE: no cache-size property\n"); + return -ENODEV; + } + if (of_property_read_u32(np, "cache-level", &level)) { rc = -ENOENT; goto err_unmap; @@ -305,17 +386,17 @@ static int __init sifive_ccache_init(void) } of_node_put(np); + ccache_config_read(); + #ifdef CONFIG_RISCV_DMA_NONCOHERENT if (!of_property_read_u64(np, "uncached-offset", &offset)) { uncached_offset = offset; static_branch_enable(&sifive_ccache_handle_noncoherent_key); - riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; + riscv_cbom_block_size = flush_line_len; riscv_noncoherent_supported(); } #endif - ccache_config_read(); - if (IS_ENABLED(CONFIG_SIFIVE_U74_L2_PMU)) { for_each_cpu(cpu, cpu_possible_mask) { rc = sifive_u74_l2_pmu_probe(np, ccache_base, cpu); diff --git a/include/soc/sifive/sifive_ccache.h b/include/soc/sifive/sifive_ccache.h index e336ac3f73cb..358693ba3753 100644 --- a/include/soc/sifive/sifive_ccache.h +++ b/include/soc/sifive/sifive_ccache.h @@ -27,6 +27,7 @@ static inline bool sifive_ccache_handle_noncoherent(void) #endif } +void sifive_ccache_flush_entire(void); void sifive_ccache_flush_range(phys_addr_t start, size_t len); void sifive_l2_flush64_range(phys_addr_t start, size_t len); void *sifive_ccache_set_uncached(void *addr, size_t size); |