diff options
| -rw-r--r-- | drivers/irqchip/irq-gic-v5-irs.c | 92 |
1 files changed, 50 insertions, 42 deletions
diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c index ce2732d649a3..7db44a91f043 100644 --- a/drivers/irqchip/irq-gic-v5-irs.c +++ b/drivers/irqchip/irq-gic-v5-irs.c @@ -545,15 +545,13 @@ int gicv5_irs_register_cpu(int cpuid) static void __init gicv5_irs_init_bases(struct gicv5_irs_chip_data *irs_data, void __iomem *irs_base, - struct fwnode_handle *handle) + bool noncoherent) { - struct device_node *np = to_of_node(handle); u32 cr0, cr1; - irs_data->fwnode = handle; irs_data->irs_base = irs_base; - if (of_property_read_bool(np, "dma-noncoherent")) { + if (noncoherent) { /* * A non-coherent IRS implies that some cache levels cannot be * used coherently by the cores and GIC. Our only option is to mark @@ -678,12 +676,52 @@ static void irs_setup_pri_bits(u32 idr1) } } -static int __init gicv5_irs_init(struct device_node *node) +static int __init gicv5_irs_init(struct gicv5_irs_chip_data *irs_data) +{ + u32 spi_count, idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR2); + + if (WARN(!FIELD_GET(GICV5_IRS_IDR2_LPI, idr), + "LPI support not available - no IPIs, can't proceed\n")) { + return -ENODEV; + } + + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR7); + irs_data->spi_min = FIELD_GET(GICV5_IRS_IDR7_SPI_BASE, idr); + + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR6); + irs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr); + + /* + * Do the global setting only on the first IRS. + * Global properties (iaffid_bits, global spi count) are guaranteed to + * be consistent across IRSes by the architecture. + */ + if (list_empty(&irs_nodes)) { + + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1); + irs_setup_pri_bits(idr); + + idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR5); + + spi_count = FIELD_GET(GICV5_IRS_IDR5_SPI_RANGE, idr); + gicv5_global_data.global_spi_count = spi_count; + + gicv5_init_lpi_domain(); + + pr_debug("Detected %u SPIs globally\n", spi_count); + } + + list_add_tail(&irs_data->entry, &irs_nodes); + + return 0; +} + +static int __init gicv5_irs_of_init(struct device_node *node) { struct gicv5_irs_chip_data *irs_data; void __iomem *irs_base; - u32 idr, spi_count; u8 iaffid_bits; + u32 idr; int ret; irs_data = kzalloc(sizeof(*irs_data), GFP_KERNEL); @@ -705,7 +743,8 @@ static int __init gicv5_irs_init(struct device_node *node) goto out_err; } - gicv5_irs_init_bases(irs_data, irs_base, &node->fwnode); + irs_data->fwnode = of_fwnode_handle(node); + gicv5_irs_init_bases(irs_data, irs_base, of_property_read_bool(node, "dma-noncoherent")); idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1); iaffid_bits = FIELD_GET(GICV5_IRS_IDR1_IAFFID_BITS, idr) + 1; @@ -716,18 +755,9 @@ static int __init gicv5_irs_init(struct device_node *node) goto out_iomem; } - idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR2); - if (WARN(!FIELD_GET(GICV5_IRS_IDR2_LPI, idr), - "LPI support not available - no IPIs, can't proceed\n")) { - ret = -ENODEV; + ret = gicv5_irs_init(irs_data); + if (ret) goto out_iomem; - } - - idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR7); - irs_data->spi_min = FIELD_GET(GICV5_IRS_IDR7_SPI_BASE, idr); - - idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR6); - irs_data->spi_range = FIELD_GET(GICV5_IRS_IDR6_SPI_IRS_RANGE, idr); if (irs_data->spi_range) { pr_info("%s detected SPI range [%u-%u]\n", @@ -737,29 +767,7 @@ static int __init gicv5_irs_init(struct device_node *node) irs_data->spi_range - 1); } - /* - * Do the global setting only on the first IRS. - * Global properties (iaffid_bits, global spi count) are guaranteed to - * be consistent across IRSes by the architecture. - */ - if (list_empty(&irs_nodes)) { - - idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR1); - irs_setup_pri_bits(idr); - - idr = irs_readl_relaxed(irs_data, GICV5_IRS_IDR5); - - spi_count = FIELD_GET(GICV5_IRS_IDR5_SPI_RANGE, idr); - gicv5_global_data.global_spi_count = spi_count; - - gicv5_init_lpi_domain(); - - pr_debug("Detected %u SPIs globally\n", spi_count); - } - - list_add_tail(&irs_data->entry, &irs_nodes); - - return 0; + return ret; out_iomem: iounmap(irs_base); @@ -818,7 +826,7 @@ int __init gicv5_irs_of_probe(struct device_node *parent) if (!of_device_is_compatible(np, "arm,gic-v5-irs")) continue; - ret = gicv5_irs_init(np); + ret = gicv5_irs_of_init(np); if (ret) pr_err("Failed to init IRS %s\n", np->full_name); } |
