Commit 92877b9e authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch irq/plic-cleanups into irq/irqchip-next



* irq/plic-cleanups:
  : .
  : SiFive PLIC cleanups from Niklas Cassel:
  :
  : - Clarify some of the namings in the driver
  :
  : - Make sure S-mode interrupts are disabled when running in M-mode
  : .
  irqchip/sifive-plic: Disable S-mode IRQs if running in M-mode
  irqchip/sifive-plic: Improve naming scheme for per context offsets

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 0c8b522d 098fdbc3
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -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++)