116242d27SWill Deacon #include "kvm/devices.h"
216242d27SWill Deacon #include "kvm/fdt.h"
36078a454SJean-Philippe Brucker #include "kvm/kvm.h"
416242d27SWill Deacon #include "kvm/of_pci.h"
516242d27SWill Deacon #include "kvm/pci.h"
616242d27SWill Deacon #include "kvm/util.h"
716242d27SWill Deacon
816242d27SWill Deacon #include "arm-common/pci.h"
9*95f47968SAlexandru Elisei #include "arm-common/gic.h"
1016242d27SWill Deacon
1116242d27SWill Deacon /*
1216242d27SWill Deacon * An entry in the interrupt-map table looks like:
1316242d27SWill Deacon * <pci unit address> <pci interrupt pin> <gic phandle> <gic interrupt>
1416242d27SWill Deacon */
1516242d27SWill Deacon
1616242d27SWill Deacon struct of_gic_irq {
1716242d27SWill Deacon u32 type, num, flags;
1816242d27SWill Deacon } __attribute__((packed));
1916242d27SWill Deacon
2016242d27SWill Deacon struct of_interrupt_map_entry {
2116242d27SWill Deacon struct of_pci_irq_mask pci_irq_mask;
2216242d27SWill Deacon u32 gic_phandle;
2314421de9SAndre Przywara u32 gic_addr_hi;
2414421de9SAndre Przywara u32 gic_addr_lo;
2516242d27SWill Deacon struct of_gic_irq gic_irq;
2616242d27SWill Deacon } __attribute__((packed));
2716242d27SWill Deacon
pci__generate_fdt_nodes(void * fdt,struct kvm * kvm)28*95f47968SAlexandru Elisei void pci__generate_fdt_nodes(void *fdt, struct kvm *kvm)
2916242d27SWill Deacon {
30*95f47968SAlexandru Elisei enum irqchip_type irqchip = kvm->cfg.arch.irqchip;
3116242d27SWill Deacon struct device_header *dev_hdr;
3216242d27SWill Deacon struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
3316242d27SWill Deacon unsigned nentries = 0;
341fcf0d77SWill Deacon /* Bus range */
35c94286f0SAlexandru Elisei u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(0), };
361fcf0d77SWill Deacon /* Configuration Space */
371fcf0d77SWill Deacon u64 cfg_reg_prop[] = { cpu_to_fdt64(KVM_PCI_CFG_AREA),
381fcf0d77SWill Deacon cpu_to_fdt64(ARM_PCI_CFG_SIZE), };
391fcf0d77SWill Deacon /* Describe the memory ranges */
4016242d27SWill Deacon struct of_pci_ranges_entry ranges[] = {
4116242d27SWill Deacon {
4216242d27SWill Deacon .pci_addr = {
4316242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_IO)),
4416242d27SWill Deacon .mid = 0,
4516242d27SWill Deacon .lo = 0,
4616242d27SWill Deacon },
4716242d27SWill Deacon .cpu_addr = cpu_to_fdt64(KVM_IOPORT_AREA),
4816242d27SWill Deacon .length = cpu_to_fdt64(ARM_IOPORT_SIZE),
4916242d27SWill Deacon },
5016242d27SWill Deacon {
5116242d27SWill Deacon .pci_addr = {
5216242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_M32)),
531fcf0d77SWill Deacon .mid = cpu_to_fdt32(KVM_PCI_MMIO_AREA >> 32),
541fcf0d77SWill Deacon .lo = cpu_to_fdt32(KVM_PCI_MMIO_AREA),
5516242d27SWill Deacon },
5616242d27SWill Deacon .cpu_addr = cpu_to_fdt64(KVM_PCI_MMIO_AREA),
5716242d27SWill Deacon .length = cpu_to_fdt64(ARM_PCI_MMIO_SIZE),
5816242d27SWill Deacon },
5916242d27SWill Deacon };
6016242d27SWill Deacon
6116242d27SWill Deacon /* Boilerplate PCI properties */
6216242d27SWill Deacon _FDT(fdt_begin_node(fdt, "pci"));
631fcf0d77SWill Deacon _FDT(fdt_property_string(fdt, "device_type", "pci"));
6416242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#address-cells", 0x3));
6516242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
6616242d27SWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", 0x1));
67e69b7663SAlexandru Elisei _FDT(fdt_property_string(fdt, "compatible", "pci-host-ecam-generic"));
689a8af7e3SRobin Murphy _FDT(fdt_property(fdt, "dma-coherent", NULL, 0));
6916242d27SWill Deacon
701fcf0d77SWill Deacon _FDT(fdt_property(fdt, "bus-range", bus_range, sizeof(bus_range)));
711fcf0d77SWill Deacon _FDT(fdt_property(fdt, "reg", &cfg_reg_prop, sizeof(cfg_reg_prop)));
7216242d27SWill Deacon _FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges)));
73*95f47968SAlexandru Elisei
74*95f47968SAlexandru Elisei if (irqchip == IRQCHIP_GICV2M || irqchip == IRQCHIP_GICV3_ITS)
7514421de9SAndre Przywara _FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_MSI));
7616242d27SWill Deacon
7716242d27SWill Deacon /* Generate the interrupt map ... */
7816242d27SWill Deacon dev_hdr = device__first_dev(DEVICE_BUS_PCI);
7916242d27SWill Deacon while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
8016242d27SWill Deacon struct of_interrupt_map_entry *entry = &irq_map[nentries];
8116242d27SWill Deacon struct pci_device_header *pci_hdr = dev_hdr->data;
8216242d27SWill Deacon u8 dev_num = dev_hdr->dev_num;
8316242d27SWill Deacon u8 pin = pci_hdr->irq_pin;
8416242d27SWill Deacon u8 irq = pci_hdr->irq_line;
85ff01b5dbSJean-Philippe Brucker u32 irq_flags = pci_hdr->irq_type;
8616242d27SWill Deacon
877a60af05SSathyam Panda /*
887a60af05SSathyam Panda * Avoid adding entries in "interrupt-map" for devices that
897a60af05SSathyam Panda * will be using advance interrupt mechanisms like MSI or
907a60af05SSathyam Panda * MSI-X instead of legacy interrupt pins INTA#..INTD#
917a60af05SSathyam Panda */
927a60af05SSathyam Panda if (pin == 0) {
937a60af05SSathyam Panda dev_hdr = device__next_dev(dev_hdr);
947a60af05SSathyam Panda continue;
957a60af05SSathyam Panda }
967a60af05SSathyam Panda
9716242d27SWill Deacon *entry = (struct of_interrupt_map_entry) {
9816242d27SWill Deacon .pci_irq_mask = {
9916242d27SWill Deacon .pci_addr = {
10016242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ddddd(dev_num)),
10116242d27SWill Deacon .mid = 0,
10216242d27SWill Deacon .lo = 0,
10316242d27SWill Deacon },
10416242d27SWill Deacon .pci_pin = cpu_to_fdt32(pin),
10516242d27SWill Deacon },
1060063d50cSAndre Przywara .gic_phandle = cpu_to_fdt32(PHANDLE_GIC),
10714421de9SAndre Przywara .gic_addr_hi = 0,
10814421de9SAndre Przywara .gic_addr_lo = 0,
10916242d27SWill Deacon .gic_irq = {
11016242d27SWill Deacon .type = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI),
11116242d27SWill Deacon .num = cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE),
112ff01b5dbSJean-Philippe Brucker .flags = cpu_to_fdt32(irq_flags),
11316242d27SWill Deacon },
11416242d27SWill Deacon };
11516242d27SWill Deacon
11616242d27SWill Deacon nentries++;
11716242d27SWill Deacon dev_hdr = device__next_dev(dev_hdr);
11816242d27SWill Deacon }
11916242d27SWill Deacon
12016242d27SWill Deacon _FDT(fdt_property(fdt, "interrupt-map", irq_map,
12116242d27SWill Deacon sizeof(struct of_interrupt_map_entry) * nentries));
12216242d27SWill Deacon
12316242d27SWill Deacon /* ... and the corresponding mask. */
12416242d27SWill Deacon if (nentries) {
12516242d27SWill Deacon struct of_pci_irq_mask irq_mask = {
12616242d27SWill Deacon .pci_addr = {
12716242d27SWill Deacon .hi = cpu_to_fdt32(of_pci_b_ddddd(-1)),
12816242d27SWill Deacon .mid = 0,
12916242d27SWill Deacon .lo = 0,
13016242d27SWill Deacon },
13116242d27SWill Deacon .pci_pin = cpu_to_fdt32(7),
13216242d27SWill Deacon };
13316242d27SWill Deacon
13416242d27SWill Deacon _FDT(fdt_property(fdt, "interrupt-map-mask", &irq_mask,
13516242d27SWill Deacon sizeof(irq_mask)));
13616242d27SWill Deacon }
13716242d27SWill Deacon
13816242d27SWill Deacon _FDT(fdt_end_node(fdt));
13916242d27SWill Deacon }
140