Commit c3b2f9dc authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/controller/apple'

- Skip ports disabled in DT when setting up ports (Janne Grunau)

- Add t6020 compatible string (Alyssa Rosenzweig)

- Extract ECAM bridge creation helper from pci_host_common_probe() to
  separate driver-specific things like MSI from PCI things (Marc Zyngier)

- Dynamically allocate RID-to_SID bitmap to prepare for SoCs with varying
  capabilities (Marc Zyngier)

- Directly set/clear INTx mask bits because T602x dropped the accessors
  that could do this without locking (Marc Zyngier)

- Move port PHY registers to their own reg items to accommodate T602x,
  which moves them around; retain default offsets for existing DTs that
  lack phy%d entries with the reg offsets (Hector Martin)

- Stop polling for core refclk, which doesn't work on T602x and the
  bootloader has already done anyway (Hector Martin)

- Use gpiod_set_value_cansleep() when asserting PERST# in probe because
  we're allowed to sleep there (Hector Martin)

- Move register offsets into SoC-specific structure (Hector Martin)

- Add T602x PCIe support (Hector Martin)

* pci/controller/apple:
  PCI: apple: Add T602x PCIe support
  PCI: apple: Abstract register offsets via a SoC-specific structure
  PCI: apple: Use gpiod_set_value_cansleep in probe flow
  PCI: apple: Drop poll for CORE_RC_PHYIF_STAT_REFCLK
  PCI: apple: Move port PHY registers to their own reg items
  PCI: apple: Fix missing OF node reference in apple_pcie_setup_port
  PCI: apple: Move away from INTMSK{SET,CLR} for INTx and private interrupts
  PCI: apple: Dynamically allocate RID-to_SID bitmap
  PCI: apple: Move over to standalone probing
  PCI: ecam: Allow cfg->priv to be pre-populated from the root port device
  PCI: host-generic: Extract an ECAM bridge creation helper from pci_host_common_probe()
  dt-bindings: pci: apple,pcie: Add t6020 compatible string
  PCI: apple: Set only available ports up
parents 2ce73872 4e639f11
Loading
Loading
Loading
Loading
+26 −7
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@ description: |
  implements its root ports.  But the ATU found on most DesignWare
  PCIe host bridges is absent.

  On systems derived from T602x, the PHY registers are in a region
  separate from the port registers. In that case, there is one PHY
  register range per port register range.

  All root ports share a single ECAM space, but separate GPIOs are
  used to take the PCI devices on those ports out of reset.  Therefore
  the standard "reset-gpios" and "max-link-speed" properties appear on
@@ -30,16 +34,18 @@ description: |

properties:
  compatible:
    items:
    oneOf:
      - items:
          - enum:
              - apple,t8103-pcie
              - apple,t8112-pcie
              - apple,t6000-pcie
          - const: apple,pcie
      - const: apple,t6020-pcie

  reg:
    minItems: 3
    maxItems: 6
    maxItems: 10

  reg-names:
    minItems: 3
@@ -50,6 +56,10 @@ properties:
      - const: port1
      - const: port2
      - const: port3
      - const: phy0
      - const: phy1
      - const: phy2
      - const: phy3

  ranges:
    minItems: 2
@@ -98,6 +108,15 @@ allOf:
          maxItems: 5
        interrupts:
          maxItems: 3
  - if:
      properties:
        compatible:
          contains:
            const: apple,t6020-pcie
    then:
      properties:
        reg-names:
          minItems: 10

examples:
  - |
+16 −8
Original line number Diff line number Diff line
@@ -49,23 +49,17 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
	return cfg;
}

