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) {