Skip to content

Commit 0d5701d

Browse files
esmilConchuOD
authored andcommitted
soc: sifive: ccache: Add StarFive JH7100 support
This adds support for the StarFive JH7100 SoC which also features this SiFive cache controller. The JH7100 has non-coherent DMAs but predate the standard RISC-V Zicbom exension, so instead we need to use this cache controller for non-standard cache management operations. Unfortunately the interrupt for uncorrected data is broken on the JH7100 and fires continuously, so add a quirk to not register a handler for it. Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
1 parent 3d70b98 commit 0d5701d

1 file changed

Lines changed: 60 additions & 2 deletions

File tree

drivers/cache/sifive_ccache.c

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
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
@@ -39,10 +42,14 @@
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

4754
static void __iomem *ccache_base;
4855
static 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
6072
static struct dentry *sifive_test;
6173

@@ -106,6 +118,8 @@ static void ccache_config_read(void)
106118
static 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
}
125139
EXPORT_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+
127169
static 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

Comments
 (0)