diff options
author | Andre Przywara <andre.przywara@arm.com> | 2017-04-25 15:39:27 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2017-06-09 11:16:47 +0100 |
commit | 14421de9e076ac4f22dd2b2715bfc878986dc66a (patch) | |
tree | c548e56fd484aa0c9a3a27dfe80908a0243e489e | |
parent | 12ca14010ba43fc76c3a00bee4c594d417b729e6 (diff) | |
download | kvmtool-14421de9e076ac4f22dd2b2715bfc878986dc66a.tar.gz |
arm: FDT: create MSI controller DT node
The ARM GICv3 ITS requires a separate device tree node to describe
the ITS. Add this as a child to the GIC interrupt controller node
to let a guest discover and use the ITS if the user requests it.
Since we now need to specify #address-cells for the GIC node, we
have to add two zeroes to the interrupt map to match that.
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arm/gic.c | 22 | ||||
-rw-r--r-- | arm/include/arm-common/fdt-arch.h | 2 | ||||
-rw-r--r-- | arm/pci.c | 5 |
3 files changed, 27 insertions, 2 deletions
@@ -251,7 +251,8 @@ late_init(gic__init_gic) void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type) { - const char *compatible; + const char *compatible, *msi_compatible = NULL; + u64 msi_prop[2]; u64 reg_prop[] = { cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE), 0, 0, /* to be filled */ @@ -263,6 +264,9 @@ void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type) reg_prop[2] = cpu_to_fdt64(ARM_GIC_CPUI_BASE); reg_prop[3] = cpu_to_fdt64(ARM_GIC_CPUI_SIZE); break; + case IRQCHIP_GICV3_ITS: + msi_compatible = "arm,gic-v3-its"; + /* fall-through */ case IRQCHIP_GICV3: compatible = "arm,gic-v3"; reg_prop[2] = cpu_to_fdt64(gic_redists_base); @@ -278,6 +282,22 @@ void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type) _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0)); _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_GIC)); + _FDT(fdt_property_cell(fdt, "#address-cells", 2)); + _FDT(fdt_property_cell(fdt, "#size-cells", 2)); + + if (msi_compatible) { + _FDT(fdt_property(fdt, "ranges", NULL, 0)); + + _FDT(fdt_begin_node(fdt, "msic")); + _FDT(fdt_property_string(fdt, "compatible", msi_compatible)); + _FDT(fdt_property(fdt, "msi-controller", NULL, 0)); + _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_MSI)); + msi_prop[0] = cpu_to_fdt64(gic_msi_base); + msi_prop[1] = cpu_to_fdt64(gic_msi_size); + _FDT(fdt_property(fdt, "reg", msi_prop, sizeof(msi_prop))); + _FDT(fdt_end_node(fdt)); + } + _FDT(fdt_end_node(fdt)); } diff --git a/arm/include/arm-common/fdt-arch.h b/arm/include/arm-common/fdt-arch.h index 53ba6331..60c2d406 100644 --- a/arm/include/arm-common/fdt-arch.h +++ b/arm/include/arm-common/fdt-arch.h @@ -1,6 +1,6 @@ #ifndef ARM__FDT_H #define ARM__FDT_H -enum phandles {PHANDLE_RESERVED = 0, PHANDLE_GIC, PHANDLES_MAX}; +enum phandles {PHANDLE_RESERVED = 0, PHANDLE_GIC, PHANDLE_MSI, PHANDLES_MAX}; #endif /* ARM__FDT_H */ @@ -18,6 +18,8 @@ struct of_gic_irq { struct of_interrupt_map_entry { struct of_pci_irq_mask pci_irq_mask; u32 gic_phandle; + u32 gic_addr_hi; + u32 gic_addr_lo; struct of_gic_irq gic_irq; } __attribute__((packed)); @@ -65,6 +67,7 @@ void pci__generate_fdt_nodes(void *fdt) _FDT(fdt_property(fdt, "bus-range", bus_range, sizeof(bus_range))); _FDT(fdt_property(fdt, "reg", &cfg_reg_prop, sizeof(cfg_reg_prop))); _FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges))); + _FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_MSI)); /* Generate the interrupt map ... */ dev_hdr = device__first_dev(DEVICE_BUS_PCI); @@ -85,6 +88,8 @@ void pci__generate_fdt_nodes(void *fdt) .pci_pin = cpu_to_fdt32(pin), }, .gic_phandle = cpu_to_fdt32(PHANDLE_GIC), + .gic_addr_hi = 0, + .gic_addr_lo = 0, .gic_irq = { .type = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), .num = cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE), |