int pci_host_common_probe(struct platform_device *pdev)
int pci_host_common_init(struct platform_device *pdev,
			 const struct pci_ecam_ops *ops)
{
	struct device *dev = &pdev->dev;
	struct pci_host_bridge *bridge;
	struct pci_config_window *cfg;
	const struct pci_ecam_ops *ops;

	ops = of_device_get_match_data(&pdev->dev);
	if (!ops)
		return -ENODEV;

	bridge = devm_pci_alloc_host_bridge(dev, 0);
	if (!bridge)
		return -ENOMEM;

	platform_set_drvdata(pdev, bridge);

	of_pci_check_probe_only();

	/* Parse and map our Configuration Space windows */
@@ -73,6 +67,8 @@ int pci_host_common_probe(struct platform_device *pdev)
	if (IS_ERR(cfg))
		return PTR_ERR(cfg);

	platform_set_drvdata(pdev, bridge);

	bridge->sysdata = cfg;
	bridge->ops = (struct pci_ops *)&ops->pci_ops;
	bridge->enable_device = ops->enable_device;
@@ -81,6 +77,18 @@ int pci_host_common_probe(struct platform_device *pdev)

	return pci_host_probe(bridge);
}
EXPORT_SYMBOL_GPL(pci_host_common_init);

int pci_host_common_probe(struct platform_device *pdev)
{
	const struct pci_ecam_ops *ops;

	ops = of_device_get_match_data(&pdev->dev);
	if (!ops)
		return -ENODEV;

	return pci_host_common_init(pdev, ops);
}
EXPORT_SYMBOL_GPL(pci_host_common_probe);

void pci_host_common_remove(struct platform_device *pdev)
+174 −67
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
 * Author: Marc Zyngier <maz@kernel.org>
 */

#include <linux/bitfield.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/iopoll.h>
@@ -29,6 +30,7 @@
#include <linux/of_irq.h>
#include <linux/pci-ecam.h>

/* T8103 (original M1) and related SoCs */
#define CORE_RC_PHYIF_CTL		0x00024
#define   CORE_RC_PHYIF_CTL_RUN		BIT(0)
#define CORE_RC_PHYIF_STAT		0x00028
@@ -39,14 +41,18 @@
#define   CORE_RC_STAT_READY		BIT(0)
#define CORE_FABRIC_STAT		0x04000
#define   CORE_FABRIC_STAT_MASK		0x001F001F
#define CORE_LANE_CFG(port)		(0x84000 + 0x4000 * (port))
#define   CORE_LANE_CFG_REFCLK0REQ	BIT(0)
#define   CORE_LANE_CFG_REFCLK1REQ	BIT(1)
#define   CORE_LANE_CFG_REFCLK0ACK	BIT(2)
#define   CORE_LANE_CFG_REFCLK1ACK	BIT(3)
#define   CORE_LANE_CFG_REFCLKEN	(BIT(9) | BIT(10))
#define CORE_LANE_CTL(port)		(0x84004 + 0x4000 * (port))
#define   CORE_LANE_CTL_CFGACC		BIT(15)

#define CORE_PHY_DEFAULT_BASE(port)	(0x84000 + 0x4000 * (port))

#define PHY_LANE_CFG			0x00000
#define   PHY_LANE_CFG_REFCLK0REQ	BIT(0)
#define   PHY_LANE_CFG_REFCLK1REQ	BIT(1)
#define   PHY_LANE_CFG_REFCLK0ACK	BIT(2)
#define   PHY_LANE_CFG_REFCLK1ACK	BIT(3)
#define   PHY_LANE_CFG_REFCLKEN		(BIT(9) | BIT(10))
#define   PHY_LANE_CFG_REFCLKCGEN	(BIT(30) | BIT(31))
#define PHY_LANE_CTL			0x00004
#define   PHY_LANE_CTL_CFGACC		BIT(15)

#define PORT_LTSSMCTL			0x00080
#define   PORT_LTSSMCTL_START		BIT(0)
@@ -100,7 +106,7 @@
#define   PORT_REFCLK_CGDIS		BIT(8)
#define PORT_PERST			0x00814
#define   PORT_PERST_OFF		BIT(0)
#define PORT_RID2SID(i16)		(0x00828 + 4 * (i16))
#define PORT_RID2SID			0x00828
#define   PORT_RID2SID_VALID		BIT(31)
#define   PORT_RID2SID_SID_SHIFT	16
#define   PORT_RID2SID_BUS_SHIFT	8
@@ -118,7 +124,15 @@
#define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1)
#define PORT_PREFMEM_ENABLE		0x00994

