diff mbox series

[v6,14/17] hw/loongarch: fdt adds pcie irq_map node

Message ID 20240307164835.300412-15-gaosong@loongson.cn
State New
Headers show
Series Add boot LoongArch elf kernel with FDT | expand

Commit Message

Song Gao March 7, 2024, 4:48 p.m. UTC
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20240301093839.663947-15-gaosong@loongson.cn>
---
 hw/loongarch/virt.c | 73 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 4 deletions(-)

Comments

maobibo March 8, 2024, 8:44 a.m. UTC | #1
On 2024/3/8 上午12:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> Message-Id: <20240301093839.663947-15-gaosong@loongson.cn>
> ---
>   hw/loongarch/virt.c | 73 ++++++++++++++++++++++++++++++++++++++++++---
>   1 file changed, 69 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 1e767c49f8..d00343f0c2 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -352,7 +352,62 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams)
>       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;
>       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,
>                                    1, FDT_PCI_RANGE_MMIO, 2, base_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);
>   }
>   
> @@ -541,7 +601,10 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic)
>       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);
>       DeviceState *gpex_dev;
> @@ -587,6 +650,9 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
>           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,
>                      qdev_get_gpio_in(pch_pic,
>                                       VIRT_UART_IRQ - VIRT_GSI_BASE),
> @@ -733,7 +799,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
>       /* Add PCH MSI node */
>       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)
> @@ -956,7 +1022,6 @@ static void loongarch_init(MachineState *machine)
>       lams->powerdown_notifier.notify = virt_powerdown_req;
>       qemu_register_powerdown_notifier(&lams->powerdown_notifier);
>   
> -    fdt_add_pcie_node(lams);
>       /*
>        * 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
> 
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
diff mbox series

Patch

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 1e767c49f8..d00343f0c2 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -352,7 +352,62 @@  static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams)
     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;
     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,
                                  1, FDT_PCI_RANGE_MMIO, 2, base_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);
 }
 
@@ -541,7 +601,10 @@  static DeviceState *create_platform_bus(DeviceState *pch_pic)
     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);
     DeviceState *gpex_dev;
@@ -587,6 +650,9 @@  static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
         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,
                    qdev_get_gpio_in(pch_pic,
                                     VIRT_UART_IRQ - VIRT_GSI_BASE),
@@ -733,7 +799,7 @@  static void loongarch_irq_init(LoongArchMachineState *lams)
     /* Add PCH MSI node */
     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)
@@ -956,7 +1022,6 @@  static void loongarch_init(MachineState *machine)
     lams->powerdown_notifier.notify = virt_powerdown_req;
     qemu_register_powerdown_notifier(&lams->powerdown_notifier);
 
-    fdt_add_pcie_node(lams);
     /*
      * 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