hw/loongarch: fdt adds pcie irq_map node
This patch adds pcie irq_map node for FDT. Signed-off-by: Song Gao <gaosong@loongson.cn> Reviewed-by: Bibo Mao <maobibo@loongson.cn> Message-Id: <20240426091551.2397867-15-gaosong@loongson.cn>
This commit is contained in:
parent
572d45e546
commit
07bf0b6aa1
@ -352,7 +352,62 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams)
|
|||||||
g_free(nodename);
|
g_free(nodename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fdt_add_pcie_node(const LoongArchMachineState *lams)
|
static void fdt_add_pcie_irq_map_node(const LoongArchMachineState *lams,
|
||||||
|
char *nodename,
|
||||||
|
uint32_t *pch_pic_phandle)
|
||||||
|
{
|
||||||
|
int pin, dev;
|
||||||
|
uint32_t irq_map_stride = 0;
|
||||||
|
uint32_t full_irq_map[GPEX_NUM_IRQS *GPEX_NUM_IRQS * 10] = {};
|
||||||
|
uint32_t *irq_map = full_irq_map;
|
||||||
|
const MachineState *ms = MACHINE(lams);
|
||||||
|
|
||||||
|
/* This code creates a standard swizzle of interrupts such that
|
||||||
|
* each device's first interrupt is based on it's PCI_SLOT number.
|
||||||
|
* (See pci_swizzle_map_irq_fn())
|
||||||
|
*
|
||||||
|
* We only need one entry per interrupt in the table (not one per
|
||||||
|
* possible slot) seeing the interrupt-map-mask will allow the table
|
||||||
|
* to wrap to any number of devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
|
||||||
|
int devfn = dev * 0x8;
|
||||||
|
|
||||||
|
for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
|
||||||
|
int irq_nr = 16 + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* Fill PCI address cells */
|
||||||
|
irq_map[i] = cpu_to_be32(devfn << 8);
|
||||||
|
i += 3;
|
||||||
|
|
||||||
|
/* Fill PCI Interrupt cells */
|
||||||
|
irq_map[i] = cpu_to_be32(pin + 1);
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
/* Fill interrupt controller phandle and cells */
|
||||||
|
irq_map[i++] = cpu_to_be32(*pch_pic_phandle);
|
||||||
|
irq_map[i++] = cpu_to_be32(irq_nr);
|
||||||
|
|
||||||
|
if (!irq_map_stride) {
|
||||||
|
irq_map_stride = i;
|
||||||
|
}
|
||||||
|
irq_map += irq_map_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qemu_fdt_setprop(ms->fdt, nodename, "interrupt-map", full_irq_map,
|
||||||
|
GPEX_NUM_IRQS * GPEX_NUM_IRQS *
|
||||||
|
irq_map_stride * sizeof(uint32_t));
|
||||||
|
qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-map-mask",
|
||||||
|
0x1800, 0, 0, 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fdt_add_pcie_node(const LoongArchMachineState *lams,
|
||||||
|
uint32_t *pch_pic_phandle,
|
||||||
|
uint32_t *pch_msi_phandle)
|
||||||
{
|
{
|
||||||
char *nodename;
|
char *nodename;
|
||||||
hwaddr base_mmio = VIRT_PCI_MEM_BASE;
|
hwaddr base_mmio = VIRT_PCI_MEM_BASE;
|
||||||
@ -383,6 +438,11 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams)
|
|||||||
2, base_pio, 2, size_pio,
|
2, base_pio, 2, size_pio,
|
||||||
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
|
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
|
||||||
2, base_mmio, 2, size_mmio);
|
2, base_mmio, 2, size_mmio);
|
||||||
|
qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-map",
|
||||||
|
0, *pch_msi_phandle, 0, 0x10000);
|
||||||
|
|
||||||
|
fdt_add_pcie_irq_map_node(lams, nodename, pch_pic_phandle);
|
||||||
|
|
||||||
g_free(nodename);
|
g_free(nodename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,7 +602,10 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic)
|
|||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *lams)
|
static void loongarch_devices_init(DeviceState *pch_pic,
|
||||||
|
LoongArchMachineState *lams,
|
||||||
|
uint32_t *pch_pic_phandle,
|
||||||
|
uint32_t *pch_msi_phandle)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(lams);
|
MachineClass *mc = MACHINE_GET_CLASS(lams);
|
||||||
DeviceState *gpex_dev;
|
DeviceState *gpex_dev;
|
||||||
@ -588,6 +651,9 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
|
|||||||
gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
|
gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add pcie node */
|
||||||
|
fdt_add_pcie_node(lams, pch_pic_phandle, pch_msi_phandle);
|
||||||
|
|
||||||
serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
|
serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
|
||||||
qdev_get_gpio_in(pch_pic,
|
qdev_get_gpio_in(pch_pic,
|
||||||
VIRT_UART_IRQ - VIRT_GSI_BASE),
|
VIRT_UART_IRQ - VIRT_GSI_BASE),
|
||||||
@ -734,7 +800,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
|||||||
/* Add PCH MSI node */
|
/* Add PCH MSI node */
|
||||||
fdt_add_pch_msi_node(lams, &eiointc_phandle, &pch_msi_phandle);
|
fdt_add_pch_msi_node(lams, &eiointc_phandle, &pch_msi_phandle);
|
||||||
|
|
||||||
loongarch_devices_init(pch_pic, lams);
|
loongarch_devices_init(pch_pic, lams, &pch_pic_phandle, &pch_msi_phandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loongarch_firmware_init(LoongArchMachineState *lams)
|
static void loongarch_firmware_init(LoongArchMachineState *lams)
|
||||||
@ -956,7 +1022,6 @@ static void loongarch_init(MachineState *machine)
|
|||||||
lams->powerdown_notifier.notify = virt_powerdown_req;
|
lams->powerdown_notifier.notify = virt_powerdown_req;
|
||||||
qemu_register_powerdown_notifier(&lams->powerdown_notifier);
|
qemu_register_powerdown_notifier(&lams->powerdown_notifier);
|
||||||
|
|
||||||
fdt_add_pcie_node(lams);
|
|
||||||
/*
|
/*
|
||||||
* Since lowmem region starts from 0 and Linux kernel legacy start address
|
* Since lowmem region starts from 0 and Linux kernel legacy start address
|
||||||
* at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
|
* at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
|
||||||
|
Loading…
Reference in New Issue
Block a user