#define MAX_RID2SID			64
/* T602x (M2-pro and co) */
#define PORT_T602X_MSIADDR	0x016c
#define PORT_T602X_MSIADDR_HI	0x0170
#define PORT_T602X_PERST	0x082c
#define PORT_T602X_RID2SID	0x3000
#define PORT_T602X_MSIMAP	0x3800

#define PORT_MSIMAP_ENABLE	BIT(31)
#define PORT_MSIMAP_TARGET	GENMASK(7, 0)

/*
 * The doorbell address is set to 0xfffff000, which by convention
@@ -129,10 +143,45 @@
 */
#define DOORBELL_ADDR		CONFIG_PCIE_APPLE_MSI_DOORBELL_ADDR

struct hw_info {
	u32 phy_lane_ctl;
	u32 port_msiaddr;
	u32 port_msiaddr_hi;
	u32 port_refclk;
	u32 port_perst;
	u32 port_rid2sid;
	u32 port_msimap;
	u32 max_rid2sid;
};

static const struct hw_info t8103_hw = {
	.phy_lane_ctl		= PHY_LANE_CTL,
	.port_msiaddr		= PORT_MSIADDR,
	.port_msiaddr_hi	= 0,
	.port_refclk		= PORT_REFCLK,
	.port_perst		= PORT_PERST,
	.port_rid2sid		= PORT_RID2SID,
	.port_msimap		= 0,
	.max_rid2sid		= 64,
};

static const struct hw_info t602x_hw = {
	.phy_lane_ctl		= 0,
	.port_msiaddr		= PORT_T602X_MSIADDR,
	.port_msiaddr_hi	= PORT_T602X_MSIADDR_HI,
	.port_refclk		= 0,
	.port_perst		= PORT_T602X_PERST,
	.port_rid2sid		= PORT_T602X_RID2SID,
	.port_msimap		= PORT_T602X_MSIMAP,
	/* 16 on t602x, guess for autodetect on future HW */
	.max_rid2sid		= 512,
};

struct apple_pcie {
	struct mutex		lock;
	struct device		*dev;
	void __iomem            *base;
	const struct hw_info	*hw;
	struct irq_domain	*domain;
	unsigned long		*bitmap;
	struct list_head	ports;
@@ -142,12 +191,14 @@ struct apple_pcie {
};

struct apple_pcie_port {
	raw_spinlock_t		lock;
	struct apple_pcie	*pcie;
	struct device_node	*np;
	void __iomem		*base;
	void __iomem		*phy;
	struct irq_domain	*domain;
	struct list_head	entry;
	DECLARE_BITMAP(sid_map, MAX_RID2SID);
	unsigned long		*sid_map;
	int			sid_map_sz;
	int			idx;
};
@@ -261,14 +312,16 @@ static void apple_port_irq_mask(struct irq_data *data)
{
	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data);

	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKSET);
	guard(raw_spinlock_irqsave)(&port->lock);
	rmw_set(BIT(data->hwirq), port->base + PORT_INTMSK);
}

static void apple_port_irq_unmask(struct irq_data *data)
{
	struct apple_pcie_port *port = irq_data_get_irq_chip_data(data);

	writel_relaxed(BIT(data->hwirq), port->base + PORT_INTMSKCLR);
	guard(raw_spinlock_irqsave)(&port->lock);
	rmw_clear(BIT(data->hwirq), port->base + PORT_INTMSK);
}

