Merge tag 'riscv/for-v5.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Dec 2019 18:22:47 +0000 (10:22 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Dec 2019 18:22:47 +0000 (10:22 -0800)
Pull RISC-V fixes from Paul Walmsley:
 "Several fixes, and one cleanup, for RISC-V.

  Fixes:

   - Fix an error in a Kconfig file that resulted in an undefined
     Kconfig option "CONFIG_CONFIG_MMU"

   - Fix undefined Kconfig option "CONFIG_CONFIG_MMU"

   - Fix scratch register clearing in M-mode (affects nommu users)

   - Fix a mismerge on my part that broke the build for
     CONFIG_SPARSEMEM_VMEMMAP users

  Cleanup:

   - Move SiFive L2 cache-related code to drivers/soc, per request"

* tag 'riscv/for-v5.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
  riscv: move sifive_l2_cache.c to drivers/soc
  riscv: define vmemmap before pfn_to_page calls
  riscv: fix scratch register clearing in M-mode.
  riscv: Fix use of undefined config option CONFIG_CONFIG_MMU

12 files changed:
MAINTAINERS
arch/riscv/Kconfig
arch/riscv/include/asm/pgtable.h
arch/riscv/kernel/head.S
arch/riscv/mm/Makefile
arch/riscv/mm/sifive_l2_cache.c [deleted file]
drivers/edac/Kconfig
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/sifive/Kconfig [new file with mode: 0644]
drivers/soc/sifive/Makefile [new file with mode: 0644]
drivers/soc/sifive/sifive_l2_cache.c [new file with mode: 0644]

index 06db726..1b998c8 100644 (file)
@@ -6027,6 +6027,7 @@ M:        Yash Shah <yash.shah@sifive.com>
 L:     linux-edac@vger.kernel.org
 S:     Supported
 F:     drivers/edac/sifive_edac.c
+F:     drivers/soc/sifive_l2_cache.c
 
 EDAC-SKYLAKE
 M:     Tony Luck <tony.luck@intel.com>
index 759ffb0..d8efbaa 100644 (file)
@@ -154,7 +154,7 @@ config GENERIC_HWEIGHT
        def_bool y
 
 config FIX_EARLYCON_MEM
-       def_bool CONFIG_MMU
+       def_bool MMU
 
 config PGTABLE_LEVELS
        int
index 7ff0ed4..36ae017 100644 (file)
@@ -90,6 +90,27 @@ extern pgd_t swapper_pg_dir[];
 #define __S110 PAGE_SHARED_EXEC
 #define __S111 PAGE_SHARED_EXEC
 
