diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2022-03-14 10:23:22 +0100 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2022-03-14 10:23:22 +0100 |
commit | f0fae8a0edd445d042ee94153f127e8939fcf3d3 (patch) | |
tree | e0fda9e211750c5ecc1838403bb2bb2fa59a9ed8 /drivers/irqchip/irq-sifive-plic.c | |
parent | ff8dcfebe08dfb2524041116d4afce53ffe0b015 (diff) | |
parent | de26a7424331493311c08625a700cf45d1eaf151 (diff) | |
download | linux-f0fae8a0edd445d042ee94153f127e8939fcf3d3.tar.gz |
Merge tag 'irqchip-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates from Marc Zyngier:
- Add support for the STM32MP13 variant
- Move parent device away from struct irq_chip
- Remove all instances of non-const strings assigned to
struct irq_chip::name, enabling a nice cleanup for VIC and GIC)
- Simplify the Qualcomm PDC driver
- A bunch of SiFive PLIC cleanups
- Add support for a new variant of the Meson GPIO block
- Add support for the irqchip side of the Apple M1 PMU
- Add support for the Apple M1 Pro/Max AICv2 irqchip
- Add support for the Qualcomm MPM wakeup gadget
- Move the Xilinx driver over to the generic irqdomain handling
- Tiny speedup for IPIs on GICv3 systems
- The usual odd cleanups
Link: https://lore.kernel.org/all/20220313105142.704579-1-maz@kernel.org
Diffstat (limited to 'drivers/irqchip/irq-sifive-plic.c')
-rw-r--r-- | drivers/irqchip/irq-sifive-plic.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index 09cc98266d30..bb87e4c3b88e 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -44,8 +44,8 @@ * Each hart context has a vector of interrupt enable bits associated with it. * There's one bit for each interrupt source. */ -#define ENABLE_BASE 0x2000 -#define ENABLE_PER_HART 0x80 +#define CONTEXT_ENABLE_BASE 0x2000 +#define CONTEXT_ENABLE_SIZE 0x80 /* * Each hart context has a set of control registers associated with it. Right @@ -53,7 +53,7 @@ * take an interrupt, and a register to claim interrupts. */ #define CONTEXT_BASE 0x200000 -#define CONTEXT_PER_HART 0x1000 +#define CONTEXT_SIZE 0x1000 #define CONTEXT_THRESHOLD 0x00 #define CONTEXT_CLAIM 0x04 @@ -81,17 +81,21 @@ static int plic_parent_irq __ro_after_init; static bool plic_cpuhp_setup_done __ro_after_init; static DEFINE_PER_CPU(struct plic_handler, plic_handlers); -static inline void plic_toggle(struct plic_handler *handler, - int hwirq, int enable) +static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable) { - u32 __iomem *reg = handler->enable_base + (hwirq / 32) * sizeof(u32); + u32 __iomem *reg = enable_base + (hwirq / 32) * sizeof(u32); u32 hwirq_mask = 1 << (hwirq % 32); - raw_spin_lock(&handler->enable_lock); if (enable) writel(readl(reg) | hwirq_mask, reg); else writel(readl(reg) & ~hwirq_mask, reg); +} + +static void plic_toggle(struct plic_handler *handler, int hwirq, int enable) +{ + raw_spin_lock(&handler->enable_lock); + __plic_toggle(handler->enable_base, hwirq, enable); raw_spin_unlock(&handler->enable_lock); } @@ -324,8 +328,18 @@ static int __init plic_init(struct device_node *node, * Skip contexts other than external interrupts for our * privilege level. */ - if (parent.args[0] != RV_IRQ_EXT) + if (parent.args[0] != RV_IRQ_EXT) { + /* Disable S-mode enable bits if running in M-mode. */ + if (IS_ENABLED(CONFIG_RISCV_M_MODE)) { + void __iomem *enable_base = priv->regs + + CONTEXT_ENABLE_BASE + + i * CONTEXT_ENABLE_SIZE; + + for (hwirq = 1; hwirq <= nr_irqs; hwirq++) + __plic_toggle(enable_base, hwirq, 0); + } continue; + } hartid = riscv_of_parent_hartid(parent.np); if (hartid < 0) { @@ -361,11 +375,11 @@ static int __init plic_init(struct device_node *node, cpumask_set_cpu(cpu, &priv->lmask); handler->present = true; - handler->hart_base = - priv->regs + CONTEXT_BASE + i * CONTEXT_PER_HART; + handler->hart_base = priv->regs + CONTEXT_BASE + + i * CONTEXT_SIZE; raw_spin_lock_init(&handler->enable_lock); - handler->enable_base = - priv->regs + ENABLE_BASE + i * ENABLE_PER_HART; + handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + + i * CONTEXT_ENABLE_SIZE; handler->priv = priv; done: for (hwirq = 1; hwirq <= nr_irqs; hwirq++) |