18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/** 38c2ecf20Sopenharmony_ci * APM X-Gene PCIe Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2014 Applied Micro Circuits Corporation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Tanmay Inamdar <tinamdar@apm.com>. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 138c2ecf20Sopenharmony_ci#include <linux/memblock.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/of.h> 168c2ecf20Sopenharmony_ci#include <linux/of_address.h> 178c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 188c2ecf20Sopenharmony_ci#include <linux/of_pci.h> 198c2ecf20Sopenharmony_ci#include <linux/pci.h> 208c2ecf20Sopenharmony_ci#include <linux/pci-acpi.h> 218c2ecf20Sopenharmony_ci#include <linux/pci-ecam.h> 228c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "../pci.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define PCIECORE_CTLANDSTATUS 0x50 288c2ecf20Sopenharmony_ci#define PIM1_1L 0x80 298c2ecf20Sopenharmony_ci#define IBAR2 0x98 308c2ecf20Sopenharmony_ci#define IR2MSK 0x9c 318c2ecf20Sopenharmony_ci#define PIM2_1L 0xa0 328c2ecf20Sopenharmony_ci#define IBAR3L 0xb4 338c2ecf20Sopenharmony_ci#define IR3MSKL 0xbc 348c2ecf20Sopenharmony_ci#define PIM3_1L 0xc4 358c2ecf20Sopenharmony_ci#define OMR1BARL 0x100 368c2ecf20Sopenharmony_ci#define OMR2BARL 0x118 378c2ecf20Sopenharmony_ci#define OMR3BARL 0x130 388c2ecf20Sopenharmony_ci#define CFGBARL 0x154 398c2ecf20Sopenharmony_ci#define CFGBARH 0x158 408c2ecf20Sopenharmony_ci#define CFGCTL 0x15c 418c2ecf20Sopenharmony_ci#define RTDID 0x160 428c2ecf20Sopenharmony_ci#define BRIDGE_CFG_0 0x2000 438c2ecf20Sopenharmony_ci#define BRIDGE_CFG_4 0x2010 448c2ecf20Sopenharmony_ci#define BRIDGE_STATUS_0 0x2600 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define LINK_UP_MASK 0x00000100 478c2ecf20Sopenharmony_ci#define AXI_EP_CFG_ACCESS 0x10000 488c2ecf20Sopenharmony_ci#define EN_COHERENCY 0xF0000000 498c2ecf20Sopenharmony_ci#define EN_REG 0x00000001 508c2ecf20Sopenharmony_ci#define OB_LO_IO 0x00000002 518c2ecf20Sopenharmony_ci#define XGENE_PCIE_VENDORID 0x10E8 528c2ecf20Sopenharmony_ci#define XGENE_PCIE_DEVICEID 0xE004 538c2ecf20Sopenharmony_ci#define SZ_1T (SZ_1G*1024ULL) 548c2ecf20Sopenharmony_ci#define PIPE_PHY_RATE_RD(src) ((0xc000 & (u32)(src)) >> 0xe) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define XGENE_V1_PCI_EXP_CAP 0x40 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* PCIe IP version */ 598c2ecf20Sopenharmony_ci#define XGENE_PCIE_IP_VER_UNKN 0 608c2ecf20Sopenharmony_ci#define XGENE_PCIE_IP_VER_1 1 618c2ecf20Sopenharmony_ci#define XGENE_PCIE_IP_VER_2 2 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#if defined(CONFIG_PCI_XGENE) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) 648c2ecf20Sopenharmony_cistruct xgene_pcie_port { 658c2ecf20Sopenharmony_ci struct device_node *node; 668c2ecf20Sopenharmony_ci struct device *dev; 678c2ecf20Sopenharmony_ci struct clk *clk; 688c2ecf20Sopenharmony_ci void __iomem *csr_base; 698c2ecf20Sopenharmony_ci void __iomem *cfg_base; 708c2ecf20Sopenharmony_ci unsigned long cfg_addr; 718c2ecf20Sopenharmony_ci bool link_up; 728c2ecf20Sopenharmony_ci u32 version; 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic u32 xgene_pcie_readl(struct xgene_pcie_port *port, u32 reg) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci return readl(port->csr_base + reg); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic void xgene_pcie_writel(struct xgene_pcie_port *port, u32 reg, u32 val) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci writel(val, port->csr_base + reg); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic inline u32 pcie_bar_low_val(u32 addr, u32 flags) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci return (addr & PCI_BASE_ADDRESS_MEM_MASK) | flags; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic inline struct xgene_pcie_port *pcie_bus_to_port(struct pci_bus *bus) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct pci_config_window *cfg; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (acpi_disabled) 958c2ecf20Sopenharmony_ci return (struct xgene_pcie_port *)(bus->sysdata); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci cfg = bus->sysdata; 988c2ecf20Sopenharmony_ci return (struct xgene_pcie_port *)(cfg->priv); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * When the address bit [17:16] is 2'b01, the Configuration access will be 1038c2ecf20Sopenharmony_ci * treated as Type 1 and it will be forwarded to external PCIe device. 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct xgene_pcie_port *port = pcie_bus_to_port(bus); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (bus->number >= (bus->primary + 1)) 1108c2ecf20Sopenharmony_ci return port->cfg_base + AXI_EP_CFG_ACCESS; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return port->cfg_base; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci * For Configuration request, RTDID register is used as Bus Number, 1178c2ecf20Sopenharmony_ci * Device Number and Function number of the header fields. 1188c2ecf20Sopenharmony_ci */ 1198c2ecf20Sopenharmony_cistatic void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci struct xgene_pcie_port *port = pcie_bus_to_port(bus); 1228c2ecf20Sopenharmony_ci unsigned int b, d, f; 1238c2ecf20Sopenharmony_ci u32 rtdid_val = 0; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci b = bus->number; 1268c2ecf20Sopenharmony_ci d = PCI_SLOT(devfn); 1278c2ecf20Sopenharmony_ci f = PCI_FUNC(devfn); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (!pci_is_root_bus(bus)) 1308c2ecf20Sopenharmony_ci rtdid_val = (b << 8) | (d << 3) | f; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci xgene_pcie_writel(port, RTDID, rtdid_val); 1338c2ecf20Sopenharmony_ci /* read the register back to ensure flush */ 1348c2ecf20Sopenharmony_ci xgene_pcie_readl(port, RTDID); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * X-Gene PCIe port uses BAR0-BAR1 of RC's configuration space as 1398c2ecf20Sopenharmony_ci * the translation from PCI bus to native BUS. Entire DDR region 1408c2ecf20Sopenharmony_ci * is mapped into PCIe space using these registers, so it can be 1418c2ecf20Sopenharmony_ci * reached by DMA from EP devices. The BAR0/1 of bridge should be 1428c2ecf20Sopenharmony_ci * hidden during enumeration to avoid the sizing and resource allocation 1438c2ecf20Sopenharmony_ci * by PCIe core. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_cistatic bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci if (pci_is_root_bus(bus) && ((offset == PCI_BASE_ADDRESS_0) || 1488c2ecf20Sopenharmony_ci (offset == PCI_BASE_ADDRESS_1))) 1498c2ecf20Sopenharmony_ci return true; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return false; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic void __iomem *xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, 1558c2ecf20Sopenharmony_ci int offset) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci if ((pci_is_root_bus(bus) && devfn != 0) || 1588c2ecf20Sopenharmony_ci xgene_pcie_hide_rc_bars(bus, offset)) 1598c2ecf20Sopenharmony_ci return NULL; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci xgene_pcie_set_rtdid_reg(bus, devfn); 1628c2ecf20Sopenharmony_ci return xgene_pcie_get_cfg_base(bus) + offset; 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, 1668c2ecf20Sopenharmony_ci int where, int size, u32 *val) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci struct xgene_pcie_port *port = pcie_bus_to_port(bus); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) != 1718c2ecf20Sopenharmony_ci PCIBIOS_SUCCESSFUL) 1728c2ecf20Sopenharmony_ci return PCIBIOS_DEVICE_NOT_FOUND; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci /* 1758c2ecf20Sopenharmony_ci * The v1 controller has a bug in its Configuration Request 1768c2ecf20Sopenharmony_ci * Retry Status (CRS) logic: when CRS is enabled and we read the 1778c2ecf20Sopenharmony_ci * Vendor and Device ID of a non-existent device, the controller 1788c2ecf20Sopenharmony_ci * fabricates return data of 0xFFFF0001 ("device exists but is not 1798c2ecf20Sopenharmony_ci * ready") instead of 0xFFFFFFFF ("device does not exist"). This 1808c2ecf20Sopenharmony_ci * causes the PCI core to retry the read until it times out. 1818c2ecf20Sopenharmony_ci * Avoid this by not claiming to support CRS. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) && 1848c2ecf20Sopenharmony_ci ((where & ~0x3) == XGENE_V1_PCI_EXP_CAP + PCI_EXP_RTCTL)) 1858c2ecf20Sopenharmony_ci *val &= ~(PCI_EXP_RTCAP_CRSVIS << 16); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (size <= 2) 1888c2ecf20Sopenharmony_ci *val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci#endif 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) 1958c2ecf20Sopenharmony_cistatic int xgene_get_csr_resource(struct acpi_device *adev, 1968c2ecf20Sopenharmony_ci struct resource *res) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct device *dev = &adev->dev; 1998c2ecf20Sopenharmony_ci struct resource_entry *entry; 2008c2ecf20Sopenharmony_ci struct list_head list; 2018c2ecf20Sopenharmony_ci unsigned long flags; 2028c2ecf20Sopenharmony_ci int ret; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&list); 2058c2ecf20Sopenharmony_ci flags = IORESOURCE_MEM; 2068c2ecf20Sopenharmony_ci ret = acpi_dev_get_resources(adev, &list, 2078c2ecf20Sopenharmony_ci acpi_dev_filter_resource_type_cb, 2088c2ecf20Sopenharmony_ci (void *) flags); 2098c2ecf20Sopenharmony_ci if (ret < 0) { 2108c2ecf20Sopenharmony_ci dev_err(dev, "failed to parse _CRS method, error code %d\n", 2118c2ecf20Sopenharmony_ci ret); 2128c2ecf20Sopenharmony_ci return ret; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (ret == 0) { 2168c2ecf20Sopenharmony_ci dev_err(dev, "no IO and memory resources present in _CRS\n"); 2178c2ecf20Sopenharmony_ci return -EINVAL; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci entry = list_first_entry(&list, struct resource_entry, node); 2218c2ecf20Sopenharmony_ci *res = *entry->res; 2228c2ecf20Sopenharmony_ci acpi_dev_free_resource_list(&list); 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int xgene_pcie_ecam_init(struct pci_config_window *cfg, u32 ipversion) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci struct device *dev = cfg->parent; 2298c2ecf20Sopenharmony_ci struct acpi_device *adev = to_acpi_device(dev); 2308c2ecf20Sopenharmony_ci struct xgene_pcie_port *port; 2318c2ecf20Sopenharmony_ci struct resource csr; 2328c2ecf20Sopenharmony_ci int ret; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); 2358c2ecf20Sopenharmony_ci if (!port) 2368c2ecf20Sopenharmony_ci return -ENOMEM; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci ret = xgene_get_csr_resource(adev, &csr); 2398c2ecf20Sopenharmony_ci if (ret) { 2408c2ecf20Sopenharmony_ci dev_err(dev, "can't get CSR resource\n"); 2418c2ecf20Sopenharmony_ci return ret; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci port->csr_base = devm_pci_remap_cfg_resource(dev, &csr); 2448c2ecf20Sopenharmony_ci if (IS_ERR(port->csr_base)) 2458c2ecf20Sopenharmony_ci return PTR_ERR(port->csr_base); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci port->cfg_base = cfg->win; 2488c2ecf20Sopenharmony_ci port->version = ipversion; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci cfg->priv = port; 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci return xgene_pcie_ecam_init(cfg, XGENE_PCIE_IP_VER_1); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciconst struct pci_ecam_ops xgene_v1_pcie_ecam_ops = { 2608c2ecf20Sopenharmony_ci .bus_shift = 16, 2618c2ecf20Sopenharmony_ci .init = xgene_v1_pcie_ecam_init, 2628c2ecf20Sopenharmony_ci .pci_ops = { 2638c2ecf20Sopenharmony_ci .map_bus = xgene_pcie_map_bus, 2648c2ecf20Sopenharmony_ci .read = xgene_pcie_config_read32, 2658c2ecf20Sopenharmony_ci .write = pci_generic_config_write, 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci}; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic int xgene_v2_pcie_ecam_init(struct pci_config_window *cfg) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci return xgene_pcie_ecam_init(cfg, XGENE_PCIE_IP_VER_2); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciconst struct pci_ecam_ops xgene_v2_pcie_ecam_ops = { 2758c2ecf20Sopenharmony_ci .bus_shift = 16, 2768c2ecf20Sopenharmony_ci .init = xgene_v2_pcie_ecam_init, 2778c2ecf20Sopenharmony_ci .pci_ops = { 2788c2ecf20Sopenharmony_ci .map_bus = xgene_pcie_map_bus, 2798c2ecf20Sopenharmony_ci .read = xgene_pcie_config_read32, 2808c2ecf20Sopenharmony_ci .write = pci_generic_config_write, 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci}; 2838c2ecf20Sopenharmony_ci#endif 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#if defined(CONFIG_PCI_XGENE) 2868c2ecf20Sopenharmony_cistatic u64 xgene_pcie_set_ib_mask(struct xgene_pcie_port *port, u32 addr, 2878c2ecf20Sopenharmony_ci u32 flags, u64 size) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci u64 mask = (~(size - 1) & PCI_BASE_ADDRESS_MEM_MASK) | flags; 2908c2ecf20Sopenharmony_ci u32 val32 = 0; 2918c2ecf20Sopenharmony_ci u32 val; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, addr); 2948c2ecf20Sopenharmony_ci val = (val32 & 0x0000ffff) | (lower_32_bits(mask) << 16); 2958c2ecf20Sopenharmony_ci xgene_pcie_writel(port, addr, val); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, addr + 0x04); 2988c2ecf20Sopenharmony_ci val = (val32 & 0xffff0000) | (lower_32_bits(mask) >> 16); 2998c2ecf20Sopenharmony_ci xgene_pcie_writel(port, addr + 0x04, val); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, addr + 0x04); 3028c2ecf20Sopenharmony_ci val = (val32 & 0x0000ffff) | (upper_32_bits(mask) << 16); 3038c2ecf20Sopenharmony_ci xgene_pcie_writel(port, addr + 0x04, val); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, addr + 0x08); 3068c2ecf20Sopenharmony_ci val = (val32 & 0xffff0000) | (upper_32_bits(mask) >> 16); 3078c2ecf20Sopenharmony_ci xgene_pcie_writel(port, addr + 0x08, val); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return mask; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic void xgene_pcie_linkup(struct xgene_pcie_port *port, 3138c2ecf20Sopenharmony_ci u32 *lanes, u32 *speed) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci u32 val32; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci port->link_up = false; 3188c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, PCIECORE_CTLANDSTATUS); 3198c2ecf20Sopenharmony_ci if (val32 & LINK_UP_MASK) { 3208c2ecf20Sopenharmony_ci port->link_up = true; 3218c2ecf20Sopenharmony_ci *speed = PIPE_PHY_RATE_RD(val32); 3228c2ecf20Sopenharmony_ci val32 = xgene_pcie_readl(port, BRIDGE_STATUS_0); 3238c2ecf20Sopenharmony_ci *lanes = val32 >> 26; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int xgene_pcie_init_port(struct xgene_pcie_port *port) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct device *dev = port->dev; 3308c2ecf20Sopenharmony_ci int rc; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci port->clk = clk_get(dev, NULL); 3338c2ecf20Sopenharmony_ci if (IS_ERR(port->clk)) { 3348c2ecf20Sopenharmony_ci dev_err(dev, "clock not available\n"); 3358c2ecf20Sopenharmony_ci return -ENODEV; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci rc = clk_prepare_enable(port->clk); 3398c2ecf20Sopenharmony_ci if (rc) { 3408c2ecf20Sopenharmony_ci dev_err(dev, "clock enable failed\n"); 3418c2ecf20Sopenharmony_ci return rc; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return 0; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int xgene_pcie_map_reg(struct xgene_pcie_port *port, 3488c2ecf20Sopenharmony_ci struct platform_device *pdev) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct device *dev = port->dev; 3518c2ecf20Sopenharmony_ci struct resource *res; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr"); 3548c2ecf20Sopenharmony_ci port->csr_base = devm_pci_remap_cfg_resource(dev, res); 3558c2ecf20Sopenharmony_ci if (IS_ERR(port->csr_base)) 3568c2ecf20Sopenharmony_ci return PTR_ERR(port->csr_base); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg"); 3598c2ecf20Sopenharmony_ci port->cfg_base = devm_ioremap_resource(dev, res); 3608c2ecf20Sopenharmony_ci if (IS_ERR(port->cfg_base)) 3618c2ecf20Sopenharmony_ci return PTR_ERR(port->cfg_base); 3628c2ecf20Sopenharmony_ci port->cfg_addr = res->start; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic void xgene_pcie_setup_ob_reg(struct xgene_pcie_port *port, 3688c2ecf20Sopenharmony_ci struct resource *res, u32 offset, 3698c2ecf20Sopenharmony_ci u64 cpu_addr, u64 pci_addr) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci struct device *dev = port->dev; 3728c2ecf20Sopenharmony_ci resource_size_t size = resource_size(res); 3738c2ecf20Sopenharmony_ci u64 restype = resource_type(res); 3748c2ecf20Sopenharmony_ci u64 mask = 0; 3758c2ecf20Sopenharmony_ci u32 min_size; 3768c2ecf20Sopenharmony_ci u32 flag = EN_REG; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci if (restype == IORESOURCE_MEM) { 3798c2ecf20Sopenharmony_ci min_size = SZ_128M; 3808c2ecf20Sopenharmony_ci } else { 3818c2ecf20Sopenharmony_ci min_size = 128; 3828c2ecf20Sopenharmony_ci flag |= OB_LO_IO; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (size >= min_size) 3868c2ecf20Sopenharmony_ci mask = ~(size - 1) | flag; 3878c2ecf20Sopenharmony_ci else 3888c2ecf20Sopenharmony_ci dev_warn(dev, "res size 0x%llx less than minimum 0x%x\n", 3898c2ecf20Sopenharmony_ci (u64)size, min_size); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset, lower_32_bits(cpu_addr)); 3928c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset + 0x04, upper_32_bits(cpu_addr)); 3938c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset + 0x08, lower_32_bits(mask)); 3948c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset + 0x0c, upper_32_bits(mask)); 3958c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset + 0x10, lower_32_bits(pci_addr)); 3968c2ecf20Sopenharmony_ci xgene_pcie_writel(port, offset + 0x14, upper_32_bits(pci_addr)); 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_cistatic void xgene_pcie_setup_cfg_reg(struct xgene_pcie_port *port) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci u64 addr = port->cfg_addr; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci xgene_pcie_writel(port, CFGBARL, lower_32_bits(addr)); 4048c2ecf20Sopenharmony_ci xgene_pcie_writel(port, CFGBARH, upper_32_bits(addr)); 4058c2ecf20Sopenharmony_ci xgene_pcie_writel(port, CFGCTL, EN_REG); 4068c2ecf20Sopenharmony_ci} 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic int xgene_pcie_map_ranges(struct xgene_pcie_port *port) 4098c2ecf20Sopenharmony_ci{ 4108c2ecf20Sopenharmony_ci struct pci_host_bridge *bridge = pci_host_bridge_from_priv(port); 4118c2ecf20Sopenharmony_ci struct resource_entry *window; 4128c2ecf20Sopenharmony_ci struct device *dev = port->dev; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci resource_list_for_each_entry(window, &bridge->windows) { 4158c2ecf20Sopenharmony_ci struct resource *res = window->res; 4168c2ecf20Sopenharmony_ci u64 restype = resource_type(res); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci dev_dbg(dev, "%pR\n", res); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci switch (restype) { 4218c2ecf20Sopenharmony_ci case IORESOURCE_IO: 4228c2ecf20Sopenharmony_ci xgene_pcie_setup_ob_reg(port, res, OMR3BARL, 4238c2ecf20Sopenharmony_ci pci_pio_to_address(res->start), 4248c2ecf20Sopenharmony_ci res->start - window->offset); 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci case IORESOURCE_MEM: 4278c2ecf20Sopenharmony_ci if (res->flags & IORESOURCE_PREFETCH) 4288c2ecf20Sopenharmony_ci xgene_pcie_setup_ob_reg(port, res, OMR2BARL, 4298c2ecf20Sopenharmony_ci res->start, 4308c2ecf20Sopenharmony_ci res->start - 4318c2ecf20Sopenharmony_ci window->offset); 4328c2ecf20Sopenharmony_ci else 4338c2ecf20Sopenharmony_ci xgene_pcie_setup_ob_reg(port, res, OMR1BARL, 4348c2ecf20Sopenharmony_ci res->start, 4358c2ecf20Sopenharmony_ci res->start - 4368c2ecf20Sopenharmony_ci window->offset); 4378c2ecf20Sopenharmony_ci break; 4388c2ecf20Sopenharmony_ci case IORESOURCE_BUS: 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci default: 4418c2ecf20Sopenharmony_ci dev_err(dev, "invalid resource %pR\n", res); 4428c2ecf20Sopenharmony_ci return -EINVAL; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci xgene_pcie_setup_cfg_reg(port); 4468c2ecf20Sopenharmony_ci return 0; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic void xgene_pcie_setup_pims(struct xgene_pcie_port *port, u32 pim_reg, 4508c2ecf20Sopenharmony_ci u64 pim, u64 size) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci xgene_pcie_writel(port, pim_reg, lower_32_bits(pim)); 4538c2ecf20Sopenharmony_ci xgene_pcie_writel(port, pim_reg + 0x04, 4548c2ecf20Sopenharmony_ci upper_32_bits(pim) | EN_COHERENCY); 4558c2ecf20Sopenharmony_ci xgene_pcie_writel(port, pim_reg + 0x10, lower_32_bits(size)); 4568c2ecf20Sopenharmony_ci xgene_pcie_writel(port, pim_reg + 0x14, upper_32_bits(size)); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci/* 4608c2ecf20Sopenharmony_ci * X-Gene PCIe support maximum 3 inbound memory regions 4618c2ecf20Sopenharmony_ci * This function helps to select a region based on size of region 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_cistatic int xgene_pcie_select_ib_reg(u8 *ib_reg_mask, u64 size) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci if ((size > 4) && (size < SZ_16M) && !(*ib_reg_mask & (1 << 1))) { 4668c2ecf20Sopenharmony_ci *ib_reg_mask |= (1 << 1); 4678c2ecf20Sopenharmony_ci return 1; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if ((size > SZ_1K) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 0))) { 4718c2ecf20Sopenharmony_ci *ib_reg_mask |= (1 << 0); 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if ((size > SZ_1M) && (size < SZ_1T) && !(*ib_reg_mask & (1 << 2))) { 4768c2ecf20Sopenharmony_ci *ib_reg_mask |= (1 << 2); 4778c2ecf20Sopenharmony_ci return 2; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return -EINVAL; 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic void xgene_pcie_setup_ib_reg(struct xgene_pcie_port *port, 4848c2ecf20Sopenharmony_ci struct of_pci_range *range, u8 *ib_reg_mask) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci void __iomem *cfg_base = port->cfg_base; 4878c2ecf20Sopenharmony_ci struct device *dev = port->dev; 4888c2ecf20Sopenharmony_ci void *bar_addr; 4898c2ecf20Sopenharmony_ci u32 pim_reg; 4908c2ecf20Sopenharmony_ci u64 cpu_addr = range->cpu_addr; 4918c2ecf20Sopenharmony_ci u64 pci_addr = range->pci_addr; 4928c2ecf20Sopenharmony_ci u64 size = range->size; 4938c2ecf20Sopenharmony_ci u64 mask = ~(size - 1) | EN_REG; 4948c2ecf20Sopenharmony_ci u32 flags = PCI_BASE_ADDRESS_MEM_TYPE_64; 4958c2ecf20Sopenharmony_ci u32 bar_low; 4968c2ecf20Sopenharmony_ci int region; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci region = xgene_pcie_select_ib_reg(ib_reg_mask, range->size); 4998c2ecf20Sopenharmony_ci if (region < 0) { 5008c2ecf20Sopenharmony_ci dev_warn(dev, "invalid pcie dma-range config\n"); 5018c2ecf20Sopenharmony_ci return; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci if (range->flags & IORESOURCE_PREFETCH) 5058c2ecf20Sopenharmony_ci flags |= PCI_BASE_ADDRESS_MEM_PREFETCH; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci bar_low = pcie_bar_low_val((u32)cpu_addr, flags); 5088c2ecf20Sopenharmony_ci switch (region) { 5098c2ecf20Sopenharmony_ci case 0: 5108c2ecf20Sopenharmony_ci xgene_pcie_set_ib_mask(port, BRIDGE_CFG_4, flags, size); 5118c2ecf20Sopenharmony_ci bar_addr = cfg_base + PCI_BASE_ADDRESS_0; 5128c2ecf20Sopenharmony_ci writel(bar_low, bar_addr); 5138c2ecf20Sopenharmony_ci writel(upper_32_bits(cpu_addr), bar_addr + 0x4); 5148c2ecf20Sopenharmony_ci pim_reg = PIM1_1L; 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci case 1: 5178c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IBAR2, bar_low); 5188c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IR2MSK, lower_32_bits(mask)); 5198c2ecf20Sopenharmony_ci pim_reg = PIM2_1L; 5208c2ecf20Sopenharmony_ci break; 5218c2ecf20Sopenharmony_ci case 2: 5228c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IBAR3L, bar_low); 5238c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IBAR3L + 0x4, upper_32_bits(cpu_addr)); 5248c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IR3MSKL, lower_32_bits(mask)); 5258c2ecf20Sopenharmony_ci xgene_pcie_writel(port, IR3MSKL + 0x4, upper_32_bits(mask)); 5268c2ecf20Sopenharmony_ci pim_reg = PIM3_1L; 5278c2ecf20Sopenharmony_ci break; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci xgene_pcie_setup_pims(port, pim_reg, pci_addr, ~(size - 1)); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic int xgene_pcie_parse_map_dma_ranges(struct xgene_pcie_port *port) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci struct device_node *np = port->node; 5368c2ecf20Sopenharmony_ci struct of_pci_range range; 5378c2ecf20Sopenharmony_ci struct of_pci_range_parser parser; 5388c2ecf20Sopenharmony_ci struct device *dev = port->dev; 5398c2ecf20Sopenharmony_ci u8 ib_reg_mask = 0; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (of_pci_dma_range_parser_init(&parser, np)) { 5428c2ecf20Sopenharmony_ci dev_err(dev, "missing dma-ranges property\n"); 5438c2ecf20Sopenharmony_ci return -EINVAL; 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci /* Get the dma-ranges from DT */ 5478c2ecf20Sopenharmony_ci for_each_of_pci_range(&parser, &range) { 5488c2ecf20Sopenharmony_ci u64 end = range.cpu_addr + range.size - 1; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci dev_dbg(dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", 5518c2ecf20Sopenharmony_ci range.flags, range.cpu_addr, end, range.pci_addr); 5528c2ecf20Sopenharmony_ci xgene_pcie_setup_ib_reg(port, &range, &ib_reg_mask); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* clear BAR configuration which was done by firmware */ 5588c2ecf20Sopenharmony_cistatic void xgene_pcie_clear_config(struct xgene_pcie_port *port) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci int i; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci for (i = PIM1_1L; i <= CFGCTL; i += 4) 5638c2ecf20Sopenharmony_ci xgene_pcie_writel(port, i, 0); 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic int xgene_pcie_setup(struct xgene_pcie_port *port) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct device *dev = port->dev; 5698c2ecf20Sopenharmony_ci u32 val, lanes = 0, speed = 0; 5708c2ecf20Sopenharmony_ci int ret; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci xgene_pcie_clear_config(port); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci /* setup the vendor and device IDs correctly */ 5758c2ecf20Sopenharmony_ci val = (XGENE_PCIE_DEVICEID << 16) | XGENE_PCIE_VENDORID; 5768c2ecf20Sopenharmony_ci xgene_pcie_writel(port, BRIDGE_CFG_0, val); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci ret = xgene_pcie_map_ranges(port); 5798c2ecf20Sopenharmony_ci if (ret) 5808c2ecf20Sopenharmony_ci return ret; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci ret = xgene_pcie_parse_map_dma_ranges(port); 5838c2ecf20Sopenharmony_ci if (ret) 5848c2ecf20Sopenharmony_ci return ret; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci xgene_pcie_linkup(port, &lanes, &speed); 5878c2ecf20Sopenharmony_ci if (!port->link_up) 5888c2ecf20Sopenharmony_ci dev_info(dev, "(rc) link down\n"); 5898c2ecf20Sopenharmony_ci else 5908c2ecf20Sopenharmony_ci dev_info(dev, "(rc) x%d gen-%d link up\n", lanes, speed + 1); 5918c2ecf20Sopenharmony_ci return 0; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistatic struct pci_ops xgene_pcie_ops = { 5958c2ecf20Sopenharmony_ci .map_bus = xgene_pcie_map_bus, 5968c2ecf20Sopenharmony_ci .read = xgene_pcie_config_read32, 5978c2ecf20Sopenharmony_ci .write = pci_generic_config_write32, 5988c2ecf20Sopenharmony_ci}; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_cistatic int xgene_pcie_probe(struct platform_device *pdev) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 6038c2ecf20Sopenharmony_ci struct device_node *dn = dev->of_node; 6048c2ecf20Sopenharmony_ci struct xgene_pcie_port *port; 6058c2ecf20Sopenharmony_ci struct pci_host_bridge *bridge; 6068c2ecf20Sopenharmony_ci int ret; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port)); 6098c2ecf20Sopenharmony_ci if (!bridge) 6108c2ecf20Sopenharmony_ci return -ENOMEM; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci port = pci_host_bridge_priv(bridge); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci port->node = of_node_get(dn); 6158c2ecf20Sopenharmony_ci port->dev = dev; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci port->version = XGENE_PCIE_IP_VER_UNKN; 6188c2ecf20Sopenharmony_ci if (of_device_is_compatible(port->node, "apm,xgene-pcie")) 6198c2ecf20Sopenharmony_ci port->version = XGENE_PCIE_IP_VER_1; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci ret = xgene_pcie_map_reg(port, pdev); 6228c2ecf20Sopenharmony_ci if (ret) 6238c2ecf20Sopenharmony_ci return ret; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci ret = xgene_pcie_init_port(port); 6268c2ecf20Sopenharmony_ci if (ret) 6278c2ecf20Sopenharmony_ci return ret; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci ret = xgene_pcie_setup(port); 6308c2ecf20Sopenharmony_ci if (ret) 6318c2ecf20Sopenharmony_ci return ret; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci bridge->sysdata = port; 6348c2ecf20Sopenharmony_ci bridge->ops = &xgene_pcie_ops; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci return pci_host_probe(bridge); 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic const struct of_device_id xgene_pcie_match_table[] = { 6408c2ecf20Sopenharmony_ci {.compatible = "apm,xgene-pcie",}, 6418c2ecf20Sopenharmony_ci {}, 6428c2ecf20Sopenharmony_ci}; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic struct platform_driver xgene_pcie_driver = { 6458c2ecf20Sopenharmony_ci .driver = { 6468c2ecf20Sopenharmony_ci .name = "xgene-pcie", 6478c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(xgene_pcie_match_table), 6488c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 6498c2ecf20Sopenharmony_ci }, 6508c2ecf20Sopenharmony_ci .probe = xgene_pcie_probe, 6518c2ecf20Sopenharmony_ci}; 6528c2ecf20Sopenharmony_cibuiltin_platform_driver(xgene_pcie_driver); 6538c2ecf20Sopenharmony_ci#endif 654