+#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
+#define VMALLOC_END      (PAGE_OFFSET - 1)
+#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
+
+/*
+ * Roughly size the vmemmap space to be large enough to fit enough
+ * struct pages to map half the virtual address space. Then
+ * position vmemmap directly below the VMALLOC region.
+ */
+#define VMEMMAP_SHIFT \
+       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
+#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
+#define VMEMMAP_END    (VMALLOC_START - 1)
+#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
+
+/*
+ * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel
+ * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled.
+ */
+#define vmemmap                ((struct page *)VMEMMAP_START)
+
 static inline int pmd_present(pmd_t pmd)
 {
        return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
@@ -400,23 +421,6 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
 
-#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
-#define VMALLOC_END      (PAGE_OFFSET - 1)
-#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
-
-/*
- * Roughly size the vmemmap space to be large enough to fit enough
- * struct pages to map half the virtual address space. Then
- * position vmemmap directly below the VMALLOC region.
- */
-#define VMEMMAP_SHIFT \
-       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
-#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
-#define VMEMMAP_END    (VMALLOC_START - 1)
-#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
-
-#define vmemmap                ((struct page *)VMEMMAP_START)
-
 #define PCI_IO_SIZE      SZ_16M
 #define PCI_IO_END       VMEMMAP_START
 #define PCI_IO_START     (PCI_IO_END - PCI_IO_SIZE)
index 84a6f0a..797802c 100644 (file)
@@ -246,7 +246,7 @@ ENTRY(reset_regs)
        li      t4, 0
        li      t5, 0
        li      t6, 0
-       csrw    sscratch, 0
+       csrw    CSR_SCRATCH, 0
 
 #ifdef CONFIG_FPU
        csrr    t0, CSR_MISA
index 3c8b332..a1bd95c 100644 (file)
@@ -10,7 +10,6 @@ obj-y += extable.o
 obj-$(CONFIG_MMU) += fault.o
 obj-y += cacheflush.o
 obj-y += context.o
-obj-y += sifive_l2_cache.o
 
 ifeq ($(CONFIG_MMU),y)
 obj-$(CONFIG_SMP) += tlbflush.o
diff --git a/arch/riscv/mm/sifive_l2_cache.c b/arch/riscv/mm/sifive_l2_cache.c
deleted file mode 100644 (file)
index a9ffff3..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SiFive L2 cache controller Driver
- *
- * Copyright (C) 2018-2019 SiFive, Inc.
- *
- */
-#include <linux/debugfs.h>
-#include <linux/interrupt.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <asm/sifive_l2_cache.h>
-
-#define SIFIVE_L2_DIRECCFIX_LOW 0x100
-#define SIFIVE_L2_DIRECCFIX_HIGH 0x104
-#define SIFIVE_L2_DIRECCFIX_COUNT 0x108
-
-#define SIFIVE_L2_DATECCFIX_LOW 0x140
-#define SIFIVE_L2_DATECCFIX_HIGH 0x144
-#define SIFIVE_L2_DATECCFIX_COUNT 0x148
-
-#define SIFIVE_L2_DATECCFAIL_LOW 0x160
-#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
-#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
-
-#define SIFIVE_L2_CONFIG 0x00
-#define SIFIVE_L2_WAYENABLE 0x08
-#define SIFIVE_L2_ECCINJECTERR 0x40
-
-#define SIFIVE_L2_MAX_ECCINTR 3
-
-static void __iomem *l2_base;
-static int g_irq[SIFIVE_L2_MAX_ECCINTR];
-
-enum {
-       DIR_CORR = 0,
-       DATA_CORR,
-       DATA_UNCORR,
-};
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *sifive_test;
-
-static ssize_t l2_write(struct file *file, const char __user *data,
-                       size_t count, loff_t *ppos)
-{
-       unsigned int val;
-
-       if (kstrtouint_from_user(data, count, 0, &val))
-               return -EINVAL;
-       if ((val >= 0 && val < 0xFF) || (val >= 0x10000 && val < 0x100FF))
-               writel(val, l2_base + SIFIVE_L2_ECCINJECTERR);
-       else
-               return -EINVAL;
-       return count;
-}
-
-static const struct file_operations l2_fops = {
-       .owner = THIS_MODULE,
-       .open = simple_open,
-       .write = l2_write
-};
-
-static void setup_sifive_debug(void)
-{
-       sifive_test = debugfs_create_dir("sifive_l2_cache", NULL);
-
-       debugfs_create_file("sifive_debug_inject_error", 0200,
-                           sifive_test, NULL, &l2_fops);
-}
-#endif
-
-static void l2_config_read(void)
-{
-       u32 regval, val;
-
-       regval = readl(l2_base + SIFIVE_L2_CONFIG);
-       val = regval & 0xFF;
-       pr_info("L2CACHE: No. of Banks in the cache: %d\n", val);
-       val = (regval & 0xFF00) >> 8;
-       pr_info("L2CACHE: No. of ways per bank: %d\n", val);
-       val = (regval & 0xFF0000) >> 16;
-       pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val);
-       val = (regval & 0xFF000000) >> 24;
-       pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val);
-
-       regval = readl(l2_base + SIFIVE_L2_WAYENABLE);
-       pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval);
-}
-
-static const struct of_device_id sifive_l2_ids[] = {
-       { .compatible = "sifive,fu540-c000-ccache" },
-       { /* end of table */ },
-};
-
-static ATOMIC_NOTIFIER_HEAD(l2_err_chain);
-
-int register_sifive_l2_error_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&l2_err_chain, nb);
-}
-EXPORT_SYMBOL_GPL(register_sifive_l2_error_notifier);
-
-int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&l2_err_chain, nb);
-}
-EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
-
-static irqreturn_t l2_int_handler(int irq, void *device)
-{
-       unsigned int add_h, add_l;
-
-       if (irq == g_irq[DIR_CORR]) {
-               add_h = readl(l2_base + SIFIVE_L2_DIRECCFIX_HIGH);
-               add_l = readl(l2_base + SIFIVE_L2_DIRECCFIX_LOW);
-               pr_err("L2CACHE: DirError @ 0x%08X.%08X\n", add_h, add_l);
-               /* Reading this register clears the DirError interrupt sig */
-               readl(l2_base + SIFIVE_L2_DIRECCFIX_COUNT);
-               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
-                                          "DirECCFix");
-       }
-       if (irq == g_irq[DATA_CORR]) {
-               add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH);
-               add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW);
-               pr_err("L2CACHE: DataError @ 0x%08X.%08X\n", add_h, add_l);
-               /* Reading this register clears the DataError interrupt sig */
-               readl(l2_base + SIFIVE_L2_DATECCFIX_COUNT);
-               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
-                                          "DatECCFix");
-       }
-       if (irq == g_irq[DATA_UNCORR]) {
-               add_h = readl(l2_base + SIFIVE_L2_DATECCFAIL_HIGH);
-               add_l = readl(l2_base + SIFIVE_L2_DATECCFAIL_LOW);
-               pr_err("L2CACHE: DataFail @ 0x%08X.%08X\n", add_h, add_l);
-               /* Reading this register clears the DataFail interrupt sig */
-               readl(l2_base + SIFIVE_L2_DATECCFAIL_COUNT);
-               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
-                                          "DatECCFail");
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int __init sifive_l2_init(void)
-{
-       struct device_node *np;
-       struct resource res;
-       int i, rc;
-
-       np = of_find_matching_node(NULL, sifive_l2_ids);
-       if (!np)
-               return -ENODEV;
-
-       if (of_address_to_resource(np, 0, &res))
-               return -ENODEV;
-
-       l2_base = ioremap(res.start, resource_size(&res));
-       if (!l2_base)
-               return -ENOMEM;
-
-       for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) {
-               g_irq[i] = irq_of_parse_and_map(np, i);
-               rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL);
-               if (rc) {
-                       pr_err("L2CACHE: Could not request IRQ %d\n", g_irq[i]);
-                       return rc;
-               }
-       }
-
-       l2_config_read();
-
-#ifdef CONFIG_DEBUG_FS
-       setup_sifive_debug();
-#endif
-       return 0;
-}
-device_initcall(sifive_l2_init);
index 417dad6..5c82723 100644 (file)
@@ -462,7 +462,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SIFIVE
        bool "Sifive platform EDAC driver"
