Merge tag 'riscv-for-linus-5.20-mw0' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 6 Aug 2022 22:04:48 +0000 (15:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 6 Aug 2022 22:04:48 +0000 (15:04 -0700)
Pull RISC-V updates from Palmer Dabbelt:

 - Enabling the FPU is now a static_key

 - Improvements to the Svpbmt support

 - CPU topology bindings for a handful of systems

 - Support for systems with 64-bit hart IDs

 - Many settings have been enabled in the defconfig, including both
   support for the StarFive systems and many of the Docker requirements

There are also a handful of cleanups and improvements, as usual.

* tag 'riscv-for-linus-5.20-mw0' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (28 commits)
  riscv: enable Docker requirements in defconfig
  riscv: convert the t-head pbmt errata to use the __nops macro
  riscv: introduce nops and __nops macros for NOP sequences
  RISC-V: Add fast call path of crash_kexec()
  riscv: mmap with PROT_WRITE but no PROT_READ is invalid
  riscv/efi_stub: Add 64bit boot-hartid support on RV64
  riscv: cpu: Add 64bit hartid support on RV64
  riscv: smp: Add 64bit hartid support on RV64
  riscv: spinwait: Fix hartid variable type
  riscv: cpu_ops_sbi: Add 64bit hartid support on RV64
  riscv: dts: sifive: "fix" pmic watchdog node name
  riscv: dts: canaan: Add k210 topology information
  riscv: dts: sifive: Add fu740 topology information
  riscv: dts: sifive: Add fu540 topology information
  riscv: dts: starfive: Add JH7100 CPU topology
  RISC-V: Add CONFIG_{NON,}PORTABLE
  riscv: config: enable SOC_STARFIVE in defconfig
  riscv: dts: microchip: Add mpfs' topology information
  riscv: Kconfig.socs: Add comments
  riscv: Kconfig.erratas: Add comments
  ...

1  2 
arch/riscv/Kconfig
arch/riscv/boot/dts/microchip/mpfs.dtsi
arch/riscv/include/asm/errata_list.h
arch/riscv/include/asm/pci.h
drivers/irqchip/irq-sifive-plic.c

diff --combined arch/riscv/Kconfig
@@@ -38,7 -38,7 +38,7 @@@ config RISC
        select ARCH_SUPPORTS_ATOMIC_RMW
        select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
        select ARCH_SUPPORTS_HUGETLBFS if MMU
 -      select ARCH_SUPPORTS_PAGE_TABLE_CHECK
 +      select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
        select ARCH_USE_MEMTEST
        select ARCH_USE_QUEUED_RWLOCKS
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
@@@ -86,7 -86,7 +86,7 @@@
        select HAVE_ARCH_THREAD_STRUCT_WHITELIST
        select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
        select HAVE_ASM_MODVERSIONS
 -      select HAVE_CONTEXT_TRACKING
 +      select HAVE_CONTEXT_TRACKING_USER
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_EBPF_JIT if MMU
@@@ -223,6 -223,21 +223,21 @@@ source "arch/riscv/Kconfig.erratas
  
  menu "Platform type"
  
+ config NONPORTABLE
+       bool "Allow configurations that result in non-portable kernels"
+       help
+         RISC-V kernel binaries are compatible between all known systems
+         whenever possible, but there are some use cases that can only be
+         satisfied by configurations that result in kernel binaries that are
+         not portable between systems.
+         Selecting N does not guarantee kernels will be portable to all known
+         systems.  Selecting any of the options guarded by NONPORTABLE will
+         result in kernel binaries that are unlikely to be portable between
+         systems.
+         If unsure, say N.
  choice
        prompt "Base ISA"
        default ARCH_RV64I
  
  config ARCH_RV32I
        bool "RV32I"
+       depends on NONPORTABLE
        select 32BIT
        select GENERIC_LIB_ASHLDI3
        select GENERIC_LIB_ASHRDI3
@@@ -352,11 -368,11 +368,11 @@@ config RISCV_ISA_
        bool "Emit compressed instructions when building Linux"
        default y
        help
-          Adds "C" to the ISA subsets that the toolchain is allowed to emit
-          when building Linux, which results in compressed instructions in the
-          Linux binary.
+         Adds "C" to the ISA subsets that the toolchain is allowed to emit
+         when building Linux, which results in compressed instructions in the
+         Linux binary.
  
-          If you don't know what to do here, say Y.
+         If you don't know what to do here, say Y.
  
  config RISCV_ISA_SVPBMT
        bool "SVPBMT extension support"
@@@ -385,7 -401,7 +401,7 @@@ config FP
  
          If you don't know what to do here, say Y.
  
- endmenu
+ endmenu # "Platform type"
  
  menu "Kernel features"
  
@@@ -474,7 -490,7 +490,7 @@@ config COMPA
  
          If you want to execute 32-bit userspace applications, say Y.
  
- endmenu
+ endmenu # "Kernel features"
  
  menu "Boot options"
  
@@@ -510,7 -526,6 +526,6 @@@ config CMDLINE_EXTEN
          cases where the provided arguments are insufficient and
          you don't want to or cannot modify them.
  
  config CMDLINE_FORCE
        bool "Always use the default kernel command string"
        help
@@@ -553,6 -568,7 +568,7 @@@ config STACKPROTECTOR_PER_TAS
  
  config PHYS_RAM_BASE_FIXED
        bool "Explicitly specified physical RAM address"
+       depends on NONPORTABLE
        default n
  
  config PHYS_RAM_BASE
  
  config XIP_KERNEL
        bool "Kernel Execute-In-Place from ROM"
-       depends on MMU && SPARSEMEM
+       depends on MMU && SPARSEMEM && NONPORTABLE
        # This prevents XIP from being enabled by all{yes,mod}config, which
        # fail to build since XIP doesn't support large kernels.
        depends on !COMPILE_TEST
@@@ -602,23 -618,30 +618,30 @@@ config XIP_PHYS_ADD
          be linked for and stored to.  This address is dependent on your
          own flash usage.
  
- endmenu
+ endmenu # "Boot options"
  
  config BUILTIN_DTB
        bool
-       depends on OF
+       depends on OF && NONPORTABLE
        default y if XIP_KERNEL
  
+ config PORTABLE
+       bool
+       default !NONPORTABLE
+       select EFI
+       select OF
+       select MMU
  menu "Power management options"
  
  source "kernel/power/Kconfig"
  
- endmenu
+ endmenu # "Power management options"
  
  menu "CPU Power Management"
  
  source "drivers/cpuidle/Kconfig"
  
- endmenu
+ endmenu # "CPU Power Management"
  
  source "arch/riscv/kvm/Kconfig"
@@@ -50,7 -50,6 +50,7 @@@
                        riscv,isa = "rv64imafdc";
                        clocks = <&clkcfg CLK_CPU>;
                        tlb-split;
 +                      next-level-cache = <&cctrllr>;
                        status = "okay";
  
                        cpu1_intc: interrupt-controller {
@@@ -78,7 -77,6 +78,7 @@@
                        riscv,isa = "rv64imafdc";
                        clocks = <&clkcfg CLK_CPU>;
                        tlb-split;
 +                      next-level-cache = <&cctrllr>;
                        status = "okay";
  
                        cpu2_intc: interrupt-controller {
                        riscv,isa = "rv64imafdc";
                        clocks = <&clkcfg CLK_CPU>;
                        tlb-split;
 +                      next-level-cache = <&cctrllr>;
                        status = "okay";
  
                        cpu3_intc: interrupt-controller {
                        riscv,isa = "rv64imafdc";
                        clocks = <&clkcfg CLK_CPU>;
                        tlb-split;
 +                      next-level-cache = <&cctrllr>;
                        status = "okay";
                        cpu4_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                interrupt-controller;
                        };
                };
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&cpu0>;
+                               };
+                               core1 {
+                                       cpu = <&cpu1>;
+                               };
+                               core2 {
+                                       cpu = <&cpu2>;
+                               };
+                               core3 {
+                                       cpu = <&cpu3>;
+                               };
+                               core4 {
+                                       cpu = <&cpu4>;
+                               };
+                       };
+               };
        };
  
        refclk: mssrefclk {
                        riscv,ndev = <186>;
                };
  
 +              pdma: dma-controller@3000000 {
 +                      compatible = "sifive,fu540-c000-pdma", "sifive,pdma0";
 +                      reg = <0x0 0x3000000 0x0 0x8000>;
 +                      interrupt-parent = <&plic>;
 +                      interrupts = <5 6>, <7 8>, <9 10>, <11 12>;
 +                      dma-channels = <4>;
 +                      #dma-cells = <1>;
 +              };
 +
                clkcfg: clkcfg@20002000 {
                        compatible = "microchip,mpfs-clkcfg";
                        reg = <0x0 0x20002000 0x0 0x1000>, <0x0 0x3E001000 0x0 0x1000>;
                        interrupt-parent = <&plic>;
                        interrupts = <54>;
                        clocks = <&clkcfg CLK_SPI0>;
-                       spi-max-frequency = <25000000>;
                        status = "disabled";
                };
  
                        interrupt-parent = <&plic>;
                        interrupts = <55>;
                        clocks = <&clkcfg CLK_SPI1>;
