summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorJason Cooper <jason@lakedaemon.net>2015-03-14 21:46:04 -0400
committerJason Cooper <jason@lakedaemon.net>2015-03-14 21:46:04 -0400
commit9df5126b69294788f5ca3dc7aeafc80a42c6d4a7 (patch)
treef577adbc91229110f692732a6ea2ece28128a003 /drivers/irqchip
parent6e3aca4419e1363ff9abb3e1710c52858fc45b66 (diff)
parent28da06dfd9e4b04577c517f9c4b52aaa73e3d1c7 (diff)
Merge branch 'irqchip/mvebu' into irqchip/core
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c105
1 files changed, 75 insertions, 30 deletions
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 463c235acbdc..b36373c019ba 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -38,6 +38,8 @@
38/* Interrupt Controller Registers Map */ 38/* Interrupt Controller Registers Map */
39#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) 39#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
40#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C) 40#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
41#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
42#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)
41 43
42#define ARMADA_370_XP_INT_CONTROL (0x00) 44#define ARMADA_370_XP_INT_CONTROL (0x00)
43#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) 45#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
@@ -56,6 +58,7 @@
56#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) 58#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
57 59
58#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5) 60#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5)
61#define ARMADA_370_XP_FABRIC_IRQ (3)
59 62
60#define IPI_DOORBELL_START (0) 63#define IPI_DOORBELL_START (0)
61#define IPI_DOORBELL_END (8) 64#define IPI_DOORBELL_END (8)
@@ -69,6 +72,7 @@ static void __iomem *per_cpu_int_base;
69static void __iomem *main_int_base; 72static void __iomem *main_int_base;
70static struct irq_domain *armada_370_xp_mpic_domain; 73static struct irq_domain *armada_370_xp_mpic_domain;
71static u32 doorbell_mask_reg; 74static u32 doorbell_mask_reg;
75static int parent_irq;
72#ifdef CONFIG_PCI_MSI 76#ifdef CONFIG_PCI_MSI
73static struct irq_domain *armada_370_xp_msi_domain; 77static struct irq_domain *armada_370_xp_msi_domain;
74static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); 78static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
@@ -76,6 +80,17 @@ static DEFINE_MUTEX(msi_used_lock);
76static phys_addr_t msi_doorbell_addr; 80static phys_addr_t msi_doorbell_addr;
77#endif 81#endif
78 82
83static inline bool is_percpu_irq(irq_hw_number_t irq)
84{
85 switch (irq) {
86 case ARMADA_370_XP_TIMER0_PER_CPU_IRQ:
87 case ARMADA_370_XP_FABRIC_IRQ:
88 return true;
89 default:
90 return false;
91 }
92}
93
79/* 94/*
80 * In SMP mode: 95 * In SMP mode:
81 * For shared global interrupts, mask/unmask global enable bit 96 * For shared global interrupts, mask/unmask global enable bit
@@ -85,7 +100,7 @@ static void armada_370_xp_irq_mask(struct irq_data *d)
85{ 100{
86 irq_hw_number_t hwirq = irqd_to_hwirq(d); 101 irq_hw_number_t hwirq = irqd_to_hwirq(d);
87 102
88 if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) 103 if (!is_percpu_irq(hwirq))
89 writel(hwirq, main_int_base + 104 writel(hwirq, main_int_base +
90 ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); 105 ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
91 else 106 else
@@ -97,7 +112,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
97{ 112{
98 irq_hw_number_t hwirq = irqd_to_hwirq(d); 113 irq_hw_number_t hwirq = irqd_to_hwirq(d);
99 114
100 if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) 115 if (!is_percpu_irq(hwirq))
101 writel(hwirq, main_int_base + 116 writel(hwirq, main_int_base +
102 ARMADA_370_XP_INT_SET_ENABLE_OFFS); 117 ARMADA_370_XP_INT_SET_ENABLE_OFFS);
103 else 118 else
@@ -286,14 +301,14 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
286 unsigned int virq, irq_hw_number_t hw) 301 unsigned int virq, irq_hw_number_t hw)
287{ 302{
288 armada_370_xp_irq_mask(irq_get_irq_data(virq)); 303 armada_370_xp_irq_mask(irq_get_irq_data(virq));
289 if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) 304 if (!is_percpu_irq(hw))
290 writel(hw, per_cpu_int_base + 305 writel(hw, per_cpu_int_base +
291 ARMADA_370_XP_INT_CLEAR_MASK_OFFS); 306 ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
292 else 307 else
293 writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); 308 writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
294 irq_set_status_flags(virq, IRQ_LEVEL); 309 irq_set_status_flags(virq, IRQ_LEVEL);
295 310
296 if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) { 311 if (is_percpu_irq(hw)) {
297 irq_set_percpu_devid(virq); 312 irq_set_percpu_devid(virq);
298 irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, 313 irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
299 handle_percpu_devid_irq); 314 handle_percpu_devid_irq);
@@ -307,28 +322,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
307 return 0; 322 return 0;
308} 323}
309 324
310#ifdef CONFIG_SMP
311static void armada_mpic_send_doorbell(const struct cpumask *mask,
312 unsigned int irq)
313{
314 int cpu;
315 unsigned long map = 0;
316
317 /* Convert our logical CPU mask into a physical one. */
318 for_each_cpu(cpu, mask)
319 map |= 1 << cpu_logical_map(cpu);
320
321 /*
322 * Ensure that stores to Normal memory are visible to the
323 * other CPUs before issuing the IPI.
324 */
325 dsb();
326
327 /* submit softirq */
328 writel((map << 8) | irq, main_int_base +
329 ARMADA_370_XP_SW_TRIG_INT_OFFS);
330}
331
332static void armada_xp_mpic_smp_cpu_init(void) 325static void armada_xp_mpic_smp_cpu_init(void)
333{ 326{
334 u32 control; 327 u32 control;
@@ -351,11 +344,45 @@ static void armada_xp_mpic_smp_cpu_init(void)
351 writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); 344 writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
352} 345}
353 346
347static void armada_xp_mpic_perf_init(void)
348{
349 unsigned long cpuid = cpu_logical_map(smp_processor_id());
350
351 /* Enable Performance Counter Overflow interrupts */
352 writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
353 per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);
354}
355
356#ifdef CONFIG_SMP
357static void armada_mpic_send_doorbell(const struct cpumask *mask,
358 unsigned int irq)
359{
360 int cpu;
361 unsigned long map = 0;
362
363 /* Convert our logical CPU mask into a physical one. */
364 for_each_cpu(cpu, mask)
365 map |= 1 << cpu_logical_map(cpu);
366
367 /*
368 * Ensure that stores to Normal memory are visible to the
369 * other CPUs before issuing the IPI.
370 */
371 dsb();
372
373 /* submit softirq */
374 writel((map << 8) | irq, main_int_base +
375 ARMADA_370_XP_SW_TRIG_INT_OFFS);
376}
377
354static int armada_xp_mpic_secondary_init(struct notifier_block *nfb, 378static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
355 unsigned long action, void *hcpu) 379 unsigned long action, void *hcpu)
356{ 380{
357 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) 381 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
382 armada_xp_mpic_perf_init();
358 armada_xp_mpic_smp_cpu_init(); 383 armada_xp_mpic_smp_cpu_init();
384 }
385
359 return NOTIFY_OK; 386 return NOTIFY_OK;
360} 387}
361 388
@@ -364,6 +391,21 @@ static struct notifier_block armada_370_xp_mpic_cpu_notifier = {
364 .priority = 100, 391 .priority = 100,
365}; 392};
366 393
394static int mpic_cascaded_secondary_init(struct notifier_block *nfb,
395 unsigned long action, void *hcpu)
396{
397 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
398 armada_xp_mpic_perf_init();
399 enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
400 }
401
402 return NOTIFY_OK;
403}
404
405static struct notifier_block mpic_cascaded_cpu_notifier = {
406 .notifier_call = mpic_cascaded_secondary_init,
407 .priority = 100,
408};
367#endif /* CONFIG_SMP */ 409#endif /* CONFIG_SMP */
368 410
369static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { 411static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
@@ -539,7 +581,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
539 struct device_node *parent) 581 struct device_node *parent)
540{ 582{
541 struct resource main_int_res, per_cpu_int_res; 583 struct resource main_int_res, per_cpu_int_res;
542 int parent_irq, nr_irqs, i; 584 int nr_irqs, i;
543 u32 control; 585 u32 control;
544 586
545 BUG_ON(of_address_to_resource(node, 0, &main_int_res)); 587 BUG_ON(of_address_to_resource(node, 0, &main_int_res));
@@ -572,9 +614,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
572 614
573 BUG_ON(!armada_370_xp_mpic_domain); 615 BUG_ON(!armada_370_xp_mpic_domain);
574 616
575#ifdef CONFIG_SMP 617 /* Setup for the boot CPU */
618 armada_xp_mpic_perf_init();
576 armada_xp_mpic_smp_cpu_init(); 619 armada_xp_mpic_smp_cpu_init();
577#endif
578 620
579 armada_370_xp_msi_init(node, main_int_res.start); 621 armada_370_xp_msi_init(node, main_int_res.start);
580 622
@@ -587,6 +629,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
587 register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier); 629 register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier);
588#endif 630#endif
589 } else { 631 } else {
632#ifdef CONFIG_SMP
633 register_cpu_notifier(&mpic_cascaded_cpu_notifier);
634#endif
590 irq_set_chained_handler(parent_irq, 635 irq_set_chained_handler(parent_irq,
591 armada_370_xp_mpic_handle_cascade_irq); 636 armada_370_xp_mpic_handle_cascade_irq);
592 } 637 }