-       depends on EDAC=y && RISCV
+       depends on EDAC=y && SIFIVE_L2
        help
          Support for error detection and correction on the SiFive SoCs.
 
index 833e04a..1778f8c 100644 (file)
@@ -14,6 +14,7 @@ source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
 source "drivers/soc/samsung/Kconfig"
+source "drivers/soc/sifive/Kconfig"
 source "drivers/soc/sunxi/Kconfig"
 source "drivers/soc/tegra/Kconfig"
 source "drivers/soc/ti/Kconfig"
index 2ec3550..8b49d78 100644 (file)
@@ -20,6 +20,7 @@ obj-y                         += qcom/
 obj-y                          += renesas/
 obj-$(CONFIG_ARCH_ROCKCHIP)    += rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)      += samsung/
+obj-$(CONFIG_SOC_SIFIVE)       += sifive/
 obj-y                          += sunxi/
 obj-$(CONFIG_ARCH_TEGRA)       += tegra/
 obj-y                          += ti/
diff --git a/drivers/soc/sifive/Kconfig b/drivers/soc/sifive/Kconfig
new file mode 100644 (file)
index 0000000..58cf8c4
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if SOC_SIFIVE
+
+config SIFIVE_L2
+       bool "Sifive L2 Cache controller"
+       help
+         Support for the L2 cache controller on SiFive platforms.
+
+endif
diff --git a/drivers/soc/sifive/Makefile b/drivers/soc/sifive/Makefile
new file mode 100644 (file)
index 0000000..b5caff7
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SIFIVE_L2)        += sifive_l2_cache.o
diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
new file mode 100644 (file)
index 0000000..a9ffff3
--- /dev/null
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SiFive L2 cache controller Driver
+ *
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <asm/sifive_l2_cache.h>
+
+#define SIFIVE_L2_DIRECCFIX_LOW 0x100
+#define SIFIVE_L2_DIRECCFIX_HIGH 0x104
+#define SIFIVE_L2_DIRECCFIX_COUNT 0x108
+
+#define SIFIVE_L2_DATECCFIX_LOW 0x140
+#define SIFIVE_L2_DATECCFIX_HIGH 0x144
+#define SIFIVE_L2_DATECCFIX_COUNT 0x148
+
+#define SIFIVE_L2_DATECCFAIL_LOW 0x160
+#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
+#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
+
+#define SIFIVE_L2_CONFIG 0x00
+#define SIFIVE_L2_WAYENABLE 0x08
+#define SIFIVE_L2_ECCINJECTERR 0x40
+
+#define SIFIVE_L2_MAX_ECCINTR 3
+
+static void __iomem *l2_base;
+static int g_irq[SIFIVE_L2_MAX_ECCINTR];
+
+enum {
+       DIR_CORR = 0,
+       DATA_CORR,
+       DATA_UNCORR,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *sifive_test;
+
+static ssize_t l2_write(struct file *file, const char __user *data,
+                       size_t count, loff_t *ppos)
+{
+       unsigned int val;
+
+       if (kstrtouint_from_user(data, count, 0, &val))
+               return -EINVAL;
+       if ((val >= 0 && val < 0xFF) || (val >= 0x10000 && val < 0x100FF))
+               writel(val, l2_base + SIFIVE_L2_ECCINJECTERR);
+       else
+               return -EINVAL;
+       return count;
+}
+
+static const struct file_operations l2_fops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .write = l2_write
+};
+
+static void setup_sifive_debug(void)
+{
+       sifive_test = debugfs_create_dir("sifive_l2_cache", NULL);
+
+       debugfs_create_file("sifive_debug_inject_error", 0200,
+                           sifive_test, NULL, &l2_fops);
+}
+#endif
+
+static void l2_config_read(void)
+{
+       u32 regval, val;
+
+       regval = readl(l2_base + SIFIVE_L2_CONFIG);
+       val = regval & 0xFF;
+       pr_info("L2CACHE: No. of Banks in the cache: %d\n", val);
+       val = (regval & 0xFF00) >> 8;
+       pr_info("L2CACHE: No. of ways per bank: %d\n", val);
+       val = (regval & 0xFF0000) >> 16;
+       pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val);
+       val = (regval & 0xFF000000) >> 24;
+       pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val);
+
+       regval = readl(l2_base + SIFIVE_L2_WAYENABLE);
+       pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval);
+}
+
+static const struct of_device_id sifive_l2_ids[] = {
+       { .compatible = "sifive,fu540-c000-ccache" },
+       { /* end of table */ },
+};
+
+static ATOMIC_NOTIFIER_HEAD(l2_err_chain);
+
+int register_sifive_l2_error_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&l2_err_chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_sifive_l2_error_notifier);
+
+int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_unregister(&l2_err_chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
+
+static irqreturn_t l2_int_handler(int irq, void *device)
+{
+       unsigned int add_h, add_l;
+
+       if (irq == g_irq[DIR_CORR]) {
+               add_h = readl(l2_base + SIFIVE_L2_DIRECCFIX_HIGH);
+               add_l = readl(l2_base + SIFIVE_L2_DIRECCFIX_LOW);
+               pr_err("L2CACHE: DirError @ 0x%08X.%08X\n", add_h, add_l);
+               /* Reading this register clears the DirError interrupt sig */
+               readl(l2_base + SIFIVE_L2_DIRECCFIX_COUNT);
+               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
+                                          "DirECCFix");
+       }
+       if (irq == g_irq[DATA_CORR]) {
+               add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH);
+               add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW);
+               pr_err("L2CACHE: DataError @ 0x%08X.%08X\n", add_h, add_l);
+               /* Reading this register clears the DataError interrupt sig */
+               readl(l2_base + SIFIVE_L2_DATECCFIX_COUNT);
+               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
+                                          "DatECCFix");
+       }
+       if (irq == g_irq[DATA_UNCORR]) {
+               add_h = readl(l2_base + SIFIVE_L2_DATECCFAIL_HIGH);
+               add_l = readl(l2_base + SIFIVE_L2_DATECCFAIL_LOW);
+               pr_err("L2CACHE: DataFail @ 0x%08X.%08X\n", add_h, add_l);
+               /* Reading this register clears the DataFail interrupt sig */
+               readl(l2_base + SIFIVE_L2_DATECCFAIL_COUNT);
+               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
+                                          "DatECCFail");
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int __init sifive_l2_init(void)
+{
+       struct device_node *np;
+       struct resource res;
+       int i, rc;
+
+       np = of_find_matching_node(NULL, sifive_l2_ids);
+       if (!np)
+               return -ENODEV;
+
+       if (of_address_to_resource(np, 0, &res))
+               return -ENODEV;
+
+       l2_base = ioremap(res.start, resource_size(&res));
+       if (!l2_base)
+               return -ENOMEM;
+
+       for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) {
+               g_irq[i] = irq_of_parse_and_map(np, i);
+               rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL);
+               if (rc) {
+                       pr_err("L2CACHE: Could not request IRQ %d\n", g_irq[i]);
+                       return rc;
+               }
+       }
+
+       l2_config_read();
+
+#ifdef CONFIG_DEBUG_FS
+       setup_sifive_debug();
+#endif
+       return 0;
+}
+device_initcall(sifive_l2_init);