Rvic (b0rken) PCI support

Signed-off-by: Marc Zyngier <maz@kernel.org>
diff --git a/arm/pci.c b/arm/pci.c
index ed325fa..28ae5f2 100644
--- a/arm/pci.c
+++ b/arm/pci.c
@@ -16,7 +16,7 @@
 	u32 type, num, flags;
 } __attribute__((packed));
 
-struct of_interrupt_map_entry {
+struct of_gic_interrupt_map_entry {
 	struct of_pci_irq_mask		pci_irq_mask;
 	u32				gic_phandle;
 	u32				gic_addr_hi;
@@ -24,10 +24,98 @@
 	struct of_gic_irq		gic_irq;
 } __attribute__((packed));
 
+struct of_rvic_irq {		/* FIXME: Can't describe level interrupts... */
+	u32 num;
+} __attribute__((packed));
+
+struct of_rvic_interrupt_map_entry {
+	struct of_pci_irq_mask		pci_irq_mask;
+	u32				phandle;
+	u32				addr_hi;
+	u32				addr_lo;
+	struct of_rvic_irq		irq;
+} __attribute__((packed));
+
+static void gic_generate_interrupt_map(void *fdt, struct device_header *dev_hdr)
+{
+	struct of_gic_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
+	unsigned nentries = 0;
+
+	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
+		struct of_gic_interrupt_map_entry *entry = &irq_map[nentries];
+		struct pci_device_header *pci_hdr = dev_hdr->data;
+		u8 dev_num = dev_hdr->dev_num;
+		u8 pin = pci_hdr->irq_pin;
+		u8 irq = pci_hdr->irq_line;
+		u32 irq_flags = pci_hdr->irq_type;
+
+		*entry = (struct of_gic_interrupt_map_entry) {
+			.pci_irq_mask = {
+				.pci_addr = {
+					.hi	= cpu_to_fdt32(of_pci_b_ddddd(dev_num)),
+					.mid	= 0,
+					.lo	= 0,
+				},
+				.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),
+				.flags	= cpu_to_fdt32(irq_flags),
+			},
+		};
+
+		nentries++;
+		dev_hdr = device__next_dev(dev_hdr);
+	}
+
+	_FDT(fdt_property(fdt, "interrupt-map", irq_map,
+			  sizeof(struct of_gic_interrupt_map_entry) * nentries));
+}
+
+static void rvic_generate_interrupt_map(void *fdt, struct device_header *dev_hdr)
+{
+	struct of_rvic_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
+	unsigned nentries = 0;
+
+	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
+		struct of_rvic_interrupt_map_entry *entry = &irq_map[nentries];
+		struct pci_device_header *pci_hdr = dev_hdr->data;
+		u8 dev_num = dev_hdr->dev_num;
+		u8 pin = pci_hdr->irq_pin;
+		u8 irq = pci_hdr->irq_line;
+
+		*entry = (struct of_rvic_interrupt_map_entry) {
+			.pci_irq_mask = {
+				.pci_addr = {
+					.hi	= cpu_to_fdt32(of_pci_b_ddddd(dev_num)),
+					.mid	= 0,
+					.lo	= 0,
+				},
+				.pci_pin	= cpu_to_fdt32(pin),
+			},
+			.phandle	= cpu_to_fdt32(PHANDLE_RVID),
+			.addr_hi	= 0,
+			.addr_lo	= 0,
+			.irq = {
+				.num	= cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE),
+			},
+		};
+
+		nentries++;
+		dev_hdr = device__next_dev(dev_hdr);
+	}
+
+	_FDT(fdt_property(fdt, "interrupt-map", irq_map,
+			  sizeof(struct of_gic_interrupt_map_entry) * nentries));
+}
+
 void pci__generate_fdt_nodes(void *fdt)
 {
 	struct device_header *dev_hdr;
-	struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
 	unsigned nentries = 0;
 	/* Bus range */
 	u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(0), };
@@ -55,6 +143,8 @@
 			.length		= cpu_to_fdt64(ARM_PCI_MMIO_SIZE),
 		},
 	};
+	/* interrupt parent */
+	u32 intc = (gic_type == IRQCHIP_RVIC) ? PHANDLE_RVID : PHANDLE_GIC;
 
 	/* Boilerplate PCI properties */
 	_FDT(fdt_begin_node(fdt, "pci"));
@@ -69,42 +159,14 @@
 	_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));
+	_FDT(fdt_property_cell(fdt, "interrupt-parent", intc));
 
 	/* Generate the interrupt map ... */
 	dev_hdr = device__first_dev(DEVICE_BUS_PCI);
-	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
-		struct of_interrupt_map_entry *entry = &irq_map[nentries];
-		struct pci_device_header *pci_hdr = dev_hdr->data;
-		u8 dev_num = dev_hdr->dev_num;
-		u8 pin = pci_hdr->irq_pin;
-		u8 irq = pci_hdr->irq_line;
-		u32 irq_flags = pci_hdr->irq_type;
-
-		*entry = (struct of_interrupt_map_entry) {
-			.pci_irq_mask = {
-				.pci_addr = {
-					.hi	= cpu_to_fdt32(of_pci_b_ddddd(dev_num)),
-					.mid	= 0,
-					.lo	= 0,
-				},
-				.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),
-				.flags	= cpu_to_fdt32(irq_flags),
-			},
-		};
-
-		nentries++;
-		dev_hdr = device__next_dev(dev_hdr);
-	}
-
-	_FDT(fdt_property(fdt, "interrupt-map", irq_map,
-			  sizeof(struct of_interrupt_map_entry) * nentries));
+	if (gic_type == IRQCHIP_RVIC)
+		rvic_generate_interrupt_map(fdt, dev_hdr);
+	else
+		gic_generate_interrupt_map(fdt, dev_hdr);
 
 	/* ... and the corresponding mask. */
 	if (nentries) {