From: Mason Huo Date: Thu, 16 Apr 2026 06:47:50 +0000 (-0700) Subject: irqchip/starfive: Increase the interrupt source number up to 64 X-Git-Tag: v7.2-rc1~204^2~25 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=5d1b12880fd878f315f41ac5dd19fd9fb476e7a0;p=thirdparty%2Fkernel%2Flinux.git irqchip/starfive: Increase the interrupt source number up to 64 StarFive JHB100 SoC interrupt controller actually supports 64 interrupt sources, the original code only supported up to 32. now it is extended to 64. Also use guard(raw_spinlock) to automatically release spinlocks. Signed-off-by: Mason Huo Signed-off-by: Changhuang Liang Signed-off-by: Thomas Gleixner Link: https://patch.msgid.link/20260416064751.632138-5-changhuang.liang@starfivetech.com --- diff --git a/drivers/irqchip/irq-starfive-jhb100-intc.c b/drivers/irqchip/irq-starfive-jhb100-intc.c index c33229b39a409..b3d86bd926ed8 100644 --- a/drivers/irqchip/irq-starfive-jhb100-intc.c +++ b/drivers/irqchip/irq-starfive-jhb100-intc.c @@ -19,10 +19,11 @@ #include #include -#define STARFIVE_INTC_SRC0_CLEAR 0x10 -#define STARFIVE_INTC_SRC0_MASK 0x14 -#define STARFIVE_INTC_SRC0_INT 0x1c +#define STARFIVE_INTC_SRC_CLEAR(n) (0x10 + ((n) * 0x20)) +#define STARFIVE_INTC_SRC_MASK(n) (0x14 + ((n) * 0x20)) +#define STARFIVE_INTC_SRC_INT(n) (0x1c + ((n) * 0x20)) +#define STARFIVE_INTC_NUM 2 #define STARFIVE_INTC_SRC_IRQ_NUM 32 struct starfive_irq_chip { @@ -54,19 +55,25 @@ static void starfive_intc_bit_clear(struct starfive_irq_chip *irqc, static void starfive_intc_unmask(struct irq_data *d) { struct starfive_irq_chip *irqc = irq_data_get_irq_chip_data(d); + int i, bitpos; - raw_spin_lock(&irqc->lock); - starfive_intc_bit_clear(irqc, STARFIVE_INTC_SRC0_MASK, BIT(d->hwirq)); - raw_spin_unlock(&irqc->lock); + i = d->hwirq / STARFIVE_INTC_SRC_IRQ_NUM; + bitpos = d->hwirq % STARFIVE_INTC_SRC_IRQ_NUM; + + guard(raw_spinlock)(&irqc->lock); + starfive_intc_bit_clear(irqc, STARFIVE_INTC_SRC_MASK(i), BIT(bitpos)); } static void starfive_intc_mask(struct irq_data *d) { struct starfive_irq_chip *irqc = irq_data_get_irq_chip_data(d); + int i, bitpos; + + i = d->hwirq / STARFIVE_INTC_SRC_IRQ_NUM; + bitpos = d->hwirq % STARFIVE_INTC_SRC_IRQ_NUM; - raw_spin_lock(&irqc->lock); - starfive_intc_bit_set(irqc, STARFIVE_INTC_SRC0_MASK, BIT(d->hwirq)); - raw_spin_unlock(&irqc->lock); + guard(raw_spinlock)(&irqc->lock); + starfive_intc_bit_set(irqc, STARFIVE_INTC_SRC_MASK(i), BIT(bitpos)); } static struct irq_chip intc_dev = { @@ -98,16 +105,19 @@ static void starfive_intc_irq_handler(struct irq_desc *desc) chained_irq_enter(chip, desc); - value = ioread32(irqc->base + STARFIVE_INTC_SRC0_INT); - while (value) { - hwirq = ffs(value) - 1; + for (int i = 0; i < STARFIVE_INTC_NUM; i++) { + value = ioread32(irqc->base + STARFIVE_INTC_SRC_INT(i)); + while (value) { + hwirq = ffs(value) - 1; - generic_handle_domain_irq(irqc->domain, hwirq); + generic_handle_domain_irq(irqc->domain, + hwirq + i * STARFIVE_INTC_SRC_IRQ_NUM); - starfive_intc_bit_set(irqc, STARFIVE_INTC_SRC0_CLEAR, BIT(hwirq)); - starfive_intc_bit_clear(irqc, STARFIVE_INTC_SRC0_CLEAR, BIT(hwirq)); + starfive_intc_bit_set(irqc, STARFIVE_INTC_SRC_CLEAR(i), BIT(hwirq)); + starfive_intc_bit_clear(irqc, STARFIVE_INTC_SRC_CLEAR(i), BIT(hwirq)); - __clear_bit(hwirq, &value); + __clear_bit(hwirq, &value); + } } chained_irq_exit(chip, desc); @@ -140,7 +150,8 @@ static int starfive_intc_probe(struct platform_device *pdev, struct device_node raw_spin_lock_init(&irqc->lock); - irqc->domain = irq_domain_create_linear(of_fwnode_handle(intc), STARFIVE_INTC_SRC_IRQ_NUM, + irqc->domain = irq_domain_create_linear(of_fwnode_handle(intc), + STARFIVE_INTC_SRC_IRQ_NUM * STARFIVE_INTC_NUM, &starfive_intc_domain_ops, irqc); if (!irqc->domain) return dev_err_probe(&pdev->dev, -EINVAL, "Unable to create IRQ domain\n"); @@ -155,7 +166,7 @@ static int starfive_intc_probe(struct platform_device *pdev, struct device_node irqc); dev_info(&pdev->dev, "Interrupt controller register, nr_irqs %d\n", - STARFIVE_INTC_SRC_IRQ_NUM); + STARFIVE_INTC_SRC_IRQ_NUM * STARFIVE_INTC_NUM); retain_and_null_ptr(irqc); return 0;