diff options
Diffstat (limited to 'drivers/irqchip/irq-realtek-rtl.c')
| -rw-r--r-- | drivers/irqchip/irq-realtek-rtl.c | 18 | 
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/irqchip/irq-realtek-rtl.c b/drivers/irqchip/irq-realtek-rtl.c index fd9f275592d2..50a56820c99b 100644 --- a/drivers/irqchip/irq-realtek-rtl.c +++ b/drivers/irqchip/irq-realtek-rtl.c @@ -62,7 +62,7 @@ static struct irq_chip realtek_ictl_irq = {  static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)  { -	irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq); +	irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);  	return 0;  } @@ -76,16 +76,20 @@ static void realtek_irq_dispatch(struct irq_desc *desc)  {  	struct irq_chip *chip = irq_desc_get_chip(desc);  	struct irq_domain *domain; -	unsigned int pending; +	unsigned long pending; +	unsigned int soc_int;  	chained_irq_enter(chip, desc);  	pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR)); +  	if (unlikely(!pending)) {  		spurious_interrupt();  		goto out;  	} +  	domain = irq_desc_get_handler_data(desc); -	generic_handle_domain_irq(domain, __ffs(pending)); +	for_each_set_bit(soc_int, &pending, 32) +		generic_handle_domain_irq(domain, soc_int);  out:  	chained_irq_exit(chip, desc); @@ -95,7 +99,8 @@ out:   * SoC interrupts are cascaded to MIPS CPU interrupts according to the   * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for   * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts - * thus go into 4 IRRs. + * thus go into 4 IRRs. A routing value of '0' means the interrupt is left + * disconnected. Routing values {1..15} connect to output lines {0..14}.   */  static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)  { @@ -134,7 +139,7 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do  		of_node_put(cpu_ictl);  		cpu_int = be32_to_cpup(imap + 2); -		if (cpu_int > 7) +		if (cpu_int > 7 || cpu_int < 2)  			return -EINVAL;  		if (!(mips_irqs_set & BIT(cpu_int))) { @@ -143,7 +148,8 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do  			mips_irqs_set |= BIT(cpu_int);  		} -		regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32; +		/* Use routing values (1..6) for CPU interrupts (2..7) */ +		regs[(soc_int * 4) / 32] |= (cpu_int - 1) << (soc_int * 4) % 32;  		imap += 3;  	}  |