Commit da33f31d authored by Marc Zyngier's avatar Marc Zyngier Committed by Jason Cooper

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: default avatarMarc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1416839720-18400-12-git-send-email-marc.zyngier@arm.comSigned-off-by: default avatarJason Cooper <jason@lakedaemon.net>
parent 4c21f3c2
...@@ -76,9 +76,6 @@ static inline void __iomem *gic_dist_base(struct irq_data *d) ...@@ -76,9 +76,6 @@ static inline void __iomem *gic_dist_base(struct irq_data *d)
if (d->hwirq <= 1023) /* SPI -> dist_base */ if (d->hwirq <= 1023) /* SPI -> dist_base */
return gic_data.dist_base; return gic_data.dist_base;
if (d->hwirq >= 8192)
BUG(); /* LPI Detected!!! */
return NULL; return NULL;
} }
...@@ -276,11 +273,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs ...@@ -276,11 +273,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
do { do {
irqnr = gic_read_iar(); irqnr = gic_read_iar();
if (likely(irqnr > 15 && irqnr < 1020)) { if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
int err; int err;
err = handle_domain_irq(gic_data.domain, irqnr, regs); err = handle_domain_irq(gic_data.domain, irqnr, regs);
if (err) { if (err) {
WARN_ONCE(true, "Unexpected SPI received!\n"); WARN_ONCE(true, "Unexpected interrupt received!\n");
gic_write_eoir(irqnr); gic_write_eoir(irqnr);
} }
continue; continue;
...@@ -393,6 +390,11 @@ static void gic_cpu_sys_reg_init(void) ...@@ -393,6 +390,11 @@ static void gic_cpu_sys_reg_init(void)
gic_write_grpen1(1); gic_write_grpen1(1);
} }
static int gic_dist_supports_lpis(void)
{
return !!(readl_relaxed(gic_data.dist_base + GICD_TYPER) & GICD_TYPER_LPIS);
}
static void gic_cpu_init(void) static void gic_cpu_init(void)
{ {
void __iomem *rbase; void __iomem *rbase;
...@@ -407,6 +409,10 @@ static void gic_cpu_init(void) ...@@ -407,6 +409,10 @@ static void gic_cpu_init(void)
gic_cpu_config(rbase, gic_redist_wait_for_rwp); gic_cpu_config(rbase, gic_redist_wait_for_rwp);
/* Give LPIs a spin */
if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
its_cpu_init();
/* initialise system registers */ /* initialise system registers */
gic_cpu_sys_reg_init(); gic_cpu_sys_reg_init();
} }
...@@ -593,12 +599,21 @@ static struct irq_chip gic_chip = { ...@@ -593,12 +599,21 @@ static struct irq_chip gic_chip = {
.irq_set_affinity = gic_set_affinity, .irq_set_affinity = gic_set_affinity,
}; };
#define GIC_ID_NR (1U << gic_data.rdists.id_bits)
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw) irq_hw_number_t hw)
{ {
/* SGIs are private to the core kernel */ /* SGIs are private to the core kernel */
if (hw < 16) if (hw < 16)
return -EPERM; return -EPERM;
/* Nothing here */
if (hw >= gic_data.irq_nr && hw < 8192)
return -EPERM;
/* Off limits */
if (hw >= GIC_ID_NR)
return -EPERM;
/* PPIs */ /* PPIs */
if (hw < 32) { if (hw < 32) {
irq_set_percpu_devid(irq); irq_set_percpu_devid(irq);
...@@ -612,7 +627,15 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, ...@@ -612,7 +627,15 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
handle_fasteoi_irq, NULL, NULL); handle_fasteoi_irq, NULL, NULL);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
} }
irq_set_chip_data(irq, d->host_data); /* LPIs */
if (hw >= 8192 && hw < GIC_ID_NR) {
if (!gic_dist_supports_lpis())
return -EPERM;
irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
set_irq_flags(irq, IRQF_VALID);
}
return 0; return 0;
} }
...@@ -633,6 +656,9 @@ static int gic_irq_domain_xlate(struct irq_domain *d, ...@@ -633,6 +656,9 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
case 1: /* PPI */ case 1: /* PPI */
*out_hwirq = intspec[1] + 16; *out_hwirq = intspec[1] + 16;
break; break;
case GIC_IRQ_TYPE_LPI: /* LPI */
*out_hwirq = intspec[1];
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -759,6 +785,9 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare ...@@ -759,6 +785,9 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
set_handle_irq(gic_handle_irq); set_handle_irq(gic_handle_irq);
if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
its_init(node, &gic_data.rdists, gic_data.domain);
gic_smp_init(); gic_smp_init();
gic_dist_init(); gic_dist_init();
gic_cpu_init(); gic_cpu_init();
......
...@@ -318,6 +318,11 @@ static inline void gic_write_eoir(u64 irq) ...@@ -318,6 +318,11 @@ static inline void gic_write_eoir(u64 irq)
isb(); isb();
} }
struct irq_domain;
int its_cpu_init(void);
int its_init(struct device_node *node, struct rdists *rdists,
struct irq_domain *domain);
#endif #endif
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment