summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Hu <andy.hu@starfivetech.com>2024-01-11 14:28:23 +0300
committerAndy Hu <andy.hu@starfivetech.com>2024-01-11 14:28:23 +0300
commita06538ffde0e22e7048a9f9ad76c46ca8859860c (patch)
tree70e12d55e98fcc28438da1ed5ecda892bbce4120
parentb1ba9bb42d0ea2fe2a256c35a651c649535a7a9b (diff)
parentc1d57ddbd8dbd3a27bbb79350e5eebf9efa5dcc9 (diff)
downloadlinux-a06538ffde0e22e7048a9f9ad76c46ca8859860c.tar.xz
Merge tag 'JH7110_SDK_515_v5.10.5' into vf2-515-devel
-rwxr-xr-xarch/riscv/boot/dts/starfive/jh7110.dtsi2
-rw-r--r--drivers/gpu/drm/verisilicon/vs_dc.c7
-rw-r--r--drivers/soc/sifive/sifive_l2_cache.c102
-rw-r--r--include/soc/sifive/sifive_l2_cache.h1
4 files changed, 95 insertions, 17 deletions
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index 80793fd673ad..1ef9bea433c3 100755
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -246,7 +246,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 f6d8749183e6..b16875aac385 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;
}
diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
index 243bf43edb9c..8af044676c05 100644
--- a/drivers/soc/sifive/sifive_l2_cache.c
+++ b/drivers/soc/sifive/sifive_l2_cache.c
@@ -35,19 +35,32 @@
#define SIFIVE_L2_FLUSH64 0x200
#define SIFIVE_L2_FLUSH32 0x240
+#define SIFIVE_L2_WAYMASK_BASE 0x800
+#define SIFIVE_L2_MAX_MASTER_ID 32
+
#define SIFIVE_L2_CONFIG 0x00
#define SIFIVE_L2_WAYENABLE 0x08
#define SIFIVE_L2_ECCINJECTERR 0x40
#define SIFIVE_L2_MAX_ECCINTR 4
-#define SIFIVE_L2_FLUSH64_LINE_LEN 64
+#define SIFIVE_L2_DEFAULT_WAY_MASK 0xffff
+
static void __iomem *l2_base;
static int g_irq[SIFIVE_L2_MAX_ECCINTR];
static struct riscv_cacheinfo_ops l2_cache_ops;
static phys_addr_t uncached_offset;
DEFINE_STATIC_KEY_FALSE(sifive_l2_handle_noncoherent_key);
+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,
@@ -94,15 +107,26 @@ static void l2_config_read(void)
regval = readl(l2_base + SIFIVE_L2_CONFIG);
val = regval & 0xFF;
pr_info("L2CACHE: No. of Banks in the cache: %d\n", val);
- val = (regval & 0xFF00) >> 8;
- pr_info("L2CACHE: No. of ways per bank: %d\n", val);
+ cache_ways_per_bank = (regval & 0xFF00) >> 8;
+ pr_info("L2CACHE: No. of ways per bank: %d\n", cache_ways_per_bank);
+
val = (regval & 0xFF0000) >> 16;
pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val);
- val = (regval & 0xFF000000) >> 24;
- pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val);
- regval = readl(l2_base + SIFIVE_L2_WAYENABLE);
- pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval);
+ cache_size_per_block = (regval & 0xFF000000) >> 24;
+ cache_size_per_block = 1 << cache_size_per_block;
+ pr_info("L2CACHE: Bytes per cache block: %u\n", cache_size_per_block);
+
+ 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("L2CACHE: 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(l2_base + SIFIVE_L2_WAYENABLE);
+ pr_info("L2CACHE: Index of the largest way enabled: %d\n", cache_max_enabled_way);
}
static const struct of_device_id sifive_l2_ids[] = {
@@ -125,6 +149,52 @@ int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
+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 = l2_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 = l2_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_l2_flush_range(phys_addr_t start, size_t len)
{
phys_addr_t end = start + len;
@@ -134,8 +204,8 @@ void sifive_l2_flush_range(phys_addr_t start, size_t len)
return;
mb();
- for (line = ALIGN_DOWN(start, SIFIVE_L2_FLUSH64_LINE_LEN); line < end;
- line += SIFIVE_L2_FLUSH64_LINE_LEN) {
+ for (line = ALIGN_DOWN(start, flush_line_len); line < end;
+ line += flush_line_len) {
#ifdef CONFIG_32BIT
writel(line >> 4, l2_base + SIFIVE_L2_FLUSH32);
#else
@@ -194,7 +264,7 @@ void sifive_l2_flush64_range(unsigned long start, unsigned long len)
mb(); /* sync */
for (line = start; line < start + len;
- line += SIFIVE_L2_FLUSH64_LINE_LEN) {
+ line += flush_line_len) {
writeq(line, l2_base + SIFIVE_L2_FLUSH64);
mb();
}
@@ -296,6 +366,18 @@ static int __init sifive_l2_init(void)
if (!l2_base)
return -ENOMEM;
+ 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;
+ }
+
intr_num = of_property_count_u32_elems(np, "interrupts");
if (!intr_num) {
pr_err("L2CACHE: no interrupts property\n");
diff --git a/include/soc/sifive/sifive_l2_cache.h b/include/soc/sifive/sifive_l2_cache.h
index f472e4cb1232..79adec5ba3c5 100644
--- a/include/soc/sifive/sifive_l2_cache.h
+++ b/include/soc/sifive/sifive_l2_cache.h
@@ -27,6 +27,7 @@ static inline bool sifive_l2_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_flush_range(phys_addr_t start, size_t len);
void *sifive_l2_set_uncached(void *addr, size_t size);