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