aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuriy Kolerov <yuriy.kolerov@synopsys.com>2017-01-31 06:45:23 -0500
committerVineet Gupta <vgupta@synopsys.com>2017-02-06 12:37:57 -0500
commit6f0310a126f1a46cac366327751bb7eb8941bdde (patch)
tree09e1d9b27a23ec959ea8ed4435a4e62e79e26c83
parentbe568e78dbb35383fdfd0563fd0cfbbff1bc42d0 (diff)
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>
-rw-r--r--arch/arc/kernel/mcip.c19
-rw-r--r--include/soc/arc/mcip.h17
2 files changed, 26 insertions, 10 deletions
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 9f6b68fd4f3b..21dc89704113 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -230,14 +230,12 @@ static struct irq_chip idu_irq_chip = {
230 230
231}; 231};
232 232
233static irq_hw_number_t idu_first_hwirq;
234
235static void idu_cascade_isr(struct irq_desc *desc) 233static void idu_cascade_isr(struct irq_desc *desc)
236{ 234{
237 struct irq_domain *idu_domain = irq_desc_get_handler_data(desc); 235 struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
238 struct irq_chip *core_chip = irq_desc_get_chip(desc); 236 struct irq_chip *core_chip = irq_desc_get_chip(desc);
239 irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc)); 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 chained_irq_enter(core_chip, desc); 240 chained_irq_enter(core_chip, desc);
243 generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq)); 241 generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -283,17 +281,20 @@ static int __init
283idu_of_init(struct device_node *intc, struct device_node *parent) 281idu_of_init(struct device_node *intc, struct device_node *parent)
284{ 282{
285 struct irq_domain *domain; 283 struct irq_domain *domain;
286 /* Read IDU BCR to confirm nr_irqs */ 284 int nr_irqs;
287 int nr_irqs = of_irq_count(intc);
288 int i, virq; 285 int i, virq;
289 struct mcip_bcr mp; 286 struct mcip_bcr mp;
287 struct mcip_idu_bcr idu_bcr;
290 288
291 READ_BCR(ARC_REG_MCIP_BCR, mp); 289 READ_BCR(ARC_REG_MCIP_BCR, mp);
292 290
293 if (!mp.idu) 291 if (!mp.idu)
294 panic("IDU not detected, but DeviceTree using it"); 292 panic("IDU not detected, but DeviceTree using it");
295 293
296 pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs); 294 READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr);
295 nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr);
296
297 pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs);
297 298
298 domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL); 299 domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL);
299 300
@@ -306,10 +307,8 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
306 * however we need it to get the parent virq and set IDU handler 307 * however we need it to get the parent virq and set IDU handler
307 * as first level isr 308 * as first level isr
308 */ 309 */
309 virq = irq_of_parse_and_map(intc, i); 310 virq = irq_create_mapping(NULL, i + FIRST_EXT_IRQ);
310 if (!i) 311 BUG_ON(!virq);
311 idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
312
313 irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain); 312 irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
314 } 313 }
315 314
diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index 4b6b489a8d7c..c2d1b15da136 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -14,6 +14,7 @@
14#include <soc/arc/aux.h> 14#include <soc/arc/aux.h>
15 15
16#define ARC_REG_MCIP_BCR 0x0d0 16#define ARC_REG_MCIP_BCR 0x0d0
17#define ARC_REG_MCIP_IDU_BCR 0x0D5
17#define ARC_REG_MCIP_CMD 0x600 18#define ARC_REG_MCIP_CMD 0x600
18#define ARC_REG_MCIP_WDATA 0x601 19#define ARC_REG_MCIP_WDATA 0x601
19#define ARC_REG_MCIP_READBACK 0x602 20#define ARC_REG_MCIP_READBACK 0x602
@@ -69,6 +70,22 @@ struct mcip_bcr {
69#endif 70#endif
70}; 71};
71 72
73struct mcip_idu_bcr {
74#ifdef CONFIG_CPU_BIG_ENDIAN
75 unsigned int pad:21, cirqnum:3, ver:8;
76#else
77 unsigned int ver:8, cirqnum:3, pad:21;
78#endif
79};
80
81
82/*
83 * Build register for IDU contains not an actual number of supported common
84 * interrupts but an exponent of 2 which must be multiplied by 4 to
85 * get a number of supported common interrupts.
86 */
87#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum))
88
72/* 89/*
73 * MCIP programming model 90 * MCIP programming model
74 * 91 *