88
99#define pr_fmt (fmt ) "CCACHE: " fmt
1010
11+ #include <linux/align.h>
1112#include <linux/debugfs.h>
1213#include <linux/interrupt.h>
1314#include <linux/of_irq.h>
1415#include <linux/of_address.h>
1516#include <linux/device.h>
1617#include <linux/bitfield.h>
18+ #include <asm/cacheflush.h>
1719#include <asm/cacheinfo.h>
20+ #include <asm/dma-noncoherent.h>
1821#include <soc/sifive/sifive_ccache.h>
1922
2023#define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100
3942#define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16)
4043#define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24)
4144
45+ #define SIFIVE_CCACHE_FLUSH64 0x200
46+ #define SIFIVE_CCACHE_FLUSH32 0x240
47+
4248#define SIFIVE_CCACHE_WAYENABLE 0x08
4349#define SIFIVE_CCACHE_ECCINJECTERR 0x40
4450
4551#define SIFIVE_CCACHE_MAX_ECCINTR 4
52+ #define SIFIVE_CCACHE_LINE_SIZE 64
4653
4754static void __iomem * ccache_base ;
4855static int g_irq [SIFIVE_CCACHE_MAX_ECCINTR ];
@@ -56,6 +63,11 @@ enum {
5663 DIR_UNCORR ,
5764};
5865
66+ enum {
67+ QUIRK_NONSTANDARD_CACHE_OPS = BIT (0 ),
68+ QUIRK_BROKEN_DATA_UNCORR = BIT (1 ),
69+ };
70+
5971#ifdef CONFIG_DEBUG_FS
6072static struct dentry * sifive_test ;
6173
@@ -106,6 +118,8 @@ static void ccache_config_read(void)
106118static const struct of_device_id sifive_ccache_ids [] = {
107119 { .compatible = "sifive,fu540-c000-ccache" },
108120 { .compatible = "sifive,fu740-c000-ccache" },
121+ { .compatible = "starfive,jh7100-ccache" ,
122+ .data = (void * )(QUIRK_NONSTANDARD_CACHE_OPS | QUIRK_BROKEN_DATA_UNCORR ) },
109123 { .compatible = "sifive,ccache0" },
110124 { /* end of table */ }
111125};
@@ -124,6 +138,34 @@ int unregister_sifive_ccache_error_notifier(struct notifier_block *nb)
124138}
125139EXPORT_SYMBOL_GPL (unregister_sifive_ccache_error_notifier );
126140
141+ #ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
142+ static void ccache_flush_range (phys_addr_t start , size_t len )
143+ {
144+ phys_addr_t end = start + len ;
145+ phys_addr_t line ;
146+
147+ if (!len )
148+ return ;
149+
150+ mb ();
151+ for (line = ALIGN_DOWN (start , SIFIVE_CCACHE_LINE_SIZE ); line < end ;
152+ line += SIFIVE_CCACHE_LINE_SIZE ) {
153+ #ifdef CONFIG_32BIT
154+ writel (line >> 4 , ccache_base + SIFIVE_CCACHE_FLUSH32 );
155+ #else
156+ writeq (line , ccache_base + SIFIVE_CCACHE_FLUSH64 );
157+ #endif
158+ mb ();
159+ }
160+ }
161+
162+ static const struct riscv_nonstd_cache_ops ccache_mgmt_ops __initconst = {
163+ .wback = & ccache_flush_range ,
164+ .inv = & ccache_flush_range ,
165+ .wback_inv = & ccache_flush_range ,
166+ };
167+ #endif /* CONFIG_RISCV_NONSTANDARD_CACHE_OPS */
168+
127169static int ccache_largest_wayenabled (void )
128170{
129171 return readl (ccache_base + SIFIVE_CCACHE_WAYENABLE ) & 0xFF ;
@@ -210,11 +252,15 @@ static int __init sifive_ccache_init(void)
210252 struct device_node * np ;
211253 struct resource res ;
212254 int i , rc , intr_num ;
255+ const struct of_device_id * match ;
256+ unsigned long quirks ;
213257
214- np = of_find_matching_node (NULL , sifive_ccache_ids );
258+ np = of_find_matching_node_and_match (NULL , sifive_ccache_ids , & match );
215259 if (!np )
216260 return - ENODEV ;
217261
262+ quirks = (uintptr_t )match -> data ;
263+
218264 if (of_address_to_resource (np , 0 , & res )) {
219265 rc = - ENODEV ;
220266 goto err_node_put ;
@@ -240,6 +286,10 @@ static int __init sifive_ccache_init(void)
240286
241287 for (i = 0 ; i < intr_num ; i ++ ) {
242288 g_irq [i ] = irq_of_parse_and_map (np , i );
289+
290+ if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR ))
291+ continue ;
292+
243293 rc = request_irq (g_irq [i ], ccache_int_handler , 0 , "ccache_ecc" ,
244294 NULL );
245295 if (rc ) {
@@ -249,6 +299,14 @@ static int __init sifive_ccache_init(void)
249299 }
250300 of_node_put (np );
251301
302+ #ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
303+ if (quirks & QUIRK_NONSTANDARD_CACHE_OPS ) {
304+ riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE ;
305+ riscv_noncoherent_supported ();
306+ riscv_noncoherent_register_cache_ops (& ccache_mgmt_ops );
307+ }
308+ #endif
309+
252310 ccache_config_read ();
253311
254312 ccache_cache_ops .get_priv_group = ccache_get_priv_group ;
@@ -269,4 +327,4 @@ static int __init sifive_ccache_init(void)
269327 return rc ;
270328}
271329
272- device_initcall (sifive_ccache_init );
330+ arch_initcall (sifive_ccache_init );
0 commit comments