diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2014-11-24 09:35:18 -0500 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-11-26 10:55:15 -0500 |
commit | da33f31de3e1eebb198109c1cccdc3a094e369c4 (patch) | |
tree | 8f98c92f8f2a11c40d631e2e1a3f8d9617962b4e /drivers/irqchip | |
parent | 4c21f3c26ecc25c5520628eef8e900a36e6c6ab4 (diff) |
irqchip: GICv3: ITS: plug ITS init into main GICv3 code
As the ITS is always a subsystem if GICv3, its probing/init is
driven by the main GICv3 code.
Plug that code in (guarded by a config option).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1416839720-18400-12-git-send-email-marc.zyngier@arm.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 43e57da0d80e..1a146ccee701 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -76,9 +76,6 @@ static inline void __iomem *gic_dist_base(struct irq_data *d) | |||
76 | if (d->hwirq <= 1023) /* SPI -> dist_base */ | 76 | if (d->hwirq <= 1023) /* SPI -> dist_base */ |
77 | return gic_data.dist_base; | 77 | return gic_data.dist_base; |
78 | 78 | ||
79 | if (d->hwirq >= 8192) | ||
80 | BUG(); /* LPI Detected!!! */ | ||
81 | |||
82 | return NULL; | 79 | return NULL; |
83 | } | 80 | } |
84 | 81 | ||
@@ -276,11 +273,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs | |||
276 | do { | 273 | do { |
277 | irqnr = gic_read_iar(); | 274 | irqnr = gic_read_iar(); |
278 | 275 | ||
279 | if (likely(irqnr > 15 && irqnr < 1020)) { | 276 | if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) { |
280 | int err; | 277 | int err; |
281 | err = handle_domain_irq(gic_data.domain, irqnr, regs); | 278 | err = handle_domain_irq(gic_data.domain, irqnr, regs); |
282 | if (err) { | 279 | if (err) { |
283 | WARN_ONCE(true, "Unexpected SPI received!\n"); | 280 | WARN_ONCE(true, "Unexpected interrupt received!\n"); |
284 | gic_write_eoir(irqnr); | 281 | gic_write_eoir(irqnr); |
285 | } | 282 | } |
286 | continue; | 283 | continue; |
@@ -393,6 +390,11 @@ static void gic_cpu_sys_reg_init(void) | |||
393 | gic_write_grpen1(1); | 390 | gic_write_grpen1(1); |
394 | } | 391 | } |
395 | 392 | ||
393 | static int gic_dist_supports_lpis(void) | ||
394 | { | ||
395 | return !!(readl_relaxed(gic_data.dist_base + GICD_TYPER) & GICD_TYPER_LPIS); | ||
396 | } | ||
397 | |||
396 | static void gic_cpu_init(void) | 398 | static void gic_cpu_init(void) |
397 | { | 399 | { |
398 | void __iomem *rbase; | 400 | void __iomem *rbase; |
@@ -407,6 +409,10 @@ static void gic_cpu_init(void) | |||
407 | 409 | ||
408 | gic_cpu_config(rbase, gic_redist_wait_for_rwp); | 410 | gic_cpu_config(rbase, gic_redist_wait_for_rwp); |
409 | 411 | ||
412 | /* Give LPIs a spin */ | ||
413 | if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis()) | ||
414 | its_cpu_init(); | ||
415 | |||
410 | /* initialise system registers */ | 416 | /* initialise system registers */ |
411 | gic_cpu_sys_reg_init(); | 417 | gic_cpu_sys_reg_init(); |
412 | } | 418 | } |
@@ -593,12 +599,21 @@ static struct irq_chip gic_chip = { | |||
593 | .irq_set_affinity = gic_set_affinity, | 599 | .irq_set_affinity = gic_set_affinity, |
594 | }; | 600 | }; |
595 | 601 | ||
602 | #define GIC_ID_NR (1U << gic_data.rdists.id_bits) | ||
603 | |||
596 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | 604 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, |
597 | irq_hw_number_t hw) | 605 | irq_hw_number_t hw) |
598 | { | 606 | { |
599 | /* SGIs are private to the core kernel */ | 607 | /* SGIs are private to the core kernel */ |
600 | if (hw < 16) | 608 | if (hw < 16) |
601 | return -EPERM; | 609 | return -EPERM; |
610 | /* Nothing here */ | ||
611 | if (hw >= gic_data.irq_nr && hw < 8192) | ||
612 | return -EPERM; | ||
613 | /* Off limits */ | ||
614 | if (hw >= GIC_ID_NR) | ||
615 | return -EPERM; | ||
616 | |||
602 | /* PPIs */ | 617 | /* PPIs */ |
603 | if (hw < 32) { | 618 | if (hw < 32) { |
604 | irq_set_percpu_devid(irq); | 619 | irq_set_percpu_devid(irq); |
@@ -612,7 +627,15 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | |||
612 | handle_fasteoi_irq, NULL, NULL); | 627 | handle_fasteoi_irq, NULL, NULL); |
613 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 628 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
614 | } | 629 | } |
615 | irq_set_chip_data(irq, d->host_data); | 630 | /* LPIs */ |
631 | if (hw >= 8192 && hw < GIC_ID_NR) { | ||
632 | if (!gic_dist_supports_lpis()) | ||
633 | return -EPERM; | ||
634 | irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data, | ||
635 | handle_fasteoi_irq, NULL, NULL); | ||
636 | set_irq_flags(irq, IRQF_VALID); | ||
637 | } | ||
638 | |||
616 | return 0; | 639 | return 0; |
617 | } | 640 | } |
618 | 641 | ||
@@ -633,6 +656,9 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
633 | case 1: /* PPI */ | 656 | case 1: /* PPI */ |
634 | *out_hwirq = intspec[1] + 16; | 657 | *out_hwirq = intspec[1] + 16; |
635 | break; | 658 | break; |
659 | case GIC_IRQ_TYPE_LPI: /* LPI */ | ||
660 | *out_hwirq = intspec[1]; | ||
661 | break; | ||
636 | default: | 662 | default: |
637 | return -EINVAL; | 663 | return -EINVAL; |
638 | } | 664 | } |
@@ -759,6 +785,9 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare | |||
759 | 785 | ||
760 | set_handle_irq(gic_handle_irq); | 786 | set_handle_irq(gic_handle_irq); |
761 | 787 | ||
788 | if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis()) | ||
789 | its_init(node, &gic_data.rdists, gic_data.domain); | ||
790 | |||
762 | gic_smp_init(); | 791 | gic_smp_init(); |
763 | gic_dist_init(); | 792 | gic_dist_init(); |
764 | gic_cpu_init(); | 793 | gic_cpu_init(); |