static bool hwirq_is_intx(unsigned int hwirq)
@@ -372,7 +425,9 @@ static void apple_port_irq_handler(struct irq_desc *desc)
static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
{
	struct fwnode_handle *fwnode = &port->np->fwnode;
	struct apple_pcie *pcie = port->pcie;
	unsigned int irq;
	u32 val = 0;

	/* FIXME: consider moving each interrupt under each port */
	irq = irq_of_parse_and_map(to_of_node(dev_fwnode(port->pcie->dev)),
@@ -387,20 +442,31 @@ static int apple_pcie_port_setup_irq(struct apple_pcie_port *port)
		return -ENOMEM;

	/* Disable all interrupts */
	writel_relaxed(~0, port->base + PORT_INTMSKSET);
	writel_relaxed(~0, port->base + PORT_INTMSK);
	writel_relaxed(~0, port->base + PORT_INTSTAT);
	writel_relaxed(~0, port->base + PORT_LINKCMDSTS);

	irq_set_chained_handler_and_data(irq, apple_port_irq_handler, port);

	/* Configure MSI base address */
	BUILD_BUG_ON(upper_32_bits(DOORBELL_ADDR));
	writel_relaxed(lower_32_bits(DOORBELL_ADDR), port->base + PORT_MSIADDR);
	writel_relaxed(lower_32_bits(DOORBELL_ADDR),
		       port->base + pcie->hw->port_msiaddr);
	if (pcie->hw->port_msiaddr_hi)
		writel_relaxed(0, port->base + pcie->hw->port_msiaddr_hi);

	/* Enable MSIs, shared between all ports */
	if (pcie->hw->port_msimap) {
		for (int i = 0; i < pcie->nvecs; i++)
			writel_relaxed(FIELD_PREP(PORT_MSIMAP_TARGET, i) |
				       PORT_MSIMAP_ENABLE,
				       port->base + pcie->hw->port_msimap + 4 * i);
	} else {
		writel_relaxed(0, port->base + PORT_MSIBASE);
	writel_relaxed((ilog2(port->pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT) |
		       PORT_MSICFG_EN, port->base + PORT_MSICFG);
		val = ilog2(pcie->nvecs) << PORT_MSICFG_L2MSINUM_SHIFT;
	}

	writel_relaxed(val | PORT_MSICFG_EN, port->base + PORT_MSICFG);
	return 0;
}

@@ -467,43 +533,47 @@ static int apple_pcie_setup_refclk(struct apple_pcie *pcie,
	u32 stat;
	int res;

	res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat,
					 stat & CORE_RC_PHYIF_STAT_REFCLK,
					 100, 50000);
	if (res < 0)
		return res;
	if (pcie->hw->phy_lane_ctl)
		rmw_set(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);

	rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
	rmw_set(CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx));
	rmw_set(PHY_LANE_CFG_REFCLK0REQ, port->phy + PHY_LANE_CFG);

	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx),
					 stat, stat & CORE_LANE_CFG_REFCLK0ACK,
	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
					 stat, stat & PHY_LANE_CFG_REFCLK0ACK,
					 100, 50000);
	if (res < 0)
		return res;

	rmw_set(CORE_LANE_CFG_REFCLK1REQ, pcie->base + CORE_LANE_CFG(port->idx));
	res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx),
					 stat, stat & CORE_LANE_CFG_REFCLK1ACK,
	rmw_set(PHY_LANE_CFG_REFCLK1REQ, port->phy + PHY_LANE_CFG);
	res = readl_relaxed_poll_timeout(port->phy + PHY_LANE_CFG,
					 stat, stat & PHY_LANE_CFG_REFCLK1ACK,
					 100, 50000);

	if (res < 0)
		return res;

	rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
	if (pcie->hw->phy_lane_ctl)
		rmw_clear(PHY_LANE_CTL_CFGACC, port->phy + pcie->hw->phy_lane_ctl);

	rmw_set(PHY_LANE_CFG_REFCLKEN, port->phy + PHY_LANE_CFG);

	rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx));
	rmw_set(PORT_REFCLK_EN, port->base + PORT_REFCLK);
	if (pcie->hw->port_refclk)
		rmw_set(PORT_REFCLK_EN, port->base + pcie->hw->port_refclk);

	return 0;
}

