2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-26 06:04:14 +08:00

RISC-V: sifive_l2_cache: Update L2 cache driver to support SiFive FU740

SiFive FU740 has 4 ECC interrupt sources as compared to 3 in FU540.
Update the L2 cache controller driver to support this additional
interrupt in case of FU740-C000 chip.

Signed-off-by: Yash Shah <yash.shah@sifive.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
This commit is contained in:
Yash Shah 2020-12-10 15:58:03 +05:30 committed by Palmer Dabbelt
parent af951c3a11
commit 507308b8cc
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889

View File

@ -17,6 +17,10 @@
#define SIFIVE_L2_DIRECCFIX_HIGH 0x104 #define SIFIVE_L2_DIRECCFIX_HIGH 0x104
#define SIFIVE_L2_DIRECCFIX_COUNT 0x108 #define SIFIVE_L2_DIRECCFIX_COUNT 0x108
#define SIFIVE_L2_DIRECCFAIL_LOW 0x120
#define SIFIVE_L2_DIRECCFAIL_HIGH 0x124
#define SIFIVE_L2_DIRECCFAIL_COUNT 0x128
#define SIFIVE_L2_DATECCFIX_LOW 0x140 #define SIFIVE_L2_DATECCFIX_LOW 0x140
#define SIFIVE_L2_DATECCFIX_HIGH 0x144 #define SIFIVE_L2_DATECCFIX_HIGH 0x144
#define SIFIVE_L2_DATECCFIX_COUNT 0x148 #define SIFIVE_L2_DATECCFIX_COUNT 0x148
@ -29,7 +33,7 @@
#define SIFIVE_L2_WAYENABLE 0x08 #define SIFIVE_L2_WAYENABLE 0x08
#define SIFIVE_L2_ECCINJECTERR 0x40 #define SIFIVE_L2_ECCINJECTERR 0x40
#define SIFIVE_L2_MAX_ECCINTR 3 #define SIFIVE_L2_MAX_ECCINTR 4
static void __iomem *l2_base; static void __iomem *l2_base;
static int g_irq[SIFIVE_L2_MAX_ECCINTR]; static int g_irq[SIFIVE_L2_MAX_ECCINTR];
@ -39,6 +43,7 @@ enum {
DIR_CORR = 0, DIR_CORR = 0,
DATA_CORR, DATA_CORR,
DATA_UNCORR, DATA_UNCORR,
DIR_UNCORR,
}; };
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
@ -93,6 +98,7 @@ static void l2_config_read(void)
static const struct of_device_id sifive_l2_ids[] = { static const struct of_device_id sifive_l2_ids[] = {
{ .compatible = "sifive,fu540-c000-ccache" }, { .compatible = "sifive,fu540-c000-ccache" },
{ .compatible = "sifive,fu740-c000-ccache" },
{ /* end of table */ }, { /* end of table */ },
}; };
@ -155,6 +161,15 @@ static irqreturn_t l2_int_handler(int irq, void *device)
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
"DirECCFix"); "DirECCFix");
} }
if (irq == g_irq[DIR_UNCORR]) {
add_h = readl(l2_base + SIFIVE_L2_DIRECCFAIL_HIGH);
add_l = readl(l2_base + SIFIVE_L2_DIRECCFAIL_LOW);
/* Reading this register clears the DirFail interrupt sig */
readl(l2_base + SIFIVE_L2_DIRECCFAIL_COUNT);
atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
"DirECCFail");
panic("L2CACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l);
}
if (irq == g_irq[DATA_CORR]) { if (irq == g_irq[DATA_CORR]) {
add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH); add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH);
add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW); add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW);
@ -181,7 +196,7 @@ static int __init sifive_l2_init(void)
{ {
struct device_node *np; struct device_node *np;
struct resource res; struct resource res;
int i, rc; int i, rc, intr_num;
np = of_find_matching_node(NULL, sifive_l2_ids); np = of_find_matching_node(NULL, sifive_l2_ids);
if (!np) if (!np)
@ -194,7 +209,13 @@ static int __init sifive_l2_init(void)
if (!l2_base) if (!l2_base)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) { intr_num = of_property_count_u32_elems(np, "interrupts");
if (!intr_num) {
pr_err("L2CACHE: no interrupts property\n");
return -ENODEV;
}
for (i = 0; i < intr_num; i++) {
g_irq[i] = irq_of_parse_and_map(np, i); g_irq[i] = irq_of_parse_and_map(np, i);
rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL); rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL);
if (rc) { if (rc) {