Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARCv2: IDU-intc: Use build registers for getting numbers of interrupts

This enhancement is needed to allow masking all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <&core_intc>;
#interrupt-cells = <2>;
interrupts = <24 25 26 27 28 29 30 31>;
};

and after:

idu_intc: idu-interrupt-controller {
compatible = "snps,archs-idu-intc";
interrupt-controller;
interrupt-parent = <&core_intc>;
#interrupt-cells = <2>;
};

Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>

authored by

Yuriy Kolerov and committed by
Vineet Gupta
6f0310a1 be568e78

+26 -10
+9 -10
arch/arc/kernel/mcip.c
··· 230 230 231 231 }; 232 232 233 - static irq_hw_number_t idu_first_hwirq; 234 - 235 233 static void idu_cascade_isr(struct irq_desc *desc) 236 234 { 237 235 struct irq_domain *idu_domain = irq_desc_get_handler_data(desc); 238 236 struct irq_chip *core_chip = irq_desc_get_chip(desc); 239 237 irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc)); 240 - irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq; 238 + irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ; 241 239 242 240 chained_irq_enter(core_chip, desc); 243 241 generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq)); ··· 281 283 idu_of_init(struct device_node *intc, struct device_node *parent) 282 284 { 283 285 struct irq_domain *domain; 284 - /* Read IDU BCR to confirm nr_irqs */ 285 - int nr_irqs = of_irq_count(intc); 286 + int nr_irqs; 286 287 int i, virq; 287 288 struct mcip_bcr mp; 289 + struct mcip_idu_bcr idu_bcr; 288 290 289 291 READ_BCR(ARC_REG_MCIP_BCR, mp); 290 292 291 293 if (!mp.idu) 292 294 panic("IDU not detected, but DeviceTree using it"); 293 295 294 - pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs); 296 + READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr); 297 + nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr); 298 + 299 + pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs); 295 300 296 301 domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL); 297 302 ··· 307 306 * however we need it to get the parent virq and set IDU handler 308 307 * as first level isr 309 308 */ 310 - virq = irq_of_parse_and_map(intc, i); 311 - if (!i) 312 - idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq)); 313 - 309 + virq = irq_create_mapping(NULL, i + FIRST_EXT_IRQ); 310 + BUG_ON(!virq); 314 311 irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain); 315 312 } 316 313
+17
include/soc/arc/mcip.h
··· 14 14 #include <soc/arc/aux.h> 15 15 16 16 #define ARC_REG_MCIP_BCR 0x0d0 17 + #define ARC_REG_MCIP_IDU_BCR 0x0D5 17 18 #define ARC_REG_MCIP_CMD 0x600 18 19 #define ARC_REG_MCIP_WDATA 0x601 19 20 #define ARC_REG_MCIP_READBACK 0x602 ··· 69 68 pad3:1, pw_dom:1, pad4:6; 70 69 #endif 71 70 }; 71 + 72 + struct mcip_idu_bcr { 73 + #ifdef CONFIG_CPU_BIG_ENDIAN 74 + unsigned int pad:21, cirqnum:3, ver:8; 75 + #else 76 + unsigned int ver:8, cirqnum:3, pad:21; 77 + #endif 78 + }; 79 + 80 + 81 + /* 82 + * Build register for IDU contains not an actual number of supported common 83 + * interrupts but an exponent of 2 which must be multiplied by 4 to 84 + * get a number of supported common interrupts. 85 + */ 86 + #define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum)) 72 87 73 88 /* 74 89 * MCIP programming model