Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: xilinx-xdma: Add Xilinx QDMA Root Port driver

Add support for Xilinx QDMA Soft IP core as Root Port.

The Versal Prime devices support QDMA soft IP module in programmable logic.

The integrated QDMA Soft IP block has integrated bridge function that can
act as PCIe Root Port.

Link: https://lore.kernel.org/linux-pci/20240811022345.1178203-3-thippesw@amd.com
Signed-off-by: Thippeswamy Havalige <thippesw@amd.com>
[kwilczynski: removed unused header]
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

authored by

Thippeswamy Havalige and committed by
Krzysztof Wilczyński
6ac72179 899d5482

+52 -1
+52 -1
drivers/pci/controller/pcie-xilinx-dma-pl.c
··· 71 71 72 72 /* Phy Status/Control Register definitions */ 73 73 #define XILINX_PCIE_DMA_REG_PSCR_LNKUP BIT(11) 74 + #define QDMA_BRIDGE_BASE_OFF 0xcd8 74 75 75 76 /* Number of MSI IRQs */ 76 77 #define XILINX_NUM_MSI_IRQS 64 78 + 79 + enum xilinx_pl_dma_version { 80 + XDMA, 81 + QDMA, 82 + }; 83 + 84 + /** 85 + * struct xilinx_pl_dma_variant - PL DMA PCIe variant information 86 + * @version: DMA version 87 + */ 88 + struct xilinx_pl_dma_variant { 89 + enum xilinx_pl_dma_version version; 90 + }; 77 91 78 92 struct xilinx_msi { 79 93 struct irq_domain *msi_domain; ··· 102 88 * struct pl_dma_pcie - PCIe port information 103 89 * @dev: Device pointer 104 90 * @reg_base: IO Mapped Register Base 91 + * @cfg_base: IO Mapped Configuration Base 105 92 * @irq: Interrupt number 106 93 * @cfg: Holds mappings of config space window 107 94 * @phys_reg_base: Physical address of reg base ··· 112 97 * @msi: MSI information 113 98 * @intx_irq: INTx error interrupt number 114 99 * @lock: Lock protecting shared register access 100 + * @variant: PL DMA PCIe version check pointer 115 101 */ 116 102 struct pl_dma_pcie { 117 103 struct device *dev; 118 104 void __iomem *reg_base; 105 + void __iomem *cfg_base; 119 106 int irq; 120 107 struct pci_config_window *cfg; 121 108 phys_addr_t phys_reg_base; ··· 127 110 struct xilinx_msi msi; 128 111 int intx_irq; 129 112 raw_spinlock_t lock; 113 + const struct xilinx_pl_dma_variant *variant; 130 114 }; 131 115 132 116 static inline u32 pcie_read(struct pl_dma_pcie *port, u32 reg) 133 117 { 118 + if (port->variant->version == QDMA) 119 + return readl(port->reg_base + reg + QDMA_BRIDGE_BASE_OFF); 120 + 134 121 return readl(port->reg_base + reg); 135 122 } 136 123 137 124 static inline void pcie_write(struct pl_dma_pcie *port, u32 val, u32 reg) 138 125 { 139 - writel(val, port->reg_base + reg); 126 + if (port->variant->version == QDMA) 127 + writel(val, port->reg_base + reg + QDMA_BRIDGE_BASE_OFF); 128 + else 129 + writel(val, port->reg_base + reg); 140 130 } 141 131 142 132 static inline bool xilinx_pl_dma_pcie_link_up(struct pl_dma_pcie *port) ··· 196 172 197 173 if (!xilinx_pl_dma_pcie_valid_device(bus, devfn)) 198 174 return NULL; 175 + 176 + if (port->variant->version == QDMA) 177 + return port->cfg_base + PCIE_ECAM_OFFSET(bus->number, devfn, where); 199 178 200 179 return port->reg_base + PCIE_ECAM_OFFSET(bus->number, devfn, where); 201 180 } ··· 758 731 759 732 port->reg_base = port->cfg->win; 760 733 734 + if (port->variant->version == QDMA) { 735 + port->cfg_base = port->cfg->win; 736 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "breg"); 737 + port->reg_base = devm_ioremap_resource(dev, res); 738 + if (IS_ERR(port->reg_base)) 739 + return PTR_ERR(port->reg_base); 740 + port->phys_reg_base = res->start; 741 + } 742 + 761 743 err = xilinx_request_msi_irq(port); 762 744 if (err) { 763 745 pci_ecam_free(port->cfg); ··· 795 759 bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); 796 760 if (!bus) 797 761 return -ENODEV; 762 + 763 + port->variant = of_device_get_match_data(dev); 798 764 799 765 err = xilinx_pl_dma_pcie_parse_dt(port, bus->res); 800 766 if (err) { ··· 829 791 return err; 830 792 } 831 793 794 + static const struct xilinx_pl_dma_variant xdma_host = { 795 + .version = XDMA, 796 + }; 797 + 798 + static const struct xilinx_pl_dma_variant qdma_host = { 799 + .version = QDMA, 800 + }; 801 + 832 802 static const struct of_device_id xilinx_pl_dma_pcie_of_match[] = { 833 803 { 834 804 .compatible = "xlnx,xdma-host-3.00", 805 + .data = &xdma_host, 806 + }, 807 + { 808 + .compatible = "xlnx,qdma-host-3.00", 809 + .data = &qdma_host, 835 810 }, 836 811 {} 837 812 };