Commit 1a60e1e6 authored by Marc Zyngier's avatar Marc Zyngier

irqchip/gic: Prepare for more than 16 PPIs

GICv3.1 allows up to 80 PPIs (16 legaci PPIs and 64 Extended PPIs),
meaning we can't just leave the old 16 hardcoded everywhere.

We also need to add the infrastructure to discover the number of PPIs
on a per redistributor basis, although we still pretend there is only
16 of them for now.

No functional change.
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 211bddd2
...@@ -128,26 +128,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs, ...@@ -128,26 +128,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
sync_access(); sync_access();
} }
void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
{ {
int i; int i;
/* /*
* Deal with the banked PPI and SGI interrupts - disable all * Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled. * private interrupts. Make sure everything is deactivated.
* Make sure everything is deactivated.
*/ */
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR); for (i = 0; i < nr; i += 32) {
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR); writel_relaxed(GICD_INT_EN_CLR_X32,
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); base + GIC_DIST_ACTIVE_CLEAR + i / 8);
writel_relaxed(GICD_INT_EN_CLR_X32,
base + GIC_DIST_ENABLE_CLEAR + i / 8);
}
/* /*
* Set priority on PPI and SGI interrupts * Set priority on PPI and SGI interrupts
*/ */
for (i = 0; i < 32; i += 4) for (i = 0; i < nr; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, writel_relaxed(GICD_INT_DEF_PRI_X4,
base + GIC_DIST_PRI + i * 4 / 4); base + GIC_DIST_PRI + i * 4 / 4);
/* Ensure all SGI interrupts are now enabled */
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
if (sync_access) if (sync_access)
sync_access(); sync_access();
} }
...@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type, ...@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void)); void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs, void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void)); void (*sync_access)(void));
void gic_cpu_config(void __iomem *base, void (*sync_access)(void)); void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void));
void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void *data); void *data);
void gic_enable_of_quirks(const struct device_node *np, void gic_enable_of_quirks(const struct device_node *np,
......
...@@ -51,6 +51,7 @@ struct gic_chip_data { ...@@ -51,6 +51,7 @@ struct gic_chip_data {
u32 nr_redist_regions; u32 nr_redist_regions;
u64 flags; u64 flags;
bool has_rss; bool has_rss;
unsigned int ppi_nr;
struct partition_desc *ppi_descs[16]; struct partition_desc *ppi_descs[16];
}; };
...@@ -812,19 +813,24 @@ static int gic_populate_rdist(void) ...@@ -812,19 +813,24 @@ static int gic_populate_rdist(void)
return -ENODEV; return -ENODEV;
} }
static int __gic_update_vlpi_properties(struct redist_region *region, static int __gic_update_rdist_properties(struct redist_region *region,
void __iomem *ptr) void __iomem *ptr)
{ {
u64 typer = gic_read_typer(ptr + GICR_TYPER); u64 typer = gic_read_typer(ptr + GICR_TYPER);
gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS); gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS); gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
gic_data.ppi_nr = 16;
return 1; return 1;
} }
static void gic_update_vlpi_properties(void) static void gic_update_rdist_properties(void)
{ {
gic_iterate_rdists(__gic_update_vlpi_properties); gic_data.ppi_nr = UINT_MAX;
gic_iterate_rdists(__gic_update_rdist_properties);
if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
gic_data.ppi_nr = 0;
pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
pr_info("%sVLPI support, %sdirect LPI support\n", pr_info("%sVLPI support, %sdirect LPI support\n",
!gic_data.rdists.has_vlpis ? "no " : "", !gic_data.rdists.has_vlpis ? "no " : "",
!gic_data.rdists.has_direct_lpi ? "no " : ""); !gic_data.rdists.has_direct_lpi ? "no " : "");
...@@ -968,6 +974,7 @@ static int gic_dist_supports_lpis(void) ...@@ -968,6 +974,7 @@ static int gic_dist_supports_lpis(void)
static void gic_cpu_init(void) static void gic_cpu_init(void)
{ {
void __iomem *rbase; void __iomem *rbase;
int i;
/* Register ourselves with the rest of the world */ /* Register ourselves with the rest of the world */
if (gic_populate_rdist()) if (gic_populate_rdist())
...@@ -978,9 +985,10 @@ static void gic_cpu_init(void) ...@@ -978,9 +985,10 @@ static void gic_cpu_init(void)
rbase = gic_data_rdist_sgi_base(); rbase = gic_data_rdist_sgi_base();
/* Configure SGIs/PPIs as non-secure Group-1 */ /* Configure SGIs/PPIs as non-secure Group-1 */
writel_relaxed(~0, rbase + GICR_IGROUPR0); for (i = 0; i < gic_data.ppi_nr + 16; i += 32)
writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);
gic_cpu_config(rbase, gic_redist_wait_for_rwp); gic_cpu_config(rbase, gic_data.ppi_nr + 16, gic_redist_wait_for_rwp);
/* initialise system registers */ /* initialise system registers */
gic_cpu_sys_reg_init(); gic_cpu_sys_reg_init();
...@@ -1449,7 +1457,7 @@ static int __init gic_init_bases(void __iomem *dist_base, ...@@ -1449,7 +1457,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
set_handle_irq(gic_handle_irq); set_handle_irq(gic_handle_irq);
gic_update_vlpi_properties(); gic_update_rdist_properties();
gic_smp_init(); gic_smp_init();
gic_dist_init(); gic_dist_init();
......
...@@ -543,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic) ...@@ -543,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
gic_cpu_map[i] &= ~cpu_mask; gic_cpu_map[i] &= ~cpu_mask;
} }
gic_cpu_config(dist_base, NULL); gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
gic_cpu_if_up(gic); gic_cpu_if_up(gic);
......
...@@ -273,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc) ...@@ -273,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
if (i != cpu) if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask; hip04_cpu_map[i] &= ~cpu_mask;
gic_cpu_config(dist_base, NULL); gic_cpu_config(dist_base, 32, NULL);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL); writel_relaxed(1, base + GIC_CPU_CTRL);
......
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