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
}
}
-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);
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;
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",
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);
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);
}