Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Yash Shah and committed by
Palmer Dabbelt
507308b8 af951c3a

+24 -3
+24 -3
drivers/soc/sifive/sifive_l2_cache.c
··· 17 17 #define SIFIVE_L2_DIRECCFIX_HIGH 0x104 18 18 #define SIFIVE_L2_DIRECCFIX_COUNT 0x108 19 19 20 + #define SIFIVE_L2_DIRECCFAIL_LOW 0x120 21 + #define SIFIVE_L2_DIRECCFAIL_HIGH 0x124 22 + #define SIFIVE_L2_DIRECCFAIL_COUNT 0x128 23 + 20 24 #define SIFIVE_L2_DATECCFIX_LOW 0x140 21 25 #define SIFIVE_L2_DATECCFIX_HIGH 0x144 22 26 #define SIFIVE_L2_DATECCFIX_COUNT 0x148 ··· 33 29 #define SIFIVE_L2_WAYENABLE 0x08 34 30 #define SIFIVE_L2_ECCINJECTERR 0x40 35 31 36 - #define SIFIVE_L2_MAX_ECCINTR 3 32 + #define SIFIVE_L2_MAX_ECCINTR 4 37 33 38 34 static void __iomem *l2_base; 39 35 static int g_irq[SIFIVE_L2_MAX_ECCINTR]; ··· 43 39 DIR_CORR = 0, 44 40 DATA_CORR, 45 41 DATA_UNCORR, 42 + DIR_UNCORR, 46 43 }; 47 44 48 45 #ifdef CONFIG_DEBUG_FS ··· 98 93 99 94 static const struct of_device_id sifive_l2_ids[] = { 100 95 { .compatible = "sifive,fu540-c000-ccache" }, 96 + { .compatible = "sifive,fu740-c000-ccache" }, 101 97 { /* end of table */ }, 102 98 }; 103 99 ··· 161 155 atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, 162 156 "DirECCFix"); 163 157 } 158 + if (irq == g_irq[DIR_UNCORR]) { 159 + add_h = readl(l2_base + SIFIVE_L2_DIRECCFAIL_HIGH); 160 + add_l = readl(l2_base + SIFIVE_L2_DIRECCFAIL_LOW); 161 + /* Reading this register clears the DirFail interrupt sig */ 162 + readl(l2_base + SIFIVE_L2_DIRECCFAIL_COUNT); 163 + atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE, 164 + "DirECCFail"); 165 + panic("L2CACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l); 166 + } 164 167 if (irq == g_irq[DATA_CORR]) { 165 168 add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH); 166 169 add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW); ··· 196 181 { 197 182 struct device_node *np; 198 183 struct resource res; 199 - int i, rc; 184 + int i, rc, intr_num; 200 185 201 186 np = of_find_matching_node(NULL, sifive_l2_ids); 202 187 if (!np) ··· 209 194 if (!l2_base) 210 195 return -ENOMEM; 211 196 212 - for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) { 197 + intr_num = of_property_count_u32_elems(np, "interrupts"); 198 + if (!intr_num) { 199 + pr_err("L2CACHE: no interrupts property\n"); 200 + return -ENODEV; 201 + } 202 + 203 + for (i = 0; i < intr_num; i++) { 213 204 g_irq[i] = irq_of_parse_and_map(np, i); 214 205 rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL); 215 206 if (rc) {