This controller with GICv3 ITS can handle MSI-X, but it needs to set vendor-specific registers by using the MSI address value. To get the address, add .post_init() for it. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> --- drivers/pci/controller/dwc/pcie-rcar-gen4.c | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c index e9166619b1f9..2ed62ffbde38 100644 --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c @@ -42,6 +42,13 @@ #define APP_HOLD_PHY_RST BIT(16) #define APP_LTSSM_ENABLE BIT(0) +/* INTC address */ +#define AXIINTCADDR 0x0a00 + +/* INTC control & mask */ +#define AXIINTCCONT 0x0a04 +#define AXIINTCCONT_VAL (BIT(31) | GENMASK(11, 2)) + #define RCAR_NUM_SPEED_CHANGE_RETRIES 10 #define RCAR_MAX_LINK_SPEED 4 @@ -297,6 +304,25 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp) return 0; } +static void rcar_gen4_pcie_host_post_init(struct dw_pcie_rp *pp) +{ + struct dw_pcie *dw = to_dw_pcie_from_pp(pp); + struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); + struct irq_data *data; + struct pci_dev *dev; + struct msi_msg msg; + + if (pp->has_msi_ctrl) + return; + + list_for_each_entry(dev, &pp->bridge->bus->devices, bus_list) { + data = irq_get_irq_data(dev->irq); + __pci_read_msi_msg(irq_data_get_msi_desc(data), &msg); + writel(msg.address_lo, rcar->base + AXIINTCADDR); + writel(AXIINTCCONT_VAL, rcar->base + AXIINTCCONT); + } +} + static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp) { struct dw_pcie *dw = to_dw_pcie_from_pp(pp); @@ -308,6 +334,7 @@ static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp) static const struct dw_pcie_host_ops rcar_gen4_pcie_host_ops = { .init = rcar_gen4_pcie_host_init, + .post_init = rcar_gen4_pcie_host_post_init, .deinit = rcar_gen4_pcie_host_deinit, }; -- 2.25.1