starfive: add new target for StarFive JH7100/7110 SoC
[openwrt/staging/981213.git] / target / linux / starfive / patches-6.1 / 1019-soc-sifive-ccache-Add-non-coherent-DMA-handling.patch
1 From 335c32d2653f2415e042c8ad1ae2a6b33019b96f Mon Sep 17 00:00:00 2001
2 From: Emil Renner Berthing <kernel@esmil.dk>
3 Date: Sat, 12 Jun 2021 16:48:31 -0700
4 Subject: [PATCH 1019/1024] soc: sifive: ccache: Add non-coherent DMA handling
5
6 Add functions to flush the caches and handle non-coherent DMA.
7
8 Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
9 ---
10 drivers/soc/sifive/sifive_ccache.c | 60 +++++++++++++++++++++++++++++-
11 include/soc/sifive/sifive_ccache.h | 21 +++++++++++
12 2 files changed, 80 insertions(+), 1 deletion(-)
13
14 --- a/drivers/soc/sifive/sifive_ccache.c
15 +++ b/drivers/soc/sifive/sifive_ccache.c
16 @@ -8,13 +8,16 @@
17
18 #define pr_fmt(fmt) "CCACHE: " fmt
19
20 +#include <linux/align.h>
21 #include <linux/debugfs.h>
22 #include <linux/interrupt.h>
23 #include <linux/of_irq.h>
24 #include <linux/of_address.h>
25 #include <linux/device.h>
26 #include <linux/bitfield.h>
27 +#include <asm/cacheflush.h>
28 #include <asm/cacheinfo.h>
29 +#include <asm/page.h>
30 #include <soc/sifive/sifive_ccache.h>
31
32 #define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100
33 @@ -39,10 +42,14 @@
34 #define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16)
35 #define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24)
36
37 +#define SIFIVE_CCACHE_FLUSH64 0x200
38 +#define SIFIVE_CCACHE_FLUSH32 0x240
39 +
40 #define SIFIVE_CCACHE_WAYENABLE 0x08
41 #define SIFIVE_CCACHE_ECCINJECTERR 0x40
42
43 #define SIFIVE_CCACHE_MAX_ECCINTR 4
44 +#define SIFIVE_CCACHE_LINE_SIZE 64
45
46 static void __iomem *ccache_base;
47 static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR];
48 @@ -126,6 +133,47 @@ int unregister_sifive_ccache_error_notif
49 }
50 EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier);
51
52 +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
53 +static phys_addr_t uncached_offset;
54 +DEFINE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key);
55 +
56 +void sifive_ccache_flush_range(phys_addr_t start, size_t len)
57 +{
58 + phys_addr_t end = start + len;
59 + phys_addr_t line;
60 +
61 + if (!len)
62 + return;
63 +
64 + mb();
65 + for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end;
66 + line += SIFIVE_CCACHE_LINE_SIZE) {
67 +#ifdef CONFIG_32BIT
68 + writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32);
69 +#else
70 + writeq(line, ccache_base + SIFIVE_CCACHE_FLUSH64);
71 +#endif
72 + mb();
73 + }
74 +}
75 +EXPORT_SYMBOL_GPL(sifive_ccache_flush_range);
76 +
77 +void *sifive_ccache_set_uncached(void *addr, size_t size)
78 +{
79 + phys_addr_t phys_addr = __pa(addr) + uncached_offset;
80 + void *mem_base;
81 +
82 + mem_base = memremap(phys_addr, size, MEMREMAP_WT);
83 + if (!mem_base) {
84 + pr_err("%s memremap failed for addr %p\n", __func__, addr);
85 + return ERR_PTR(-EINVAL);
86 + }
87 +
88 + return mem_base;
89 +}
90 +EXPORT_SYMBOL_GPL(sifive_ccache_set_uncached);
91 +#endif /* CONFIG_RISCV_DMA_NONCOHERENT */
92 +
93 static int ccache_largest_wayenabled(void)
94 {
95 return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF;
96 @@ -214,6 +262,7 @@ static int __init sifive_ccache_init(voi
97 int i, rc, intr_num;
98 const struct of_device_id *match;
99 unsigned long broken_irqs;
100 + u64 __maybe_unused offset;
101
102 np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match);
103 if (!np)
104 @@ -259,6 +308,15 @@ static int __init sifive_ccache_init(voi
105 }
106 of_node_put(np);
107
108 +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
109 + if (!of_property_read_u64(np, "uncached-offset", &offset)) {
110 + uncached_offset = offset;
111 + static_branch_enable(&sifive_ccache_handle_noncoherent_key);
112 + riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE;
113 + riscv_noncoherent_supported();
114 + }
115 +#endif
116 +
117 ccache_config_read();
118
119 ccache_cache_ops.get_priv_group = ccache_get_priv_group;
120 @@ -279,4 +337,4 @@ err_node_put:
121 return rc;
122 }
123
124 -device_initcall(sifive_ccache_init);
125 +arch_initcall(sifive_ccache_init);
126 --- a/include/soc/sifive/sifive_ccache.h
127 +++ b/include/soc/sifive/sifive_ccache.h
128 @@ -7,10 +7,31 @@
129 #ifndef __SOC_SIFIVE_CCACHE_H
130 #define __SOC_SIFIVE_CCACHE_H
131
132 +#include <linux/io.h>
133 +#include <linux/jump_label.h>
134 +
135 extern int register_sifive_ccache_error_notifier(struct notifier_block *nb);
136 extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb);
137
138 #define SIFIVE_CCACHE_ERR_TYPE_CE 0
139 #define SIFIVE_CCACHE_ERR_TYPE_UE 1
140
141 +DECLARE_STATIC_KEY_FALSE(sifive_ccache_handle_noncoherent_key);
142 +
143 +static inline bool sifive_ccache_handle_noncoherent(void)
144 +{
145 +#ifdef CONFIG_SIFIVE_CCACHE
146 + return static_branch_unlikely(&sifive_ccache_handle_noncoherent_key);
147 +#else
148 + return false;
149 +#endif
150 +}
151 +
152 +void sifive_ccache_flush_range(phys_addr_t start, size_t len);
153 +void *sifive_ccache_set_uncached(void *addr, size_t size);
154 +static inline void sifive_ccache_clear_uncached(void *addr, size_t size)
155 +{
156 + memunmap(addr);
157 +}
158 +
159 #endif /* __SOC_SIFIVE_CCACHE_H */