static void __iomem *port_rid2sid_addr(struct apple_pcie_port *port, int idx)
{
	return port->base + port->pcie->hw->port_rid2sid + 4 * idx;
}

static u32 apple_pcie_rid2sid_write(struct apple_pcie_port *port,
				    int idx, u32 val)
{
	writel_relaxed(val, port->base + PORT_RID2SID(idx));
	writel_relaxed(val, port_rid2sid_addr(port, idx));
	/* Read back to ensure completion of the write */
	return readl_relaxed(port->base + PORT_RID2SID(idx));
	return readl_relaxed(port_rid2sid_addr(port, idx));
}

static int apple_pcie_setup_port(struct apple_pcie *pcie,
@@ -512,6 +582,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
	struct platform_device *platform = to_platform_device(pcie->dev);
	struct apple_pcie_port *port;
	struct gpio_desc *reset;
	struct resource *res;
	char name[16];
	u32 stat, idx;
	int ret, i;

@@ -524,6 +596,10 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
	if (!port)
		return -ENOMEM;

	port->sid_map = devm_bitmap_zalloc(pcie->dev, pcie->hw->max_rid2sid, GFP_KERNEL);
	if (!port->sid_map)
		return -ENOMEM;

	ret = of_property_read_u32_index(np, "reg", 0, &idx);
	if (ret)
		return ret;
@@ -533,14 +609,28 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
	port->pcie = pcie;
	port->np = np;

	port->base = devm_platform_ioremap_resource(platform, port->idx + 2);
	raw_spin_lock_init(&port->lock);

	snprintf(name, sizeof(name), "port%d", port->idx);
	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name);
	if (!res)
		res = platform_get_resource(platform, IORESOURCE_MEM, port->idx + 2);

	port->base = devm_ioremap_resource(&platform->dev, res);
	if (IS_ERR(port->base))
		return PTR_ERR(port->base);

	snprintf(name, sizeof(name), "phy%d", port->idx);
	res = platform_get_resource_byname(platform, IORESOURCE_MEM, name);
	if (res)
		port->phy = devm_ioremap_resource(&platform->dev, res);
	else
		port->phy = pcie->base + CORE_PHY_DEFAULT_BASE(port->idx);

	rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);

	/* Assert PERST# before setting up the clock */
	gpiod_set_value(reset, 1);
	gpiod_set_value_cansleep(reset, 1);

	ret = apple_pcie_setup_refclk(pcie, port);
	if (ret < 0)
@@ -550,8 +640,8 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
	usleep_range(100, 200);

	/* Deassert PERST# */
	rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
	gpiod_set_value(reset, 0);
	rmw_set(PORT_PERST_OFF, port->base + pcie->hw->port_perst);
	gpiod_set_value_cansleep(reset, 0);

	/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
	msleep(100);
@@ -563,7 +653,11 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
		return ret;
	}

	rmw_clear(PORT_REFCLK_CGDIS, port->base + PORT_REFCLK);
	if (pcie->hw->port_refclk)
		rmw_clear(PORT_REFCLK_CGDIS, port->base + pcie->hw->port_refclk);
	else
		rmw_set(PHY_LANE_CFG_REFCLKCGEN, port->phy + PHY_LANE_CFG);

	rmw_clear(PORT_APPCLK_CGDIS, port->base + PORT_APPCLK);

	ret = apple_pcie_port_setup_irq(port);
