mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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 <mason.huo@starfivetech.com> Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Link: https://patch.msgid.link/20260416064751.632138-5-changhuang.liang@starfivetech.com
This commit is contained in:
parent
2f59ca1854
commit
5d1b12880f
|
|
@ -19,10 +19,11 @@
|
|||
#include <linux/reset.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#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;
|
||||
|
||||
raw_spin_lock(&irqc->lock);
|
||||
starfive_intc_bit_set(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_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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user