1*16242d27SWill Deacon #include "kvm/devices.h" 2*16242d27SWill Deacon #include "kvm/fdt.h" 3*16242d27SWill Deacon #include "kvm/of_pci.h" 4*16242d27SWill Deacon #include "kvm/pci.h" 5*16242d27SWill Deacon #include "kvm/util.h" 6*16242d27SWill Deacon 7*16242d27SWill Deacon #include "arm-common/pci.h" 8*16242d27SWill Deacon 9*16242d27SWill Deacon /* 10*16242d27SWill Deacon * An entry in the interrupt-map table looks like: 11*16242d27SWill Deacon * <pci unit address> <pci interrupt pin> <gic phandle> <gic interrupt> 12*16242d27SWill Deacon */ 13*16242d27SWill Deacon 14*16242d27SWill Deacon struct of_gic_irq { 15*16242d27SWill Deacon u32 type, num, flags; 16*16242d27SWill Deacon } __attribute__((packed)); 17*16242d27SWill Deacon 18*16242d27SWill Deacon struct of_interrupt_map_entry { 19*16242d27SWill Deacon struct of_pci_irq_mask pci_irq_mask; 20*16242d27SWill Deacon u32 gic_phandle; 21*16242d27SWill Deacon struct of_gic_irq gic_irq; 22*16242d27SWill Deacon } __attribute__((packed)); 23*16242d27SWill Deacon 24*16242d27SWill Deacon void pci__generate_fdt_nodes(void *fdt, u32 gic_phandle) 25*16242d27SWill Deacon { 26*16242d27SWill Deacon struct device_header *dev_hdr; 27*16242d27SWill Deacon struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX]; 28*16242d27SWill Deacon unsigned nentries = 0; 29*16242d27SWill Deacon /* Describe the memory ranges (config and memory) */ 30*16242d27SWill Deacon struct of_pci_ranges_entry ranges[] = { 31*16242d27SWill Deacon { 32*16242d27SWill Deacon .pci_addr = { 33*16242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_CONFIG)), 34*16242d27SWill Deacon .mid = 0, 35*16242d27SWill Deacon .lo = 0, 36*16242d27SWill Deacon }, 37*16242d27SWill Deacon .cpu_addr = cpu_to_fdt64(KVM_PCI_CFG_AREA), 38*16242d27SWill Deacon .length = cpu_to_fdt64(ARM_PCI_CFG_SIZE), 39*16242d27SWill Deacon }, 40*16242d27SWill Deacon { 41*16242d27SWill Deacon .pci_addr = { 42*16242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_IO)), 43*16242d27SWill Deacon .mid = 0, 44*16242d27SWill Deacon .lo = 0, 45*16242d27SWill Deacon }, 46*16242d27SWill Deacon .cpu_addr = cpu_to_fdt64(KVM_IOPORT_AREA), 47*16242d27SWill Deacon .length = cpu_to_fdt64(ARM_IOPORT_SIZE), 48*16242d27SWill Deacon }, 49*16242d27SWill Deacon { 50*16242d27SWill Deacon .pci_addr = { 51*16242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_M32)), 52*16242d27SWill Deacon .mid = 0, 53*16242d27SWill Deacon .lo = 0, 54*16242d27SWill Deacon }, 55*16242d27SWill Deacon .cpu_addr = cpu_to_fdt64(KVM_PCI_MMIO_AREA), 56*16242d27SWill Deacon .length = cpu_to_fdt64(ARM_PCI_MMIO_SIZE), 57*16242d27SWill Deacon }, 58*16242d27SWill Deacon }; 59*16242d27SWill Deacon 60*16242d27SWill Deacon /* Boilerplate PCI properties */ 61*16242d27SWill Deacon _FDT(fdt_begin_node(fdt, "pci")); 62*16242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#address-cells", 0x3)); 63*16242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#size-cells", 0x2)); 64*16242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", 0x1)); 65*16242d27SWill Deacon _FDT(fdt_property_string(fdt, "compatible", "linux,pci-virt")); 66*16242d27SWill Deacon 67*16242d27SWill Deacon _FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges))); 68*16242d27SWill Deacon 69*16242d27SWill Deacon /* Generate the interrupt map ... */ 70*16242d27SWill Deacon dev_hdr = device__first_dev(DEVICE_BUS_PCI); 71*16242d27SWill Deacon while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) { 72*16242d27SWill Deacon struct of_interrupt_map_entry *entry = &irq_map[nentries]; 73*16242d27SWill Deacon struct pci_device_header *pci_hdr = dev_hdr->data; 74*16242d27SWill Deacon u8 dev_num = dev_hdr->dev_num; 75*16242d27SWill Deacon u8 pin = pci_hdr->irq_pin; 76*16242d27SWill Deacon u8 irq = pci_hdr->irq_line; 77*16242d27SWill Deacon 78*16242d27SWill Deacon *entry = (struct of_interrupt_map_entry) { 79*16242d27SWill Deacon .pci_irq_mask = { 80*16242d27SWill Deacon .pci_addr = { 81*16242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ddddd(dev_num)), 82*16242d27SWill Deacon .mid = 0, 83*16242d27SWill Deacon .lo = 0, 84*16242d27SWill Deacon }, 85*16242d27SWill Deacon .pci_pin = cpu_to_fdt32(pin), 86*16242d27SWill Deacon }, 87*16242d27SWill Deacon .gic_phandle = cpu_to_fdt32(gic_phandle), 88*16242d27SWill Deacon .gic_irq = { 89*16242d27SWill Deacon .type = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI), 90*16242d27SWill Deacon .num = cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE), 91*16242d27SWill Deacon .flags = cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI), 92*16242d27SWill Deacon }, 93*16242d27SWill Deacon }; 94*16242d27SWill Deacon 95*16242d27SWill Deacon nentries++; 96*16242d27SWill Deacon dev_hdr = device__next_dev(dev_hdr); 97*16242d27SWill Deacon } 98*16242d27SWill Deacon 99*16242d27SWill Deacon _FDT(fdt_property(fdt, "interrupt-map", irq_map, 100*16242d27SWill Deacon sizeof(struct of_interrupt_map_entry) * nentries)); 101*16242d27SWill Deacon 102*16242d27SWill Deacon /* ... and the corresponding mask. */ 103*16242d27SWill Deacon if (nentries) { 104*16242d27SWill Deacon struct of_pci_irq_mask irq_mask = { 105*16242d27SWill Deacon .pci_addr = { 106*16242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ddddd(-1)), 107*16242d27SWill Deacon .mid = 0, 108*16242d27SWill Deacon .lo = 0, 109*16242d27SWill Deacon }, 110*16242d27SWill Deacon .pci_pin = cpu_to_fdt32(7), 111*16242d27SWill Deacon }; 112*16242d27SWill Deacon 113*16242d27SWill Deacon _FDT(fdt_property(fdt, "interrupt-map-mask", &irq_mask, 114*16242d27SWill Deacon sizeof(irq_mask))); 115*16242d27SWill Deacon } 116*16242d27SWill Deacon 117*16242d27SWill Deacon _FDT(fdt_end_node(fdt)); 118*16242d27SWill Deacon } 119