@@ -571,7 +665,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
		return ret;

	/* Reset all RID/SID mappings, and check for RAZ/WI registers */
	for (i = 0; i < MAX_RID2SID; i++) {
	for (i = 0; i < pcie->hw->max_rid2sid; i++) {
		if (apple_pcie_rid2sid_write(port, i, 0xbad1d) != 0xbad1d)
			break;
		apple_pcie_rid2sid_write(port, i, 0);
@@ -584,6 +678,9 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
	list_add_tail(&port->entry, &pcie->ports);
	init_completion(&pcie->event);

	/* In the success path, we keep a reference to np around */
	of_node_get(np);

	ret = apple_pcie_port_register_irqs(port);
	WARN_ON(ret);

@@ -716,7 +813,7 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci
	for_each_set_bit(idx, port->sid_map, port->sid_map_sz) {
		u32 val;

		val = readl_relaxed(port->base + PORT_RID2SID(idx));
		val = readl_relaxed(port_rid2sid_addr(port, idx));
		if ((val & 0xffff) == rid) {
			apple_pcie_rid2sid_write(port, idx, 0);
			bitmap_release_region(port->sid_map, idx, 0);
@@ -730,34 +827,14 @@ static void apple_pcie_disable_device(struct pci_host_bridge *bridge, struct pci

static int apple_pcie_init(struct pci_config_window *cfg)
{
	struct apple_pcie *pcie = cfg->priv;
	struct device *dev = cfg->parent;
	struct platform_device *platform = to_platform_device(dev);
	struct apple_pcie *pcie;
	int ret;

	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
	if (!pcie)
		return -ENOMEM;

	pcie->dev = dev;

	mutex_init(&pcie->lock);

	pcie->base = devm_platform_ioremap_resource(platform, 1);
	if (IS_ERR(pcie->base))
		return PTR_ERR(pcie->base);

	cfg->priv = pcie;
	INIT_LIST_HEAD(&pcie->ports);

	ret = apple_msi_init(pcie);
	if (ret)
		return ret;

	for_each_child_of_node_scoped(dev->of_node, of_port) {
	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
		ret = apple_pcie_setup_port(pcie, of_port);
		if (ret) {
			dev_err(pcie->dev, "Port %pOF setup fail: %d\n", of_port, ret);
			dev_err(dev, "Port %pOF setup fail: %d\n", of_port, ret);
			return ret;
		}
	}
@@ -776,14 +853,44 @@ static const struct pci_ecam_ops apple_pcie_cfg_ecam_ops = {
	}
};

static int apple_pcie_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct apple_pcie *pcie;
	int ret;

	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
	if (!pcie)
		return -ENOMEM;

	pcie->dev = dev;
	pcie->hw = of_device_get_match_data(dev);
	if (!pcie->hw)
		return -ENODEV;
	pcie->base = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(pcie->base))
		return PTR_ERR(pcie->base);

	mutex_init(&pcie->lock);
	INIT_LIST_HEAD(&pcie->ports);
	dev_set_drvdata(dev, pcie);

	ret = apple_msi_init(pcie);
	if (ret)
		return ret;

	return pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops);
}

static const struct of_device_id apple_pcie_of_match[] = {
	{ .compatible = "apple,pcie", .data = &apple_pcie_cfg_ecam_ops },
	{ .compatible = "apple,t6020-pcie",	.data = &t602x_hw },
	{ .compatible = "apple,pcie",		.data = &t8103_hw },
	{ }
};
MODULE_DEVICE_TABLE(of, apple_pcie_of_match);

static struct platform_driver apple_pcie_driver = {
	.probe	= pci_host_common_probe,
	.probe	= apple_pcie_probe,
	.driver	= {
		.name			= "pcie-apple",
		.of_match_table		= apple_pcie_of_match,
+2 −0
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
			goto err_exit_iomap;
	}

	cfg->priv = dev_get_drvdata(dev);

	if (ops->init) {
		err = ops->init(cfg);
		if (err)
+2 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ extern const struct pci_ecam_ops loongson_pci_ecam_ops; /* Loongson PCIe */
#if IS_ENABLED(CONFIG_PCI_HOST_COMMON)
/* for DT-based PCI controllers that support ECAM */
int pci_host_common_probe(struct platform_device *pdev);
int pci_host_common_init(struct platform_device *pdev,
			 const struct pci_ecam_ops *ops);
void pci_host_common_remove(struct platform_device *pdev);
#endif
#endif