1 #include "kvm/devices.h"
2 #include "kvm/fdt.h"
3 #include "kvm/kvm.h"
4 #include "kvm/of_pci.h"
5 #include "kvm/pci.h"
6 #include "kvm/util.h"
7
8 /*
9 * An entry in the interrupt-map table looks like:
10 * <pci unit address> <pci interrupt pin> <irqchip phandle> <irqchip line>
11 */
12
13 struct of_interrupt_map_entry {
14 struct of_pci_irq_mask pci_irq_mask;
15 u32 irqchip_phandle;
16 u32 irqchip_line;
17 u32 irqchip_sense;
18 } __attribute__((packed));
19
pci__generate_fdt_nodes(void * fdt)20 void pci__generate_fdt_nodes(void *fdt)
21 {
22 struct device_header *dev_hdr;
23 struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
24 unsigned nentries = 0, nsize;
25 /* Bus range */
26 u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
27 /* Configuration Space */
28 u64 cfg_reg_prop[] = { cpu_to_fdt64(KVM_PCI_CFG_AREA),
29 cpu_to_fdt64(RISCV_PCI_CFG_SIZE), };
30 /* Describe the memory ranges */
31 struct of_pci_ranges_entry ranges[] = {
32 {
33 .pci_addr = {
34 .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_IO)),
35 .mid = 0,
36 .lo = 0,
37 },
38 .cpu_addr = cpu_to_fdt64(KVM_IOPORT_AREA),
39 .length = cpu_to_fdt64(RISCV_IOPORT_SIZE),
40 },
41 {
42 .pci_addr = {
43 .hi = cpu_to_fdt32(of_pci_b_ss(OF_PCI_SS_M32)),
44 .mid = cpu_to_fdt32(KVM_PCI_MMIO_AREA >> 32),
45 .lo = cpu_to_fdt32(KVM_PCI_MMIO_AREA),
46 },
47 .cpu_addr = cpu_to_fdt64(KVM_PCI_MMIO_AREA),
48 .length = cpu_to_fdt64(RISCV_PCI_MMIO_SIZE),
49 },
50 };
51
52 /* Find size of each interrupt map entery */
53 nsize = sizeof(struct of_interrupt_map_entry);
54 if (!riscv_irqchip_line_sensing)
55 nsize -= sizeof(u32);
56
57 /* Boilerplate PCI properties */
58 _FDT(fdt_begin_node(fdt, "pci"));
59 _FDT(fdt_property_string(fdt, "device_type", "pci"));
60 _FDT(fdt_property_cell(fdt, "#address-cells", 0x3));
61 _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
62 _FDT(fdt_property_cell(fdt, "#interrupt-cells", 0x1));
63 _FDT(fdt_property_string(fdt, "compatible", "pci-host-ecam-generic"));
64 _FDT(fdt_property(fdt, "dma-coherent", NULL, 0));
65
66 _FDT(fdt_property(fdt, "bus-range", bus_range, sizeof(bus_range)));
67 _FDT(fdt_property(fdt, "reg", &cfg_reg_prop, sizeof(cfg_reg_prop)));
68 _FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges)));
69
70 /* Generate the interrupt map ... */
71 dev_hdr = device__first_dev(DEVICE_BUS_PCI);
72 while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
73 struct of_interrupt_map_entry *entry;
74 struct pci_device_header *pci_hdr = dev_hdr->data;
75 u8 dev_num = dev_hdr->dev_num;
76 u8 pin = pci_hdr->irq_pin;
77 u8 irq = pci_hdr->irq_line;
78
79 entry = (void *)irq_map + nsize * nentries;
80 *entry = (struct of_interrupt_map_entry) {
81 .pci_irq_mask = {
82 .pci_addr = {
83 .hi = cpu_to_fdt32(of_pci_b_ddddd(dev_num)),
84 .mid = 0,
85 .lo = 0,
86 },
87 .pci_pin = cpu_to_fdt32(pin),
88 },
89 .irqchip_phandle = cpu_to_fdt32(riscv_irqchip_phandle),
90 .irqchip_line = cpu_to_fdt32(irq),
91 };
92
93 if (riscv_irqchip_line_sensing)
94 entry->irqchip_sense = cpu_to_fdt32(IRQ_TYPE_LEVEL_HIGH);
95
96 nentries++;
97 dev_hdr = device__next_dev(dev_hdr);
98 }
99
100 _FDT(fdt_property(fdt, "interrupt-map", irq_map, nsize * nentries));
101
102 /* ... and the corresponding mask. */
103 if (nentries) {
104 struct of_pci_irq_mask irq_mask = {
105 .pci_addr = {
106 .hi = cpu_to_fdt32(of_pci_b_ddddd(-1)),
107 .mid = 0,
108 .lo = 0,
109 },
110 .pci_pin = cpu_to_fdt32(7),
111 };
112
113 _FDT(fdt_property(fdt, "interrupt-map-mask", &irq_mask,
114 sizeof(irq_mask)));
115 }
116
117 /* Set MSI parent if available */
118 if (riscv_irqchip_msi_phandle != PHANDLE_RESERVED)
119 _FDT(fdt_property_cell(fdt, "msi-parent",
120 riscv_irqchip_msi_phandle));
121
122 _FDT(fdt_end_node(fdt));
123 }
124