-                       spi-max-frequency = <25000000>;
                        status = "disabled";
                };
  
                        interrupt-parent = <&plic>;
                        interrupts = <85>;
                        clocks = <&clkcfg CLK_QSPI>;
-                       spi-max-frequency = <25000000>;
                        status = "disabled";
                };
  
                        status = "disabled";
                };
  
 +              can0: can@2010c000 {
 +                      compatible = "microchip,mpfs-can";
 +                      reg = <0x0 0x2010c000 0x0 0x1000>;
 +                      clocks = <&clkcfg CLK_CAN0>;
 +                      interrupt-parent = <&plic>;
 +                      interrupts = <56>;
 +                      status = "disabled";
 +              };
 +
 +              can1: can@2010d000 {
 +                      compatible = "microchip,mpfs-can";
 +                      reg = <0x0 0x2010d000 0x0 0x1000>;
 +                      clocks = <&clkcfg CLK_CAN1>;
 +                      interrupt-parent = <&plic>;
 +                      interrupts = <57>;
 +                      status = "disabled";
 +              };
 +
                mac0: ethernet@20110000 {
                        compatible = "cdns,macb";
                        reg = <0x0 0x20110000 0x0 0x2000>;
@@@ -68,27 -68,21 +68,21 @@@ asm(ALTERNATIVE_2("li %0, 0\t\nnop"
   */
  #define ALT_THEAD_PMA(_val)                                           \
  asm volatile(ALTERNATIVE(                                             \
-       "nop\n\t"                                                       \
-       "nop\n\t"                                                       \
-       "nop\n\t"                                                       \
-       "nop\n\t"                                                       \
-       "nop\n\t"                                                       \
-       "nop\n\t"                                                       \
-       "nop",                                                          \
+       __nops(7),                                                      \
 -      "li      t3, %2\n\t"                                            \
 -      "slli    t3, t3, %4\n\t"                                        \
 +      "li      t3, %1\n\t"                                            \
 +      "slli    t3, t3, %3\n\t"                                        \
        "and     t3, %0, t3\n\t"                                        \
        "bne     t3, zero, 2f\n\t"                                      \
 -      "li      t3, %3\n\t"                                            \
 -      "slli    t3, t3, %4\n\t"                                        \
 +      "li      t3, %2\n\t"                                            \
 +      "slli    t3, t3, %3\n\t"                                        \
        "or      %0, %0, t3\n\t"                                        \
        "2:",  THEAD_VENDOR_ID,                                         \
                ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)            \
        : "+r"(_val)                                                    \
 -      : "0"(_val),                                                    \
 -        "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT),              \
 +      : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT),              \
          "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT),                 \
 -        "I"(ALT_THEAD_PBMT_SHIFT))
 +        "I"(ALT_THEAD_PBMT_SHIFT)                                     \
 +      : "t3")
  #else
  #define ALT_THEAD_PMA(_val)
  #endif
  
  #include <asm/io.h>
  
 -/* RISC-V shim does not initialize PCI bus */
 -#define pcibios_assign_all_busses() 1
 -
 -#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
 -
 -extern int isa_dma_bridge_buggy;
 -
 -#ifdef CONFIG_PCI
 -static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 -{
 -      /* no legacy IRQ on risc-v */
 -      return -ENODEV;
 -}
 -
 -static inline int pci_proc_domain(struct pci_bus *bus)
 -{
 -      /* always show the domain in /proc */
 -      return 1;
 -}
 -
 -#ifdef        CONFIG_NUMA
 -
+ #define PCIBIOS_MIN_IO                4
+ #define PCIBIOS_MIN_MEM               16
 +#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
  static inline int pcibus_to_node(struct pci_bus *bus)
  {
        return dev_to_node(&bus->dev);
@@@ -22,9 -46,8 +25,9 @@@
                                 cpu_all_mask :                         \
                                 cpumask_of_node(pcibus_to_node(bus)))
  #endif
 -#endif        /* CONFIG_NUMA */
 +#endif /* defined(CONFIG_PCI) && defined(CONFIG_NUMA) */
  
 -#endif  /* CONFIG_PCI */
 +/* Generic PCI */
 +#include <asm-generic/pci.h>
  
  #endif  /* _ASM_RISCV_PCI_H */
  #define       PLIC_DISABLE_THRESHOLD          0x7
  #define       PLIC_ENABLE_THRESHOLD           0
  
 +#define PLIC_QUIRK_EDGE_INTERRUPT     0
 +
  struct plic_priv {
        struct cpumask lmask;
        struct irq_domain *irqdomain;
        void __iomem *regs;
 +      unsigned long plic_quirks;
  };
  
  struct plic_handler {
@@@ -84,8 -81,6 +84,8 @@@ static int plic_parent_irq __ro_after_i
  static bool plic_cpuhp_setup_done __ro_after_init;
  static DEFINE_PER_CPU(struct plic_handler, plic_handlers);
  
 +static int plic_irq_set_type(struct irq_data *d, unsigned int type);
 +
  static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)
  {
        u32 __iomem *reg = enable_base + (hwirq / 32) * sizeof(u32);
@@@ -108,43 -103,37 +108,43 @@@ static inline void plic_irq_toggle(cons
                                   struct irq_data *d, int enable)
  {
        int cpu;
 -      struct plic_priv *priv = irq_data_get_irq_chip_data(d);
  
 -      writel(enable, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
        for_each_cpu(cpu, mask) {
                struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
  
 -              if (handler->present &&
 -                  cpumask_test_cpu(cpu, &handler->priv->lmask))
 -                      plic_toggle(handler, d->hwirq, enable);
 +              plic_toggle(handler, d->hwirq, enable);
        }
  }
  
 +static void plic_irq_enable(struct irq_data *d)
 +{
 +      plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 1);
 +}
 +
 +static void plic_irq_disable(struct irq_data *d)
 +{
 +      plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 0);
 +}
 +
  static void plic_irq_unmask(struct irq_data *d)
  {
 -      struct cpumask amask;
 -      unsigned int cpu;
        struct plic_priv *priv = irq_data_get_irq_chip_data(d);
  
 -      cpumask_and(&amask, &priv->lmask, cpu_online_mask);
 -      cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
 -                                         &amask);
 -      if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
 -              return;
 -      plic_irq_toggle(cpumask_of(cpu), d, 1);
 +      writel(1, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
  }
  
  static void plic_irq_mask(struct irq_data *d)
  {
        struct plic_priv *priv = irq_data_get_irq_chip_data(d);
  
 -      plic_irq_toggle(&priv->lmask, d, 0);
 +      writel(0, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
 +}
 +
 +static void plic_irq_eoi(struct irq_data *d)
 +{
 +      struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
 +
 +      writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
  }
  
  #ifdef CONFIG_SMP
@@@ -165,68 -154,38 +165,68 @@@ static int plic_set_affinity(struct irq
        if (cpu >= nr_cpu_ids)
                return -EINVAL;
  
 -      plic_irq_toggle(&priv->lmask, d, 0);
 -      plic_irq_toggle(cpumask_of(cpu), d, !irqd_irq_masked(d));
 +      plic_irq_disable(d);
  
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
  
 +      if (!irqd_irq_disabled(d))
 +              plic_irq_enable(d);
 +
        return IRQ_SET_MASK_OK_DONE;
  }
  #endif
  
 -static void plic_irq_eoi(struct irq_data *d)
 -{
 -      struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
 -
 -      if (irqd_irq_masked(d)) {
 -              plic_irq_unmask(d);
 -              writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
 -              plic_irq_mask(d);
 -      } else {
 -              writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
 -      }
 -}
 +static struct irq_chip plic_edge_chip = {
 +      .name           = "SiFive PLIC",
 +      .irq_enable     = plic_irq_enable,
 +      .irq_disable    = plic_irq_disable,
 +      .irq_ack        = plic_irq_eoi,
 +      .irq_mask       = plic_irq_mask,
 +      .irq_unmask     = plic_irq_unmask,
 +#ifdef CONFIG_SMP
 +      .irq_set_affinity = plic_set_affinity,
 +#endif
 +      .irq_set_type   = plic_irq_set_type,
 +      .flags          = IRQCHIP_AFFINITY_PRE_STARTUP,
 +};
  
  static struct irq_chip plic_chip = {
        .name           = "SiFive PLIC",
 +      .irq_enable     = plic_irq_enable,
 +      .irq_disable    = plic_irq_disable,
        .irq_mask       = plic_irq_mask,
        .irq_unmask     = plic_irq_unmask,
        .irq_eoi        = plic_irq_eoi,
  #ifdef CONFIG_SMP
        .irq_set_affinity = plic_set_affinity,
  #endif
 +      .irq_set_type   = plic_irq_set_type,
 +      .flags          = IRQCHIP_AFFINITY_PRE_STARTUP,
  };
  
 +static int plic_irq_set_type(struct irq_data *d, unsigned int type)
 +{
 +      struct plic_priv *priv = irq_data_get_irq_chip_data(d);
 +
 +      if (!test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks))
 +              return IRQ_SET_MASK_OK_NOCOPY;
 +
 +      switch (type) {
 +      case IRQ_TYPE_EDGE_RISING:
 +              irq_set_chip_handler_name_locked(d, &plic_edge_chip,
 +                                               handle_edge_irq, NULL);
 +              break;
 +      case IRQ_TYPE_LEVEL_HIGH:
 +              irq_set_chip_handler_name_locked(d, &plic_chip,
 +                                               handle_fasteoi_irq, NULL);
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      return IRQ_SET_MASK_OK;
 +}
 +
  static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
                              irq_hw_number_t hwirq)
  {
        return 0;
  }
  
 +static int plic_irq_domain_translate(struct irq_domain *d,
 +                                   struct irq_fwspec *fwspec,
 +                                   unsigned long *hwirq,
 +                                   unsigned int *type)
 +{
 +      struct plic_priv *priv = d->host_data;
 +
 +      if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks))
 +              return irq_domain_translate_twocell(d, fwspec, hwirq, type);
 +
 +      return irq_domain_translate_onecell(d, fwspec, hwirq, type);
 +}
 +
  static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
                                 unsigned int nr_irqs, void *arg)
  {
        unsigned int type;
        struct irq_fwspec *fwspec = arg;
  
 -      ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
 +      ret = plic_irq_domain_translate(domain, fwspec, &hwirq, &type);
        if (ret)
                return ret;
  
  }
  
  static const struct irq_domain_ops plic_irqdomain_ops = {
 -      .translate      = irq_domain_translate_onecell,
 +      .translate      = plic_irq_domain_translate,
        .alloc          = plic_irq_domain_alloc,
        .free           = irq_domain_free_irqs_top,
  };
