diff options
-rw-r--r-- | arch/arc/kernel/mcip.c | 19 | ||||
-rw-r--r-- | include/soc/arc/mcip.h | 17 |
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 | ||
233 | static irq_hw_number_t idu_first_hwirq; | ||
234 | |||
235 | static void idu_cascade_isr(struct irq_desc *desc) | 233 | static 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 | |||
283 | idu_of_init(struct device_node *intc, struct device_node *parent) | 281 | idu_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 | ||
73 | struct 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 | * |