@@@ -335,9 -281,8 +335,9 @@@ static int plic_starting_cpu(unsigned i
        return 0;
  }
  
 -static int __init plic_init(struct device_node *node,
 -              struct device_node *parent)
 +static int __init __plic_init(struct device_node *node,
 +                            struct device_node *parent,
 +                            unsigned long plic_quirks)
  {
        int error = 0, nr_contexts, nr_handlers = 0, i;
        u32 nr_irqs;
        if (!priv)
                return -ENOMEM;
  
 +      priv->plic_quirks = plic_quirks;
 +
        priv->regs = of_iomap(node, 0);
        if (WARN_ON(!priv->regs)) {
                error = -EIO;
        for (i = 0; i < nr_contexts; i++) {
                struct of_phandle_args parent;
                irq_hw_number_t hwirq;
-               int cpu, hartid;
+               int cpu;
+               unsigned long hartid;
  
                if (of_irq_parse_one(node, i, &parent)) {
                        pr_err("failed to parse parent for context %d.\n", i);
                        continue;
                }
  
-               hartid = riscv_of_parent_hartid(parent.np);
-               if (hartid < 0) {
+               error = riscv_of_parent_hartid(parent.np, &hartid);
+               if (error < 0) {
                        pr_warn("failed to parse hart ID for context %d.\n", i);
                        continue;
                }
                        i * CONTEXT_ENABLE_SIZE;
                handler->priv = priv;
  done:
 -              for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
 +              for (hwirq = 1; hwirq <= nr_irqs; hwirq++) {
                        plic_toggle(handler, hwirq, 0);
 +                      writel(1, priv->regs + PRIORITY_BASE +
 +                                hwirq * PRIORITY_PER_ID);
 +              }
                nr_handlers++;
        }
  
@@@ -470,20 -411,6 +471,20 @@@ out_free_priv
        return error;
  }
  
 +static int __init plic_init(struct device_node *node,
 +                          struct device_node *parent)
 +{
 +      return __plic_init(node, parent, 0);
 +}
 +
  IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
  IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
 -IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */
 +
 +static int __init plic_edge_init(struct device_node *node,
 +                               struct device_node *parent)
 +{
 +      return __plic_init(node, parent, BIT(PLIC_QUIRK_EDGE_INTERRUPT));
 +}
 +
 +IRQCHIP_DECLARE(andestech_nceplic100, "andestech,nceplic100", plic_edge_init);
 +IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init);