]> Git Repo - linux.git/commitdiff
Merge branch 'pci/host-probe-refactor'
authorBjorn Helgaas <[email protected]>
Wed, 5 Aug 2020 23:24:21 +0000 (18:24 -0500)
committerBjorn Helgaas <[email protected]>
Wed, 5 Aug 2020 23:24:21 +0000 (18:24 -0500)
- Use pci_host_bridge.windows list directly instead of splicing in a
  temporary list for cadence, mvebu, host-common (Rob Herring)

- Use pci_host_probe() instead of open-coding all the pieces for altera,
  brcmstb, iproc, mobiveil, rcar, rockchip, tegra, v3, versatile, xgene,
  xilinx, xilinx-nwl (Rob Herring)

- Convert to devm_platform_ioremap_resource_byname() instead of open-coding
  platform_get_resource_byname() and devm_ioremap_resource() for altera,
  cadence, mediatek, rockchip, tegra, xgene (Dejin Zheng)

- Convert to devm_platform_ioremap_resource() instead of open-coding
  platform_get_resource() and devm_ioremap_resource() for aardvark,
  brcmstb, exynos, ftpci100, versatile (Dejin Zheng)

- Remove redundant error messages from devm_pci_remap_cfg_resource()
  callers (Dejin Zheng)

- Drop useless PCI_ENABLE_PROC_DOMAINS from versatile driver (Rob Herring)

- Default host bridge parent device to the platform device (Rob Herring)

- Drop unnecessary zeroing of host bridge fields (Rob Herring)

- Use pci_is_root_bus() instead of tracking root bus number separately in
  aardvark, designware (imx6, keystone, designware-host), mobiveil,
  xilinx-nwl, xilinx, rockchip, rcar (Rob Herring)

- Set host bridge bus number in pci_scan_root_bus_bridge() instead of each
  driver for aardvark, designware-host, host-common, mediatek, rcar, tegra,
  v3-semi (Rob Herring)

- Use bridge resources instead of parsing DT 'ranges' again for cadence
  (Rob Herring)

- Remove private bus number and range from cadence (Rob Herring)

- Use devm_pci_alloc_host_bridge() to simplify rcar (Rob Herring)

- Use struct pci_host_bridge.windows list directly rather than a temporary
  (Rob Herring)

- Reduce OF "missing non-prefetchable window" from error to warning message
  (Rob Herring)

- Convert rcar-gen2 from old Arm-specific pci_common_init_dev() to new
  arch-independent interfaces (Rob Herring)

- Move DT resource setup into devm_pci_alloc_host_bridge() (Rob Herring)

- Set bridge map_irq and swizzle_irq to default functions; drivers that
  don't support legacy IRQs (iproc) need to undo this (Rob Herring)

* pci/host-probe-refactor:
  PCI: Set bridge map_irq and swizzle_irq to default functions
  PCI: Move DT resource setup into devm_pci_alloc_host_bridge()
  PCI: rcar-gen2: Convert to use modern host bridge probe functions
  PCI: of: Reduce missing non-prefetchable memory region to a warning
  PCI: rcar: Use struct pci_host_bridge.windows list directly
  PCI: rcar: Use devm_pci_alloc_host_bridge()
  PCI: cadence: Remove private bus number and range storage
  PCI: cadence: Use bridge resources for outbound window setup
  PCI: Move setting pci_host_bridge.busnr out of host drivers
  PCI: rcar: Use pci_is_root_bus() to check if bus is root bus
  PCI: rockchip: Use pci_is_root_bus() to check if bus is root bus
  PCI: xilinx: Use pci_is_root_bus() to check if bus is root bus
  PCI: xilinx-nwl: Use pci_is_root_bus() to check if bus is root bus
  PCI: mobiveil: Use pci_is_root_bus() to check if bus is root bus
  PCI: designware: Use pci_is_root_bus() to check if bus is root bus
  PCI: aardvark: Use pci_is_root_bus() to check if bus is root bus
  PCI: Drop unnecessary zeroing of bridge fields
  PCI: Set default bridge parent device
  PCI: versatile: Drop flag PCI_ENABLE_PROC_DOMAINS
  PCI: controller: Remove duplicate error message
  PCI: controller: Convert to devm_platform_ioremap_resource()
  PCI: controller: Convert to devm_platform_ioremap_resource_byname()
  PCI: xilinx: Use pci_host_probe() to register host
  PCI: xilinx-nwl: Use pci_host_probe() to register host
  PCI: rockchip: Use pci_host_probe() to register host
  PCI: rcar: Use pci_host_probe() to register host
  PCI: iproc: Use pci_host_probe() to register host
  PCI: altera: Use pci_host_probe() to register host
  PCI: xgene: Use pci_host_probe() to register host
  PCI: versatile: Use pci_host_probe() to register host
  PCI: v3: Use pci_host_probe() to register host
  PCI: tegra: Use pci_host_probe() to register host
  PCI: mobiveil: Use pci_host_probe() to register host
  PCI: brcmstb: Use pci_host_probe() to register host
  PCI: host-common: Use struct pci_host_bridge.windows list directly
  PCI: mvebu: Use struct pci_host_bridge.windows list directly
  PCI: cadence: Use struct pci_host_bridge.windows list directly

# Conflicts:
# drivers/pci/controller/cadence/pcie-cadence-host.c

20 files changed:
1  2 
drivers/pci/controller/cadence/pci-j721e.c
drivers/pci/controller/cadence/pcie-cadence-ep.c
drivers/pci/controller/cadence/pcie-cadence-host.c
drivers/pci/controller/cadence/pcie-cadence.c
drivers/pci/controller/cadence/pcie-cadence.h
drivers/pci/controller/dwc/pci-exynos.c
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-keystone.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.h
drivers/pci/controller/pci-aardvark.c
drivers/pci/controller/pci-loongson.c
drivers/pci/controller/pci-mvebu.c
drivers/pci/controller/pci-tegra.c
drivers/pci/controller/pcie-rcar-host.c
drivers/pci/controller/pcie-xilinx-cpm.c
drivers/pci/of.c
drivers/pci/pci.h
drivers/pci/probe.c
include/linux/pci.h

index 23ad8fa699c4851b268b6e8df846f0a4f1883892,0000000000000000000000000000000000000000..586b9d69fa5e21ffea1644bd1eefa91a877c57ca
mode 100644,000000..100644
--- /dev/null
@@@ -1,493 -1,0 +1,485 @@@
-       struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
-       struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
-       unsigned int busn = bus->number;
-       if (busn == rc->bus_range->start)
 +// SPDX-License-Identifier: GPL-2.0
 +/**
 + * pci-j721e - PCIe controller driver for TI's J721E SoCs
 + *
 + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
 + * Author: Kishon Vijay Abraham I <[email protected]>
 + */
 +
 +#include <linux/delay.h>
 +#include <linux/gpio/consumer.h>
 +#include <linux/io.h>
 +#include <linux/irqchip/chained_irq.h>
 +#include <linux/irqdomain.h>
 +#include <linux/mfd/syscon.h>
 +#include <linux/of_device.h>
 +#include <linux/of_irq.h>
 +#include <linux/pci.h>
 +#include <linux/pm_runtime.h>
 +#include <linux/regmap.h>
 +
 +#include "../../pci.h"
 +#include "pcie-cadence.h"
 +
 +#define ENABLE_REG_SYS_2      0x108
 +#define STATUS_REG_SYS_2      0x508
 +#define STATUS_CLR_REG_SYS_2  0x708
 +#define LINK_DOWN             BIT(1)
 +
 +#define J721E_PCIE_USER_CMD_STATUS    0x4
 +#define LINK_TRAINING_ENABLE          BIT(0)
 +
 +#define J721E_PCIE_USER_LINKSTATUS    0x14
 +#define LINK_STATUS                   GENMASK(1, 0)
 +
 +enum link_status {
 +      NO_RECEIVERS_DETECTED,
 +      LINK_TRAINING_IN_PROGRESS,
 +      LINK_UP_DL_IN_PROGRESS,
 +      LINK_UP_DL_COMPLETED,
 +};
 +
 +#define J721E_MODE_RC                 BIT(7)
 +#define LANE_COUNT_MASK                       BIT(8)
 +#define LANE_COUNT(n)                 ((n) << 8)
 +
 +#define GENERATION_SEL_MASK           GENMASK(1, 0)
 +
 +#define MAX_LANES                     2
 +
 +struct j721e_pcie {
 +      struct device           *dev;
 +      u32                     mode;
 +      u32                     num_lanes;
 +      struct cdns_pcie        *cdns_pcie;
 +      void __iomem            *user_cfg_base;
 +      void __iomem            *intd_cfg_base;
 +};
 +
 +enum j721e_pcie_mode {
 +      PCI_MODE_RC,
 +      PCI_MODE_EP,
 +};
 +
 +struct j721e_pcie_data {
 +      enum j721e_pcie_mode    mode;
 +};
 +
 +static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
 +{
 +      return readl(pcie->user_cfg_base + offset);
 +}
 +
 +static inline void j721e_pcie_user_writel(struct j721e_pcie *pcie, u32 offset,
 +                                        u32 value)
 +{
 +      writel(value, pcie->user_cfg_base + offset);
 +}
 +
 +static inline u32 j721e_pcie_intd_readl(struct j721e_pcie *pcie, u32 offset)
 +{
 +      return readl(pcie->intd_cfg_base + offset);
 +}
 +
 +static inline void j721e_pcie_intd_writel(struct j721e_pcie *pcie, u32 offset,
 +                                        u32 value)
 +{
 +      writel(value, pcie->intd_cfg_base + offset);
 +}
 +
 +static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
 +{
 +      struct j721e_pcie *pcie = priv;
 +      struct device *dev = pcie->dev;
 +      u32 reg;
 +
 +      reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_2);
 +      if (!(reg & LINK_DOWN))
 +              return IRQ_NONE;
 +
 +      dev_err(dev, "LINK DOWN!\n");
 +
 +      j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, LINK_DOWN);
 +      return IRQ_HANDLED;
 +}
 +
 +static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie)
 +{
 +      u32 reg;
 +
 +      reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_2);
 +      reg |= LINK_DOWN;
 +      j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
 +}
 +
 +static int j721e_pcie_start_link(struct cdns_pcie *cdns_pcie)
 +{
 +      struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev);
 +      u32 reg;
 +
 +      reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_CMD_STATUS);
 +      reg |= LINK_TRAINING_ENABLE;
 +      j721e_pcie_user_writel(pcie, J721E_PCIE_USER_CMD_STATUS, reg);
 +
 +      return 0;
 +}
 +
 +static void j721e_pcie_stop_link(struct cdns_pcie *cdns_pcie)
 +{
 +      struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev);
 +      u32 reg;
 +
 +      reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_CMD_STATUS);
 +      reg &= ~LINK_TRAINING_ENABLE;
 +      j721e_pcie_user_writel(pcie, J721E_PCIE_USER_CMD_STATUS, reg);
 +}
 +
 +static bool j721e_pcie_link_up(struct cdns_pcie *cdns_pcie)
 +{
 +      struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev);
 +      u32 reg;
 +
 +      reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_LINKSTATUS);
 +      reg &= LINK_STATUS;
 +      if (reg == LINK_UP_DL_COMPLETED)
 +              return true;
 +
 +      return false;
 +}
 +
 +static const struct cdns_pcie_ops j721e_pcie_ops = {
 +      .start_link = j721e_pcie_start_link,
 +      .stop_link = j721e_pcie_stop_link,
 +      .link_up = j721e_pcie_link_up,
 +};
 +
 +static int j721e_pcie_set_mode(struct j721e_pcie *pcie, struct regmap *syscon)
 +{
 +      struct device *dev = pcie->dev;
 +      u32 mask = J721E_MODE_RC;
 +      u32 mode = pcie->mode;
 +      u32 val = 0;
 +      int ret = 0;
 +
 +      if (mode == PCI_MODE_RC)
 +              val = J721E_MODE_RC;
 +
 +      ret = regmap_update_bits(syscon, 0, mask, val);
 +      if (ret)
 +              dev_err(dev, "failed to set pcie mode\n");
 +
 +      return ret;
 +}
 +
 +static int j721e_pcie_set_link_speed(struct j721e_pcie *pcie,
 +                                   struct regmap *syscon)
 +{
 +      struct device *dev = pcie->dev;
 +      struct device_node *np = dev->of_node;
 +      int link_speed;
 +      u32 val = 0;
 +      int ret;
 +
 +      link_speed = of_pci_get_max_link_speed(np);
 +      if (link_speed < 2)
 +              link_speed = 2;
 +
 +      val = link_speed - 1;
 +      ret = regmap_update_bits(syscon, 0, GENERATION_SEL_MASK, val);
 +      if (ret)
 +              dev_err(dev, "failed to set link speed\n");
 +
 +      return ret;
 +}
 +
 +static int j721e_pcie_set_lane_count(struct j721e_pcie *pcie,
 +                                   struct regmap *syscon)
 +{
 +      struct device *dev = pcie->dev;
 +      u32 lanes = pcie->num_lanes;
 +      u32 val = 0;
 +      int ret;
 +
 +      val = LANE_COUNT(lanes - 1);
 +      ret = regmap_update_bits(syscon, 0, LANE_COUNT_MASK, val);
 +      if (ret)
 +              dev_err(dev, "failed to set link count\n");
 +
 +      return ret;
 +}
 +
 +static int j721e_pcie_ctrl_init(struct j721e_pcie *pcie)
 +{
 +      struct device *dev = pcie->dev;
 +      struct device_node *node = dev->of_node;
 +      struct regmap *syscon;
 +      int ret;
 +
 +      syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-pcie-ctrl");
 +      if (IS_ERR(syscon)) {
 +              dev_err(dev, "Unable to get ti,syscon-pcie-ctrl regmap\n");
 +              return PTR_ERR(syscon);
 +      }
 +
 +      ret = j721e_pcie_set_mode(pcie, syscon);
 +      if (ret < 0) {
 +              dev_err(dev, "Failed to set pci mode\n");
 +              return ret;
 +      }
 +
 +      ret = j721e_pcie_set_link_speed(pcie, syscon);
 +      if (ret < 0) {
 +              dev_err(dev, "Failed to set link speed\n");
 +              return ret;
 +      }
 +
 +      ret = j721e_pcie_set_lane_count(pcie, syscon);
 +      if (ret < 0) {
 +              dev_err(dev, "Failed to set num-lanes\n");
 +              return ret;
 +      }
 +
 +      return 0;
 +}
 +
 +static int cdns_ti_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
 +                                  int where, int size, u32 *value)
 +{
-       struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
-       struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
-       unsigned int busn = bus->number;
-       if (busn == rc->bus_range->start)
++      if (pci_is_root_bus(bus))
 +              return pci_generic_config_read32(bus, devfn, where, size,
 +                                               value);
 +
 +      return pci_generic_config_read(bus, devfn, where, size, value);
 +}
 +
 +static int cdns_ti_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
 +                                   int where, int size, u32 value)
 +{
++      if (pci_is_root_bus(bus))
 +              return pci_generic_config_write32(bus, devfn, where, size,
 +                                                value);
 +
 +      return pci_generic_config_write(bus, devfn, where, size, value);
 +}
 +
 +static struct pci_ops cdns_ti_pcie_host_ops = {
 +      .map_bus        = cdns_pci_map_bus,
 +      .read           = cdns_ti_pcie_config_read,
 +      .write          = cdns_ti_pcie_config_write,
 +};
 +
 +static const struct j721e_pcie_data j721e_pcie_rc_data = {
 +      .mode = PCI_MODE_RC,
 +};
 +
 +static const struct j721e_pcie_data j721e_pcie_ep_data = {
 +      .mode = PCI_MODE_EP,
 +};
 +
 +static const struct of_device_id of_j721e_pcie_match[] = {
 +      {
 +              .compatible = "ti,j721e-pcie-host",
 +              .data = &j721e_pcie_rc_data,
 +      },
 +      {
 +              .compatible = "ti,j721e-pcie-ep",
 +              .data = &j721e_pcie_ep_data,
 +      },
 +      {},
 +};
 +
 +static int j721e_pcie_probe(struct platform_device *pdev)
 +{
 +      struct device *dev = &pdev->dev;
 +      struct device_node *node = dev->of_node;
 +      struct pci_host_bridge *bridge;
 +      struct j721e_pcie_data *data;
 +      struct cdns_pcie *cdns_pcie;
 +      struct j721e_pcie *pcie;
 +      struct cdns_pcie_rc *rc;
 +      struct cdns_pcie_ep *ep;
 +      struct gpio_desc *gpiod;
 +      void __iomem *base;
 +      u32 num_lanes;
 +      u32 mode;
 +      int ret;
 +      int irq;
 +
 +      data = (struct j721e_pcie_data *)of_device_get_match_data(dev);
 +      if (!data)
 +              return -EINVAL;
 +
 +      mode = (u32)data->mode;
 +
 +      pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
 +      if (!pcie)
 +              return -ENOMEM;
 +
 +      pcie->dev = dev;
 +      pcie->mode = mode;
 +
 +      base = devm_platform_ioremap_resource_byname(pdev, "intd_cfg");
 +      if (IS_ERR(base))
 +              return PTR_ERR(base);
 +      pcie->intd_cfg_base = base;
 +
 +      base = devm_platform_ioremap_resource_byname(pdev, "user_cfg");
 +      if (IS_ERR(base))
 +              return PTR_ERR(base);
 +      pcie->user_cfg_base = base;
 +
 +      ret = of_property_read_u32(node, "num-lanes", &num_lanes);
 +      if (ret || num_lanes > MAX_LANES)
 +              num_lanes = 1;
 +      pcie->num_lanes = num_lanes;
 +
 +      if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)))
 +              return -EINVAL;
 +
 +      irq = platform_get_irq_byname(pdev, "link_state");
 +      if (irq < 0)
 +              return irq;
 +
 +      dev_set_drvdata(dev, pcie);
 +      pm_runtime_enable(dev);
 +      ret = pm_runtime_get_sync(dev);
 +      if (ret < 0) {
 +              dev_err(dev, "pm_runtime_get_sync failed\n");
 +              goto err_get_sync;
 +      }
 +
 +      ret = j721e_pcie_ctrl_init(pcie);
 +      if (ret < 0) {
 +              dev_err(dev, "pm_runtime_get_sync failed\n");
 +              goto err_get_sync;
 +      }
 +
 +      ret = devm_request_irq(dev, irq, j721e_pcie_link_irq_handler, 0,
 +                             "j721e-pcie-link-down-irq", pcie);
 +      if (ret < 0) {
 +              dev_err(dev, "failed to request link state IRQ %d\n", irq);
 +              goto err_get_sync;
 +      }
 +
 +      j721e_pcie_config_link_irq(pcie);
 +
 +      switch (mode) {
 +      case PCI_MODE_RC:
 +              if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)) {
 +                      ret = -ENODEV;
 +                      goto err_get_sync;
 +              }
 +
 +              bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
 +              if (!bridge) {
 +                      ret = -ENOMEM;
 +                      goto err_get_sync;
 +              }
 +
 +              bridge->ops = &cdns_ti_pcie_host_ops;
 +              rc = pci_host_bridge_priv(bridge);
 +
 +              cdns_pcie = &rc->pcie;
 +              cdns_pcie->dev = dev;
 +              cdns_pcie->ops = &j721e_pcie_ops;
 +              pcie->cdns_pcie = cdns_pcie;
 +
 +              gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 +              if (IS_ERR(gpiod)) {
 +                      ret = PTR_ERR(gpiod);
 +                      if (ret != -EPROBE_DEFER)
 +                              dev_err(dev, "Failed to get reset GPIO\n");
 +                      goto err_get_sync;
 +              }
 +
 +              ret = cdns_pcie_init_phy(dev, cdns_pcie);
 +              if (ret) {
 +                      dev_err(dev, "Failed to init phy\n");
 +                      goto err_get_sync;
 +              }
 +
 +              /*
 +               * "Power Sequencing and Reset Signal Timings" table in
 +               * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 3.0
 +               * indicates PERST# should be deasserted after minimum of 100us
 +               * once REFCLK is stable. The REFCLK to the connector in RC
 +               * mode is selected while enabling the PHY. So deassert PERST#
 +               * after 100 us.
 +               */
 +              if (gpiod) {
 +                      usleep_range(100, 200);
 +                      gpiod_set_value_cansleep(gpiod, 1);
 +              }
 +
 +              ret = cdns_pcie_host_setup(rc);
 +              if (ret < 0)
 +                      goto err_pcie_setup;
 +
 +              break;
 +      case PCI_MODE_EP:
 +              if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP)) {
 +                      ret = -ENODEV;
 +                      goto err_get_sync;
 +              }
 +
 +              ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
 +              if (!ep) {
 +                      ret = -ENOMEM;
 +                      goto err_get_sync;
 +              }
 +
 +              cdns_pcie = &ep->pcie;
 +              cdns_pcie->dev = dev;
 +              cdns_pcie->ops = &j721e_pcie_ops;
 +              pcie->cdns_pcie = cdns_pcie;
 +
 +              ret = cdns_pcie_init_phy(dev, cdns_pcie);
 +              if (ret) {
 +                      dev_err(dev, "Failed to init phy\n");
 +                      goto err_get_sync;
 +              }
 +
 +              ret = cdns_pcie_ep_setup(ep);
 +              if (ret < 0)
 +                      goto err_pcie_setup;
 +
 +              break;
 +      default:
 +              dev_err(dev, "INVALID device type %d\n", mode);
 +      }
 +
 +      return 0;
 +
 +err_pcie_setup:
 +      cdns_pcie_disable_phy(cdns_pcie);
 +
 +err_get_sync:
 +      pm_runtime_put(dev);
 +      pm_runtime_disable(dev);
 +
 +      return ret;
 +}
 +
 +static int j721e_pcie_remove(struct platform_device *pdev)
 +{
 +      struct j721e_pcie *pcie = platform_get_drvdata(pdev);
 +      struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
 +      struct device *dev = &pdev->dev;
 +
 +      cdns_pcie_disable_phy(cdns_pcie);
 +      pm_runtime_put(dev);
 +      pm_runtime_disable(dev);
 +
 +      return 0;
 +}
 +
 +static struct platform_driver j721e_pcie_driver = {
 +      .probe  = j721e_pcie_probe,
 +      .remove = j721e_pcie_remove,
 +      .driver = {
 +              .name   = "j721e-pcie",
 +              .of_match_table = of_j721e_pcie_match,
 +              .suppress_bind_attrs = true,
 +      },
 +};
 +builtin_platform_driver(j721e_pcie_driver);
index ec1306da301f09fedaa0c7eae034d8a9b42bb29c,e208fa5904bc78fbe8a6ea95c16f3dcd05700f7b..254a3e1eff50e5198a23d28c871bf3eb0e054b36
@@@ -8,6 -8,7 +8,6 @@@
  #include <linux/of.h>
  #include <linux/pci-epc.h>
  #include <linux/platform_device.h>
 -#include <linux/pm_runtime.h>
  #include <linux/sizes.h>
  
  #include "pcie-cadence.h"
@@@ -51,7 -52,6 +51,7 @@@ static int cdns_pcie_ep_set_bar(struct 
                                struct pci_epf_bar *epf_bar)
  {
        struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
 +      struct cdns_pcie_epf *epf = &ep->epf[fn];
        struct cdns_pcie *pcie = &ep->pcie;
        dma_addr_t bar_phys = epf_bar->phys_addr;
        enum pci_barno bar = epf_bar->barno;
                CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
        cdns_pcie_writel(pcie, reg, cfg);
  
 +      epf->epf_bar[bar] = epf_bar;
 +
        return 0;
  }
  
@@@ -121,7 -119,6 +121,7 @@@ static void cdns_pcie_ep_clear_bar(stru
                                   struct pci_epf_bar *epf_bar)
  {
        struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
 +      struct cdns_pcie_epf *epf = &ep->epf[fn];
        struct cdns_pcie *pcie = &ep->pcie;
        enum pci_barno bar = epf_bar->barno;
        u32 reg, cfg, b, ctrl;
  
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar), 0);
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar), 0);
 +
 +      epf->epf_bar[bar] = NULL;
  }
  
  static int cdns_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, phys_addr_t addr,
                return -EINVAL;
        }
  
-       cdns_pcie_set_outbound_region(pcie, fn, r, false, addr, pci_addr, size);
+       cdns_pcie_set_outbound_region(pcie, 0, fn, r, false, addr, pci_addr, size);
  
        set_bit(r, &ep->ob_region_map);
        ep->ob_addr[r] = addr;
@@@ -230,55 -225,10 +230,55 @@@ static int cdns_pcie_ep_get_msi(struct 
        return mme;
  }
  
 +static int cdns_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
 +{
 +      struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
 +      struct cdns_pcie *pcie = &ep->pcie;
 +      u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 +      u32 val, reg;
 +
 +      reg = cap + PCI_MSIX_FLAGS;
 +      val = cdns_pcie_ep_fn_readw(pcie, func_no, reg);
 +      if (!(val & PCI_MSIX_FLAGS_ENABLE))
 +              return -EINVAL;
 +
 +      val &= PCI_MSIX_FLAGS_QSIZE;
 +
 +      return val;
 +}
 +
 +static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u16 interrupts,
 +                               enum pci_barno bir, u32 offset)
 +{
 +      struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
 +      struct cdns_pcie *pcie = &ep->pcie;
 +      u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 +      u32 val, reg;
 +
 +      reg = cap + PCI_MSIX_FLAGS;
 +      val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
 +      val &= ~PCI_MSIX_FLAGS_QSIZE;
 +      val |= interrupts;
 +      cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
 +
 +      /* Set MSIX BAR and offset */
 +      reg = cap + PCI_MSIX_TABLE;
 +      val = offset | bir;
 +      cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
 +
 +      /* Set PBA BAR and offset.  BAR must match MSIX BAR */
 +      reg = cap + PCI_MSIX_PBA;
 +      val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
 +      cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
 +
 +      return 0;
 +}
 +
  static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn,
                                     u8 intx, bool is_asserted)
  {
        struct cdns_pcie *pcie = &ep->pcie;
 +      unsigned long flags;
        u32 offset;
        u16 status;
        u8 msg_code;
        if (unlikely(ep->irq_pci_addr != CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY ||
                     ep->irq_pci_fn != fn)) {
                /* First region was reserved for IRQ writes. */
-               cdns_pcie_set_outbound_region_for_normal_msg(pcie, fn, 0,
+               cdns_pcie_set_outbound_region_for_normal_msg(pcie, 0, fn, 0,
                                                             ep->irq_phys_addr);
                ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY;
                ep->irq_pci_fn = fn;
                msg_code = MSG_CODE_DEASSERT_INTA + intx;
        }
  
 +      spin_lock_irqsave(&ep->lock, flags);
        status = cdns_pcie_ep_fn_readw(pcie, fn, PCI_STATUS);
        if (((status & PCI_STATUS_INTERRUPT) != 0) ^ (ep->irq_pending != 0)) {
                status ^= PCI_STATUS_INTERRUPT;
                cdns_pcie_ep_fn_writew(pcie, fn, PCI_STATUS, status);
        }
 +      spin_unlock_irqrestore(&ep->lock, flags);
  
        offset = CDNS_PCIE_NORMAL_MSG_ROUTING(MSG_ROUTING_LOCAL) |
                 CDNS_PCIE_NORMAL_MSG_CODE(msg_code) |
@@@ -370,7 -318,7 +370,7 @@@ static int cdns_pcie_ep_send_msi_irq(st
        if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) ||
                     ep->irq_pci_fn != fn)) {
                /* First region was reserved for IRQ writes. */
-               cdns_pcie_set_outbound_region(pcie, fn, 0,
+               cdns_pcie_set_outbound_region(pcie, 0, fn, 0,
                                              false,
                                              ep->irq_phys_addr,
                                              pci_addr & ~pci_addr_mask,
        return 0;
  }
  
-               cdns_pcie_set_outbound_region(pcie, fn, 0,
 +static int cdns_pcie_ep_send_msix_irq(struct cdns_pcie_ep *ep, u8 fn,
 +                                    u16 interrupt_num)
 +{
 +      u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
 +      u32 tbl_offset, msg_data, reg;
 +      struct cdns_pcie *pcie = &ep->pcie;
 +      struct pci_epf_msix_tbl *msix_tbl;
 +      struct cdns_pcie_epf *epf;
 +      u64 pci_addr_mask = 0xff;
 +      u64 msg_addr;
 +      u16 flags;
 +      u8 bir;
 +
 +      /* Check whether the MSI-X feature has been enabled by the PCI host. */
 +      flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSIX_FLAGS);
 +      if (!(flags & PCI_MSIX_FLAGS_ENABLE))
 +              return -EINVAL;
 +
 +      reg = cap + PCI_MSIX_TABLE;
 +      tbl_offset = cdns_pcie_ep_fn_readl(pcie, fn, reg);
 +      bir = tbl_offset & PCI_MSIX_TABLE_BIR;
 +      tbl_offset &= PCI_MSIX_TABLE_OFFSET;
 +
 +      epf = &ep->epf[fn];
 +      msix_tbl = epf->epf_bar[bir]->addr + tbl_offset;
 +      msg_addr = msix_tbl[(interrupt_num - 1)].msg_addr;
 +      msg_data = msix_tbl[(interrupt_num - 1)].msg_data;
 +
 +      /* Set the outbound region if needed. */
 +      if (ep->irq_pci_addr != (msg_addr & ~pci_addr_mask) ||
 +          ep->irq_pci_fn != fn) {
 +              /* First region was reserved for IRQ writes. */
++              cdns_pcie_set_outbound_region(pcie, 0, fn, 0,
 +                                            false,
 +                                            ep->irq_phys_addr,
 +                                            msg_addr & ~pci_addr_mask,
 +                                            pci_addr_mask + 1);
 +              ep->irq_pci_addr = (msg_addr & ~pci_addr_mask);
 +              ep->irq_pci_fn = fn;
 +      }
 +      writel(msg_data, ep->irq_cpu_addr + (msg_addr & pci_addr_mask));
 +
 +      return 0;
 +}
 +
  static int cdns_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
                                  enum pci_epc_irq_type type,
                                  u16 interrupt_num)
        case PCI_EPC_IRQ_MSI:
                return cdns_pcie_ep_send_msi_irq(ep, fn, interrupt_num);
  
 +      case PCI_EPC_IRQ_MSIX:
 +              return cdns_pcie_ep_send_msix_irq(ep, fn, interrupt_num);
 +
        default:
                break;
        }
@@@ -455,10 -355,8 +455,10 @@@ static int cdns_pcie_ep_start(struct pc
  {
        struct cdns_pcie_ep *ep = epc_get_drvdata(epc);
        struct cdns_pcie *pcie = &ep->pcie;
 +      struct device *dev = pcie->dev;
        struct pci_epf *epf;
        u32 cfg;
 +      int ret;
  
        /*
         * BIT(0) is hardwired to 1, hence function 0 is always enabled
                cfg |= BIT(epf->func_no);
        cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, cfg);
  
 +      ret = cdns_pcie_start_link(pcie);
 +      if (ret) {
 +              dev_err(dev, "Failed to start link\n");
 +              return ret;
 +      }
 +
        return 0;
  }
  
  static const struct pci_epc_features cdns_pcie_epc_features = {
        .linkup_notifier = false,
        .msi_capable = true,
 -      .msix_capable = false,
 +      .msix_capable = true,
  };
  
  static const struct pci_epc_features*
@@@ -498,8 -390,6 +498,8 @@@ static const struct pci_epc_ops cdns_pc
        .unmap_addr     = cdns_pcie_ep_unmap_addr,
        .set_msi        = cdns_pcie_ep_set_msi,
        .get_msi        = cdns_pcie_ep_get_msi,
 +      .set_msix       = cdns_pcie_ep_set_msix,
 +      .get_msix       = cdns_pcie_ep_get_msix,
        .raise_irq      = cdns_pcie_ep_raise_irq,
        .start          = cdns_pcie_ep_start,
        .get_features   = cdns_pcie_ep_get_features,
@@@ -518,8 -408,7 +518,7 @@@ int cdns_pcie_ep_setup(struct cdns_pcie
  
        pcie->is_rc = false;
  
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
-       pcie->reg_base = devm_ioremap_resource(dev, res);
+       pcie->reg_base = devm_platform_ioremap_resource_byname(pdev, "reg");
        if (IS_ERR(pcie->reg_base)) {
                dev_err(dev, "missing \"reg\"\n");
                return PTR_ERR(pcie->reg_base);
        epc = devm_pci_epc_create(dev, &cdns_pcie_epc_ops);
        if (IS_ERR(epc)) {
                dev_err(dev, "failed to create epc device\n");
 -              ret = PTR_ERR(epc);
 -              goto err_init;
 +              return PTR_ERR(epc);
        }
  
        epc_set_drvdata(epc, ep);
        if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0)
                epc->max_functions = 1;
  
 +      ep->epf = devm_kcalloc(dev, epc->max_functions, sizeof(*ep->epf),
 +                             GFP_KERNEL);
 +      if (!ep->epf)
 +              return -ENOMEM;
 +
        ret = pci_epc_mem_init(epc, pcie->mem_res->start,
                               resource_size(pcie->mem_res), PAGE_SIZE);
        if (ret < 0) {
                dev_err(dev, "failed to initialize the memory space\n");
 -              goto err_init;
 +              return ret;
        }
  
        ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr,
        ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE;
        /* Reserve region 0 for IRQs */
        set_bit(0, &ep->ob_region_map);
 +      spin_lock_init(&ep->lock);
  
        return 0;
  
   free_epc_mem:
        pci_epc_mem_exit(epc);
  
 - err_init:
 -      pm_runtime_put_sync(dev);
 -
        return ret;
  }
index 8d86560196aaf2bba88b4c39adb15c27eca46dda,e60f72780ab09b8671e8dc4033bf74935d8aec9e..4550e0d469ca8f9f73cd63dc5571845237b9093e
@@@ -3,28 -3,16 +3,28 @@@
  // Cadence PCIe host controller driver.
  // Author: Cyrille Pitchen <[email protected]>
  
 +#include <linux/delay.h>
  #include <linux/kernel.h>
 +#include <linux/list_sort.h>
  #include <linux/of_address.h>
  #include <linux/of_pci.h>
  #include <linux/platform_device.h>
 -#include <linux/pm_runtime.h>
  
  #include "pcie-cadence.h"
  
 -static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 -                                    int where)
 +static u64 bar_max_size[] = {
 +      [RP_BAR0] = _ULL(128 * SZ_2G),
 +      [RP_BAR1] = SZ_2G,
 +      [RP_NO_BAR] = _BITULL(63),
 +};
 +
 +static u8 bar_aperture_mask[] = {
 +      [RP_BAR0] = 0x1F,
 +      [RP_BAR1] = 0xF,
 +};
 +
 +void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 +                             int where)
  {
        struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
        struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
@@@ -32,7 -20,7 +32,7 @@@
        unsigned int busn = bus->number;
        u32 addr0, desc0;
  
-       if (busn == rc->bus_range->start) {
+       if (pci_is_root_bus(bus)) {
                /*
                 * Only the root port (devfn == 0) is connected to this bus.
                 * All other PCI devices are behind some bridge hence on another
@@@ -62,7 -50,7 +62,7 @@@
         * The bus number was already set once for all in desc1 by
         * cdns_pcie_host_init_address_translation().
         */
-       if (busn == rc->bus_range->start + 1)
+       if (busn == bridge->busnr + 1)
                desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
        else
                desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
@@@ -82,7 -70,6 +82,7 @@@ static int cdns_pcie_host_init_root_por
  {
        struct cdns_pcie *pcie = &rc->pcie;
        u32 value, ctrl;
 +      u32 id;
  
        /*
         * Set the root complex BAR configuration register:
        cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
  
        /* Set root port configuration space */
 -      if (rc->vendor_id != 0xffff)
 -              cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, rc->vendor_id);
 +      if (rc->vendor_id != 0xffff) {
 +              id = CDNS_PCIE_LM_ID_VENDOR(rc->vendor_id) |
 +                      CDNS_PCIE_LM_ID_SUBSYS(rc->vendor_id);
 +              cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, id);
 +      }
 +
        if (rc->device_id != 0xffff)
                cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, rc->device_id);
  
        return 0;
  }
  
-               if (err) {
 +static int cdns_pcie_host_bar_ib_config(struct cdns_pcie_rc *rc,
 +                                      enum cdns_pcie_rp_bar bar,
 +                                      u64 cpu_addr, u64 size,
 +                                      unsigned long flags)
 +{
 +      struct cdns_pcie *pcie = &rc->pcie;
 +      u32 addr0, addr1, aperture, value;
 +
 +      if (!rc->avail_ib_bar[bar])
 +              return -EBUSY;
 +
 +      rc->avail_ib_bar[bar] = false;
 +
 +      aperture = ilog2(size);
 +      addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(aperture) |
 +              (lower_32_bits(cpu_addr) & GENMASK(31, 8));
 +      addr1 = upper_32_bits(cpu_addr);
 +      cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), addr0);
 +      cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), addr1);
 +
 +      if (bar == RP_NO_BAR)
 +              return 0;
 +
 +      value = cdns_pcie_readl(pcie, CDNS_PCIE_LM_RC_BAR_CFG);
 +      value &= ~(LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar) |
 +                 LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar) |
 +                 LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar) |
 +                 LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar) |
 +                 LM_RC_BAR_CFG_APERTURE(bar, bar_aperture_mask[bar] + 2));
 +      if (size + cpu_addr >= SZ_4G) {
 +              if (!(flags & IORESOURCE_PREFETCH))
 +                      value |= LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar);
 +              value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar);
 +      } else {
 +              if (!(flags & IORESOURCE_PREFETCH))
 +                      value |= LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar);
 +              value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar);
 +      }
 +
 +      value |= LM_RC_BAR_CFG_APERTURE(bar, aperture);
 +      cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
 +
 +      return 0;
 +}
 +
 +static enum cdns_pcie_rp_bar
 +cdns_pcie_host_find_min_bar(struct cdns_pcie_rc *rc, u64 size)
 +{
 +      enum cdns_pcie_rp_bar bar, sel_bar;
 +
 +      sel_bar = RP_BAR_UNDEFINED;
 +      for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
 +              if (!rc->avail_ib_bar[bar])
 +                      continue;
 +
 +              if (size <= bar_max_size[bar]) {
 +                      if (sel_bar == RP_BAR_UNDEFINED) {
 +                              sel_bar = bar;
 +                              continue;
 +                      }
 +
 +                      if (bar_max_size[bar] < bar_max_size[sel_bar])
 +                              sel_bar = bar;
 +              }
 +      }
 +
 +      return sel_bar;
 +}
 +
 +static enum cdns_pcie_rp_bar
 +cdns_pcie_host_find_max_bar(struct cdns_pcie_rc *rc, u64 size)
 +{
 +      enum cdns_pcie_rp_bar bar, sel_bar;
 +
 +      sel_bar = RP_BAR_UNDEFINED;
 +      for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++) {
 +              if (!rc->avail_ib_bar[bar])
 +                      continue;
 +
 +              if (size >= bar_max_size[bar]) {
 +                      if (sel_bar == RP_BAR_UNDEFINED) {
 +                              sel_bar = bar;
 +                              continue;
 +                      }
 +
 +                      if (bar_max_size[bar] > bar_max_size[sel_bar])
 +                              sel_bar = bar;
 +              }
 +      }
 +
 +      return sel_bar;
 +}
 +
 +static int cdns_pcie_host_bar_config(struct cdns_pcie_rc *rc,
 +                                   struct resource_entry *entry)
 +{
 +      u64 cpu_addr, pci_addr, size, winsize;
 +      struct cdns_pcie *pcie = &rc->pcie;
 +      struct device *dev = pcie->dev;
 +      enum cdns_pcie_rp_bar bar;
 +      unsigned long flags;
 +      int ret;
 +
 +      cpu_addr = entry->res->start;
 +      pci_addr = entry->res->start - entry->offset;
 +      flags = entry->res->flags;
 +      size = resource_size(entry->res);
 +
 +      if (entry->offset) {
 +              dev_err(dev, "PCI addr: %llx must be equal to CPU addr: %llx\n",
 +                      pci_addr, cpu_addr);
 +              return -EINVAL;
 +      }
 +
 +      while (size > 0) {
 +              /*
 +               * Try to find a minimum BAR whose size is greater than
 +               * or equal to the remaining resource_entry size. This will
 +               * fail if the size of each of the available BARs is less than
 +               * the remaining resource_entry size.
 +               * If a minimum BAR is found, IB ATU will be configured and
 +               * exited.
 +               */
 +              bar = cdns_pcie_host_find_min_bar(rc, size);
 +              if (bar != RP_BAR_UNDEFINED) {
 +                      ret = cdns_pcie_host_bar_ib_config(rc, bar, cpu_addr,
 +                                                         size, flags);
 +                      if (ret)
 +                              dev_err(dev, "IB BAR: %d config failed\n", bar);
 +                      return ret;
 +              }
 +
 +              /*
 +               * If the control reaches here, it would mean the remaining
 +               * resource_entry size cannot be fitted in a single BAR. So we
 +               * find a maximum BAR whose size is less than or equal to the
 +               * remaining resource_entry size and split the resource entry
 +               * so that part of resource entry is fitted inside the maximum
 +               * BAR. The remaining size would be fitted during the next
 +               * iteration of the loop.
 +               * If a maximum BAR is not found, there is no way we can fit
 +               * this resource_entry, so we error out.
 +               */
 +              bar = cdns_pcie_host_find_max_bar(rc, size);
 +              if (bar == RP_BAR_UNDEFINED) {
 +                      dev_err(dev, "No free BAR to map cpu_addr %llx\n",
 +                              cpu_addr);
 +                      return -EINVAL;
 +              }
 +
 +              winsize = bar_max_size[bar];
 +              ret = cdns_pcie_host_bar_ib_config(rc, bar, cpu_addr, winsize,
 +                                                 flags);
 +              if (ret) {
 +                      dev_err(dev, "IB BAR: %d config failed\n", bar);
 +                      return ret;
 +              }
 +
 +              size -= winsize;
 +              cpu_addr += winsize;
 +      }
 +
 +      return 0;
 +}
 +
 +static int cdns_pcie_host_dma_ranges_cmp(void *priv, struct list_head *a, struct list_head *b)
 +{
 +      struct resource_entry *entry1, *entry2;
 +
 +        entry1 = container_of(a, struct resource_entry, node);
 +        entry2 = container_of(b, struct resource_entry, node);
 +
 +        return resource_size(entry2->res) - resource_size(entry1->res);
 +}
 +
 +static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
 +{
 +      struct cdns_pcie *pcie = &rc->pcie;
 +      struct device *dev = pcie->dev;
 +      struct device_node *np = dev->of_node;
 +      struct pci_host_bridge *bridge;
 +      struct resource_entry *entry;
 +      u32 no_bar_nbits = 32;
 +      int err;
 +
 +      bridge = pci_host_bridge_from_priv(rc);
 +      if (!bridge)
 +              return -ENOMEM;
 +
 +      if (list_empty(&bridge->dma_ranges)) {
 +              of_property_read_u32(np, "cdns,no-bar-match-nbits",
 +                                   &no_bar_nbits);
 +              err = cdns_pcie_host_bar_ib_config(rc, RP_NO_BAR, 0x0,
 +                                                 (u64)1 << no_bar_nbits, 0);
 +              if (err)
 +                      dev_err(dev, "IB BAR: %d config failed\n", RP_NO_BAR);
 +              return err;
 +      }
 +
 +      list_sort(NULL, &bridge->dma_ranges, cdns_pcie_host_dma_ranges_cmp);
 +
 +      resource_list_for_each_entry(entry, &bridge->dma_ranges) {
 +              err = cdns_pcie_host_bar_config(rc, entry);
-                       return err;
-               }
++              if (err)
 +                      dev_err(dev, "Fail to configure IB using dma-ranges\n");
++              return err;
 +      }
 +
 +      return 0;
 +}
 +
  static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
  {
        struct cdns_pcie *pcie = &rc->pcie;
-       struct resource *bus_range = rc->bus_range;
+       struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
 -      struct resource *mem_res = pcie->mem_res;
        struct resource *cfg_res = rc->cfg_res;
-       struct device *dev = pcie->dev;
-       struct device_node *np = dev->of_node;
-       struct of_pci_range_parser parser;
+       struct resource_entry *entry;
 +      u64 cpu_addr = cfg_res->start;
-       struct of_pci_range range;
        u32 addr0, addr1, desc1;
-       int r, err;
 -      u64 cpu_addr;
 -      int r, busnr = 0;
++      int r, err, busnr = 0;
+       entry = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
+       if (entry)
+               busnr = entry->res->start;
  
        /*
         * Reserve region 0 for PCI configure space accesses:
         * cdns_pci_map_bus(), other region registers are set here once for all.
         */
        addr1 = 0; /* Should be programmed to zero. */
-       desc1 = CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus_range->start);
+       desc1 = CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr);
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1);
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1);
  
 -      cpu_addr = cfg_res->start - mem_res->start;
 +      if (pcie->ops->cpu_addr_fixup)
 +              cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
 +
        addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |
                (lower_32_bits(cpu_addr) & GENMASK(31, 8));
        addr1 = upper_32_bits(cpu_addr);
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(0), addr0);
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(0), addr1);
  
-       err = of_pci_range_parser_init(&parser, np);
-       if (err)
-               return err;
        r = 1;
-       for_each_of_pci_range(&parser, &range) {
-               bool is_io;
-               if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
-                       is_io = false;
-               else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
-                       is_io = true;
+       resource_list_for_each_entry(entry, &bridge->windows) {
+               struct resource *res = entry->res;
+               u64 pci_addr = res->start - entry->offset;
+               if (resource_type(res) == IORESOURCE_IO)
+                       cdns_pcie_set_outbound_region(pcie, busnr, 0, r,
+                                                     true,
+                                                     pci_pio_to_address(res->start),
+                                                     pci_addr,
+                                                     resource_size(res));
                else
-                       continue;
+                       cdns_pcie_set_outbound_region(pcie, busnr, 0, r,
+                                                     false,
+                                                     res->start,
+                                                     pci_addr,
+                                                     resource_size(res));
  
-               cdns_pcie_set_outbound_region(pcie, 0, r, is_io,
-                                             range.cpu_addr,
-                                             range.pci_addr,
-                                             range.size);
                r++;
        }
  
 -      /*
 -       * Set Root Port no BAR match Inbound Translation registers:
 -       * needed for MSI and DMA.
 -       * Root Port BAR0 and BAR1 are disabled, hence no need to set their
 -       * inbound translation registers.
 -       */
 -      addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc->no_bar_nbits);
 -      addr1 = 0;
 -      cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(RP_NO_BAR), addr0);
 -      cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(RP_NO_BAR), addr1);
 +      err = cdns_pcie_host_map_dma_ranges(rc);
 +      if (err)
 +              return err;
  
        return 0;
  }
  
  static int cdns_pcie_host_init(struct device *dev,
-                              struct list_head *resources,
                               struct cdns_pcie_rc *rc)
  {
-       struct resource *bus_range = NULL;
-       struct pci_host_bridge *bridge;
        int err;
  
-       bridge = pci_host_bridge_from_priv(rc);
-       if (!bridge)
-               return -ENOMEM;
-       /* Parse our PCI ranges and request their resources */
-       err = pci_parse_request_of_pci_ranges(dev, resources,
-                                             &bridge->dma_ranges, &bus_range);
-       if (err)
-               return err;
-       rc->bus_range = bus_range;
-       rc->pcie.bus = bus_range->start;
        err = cdns_pcie_host_init_root_port(rc);
        if (err)
-               goto err_out;
-       err = cdns_pcie_host_init_address_translation(rc);
-       if (err)
-               goto err_out;
-       return 0;
+               return err;
  
-  err_out:
-       pci_free_resource_list(resources);
-       return err;
+       return cdns_pcie_host_init_address_translation(rc);
  }
  
 +static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie)
 +{
 +      struct device *dev = pcie->dev;
 +      int retries;
 +
 +      /* Check if the link is up or not */
 +      for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
 +              if (cdns_pcie_link_up(pcie)) {
 +                      dev_info(dev, "Link up\n");
 +                      return 0;
 +              }
 +              usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
 +      }
 +
 +      return -ETIMEDOUT;
 +}
 +
  int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
  {
        struct device *dev = rc->pcie.dev;
        struct platform_device *pdev = to_platform_device(dev);
        struct device_node *np = dev->of_node;
        struct pci_host_bridge *bridge;
-       struct list_head resources;
 +      enum cdns_pcie_rp_bar bar;
        struct cdns_pcie *pcie;
        struct resource *res;
        int ret;
        pcie = &rc->pcie;
        pcie->is_rc = true;
  
 -      rc->no_bar_nbits = 32;
 -      of_property_read_u32(np, "cdns,no-bar-match-nbits", &rc->no_bar_nbits);
 -
        rc->vendor_id = 0xffff;
        of_property_read_u32(np, "vendor-id", &rc->vendor_id);
  
        rc->device_id = 0xffff;
        of_property_read_u32(np, "device-id", &rc->device_id);
  
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
-       pcie->reg_base = devm_ioremap_resource(dev, res);
+       pcie->reg_base = devm_platform_ioremap_resource_byname(pdev, "reg");
        if (IS_ERR(pcie->reg_base)) {
                dev_err(dev, "missing \"reg\"\n");
                return PTR_ERR(pcie->reg_base);
  
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
        rc->cfg_base = devm_pci_remap_cfg_resource(dev, res);
-       if (IS_ERR(rc->cfg_base)) {
-               dev_err(dev, "missing \"cfg\"\n");
+       if (IS_ERR(rc->cfg_base))
                return PTR_ERR(rc->cfg_base);
-       }
        rc->cfg_res = res;
  
 -      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
 -      if (!res) {
 -              dev_err(dev, "missing \"mem\"\n");
 -              return -EINVAL;
 +      ret = cdns_pcie_start_link(pcie);
 +      if (ret) {
 +              dev_err(dev, "Failed to start link\n");
 +              return ret;
        }
  
 -      pcie->mem_res = res;
 +      ret = cdns_pcie_host_wait_for_link(pcie);
 +      if (ret)
 +              dev_dbg(dev, "PCIe link never came up\n");
 +
 +      for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++)
 +              rc->avail_ib_bar[bar] = true;
  
-       ret = cdns_pcie_host_init(dev, &resources, rc);
+       ret = cdns_pcie_host_init(dev, rc);
        if (ret)
 -              goto err_init;
 +              return ret;
  
-       list_splice_init(&resources, &bridge->windows);
-       bridge->dev.parent = dev;
-       bridge->busnr = pcie->bus;
 -      bridge->ops = &cdns_pcie_host_ops;
 +      if (!bridge->ops)
 +              bridge->ops = &cdns_pcie_host_ops;
-       bridge->map_irq = of_irq_parse_and_map_pci;
-       bridge->swizzle_irq = pci_common_swizzle;
  
        ret = pci_host_probe(bridge);
        if (ret < 0)
-               goto err_host_probe;
+               goto err_init;
  
        return 0;
  
-  err_host_probe:
-       pci_free_resource_list(&resources);
+  err_init:
+       pm_runtime_put_sync(dev);
  
        return ret;
  }
index 8a02981fd4569e2bd58fcb04ea2f6962345600be,fdd13765ee759d3cd0013a38e83b8bfa2caecfa0..3c3646502d05cf12cfa802e6f58499bea0bd0ae5
@@@ -7,7 -7,7 +7,7 @@@
  
  #include "pcie-cadence.h"
  
- void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 fn,
+ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
                                   u32 r, bool is_io,
                                   u64 cpu_addr, u64 pci_addr, size_t size)
  {
@@@ -60,7 -60,7 +60,7 @@@
                /* The device and function numbers are always 0. */
                desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
                         CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
-               desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(pcie->bus);
+               desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr);
        } else {
                /*
                 * Use captured values for bus and device numbers but still
@@@ -73,9 -73,7 +73,9 @@@
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(r), desc1);
  
        /* Set the CPU address */
 -      cpu_addr -= pcie->mem_res->start;
 +      if (pcie->ops->cpu_addr_fixup)
 +              cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
 +
        addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) |
                (lower_32_bits(cpu_addr) & GENMASK(31, 8));
        addr1 = upper_32_bits(cpu_addr);
@@@ -84,7 -82,8 +84,8 @@@
        cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
  }
  
- void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, u8 fn,
+ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
+                                                 u8 busnr, u8 fn,
                                                  u32 r, u64 cpu_addr)
  {
        u32 addr0, addr1, desc0, desc1;
        if (pcie->is_rc) {
                desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
                         CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
-               desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(pcie->bus);
+               desc1 |= CDNS_PCIE_AT_OB_REGION_DESC1_BUS(busnr);
        } else {
                desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(fn);
        }
  
        /* Set the CPU address */
 -      cpu_addr -= pcie->mem_res->start;
 +      if (pcie->ops->cpu_addr_fixup)
 +              cpu_addr = pcie->ops->cpu_addr_fixup(pcie, cpu_addr);
 +
        addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(17) |
                (lower_32_bits(cpu_addr) & GENMASK(31, 8));
        addr1 = upper_32_bits(cpu_addr);
index 00e44256c3e8be37c76e6c45ed19c8d921f8a80f,02803f262f0cad237be8ef382ce1a79333c4dc03..feed1e3038f451260fe20b7a2c19bf1fcd40bf87
  #include <linux/pci.h>
  #include <linux/phy/phy.h>
  
 +/* Parameters for the waiting for link up routine */
 +#define LINK_WAIT_MAX_RETRIES 10
 +#define LINK_WAIT_USLEEP_MIN  90000
 +#define LINK_WAIT_USLEEP_MAX  100000
 +
  /*
   * Local Management Registers
   */
  #define  CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS         0x6
  #define  CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS        0x7
  
 +#define LM_RC_BAR_CFG_CTRL_DISABLED(bar)              \
 +              (CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_CTRL_IO_32BITS(bar)             \
 +              (CDNS_PCIE_LM_BAR_CFG_CTRL_IO_32BITS << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar)            \
 +              (CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_32BITS << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar)       \
 +      (CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar)            \
 +              (CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar)       \
 +      (CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS << (((bar) * 8) + 6))
 +#define LM_RC_BAR_CFG_APERTURE(bar, aperture)         \
 +                                      (((aperture) - 2) << ((bar) * 8))
  
  /*
   * Endpoint Function Registers (PCI configuration space for endpoint functions)
  #define CDNS_PCIE_EP_FUNC_BASE(fn)    (((fn) << 12) & GENMASK(19, 12))
  
  #define CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET      0x90
 +#define CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET     0xb0
  
  /*
   * Root Port Registers (PCI configuration space for the root port function)
  #define CDNS_PCIE_AT_LINKDOWN (CDNS_PCIE_AT_BASE + 0x0824)
  
  enum cdns_pcie_rp_bar {
 +      RP_BAR_UNDEFINED = -1,
        RP_BAR0,
        RP_BAR1,
        RP_NO_BAR
  };
  
 +#define CDNS_PCIE_RP_MAX_IB   0x3
 +
 +struct cdns_pcie_rp_ib_bar {
 +      u64 size;
 +      bool free;
 +};
 +
  /* Endpoint Function BAR Inbound PCIe to AXI Address Translation Register */
  #define CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
        (CDNS_PCIE_AT_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
@@@ -251,32 -223,22 +251,31 @@@ enum cdns_pcie_msg_routing 
        MSG_ROUTING_GATHER,
  };
  
 +struct cdns_pcie_ops {
 +      int     (*start_link)(struct cdns_pcie *pcie);
 +      void    (*stop_link)(struct cdns_pcie *pcie);
 +      bool    (*link_up)(struct cdns_pcie *pcie);
 +      u64     (*cpu_addr_fixup)(struct cdns_pcie *pcie, u64 cpu_addr);
 +};
 +
  /**
   * struct cdns_pcie - private data for Cadence PCIe controller drivers
   * @reg_base: IO mapped register base
   * @mem_res: start/end offsets in the physical system memory to map PCI accesses
   * @is_rc: tell whether the PCIe controller mode is Root Complex or Endpoint.
   * @bus: In Root Complex mode, the bus number
 + * @ops: Platform specific ops to control various inputs from Cadence PCIe
 + *       wrapper
   */
  struct cdns_pcie {
        void __iomem            *reg_base;
        struct resource         *mem_res;
        struct device           *dev;
        bool                    is_rc;
-       u8                      bus;
        int                     phy_count;
        struct phy              **phy;
        struct device_link      **link;
 -      const struct cdns_pcie_common_ops *ops;
 +      const struct cdns_pcie_ops *ops;
  };
  
  /**
   * @dev: pointer to PCIe device
   * @cfg_res: start/end offsets in the physical system memory to map PCI
   *           configuration space accesses
-  * @bus_range: first/last buses behind the PCIe host controller
   * @cfg_base: IO mapped window to access the PCI configuration space of a
   *            single function at a time
 - * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address
 - *                translation (nbits sets into the "no BAR match" register)
   * @vendor_id: PCI vendor ID
   * @device_id: PCI device ID
 + * @avail_ib_bar: Satus of RP_BAR0, RP_BAR1 and       RP_NO_BAR if it's free or
 + *                available
   */
  struct cdns_pcie_rc {
        struct cdns_pcie        pcie;
        struct resource         *cfg_res;
-       struct resource         *bus_range;
        void __iomem            *cfg_base;
 -      u32                     no_bar_nbits;
        u32                     vendor_id;
        u32                     device_id;
 +      bool                    avail_ib_bar[CDNS_PCIE_RP_MAX_IB];
 +};
 +
 +/**
 + * struct cdns_pcie_epf - Structure to hold info about endpoint function
 + * @epf_bar: reference to the pci_epf_bar for the six Base Address Registers
 + */
 +struct cdns_pcie_epf {
 +      struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS];
  };
  
  /**
   * @irq_pci_fn: the latest PCI function that has updated the mapping of
   *            the MSI/legacy IRQ dedicated outbound region.
   * @irq_pending: bitmask of asserted legacy IRQs.
 + * @lock: spin lock to disable interrupts while modifying PCIe controller
 + *        registers fields (RMW) accessible by both remote RC and EP to
 + *        minimize time between read and write
 + * @epf: Structure to hold info about endpoint function
   */
  struct cdns_pcie_ep {
        struct cdns_pcie        pcie;
        u64                     irq_pci_addr;
        u8                      irq_pci_fn;
        u8                      irq_pending;
 +      /* protect writing to PCI_STATUS while raising legacy interrupts */
 +      spinlock_t              lock;
 +      struct cdns_pcie_epf    *epf;
  };
  
  
  /* Register access */
 -static inline void cdns_pcie_writeb(struct cdns_pcie *pcie, u32 reg, u8 value)
 +static inline void cdns_pcie_writel(struct cdns_pcie *pcie, u32 reg, u32 value)
  {
 -      writeb(value, pcie->reg_base + reg);
 +      writel(value, pcie->reg_base + reg);
  }
  
 -static inline void cdns_pcie_writew(struct cdns_pcie *pcie, u32 reg, u16 value)
 +static inline u32 cdns_pcie_readl(struct cdns_pcie *pcie, u32 reg)
  {
 -      writew(value, pcie->reg_base + reg);
 +      return readl(pcie->reg_base + reg);
  }
  
 -static inline void cdns_pcie_writel(struct cdns_pcie *pcie, u32 reg, u32 value)
 +static inline u32 cdns_pcie_read_sz(void __iomem *addr, int size)
  {
 -      writel(value, pcie->reg_base + reg);
 +      void __iomem *aligned_addr = PTR_ALIGN_DOWN(addr, 0x4);
 +      unsigned int offset = (unsigned long)addr & 0x3;
 +      u32 val = readl(aligned_addr);
 +
 +      if (!IS_ALIGNED((uintptr_t)addr, size)) {
 +              pr_warn("Address %p and size %d are not aligned\n", addr, size);
 +              return 0;
 +      }
 +
 +      if (size > 2)
 +              return val;
 +
 +      return (val >> (8 * offset)) & ((1 << (size * 8)) - 1);
  }
  
 -static inline u32 cdns_pcie_readl(struct cdns_pcie *pcie, u32 reg)
 +static inline void cdns_pcie_write_sz(void __iomem *addr, int size, u32 value)
  {
 -      return readl(pcie->reg_base + reg);
 +      void __iomem *aligned_addr = PTR_ALIGN_DOWN(addr, 0x4);
 +      unsigned int offset = (unsigned long)addr & 0x3;
 +      u32 mask;
 +      u32 val;
 +
 +      if (!IS_ALIGNED((uintptr_t)addr, size)) {
 +              pr_warn("Address %p and size %d are not aligned\n", addr, size);
 +              return;
 +      }
 +
 +      if (size > 2) {
 +              writel(value, addr);
 +              return;
 +      }
 +
 +      mask = ~(((1 << (size * 8)) - 1) << (offset * 8));
 +      val = readl(aligned_addr) & mask;
 +      val |= value << (offset * 8);
 +      writel(val, aligned_addr);
  }
  
  /* Root Port register access */
  static inline void cdns_pcie_rp_writeb(struct cdns_pcie *pcie,
                                       u32 reg, u8 value)
  {
 -      writeb(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
 +      void __iomem *addr = pcie->reg_base + CDNS_PCIE_RP_BASE + reg;
 +
 +      cdns_pcie_write_sz(addr, 0x1, value);
  }
  
  static inline void cdns_pcie_rp_writew(struct cdns_pcie *pcie,
                                       u32 reg, u16 value)
  {
 -      writew(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
 +      void __iomem *addr = pcie->reg_base + CDNS_PCIE_RP_BASE + reg;
 +
 +      cdns_pcie_write_sz(addr, 0x2, value);
  }
  
  /* Endpoint Function register access */
  static inline void cdns_pcie_ep_fn_writeb(struct cdns_pcie *pcie, u8 fn,
                                          u32 reg, u8 value)
  {
 -      writeb(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
 +      void __iomem *addr = pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg;
 +
 +      cdns_pcie_write_sz(addr, 0x1, value);
  }
  
  static inline void cdns_pcie_ep_fn_writew(struct cdns_pcie *pcie, u8 fn,
                                          u32 reg, u16 value)
  {
 -      writew(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
 +      void __iomem *addr = pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg;
 +
 +      cdns_pcie_write_sz(addr, 0x2, value);
  }
  
  static inline void cdns_pcie_ep_fn_writel(struct cdns_pcie *pcie, u8 fn,
        writel(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
  }
  
 -static inline u8 cdns_pcie_ep_fn_readb(struct cdns_pcie *pcie, u8 fn, u32 reg)
 -{
 -      return readb(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
 -}
 -
  static inline u16 cdns_pcie_ep_fn_readw(struct cdns_pcie *pcie, u8 fn, u32 reg)
  {
 -      return readw(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
 +      void __iomem *addr = pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg;
 +
 +      return cdns_pcie_read_sz(addr, 0x2);
  }
  
  static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg)
        return readl(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
  }
  
 +static inline int cdns_pcie_start_link(struct cdns_pcie *pcie)
 +{
 +      if (pcie->ops->start_link)
 +              return pcie->ops->start_link(pcie);
 +
 +      return 0;
 +}
 +
 +static inline void cdns_pcie_stop_link(struct cdns_pcie *pcie)
 +{
 +      if (pcie->ops->stop_link)
 +              pcie->ops->stop_link(pcie);
 +}
 +
 +static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
 +{
 +      if (pcie->ops->link_up)
 +              return pcie->ops->link_up(pcie);
 +
 +      return true;
 +}
 +
  #ifdef CONFIG_PCIE_CADENCE_HOST
  int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
 +void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 +                             int where);
  #else
  static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
  {
        return 0;
  }
 +
 +static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 +                                           int where)
 +{
 +      return NULL;
 +}
  #endif
  
  #ifdef CONFIG_PCIE_CADENCE_EP
@@@ -498,11 -378,12 +495,12 @@@ static inline int cdns_pcie_ep_setup(st
        return 0;
  }
  #endif
- void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 fn,
+ void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
                                   u32 r, bool is_io,
                                   u64 cpu_addr, u64 pci_addr, size_t size);
  
- void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie, u8 fn,
+ void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
+                                                 u8 busnr, u8 fn,
                                                  u32 r, u64 cpu_addr);
  
  void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r);
index a075eba45abb20e369204ceac1da65fc9dcc8ecc,5791039d6a54216c8da678fc0a833e2ed7d55038..5b136a59938d03a4605763fa4e0a856c9b9248df
@@@ -3,7 -3,7 +3,7 @@@
   * PCIe host controller driver for Samsung Exynos SoCs
   *
   * Copyright (C) 2013 Samsung Electronics Co., Ltd.
 - *            http://www.samsung.com
 + *            https://www.samsung.com
   *
   * Author: Jingoo Han <[email protected]>
   */
@@@ -84,14 -84,12 +84,12 @@@ static int exynos5440_pcie_get_mem_reso
  {
        struct dw_pcie *pci = ep->pci;
        struct device *dev = pci->dev;
-       struct resource *res;
  
        ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL);
        if (!ep->mem_res)
                return -ENOMEM;
  
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       ep->mem_res->elbi_base = devm_ioremap_resource(dev, res);
+       ep->mem_res->elbi_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(ep->mem_res->elbi_base))
                return PTR_ERR(ep->mem_res->elbi_base);
  
index 4e5c379ae41810e77f86b4a54f980b79ec0b1936,9f1e4d9c008b3d7b1aab513093db2e71da2c4a0d..12ac47178c91660131eee9c498c4000b0882ed50
@@@ -3,7 -3,7 +3,7 @@@
   * PCIe host controller driver for Freescale i.MX6 SoCs
   *
   * Copyright (C) 2013 Kosagi
 - *            http://www.kosagi.com
 + *            https://www.kosagi.com
   *
   * Author: Sean Cross <[email protected]>
   */
@@@ -1269,7 -1269,7 +1269,7 @@@ static void imx6_pcie_quirk(struct pci_
        if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver)
                return;
  
-       if (bus->number == pp->root_bus_nr) {
+       if (pci_is_root_bus(bus)) {
                struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
                struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
  
index 0b7ed21cf8d03ddddc7e69739489aea0477547e2,fcc3586c345b97c2f8ec606983217657a791b2bc..d274c64d6799c9a0c1d60622bca96c82161332c4
@@@ -3,7 -3,7 +3,7 @@@
   * PCIe host controller driver for Texas Instruments Keystone SoCs
   *
   * Copyright (C) 2013-2014 Texas Instruments., Ltd.
 - *            http://www.ti.com
 + *            https://www.ti.com
   *
   * Author: Murali Karicheri <[email protected]>
   * Implementation based on pci-exynos.c and pcie-designware.c
@@@ -440,7 -440,7 +440,7 @@@ static int ks_pcie_rd_other_conf(struc
  
        reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
                CFG_FUNC(PCI_FUNC(devfn));
-       if (bus->parent->number != pp->root_bus_nr)
+       if (!pci_is_root_bus(bus->parent))
                reg |= CFG_TYPE1;
        ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg);
  
@@@ -457,7 -457,7 +457,7 @@@ static int ks_pcie_wr_other_conf(struc
  
        reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
                CFG_FUNC(PCI_FUNC(devfn));
-       if (bus->parent->number != pp->root_bus_nr)
+       if (!pci_is_root_bus(bus->parent))
                reg |= CFG_TYPE1;
        ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg);
  
@@@ -1323,7 -1323,8 +1323,7 @@@ static int __init ks_pcie_probe(struct 
        }
  
        if (pci->version >= 0x480A) {
 -              res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu");
 -              atu_base = devm_ioremap_resource(dev, res);
 +              atu_base = devm_platform_ioremap_resource_byname(pdev, "atu");
                if (IS_ERR(atu_base)) {
                        ret = PTR_ERR(atu_base);
                        goto err_get_sync;
index 2cb286a492933f24f14be03b06ee4e7643c20adb,7461357d98f6d3371434006e026705152499db37..9dafecba347f07383fc718941c53e26f9bef3434
@@@ -3,7 -3,7 +3,7 @@@
   * Synopsys DesignWare PCIe host controller driver
   *
   * Copyright (C) 2013 Samsung Electronics Co., Ltd.
 - *            http://www.samsung.com
 + *            https://www.samsung.com
   *
   * Author: Jingoo Han <[email protected]>
   */
@@@ -346,11 -346,6 +346,6 @@@ int dw_pcie_host_init(struct pcie_port 
        if (!bridge)
                return -ENOMEM;
  
-       ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
-                                             &bridge->dma_ranges, NULL);
-       if (ret)
-               return ret;
        /* Get the I/O and memory ranges from DT */
        resource_list_for_each_entry(win, &bridge->windows) {
                switch (resource_type(win->res)) {
                goto err_free_msi;
        }
  
-       pp->root_bus_nr = pp->busn->start;
-       bridge->dev.parent = dev;
        bridge->sysdata = pp;
-       bridge->busnr = pp->root_bus_nr;
        bridge->ops = &dw_pcie_ops;
-       bridge->map_irq = of_irq_parse_and_map_pci;
-       bridge->swizzle_irq = pci_common_swizzle;
  
        ret = pci_scan_root_bus_bridge(bridge);
        if (ret)
@@@ -529,7 -518,7 +518,7 @@@ static int dw_pcie_access_other_conf(st
        busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
                 PCIE_ATU_FUNC(PCI_FUNC(devfn));
  
-       if (bus->parent->number == pp->root_bus_nr) {
+       if (pci_is_root_bus(bus->parent)) {
                type = PCIE_ATU_TYPE_CFG0;
                cpu_addr = pp->cfg0_base;
                cfg_size = pp->cfg0_size;
@@@ -585,13 -574,11 +574,11 @@@ static int dw_pcie_valid_device(struct 
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
  
        /* If there is no link, then there is no device */
-       if (bus->number != pp->root_bus_nr) {
+       if (!pci_is_root_bus(bus)) {
                if (!dw_pcie_link_up(pci))
                        return 0;
-       }
-       /* Access only one slot on each root port */
-       if (bus->number == pp->root_bus_nr && dev > 0)
+       } else if (dev > 0)
+               /* Access only one slot on each root port */
                return 0;
  
        return 1;
@@@ -607,7 -594,7 +594,7 @@@ static int dw_pcie_rd_conf(struct pci_b
                return PCIBIOS_DEVICE_NOT_FOUND;
        }
  
-       if (bus->number == pp->root_bus_nr)
+       if (pci_is_root_bus(bus))
                return dw_pcie_rd_own_conf(pp, where, size, val);
  
        return dw_pcie_rd_other_conf(pp, bus, devfn, where, size, val);
@@@ -621,7 -608,7 +608,7 @@@ static int dw_pcie_wr_conf(struct pci_b
        if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
                return PCIBIOS_DEVICE_NOT_FOUND;
  
-       if (bus->number == pp->root_bus_nr)
+       if (pci_is_root_bus(bus))
                return dw_pcie_wr_own_conf(pp, where, size, val);
  
        return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val);
index 90915dc89e086c68e673cd973c0706598314ed15,fd2146298b586bd457ec28b10f2178e534faf26d..f911760dcc69e635be8018634239898517c6af09
@@@ -3,7 -3,7 +3,7 @@@
   * Synopsys DesignWare PCIe host controller driver
   *
   * Copyright (C) 2013 Samsung Electronics Co., Ltd.
 - *            http://www.samsung.com
 + *            https://www.samsung.com
   *
   * Author: Jingoo Han <[email protected]>
   */
@@@ -173,7 -173,6 +173,6 @@@ struct dw_pcie_host_ops 
  };
  
  struct pcie_port {
-       u8                      root_bus_nr;
        u64                     cfg0_base;
        void __iomem            *va_cfg0_base;
        u32                     cfg0_size;
index 1258f45cbc11abb983158a480fdf2c530c0670ae,795e7632b06804f2702a743c604b5aa14448440b..1559f79e63b6fa9be0446ac4b3f71244ffcb8f79
@@@ -195,7 -195,6 +195,6 @@@ struct advk_pcie 
        DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
        struct mutex msi_used_lock;
        u16 msi_msg;
-       int root_bus_nr;
        int link_gen;
        struct pci_bridge_emul bridge;
        struct gpio_desc *reset_gpio;
@@@ -641,16 -640,9 +640,16 @@@ static void advk_sw_pci_bridge_init(str
  static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
                                  int devfn)
  {
-       if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0)
+       if (pci_is_root_bus(bus) && PCI_SLOT(devfn) != 0)
                return false;
  
-       if (bus->number != pcie->root_bus_nr && !advk_pcie_link_up(pcie))
 +      /*
 +       * If the link goes down after we check for link-up, nothing bad
 +       * happens but the config access times out.
 +       */
++      if (!pci_is_root_bus(bus) && !advk_pcie_link_up(pcie))
 +              return false;
 +
        return true;
  }
  
@@@ -666,7 -658,7 +665,7 @@@ static int advk_pcie_rd_conf(struct pci
                return PCIBIOS_DEVICE_NOT_FOUND;
        }
  
-       if (bus->number == pcie->root_bus_nr)
+       if (pci_is_root_bus(bus))
                return pci_bridge_emul_conf_read(&pcie->bridge, where,
                                                 size, val);
  
        /* Program the control register */
        reg = advk_readl(pcie, PIO_CTRL);
        reg &= ~PIO_CTRL_TYPE_MASK;
-       if (bus->primary ==  pcie->root_bus_nr)
+       if (pci_is_root_bus(bus->parent))
                reg |= PCIE_CONFIG_RD_TYPE0;
        else
                reg |= PCIE_CONFIG_RD_TYPE1;
        advk_writel(pcie, 1, PIO_START);
  
        ret = advk_pcie_wait_pio(pcie);
 -      if (ret < 0)
 +      if (ret < 0) {
 +              *val = 0xffffffff;
                return PCIBIOS_SET_FAILED;
 +      }
  
        advk_pcie_check_pio_status(pcie);
  
@@@ -724,7 -714,7 +723,7 @@@ static int advk_pcie_wr_conf(struct pci
        if (!advk_pcie_valid_device(pcie, bus, devfn))
                return PCIBIOS_DEVICE_NOT_FOUND;
  
-       if (bus->number == pcie->root_bus_nr)
+       if (pci_is_root_bus(bus))
                return pci_bridge_emul_conf_write(&pcie->bridge, where,
                                                  size, val);
  
        /* Program the control register */
        reg = advk_readl(pcie, PIO_CTRL);
        reg &= ~PIO_CTRL_TYPE_MASK;
-       if (bus->primary == pcie->root_bus_nr)
+       if (pci_is_root_bus(bus->parent))
                reg |= PCIE_CONFIG_WR_TYPE0;
        else
                reg |= PCIE_CONFIG_WR_TYPE1;
@@@ -1114,7 -1104,6 +1113,6 @@@ static int advk_pcie_probe(struct platf
  {
        struct device *dev = &pdev->dev;
        struct advk_pcie *pcie;
-       struct resource *res, *bus;
        struct pci_host_bridge *bridge;
        int ret, irq;
  
        pcie = pci_host_bridge_priv(bridge);
        pcie->pdev = pdev;
  
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pcie->base = devm_ioremap_resource(dev, res);
+       pcie->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(pcie->base))
                return PTR_ERR(pcie->base);
  
                return ret;
        }
  
-       ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
-                                             &bridge->dma_ranges, &bus);
-       if (ret) {
-               dev_err(dev, "Failed to parse resources\n");
-               return ret;
-       }
-       pcie->root_bus_nr = bus->start;
        pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
                                                       "reset-gpios", 0,
                                                       GPIOD_OUT_LOW,
                return ret;
        }
  
-       bridge->dev.parent = dev;
        bridge->sysdata = pcie;
-       bridge->busnr = 0;
        bridge->ops = &advk_pcie_ops;
-       bridge->map_irq = of_irq_parse_and_map_pci;
-       bridge->swizzle_irq = pci_common_swizzle;
  
        ret = pci_host_probe(bridge);
        if (ret < 0) {
index 58b862aaa6e94bccb10e467613a8a0c0fd7b4f6f,a7a7fbe2b7a50ac81c45d425085c060cd879328a..719c19fe2bfb0c1b370a169fe1378bc61102ba54
@@@ -37,11 -37,11 +37,11 @@@ static void bridge_class_quirk(struct p
  {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
  }
 -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON,
 +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
                        DEV_PCIE_PORT_0, bridge_class_quirk);
 -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON,
 +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
                        DEV_PCIE_PORT_1, bridge_class_quirk);
 -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON,
 +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
                        DEV_PCIE_PORT_2, bridge_class_quirk);
  
  static void system_bus_quirk(struct pci_dev *pdev)
@@@ -218,14 -218,6 +218,6 @@@ static int loongson_pci_probe(struct pl
                }
        }
  
-       err = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
-                                               &bridge->dma_ranges, NULL);
-       if (err) {
-               dev_err(dev, "failed to get bridge resources\n");
-               return err;
-       }
-       bridge->dev.parent = dev;
        bridge->sysdata = priv;
        bridge->ops = &loongson_pci_ops;
        bridge->map_irq = loongson_map_irq;
index 101c06602aa1be56de3e79885e31293c9ef9fe3c,12d30fb6ae6ee873f9521f30a87e65ebcf9c0732..c39978b750ec67278f45d3fbf702a9fc6ba49a49
@@@ -71,7 -71,6 +71,6 @@@ struct mvebu_pcie 
        struct platform_device *pdev;
        struct mvebu_pcie_port *ports;
        struct msi_controller *msi;
-       struct list_head resources;
        struct resource io;
        struct resource realio;
        struct resource mem;
@@@ -105,7 -104,6 +104,7 @@@ struct mvebu_pcie_port 
        struct mvebu_pcie_window memwin;
        struct mvebu_pcie_window iowin;
        u32 saved_pcie_stat;
 +      struct resource regs;
  };
  
  static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@@ -150,9 -148,7 +149,9 @@@ static void mvebu_pcie_set_local_dev_nr
  
  /*
   * Setup PCIE BARs and Address Decode Wins:
 - * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
 + * BAR[0] -> internal registers (needed for MSI)
 + * BAR[1] -> covers all DRAM banks
 + * BAR[2] -> Disabled
   * WIN[0-3] -> DRAM bank[0-3]
   */
  static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
        mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1));
        mvebu_writel(port, ((size - 1) & 0xffff0000) | 1,
                     PCIE_BAR_CTRL_OFF(1));
 +
 +      /*
 +       * Point BAR[0] to the device's internal registers.
 +       */
 +      mvebu_writel(port, round_down(port->regs.start, SZ_1M), PCIE_BAR_LO_OFF(0));
 +      mvebu_writel(port, 0, PCIE_BAR_HI_OFF(0));
  }
  
  static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
@@@ -717,13 -707,14 +716,13 @@@ static void __iomem *mvebu_pcie_map_reg
                                              struct device_node *np,
                                              struct mvebu_pcie_port *port)
  {
 -      struct resource regs;
        int ret = 0;
  
 -      ret = of_address_to_resource(np, 0, &regs);
 +      ret = of_address_to_resource(np, 0, &port->regs);
        if (ret)
                return (void __iomem *)ERR_PTR(ret);
  
 -      return devm_ioremap_resource(&pdev->dev, &regs);
 +      return devm_ioremap_resource(&pdev->dev, &port->regs);
  }
  
  #define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
@@@ -969,17 -960,16 +968,16 @@@ static int mvebu_pcie_parse_request_res
  {
        struct device *dev = &pcie->pdev->dev;
        struct device_node *np = dev->of_node;
+       struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
        int ret;
  
-       INIT_LIST_HEAD(&pcie->resources);
        /* Get the bus range */
        ret = of_pci_parse_bus_range(np, &pcie->busn);
        if (ret) {
                dev_err(dev, "failed to parse bus-range property: %d\n", ret);
                return ret;
        }
-       pci_add_resource(&pcie->resources, &pcie->busn);
+       pci_add_resource(&bridge->windows, &pcie->busn);
  
        /* Get the PCIe memory aperture */
        mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
        }
  
        pcie->mem.name = "PCI MEM";
-       pci_add_resource(&pcie->resources, &pcie->mem);
+       pci_add_resource(&bridge->windows, &pcie->mem);
  
        /* Get the PCIe IO aperture */
        mvebu_mbus_get_pcie_io_aperture(&pcie->io);
                                         resource_size(&pcie->io) - 1);
                pcie->realio.name = "PCI I/O";
  
-               pci_add_resource(&pcie->resources, &pcie->realio);
+               pci_add_resource(&bridge->windows, &pcie->realio);
        }
  
-       return devm_request_pci_bus_resources(dev, &pcie->resources);
+       return devm_request_pci_bus_resources(dev, &bridge->windows);
  }
  
  /*
@@@ -1126,13 -1116,8 +1124,8 @@@ static int mvebu_pcie_probe(struct plat
  
        pcie->nports = i;
  
-       list_splice_init(&pcie->resources, &bridge->windows);
-       bridge->dev.parent = dev;
        bridge->sysdata = pcie;
-       bridge->busnr = 0;
        bridge->ops = &mvebu_pcie_ops;
-       bridge->map_irq = of_irq_parse_and_map_pci;
-       bridge->swizzle_irq = pci_common_swizzle;
        bridge->align_resource = mvebu_pcie_align_resource;
        bridge->msi = pcie->msi;
  
index e25e661a652cdb90c9cd9d344b0ec9c8dc544f62,2789d5500f2c993e6e09e4a510bdfa81449eab17..fdbcf0d6b9c34fe38ae798ce92eb933141ee33c8
  
  #define AFI_PEXBIAS_CTRL_0            0x168
  
 -#define RP_PRIV_XP_DL         0x00000494
 -#define  RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD     (0x1ff << 1)
 -
 -#define RP_RX_HDR_LIMIT               0x00000e00
 -#define  RP_RX_HDR_LIMIT_PW_MASK      (0xff << 8)
 -#define  RP_RX_HDR_LIMIT_PW           (0x0e << 8)
 -
  #define RP_ECTL_2_R1  0x00000e84
  #define  RP_ECTL_2_R1_RX_CTLE_1C_MASK         0xffff
  
@@@ -316,6 -323,7 +316,6 @@@ struct tegra_pcie_soc 
        bool program_uphy;
        bool update_clamp_threshold;
        bool program_deskew_time;
 -      bool raw_violation_fixup;
        bool update_fc_timer;
        bool has_cache_bars;
        struct {
@@@ -651,6 -659,23 +651,6 @@@ static void tegra_pcie_apply_sw_fixup(s
                writel(value, port->base + RP_VEND_CTL0);
        }
  
 -      /* Fixup for read after write violation. */
 -      if (soc->raw_violation_fixup) {
 -              value = readl(port->base + RP_RX_HDR_LIMIT);
 -              value &= ~RP_RX_HDR_LIMIT_PW_MASK;
 -              value |= RP_RX_HDR_LIMIT_PW;
 -              writel(value, port->base + RP_RX_HDR_LIMIT);
 -
 -              value = readl(port->base + RP_PRIV_XP_DL);
 -              value |= RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD;
 -              writel(value, port->base + RP_PRIV_XP_DL);
 -
 -              value = readl(port->base + RP_VEND_XP);
 -              value &= ~RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK;
 -              value |= soc->update_fc_threshold;
 -              writel(value, port->base + RP_VEND_XP);
 -      }
 -
        if (soc->update_fc_timer) {
                value = readl(port->base + RP_VEND_XP);
                value &= ~RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK;
@@@ -1437,7 -1462,7 +1437,7 @@@ static int tegra_pcie_get_resources(str
  {
        struct device *dev = pcie->dev;
        struct platform_device *pdev = to_platform_device(dev);
-       struct resource *pads, *afi, *res;
+       struct resource *res;
        const struct tegra_pcie_soc *soc = pcie->soc;
        int err;
  
                }
        }
  
-       pads = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pads");
-       pcie->pads = devm_ioremap_resource(dev, pads);
+       pcie->pads = devm_platform_ioremap_resource_byname(pdev, "pads");
        if (IS_ERR(pcie->pads)) {
                err = PTR_ERR(pcie->pads);
                goto phys_put;
        }
  
-       afi = platform_get_resource_byname(pdev, IORESOURCE_MEM, "afi");
-       pcie->afi = devm_ioremap_resource(dev, afi);
+       pcie->afi = devm_platform_ioremap_resource_byname(pdev, "afi");
        if (IS_ERR(pcie->afi)) {
                err = PTR_ERR(pcie->afi);
                goto phys_put;
@@@ -2000,7 -2023,7 +1998,7 @@@ static int tegra_pcie_get_regulators(st
                pcie->supplies[i++].supply = "hvdd-pex";
                pcie->supplies[i++].supply = "vddio-pexctl-aud";
        } else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
 -              pcie->num_supplies = 6;
 +              pcie->num_supplies = 3;
  
                pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
                                              sizeof(*pcie->supplies),
                if (!pcie->supplies)
                        return -ENOMEM;
  
 -              pcie->supplies[i++].supply = "avdd-pll-uerefe";
                pcie->supplies[i++].supply = "hvddio-pex";
                pcie->supplies[i++].supply = "dvddio-pex";
 -              pcie->supplies[i++].supply = "dvdd-pex-pll";
 -              pcie->supplies[i++].supply = "hvdd-pex-pll-e";
                pcie->supplies[i++].supply = "vddio-pex-ctl";
        } else if (of_device_is_compatible(np, "nvidia,tegra124-pcie")) {
 -              pcie->num_supplies = 7;
 +              pcie->num_supplies = 4;
  
                pcie->supplies = devm_kcalloc(dev, pcie->num_supplies,
                                              sizeof(*pcie->supplies),
  
                pcie->supplies[i++].supply = "avddio-pex";
                pcie->supplies[i++].supply = "dvddio-pex";
 -              pcie->supplies[i++].supply = "avdd-pex-pll";
                pcie->supplies[i++].supply = "hvdd-pex";
 -              pcie->supplies[i++].supply = "hvdd-pex-pll-e";
                pcie->supplies[i++].supply = "vddio-pex-ctl";
 -              pcie->supplies[i++].supply = "avdd-pll-erefe";
        } else if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
                bool need_pexa = false, need_pexb = false;
  
@@@ -2385,6 -2414,7 +2383,6 @@@ static const struct tegra_pcie_soc tegr
        .program_uphy = true,
        .update_clamp_threshold = false,
        .program_deskew_time = false,
 -      .raw_violation_fixup = false,
        .update_fc_timer = false,
        .has_cache_bars = true,
        .ectl.enable = false,
@@@ -2414,6 -2444,7 +2412,6 @@@ static const struct tegra_pcie_soc tegr
        .program_uphy = true,
        .update_clamp_threshold = false,
        .program_deskew_time = false,
 -      .raw_violation_fixup = false,
        .update_fc_timer = false,
        .has_cache_bars = false,
        .ectl.enable = false,
@@@ -2426,6 -2457,8 +2424,6 @@@ static const struct tegra_pcie_soc tegr
        .pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
        .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
        .pads_refclk_cfg0 = 0x44ac44ac,
 -      /* FC threshold is bit[25:18] */
 -      .update_fc_threshold = 0x03fc0000,
        .has_pex_clkreq_en = true,
        .has_pex_bias_ctrl = true,
        .has_intr_prsnt_sense = true,
        .program_uphy = true,
        .update_clamp_threshold = true,
        .program_deskew_time = false,
 -      .raw_violation_fixup = true,
        .update_fc_timer = false,
        .has_cache_bars = false,
        .ectl.enable = false,
@@@ -2458,6 -2492,7 +2456,6 @@@ static const struct tegra_pcie_soc tegr
        .program_uphy = true,
        .update_clamp_threshold = true,
        .program_deskew_time = true,
 -      .raw_violation_fixup = false,
        .update_fc_timer = true,
        .has_cache_bars = false,
        .ectl = {
@@@ -2499,6 -2534,7 +2497,6 @@@ static const struct tegra_pcie_soc tegr
        .program_uphy = false,
        .update_clamp_threshold = false,
        .program_deskew_time = false,
 -      .raw_violation_fixup = false,
        .update_fc_timer = false,
        .has_cache_bars = false,
        .ectl.enable = false,
@@@ -2632,8 -2668,6 +2630,6 @@@ static int tegra_pcie_probe(struct plat
        struct device *dev = &pdev->dev;
        struct pci_host_bridge *host;
        struct tegra_pcie *pcie;
-       struct pci_bus *child;
-       struct resource *bus;
        int err;
  
        host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
        INIT_LIST_HEAD(&pcie->ports);
        pcie->dev = dev;
  
-       err = pci_parse_request_of_pci_ranges(dev, &host->windows, NULL, &bus);
-       if (err) {
-               dev_err(dev, "Getting bridge resources failed\n");
-               return err;
-       }
        err = tegra_pcie_parse_dt(pcie);
        if (err < 0)
                return err;
                goto pm_runtime_put;
        }
  
-       host->busnr = bus->start;
-       host->dev.parent = &pdev->dev;
        host->ops = &tegra_pcie_ops;
        host->map_irq = tegra_pcie_map_irq;
-       host->swizzle_irq = pci_common_swizzle;
  
-       err = pci_scan_root_bus_bridge(host);
+       err = pci_host_probe(host);
        if (err < 0) {
                dev_err(dev, "failed to register host: %d\n", err);
                goto pm_runtime_put;
        }
  
-       pci_bus_size_bridges(host->bus);
-       pci_bus_assign_resources(host->bus);
-       list_for_each_entry(child, &host->bus->children, node)
-               pcie_bus_configure_settings(child);
-       pci_bus_add_devices(host->bus);
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_pcie_debugfs_init(pcie);
                if (err < 0)
index 060c24f5221e2aa9936a15dfb1c425e09d3bb294,f6f41db31d47bcf122d0832b963af158f1ef31ef..cdc0963f154e3b1a438d3c00aa5d40e75b326c06
@@@ -53,8 -53,6 +53,6 @@@ struct rcar_pcie_host 
        struct device           *dev;
        struct phy              *phy;
        void __iomem            *base;
-       struct list_head        resources;
-       int                     root_bus_nr;
        struct clk              *bus_clk;
        struct                  rcar_msi msi;
        int                     (*phy_init_fn)(struct rcar_pcie_host *host);
@@@ -100,22 -98,14 +98,14 @@@ static int rcar_pcie_config_access(stru
                if (dev != 0)
                        return PCIBIOS_DEVICE_NOT_FOUND;
  
-               if (access_type == RCAR_PCI_ACCESS_READ) {
+               if (access_type == RCAR_PCI_ACCESS_READ)
                        *data = rcar_pci_read_reg(pcie, PCICONF(index));
-               } else {
-                       /* Keep an eye out for changes to the root bus number */
-                       if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
-                               host->root_bus_nr = *data & 0xff;
+               else
                        rcar_pci_write_reg(pcie, *data, PCICONF(index));
-               }
  
                return PCIBIOS_SUCCESSFUL;
        }
  
-       if (host->root_bus_nr < 0)
-               return PCIBIOS_DEVICE_NOT_FOUND;
        /* Clear errors */
        rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
  
                PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
  
        /* Enable the configuration access */
-       if (bus->parent->number == host->root_bus_nr)
+       if (pci_is_root_bus(bus->parent))
                rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
        else
                rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
@@@ -212,38 -202,6 +202,6 @@@ static struct pci_ops rcar_pcie_ops = 
        .write  = rcar_pcie_write_conf,
  };
  
- static int rcar_pcie_setup(struct list_head *resource,
-                          struct rcar_pcie_host *host)
- {
-       struct resource_entry *win;
-       int i = 0;
-       /* Setup PCI resources */
-       resource_list_for_each_entry(win, &host->resources) {
-               struct resource *res = win->res;
-               if (!res->flags)
-                       continue;
-               switch (resource_type(res)) {
-               case IORESOURCE_IO:
-               case IORESOURCE_MEM:
-                       rcar_pcie_set_outbound(&host->pcie, i, win);
-                       i++;
-                       break;
-               case IORESOURCE_BUS:
-                       host->root_bus_nr = res->start;
-                       break;
-               default:
-                       continue;
-               }
-               pci_add_resource(resource, res);
-       }
-       return 1;
- }
  static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
  {
        struct device *dev = pcie->dev;
@@@ -301,6 -259,7 +259,7 @@@ done
  static void rcar_pcie_hw_enable(struct rcar_pcie_host *host)
  {
        struct rcar_pcie *pcie = &host->pcie;
+       struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host);
        struct resource_entry *win;
        LIST_HEAD(res);
        int i = 0;
        rcar_pcie_force_speedup(pcie);
  
        /* Setup PCI resources */
-       resource_list_for_each_entry(win, &host->resources) {
+       resource_list_for_each_entry(win, &bridge->windows) {
                struct resource *res = win->res;
  
                if (!res->flags)
  static int rcar_pcie_enable(struct rcar_pcie_host *host)
  {
        struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host);
-       struct rcar_pcie *pcie = &host->pcie;
-       struct device *dev = pcie->dev;
-       struct pci_bus *bus, *child;
-       int ret;
-       /* Try setting 5 GT/s link speed */
-       rcar_pcie_force_speedup(pcie);
  
-       rcar_pcie_setup(&bridge->windows, host);
+       rcar_pcie_hw_enable(host);
  
        pci_add_flags(PCI_REASSIGN_ALL_BUS);
  
-       bridge->dev.parent = dev;
        bridge->sysdata = host;
-       bridge->busnr = host->root_bus_nr;
        bridge->ops = &rcar_pcie_ops;
-       bridge->map_irq = of_irq_parse_and_map_pci;
-       bridge->swizzle_irq = pci_common_swizzle;
        if (IS_ENABLED(CONFIG_PCI_MSI))
                bridge->msi = &host->msi.chip;
  
-       ret = pci_scan_root_bus_bridge(bridge);
-       if (ret < 0)
-               return ret;
-       bus = bridge->bus;
-       pci_bus_size_bridges(bus);
-       pci_bus_assign_resources(bus);
-       list_for_each_entry(child, &bus->children, node)
-               pcie_bus_configure_settings(child);
-       pci_bus_add_devices(bus);
-       return 0;
+       return pci_host_probe(bridge);
  }
  
  static int phy_wait_for_ack(struct rcar_pcie *pcie)
@@@ -968,7 -902,7 +902,7 @@@ static int rcar_pcie_probe(struct platf
        int err;
        struct pci_host_bridge *bridge;
  
-       bridge = pci_alloc_host_bridge(sizeof(*host));
+       bridge = devm_pci_alloc_host_bridge(dev, sizeof(*host));
        if (!bridge)
                return -ENOMEM;
  
        pcie->dev = dev;
        platform_set_drvdata(pdev, host);
  
-       err = pci_parse_request_of_pci_ranges(dev, &host->resources,
-                                             &bridge->dma_ranges, NULL);
-       if (err)
-               goto err_free_bridge;
        pm_runtime_enable(pcie->dev);
        err = pm_runtime_get_sync(pcie->dev);
        if (err < 0) {
                dev_err(pcie->dev, "pm_runtime_get_sync failed\n");
 -              goto err_pm_disable;
 +              goto err_pm_put;
        }
  
        err = rcar_pcie_get_resources(host);
@@@ -1057,11 -986,9 +986,7 @@@ err_unmap_msi_irqs
  
  err_pm_put:
        pm_runtime_put(dev);
 -
 -err_pm_disable:
        pm_runtime_disable(dev);
-       pci_free_resource_list(&host->resources);
- err_free_bridge:
-       pci_free_host_bridge(bridge);
  
        return err;
  }
index cd8c77457b5f6a8c7a1d413439ceacb64ead0c30,0000000000000000000000000000000000000000..f3082de44e8a8f2e6bdf6190b04e4d612f8244ac
mode 100644,000000..100644
--- /dev/null
@@@ -1,614 -1,0 +1,611 @@@
-       struct resource *bus_range;
 +// SPDX-License-Identifier: GPL-2.0+
 +/*
 + * PCIe host controller driver for Xilinx Versal CPM DMA Bridge
 + *
 + * (C) Copyright 2019 - 2020, Xilinx, Inc.
 + */
 +
 +#include <linux/bitfield.h>
 +#include <linux/interrupt.h>
 +#include <linux/irq.h>
 +#include <linux/irqchip.h>
 +#include <linux/irqchip/chained_irq.h>
 +#include <linux/irqdomain.h>
 +#include <linux/kernel.h>
 +#include <linux/module.h>
 +#include <linux/of_address.h>
 +#include <linux/of_pci.h>
 +#include <linux/of_platform.h>
 +#include <linux/of_irq.h>
 +#include <linux/pci.h>
 +#include <linux/platform_device.h>
 +#include <linux/pci-ecam.h>
 +
 +#include "../pci.h"
 +
 +/* Register definitions */
 +#define XILINX_CPM_PCIE_REG_IDR               0x00000E10
 +#define XILINX_CPM_PCIE_REG_IMR               0x00000E14
 +#define XILINX_CPM_PCIE_REG_PSCR      0x00000E1C
 +#define XILINX_CPM_PCIE_REG_RPSC      0x00000E20
 +#define XILINX_CPM_PCIE_REG_RPEFR     0x00000E2C
 +#define XILINX_CPM_PCIE_REG_IDRN      0x00000E38
 +#define XILINX_CPM_PCIE_REG_IDRN_MASK 0x00000E3C
 +#define XILINX_CPM_PCIE_MISC_IR_STATUS        0x00000340
 +#define XILINX_CPM_PCIE_MISC_IR_ENABLE        0x00000348
 +#define XILINX_CPM_PCIE_MISC_IR_LOCAL BIT(1)
 +
 +/* Interrupt registers definitions */
 +#define XILINX_CPM_PCIE_INTR_LINK_DOWN                0
 +#define XILINX_CPM_PCIE_INTR_HOT_RESET                3
 +#define XILINX_CPM_PCIE_INTR_CFG_PCIE_TIMEOUT 4
 +#define XILINX_CPM_PCIE_INTR_CFG_TIMEOUT      8
 +#define XILINX_CPM_PCIE_INTR_CORRECTABLE      9
 +#define XILINX_CPM_PCIE_INTR_NONFATAL         10
 +#define XILINX_CPM_PCIE_INTR_FATAL            11
 +#define XILINX_CPM_PCIE_INTR_CFG_ERR_POISON   12
 +#define XILINX_CPM_PCIE_INTR_PME_TO_ACK_RCVD  15
 +#define XILINX_CPM_PCIE_INTR_INTX             16
 +#define XILINX_CPM_PCIE_INTR_PM_PME_RCVD      17
 +#define XILINX_CPM_PCIE_INTR_SLV_UNSUPP               20
 +#define XILINX_CPM_PCIE_INTR_SLV_UNEXP                21
 +#define XILINX_CPM_PCIE_INTR_SLV_COMPL                22
 +#define XILINX_CPM_PCIE_INTR_SLV_ERRP         23
 +#define XILINX_CPM_PCIE_INTR_SLV_CMPABT               24
 +#define XILINX_CPM_PCIE_INTR_SLV_ILLBUR               25
 +#define XILINX_CPM_PCIE_INTR_MST_DECERR               26
 +#define XILINX_CPM_PCIE_INTR_MST_SLVERR               27
 +#define XILINX_CPM_PCIE_INTR_SLV_PCIE_TIMEOUT 28
 +
 +#define IMR(x) BIT(XILINX_CPM_PCIE_INTR_ ##x)
 +
 +#define XILINX_CPM_PCIE_IMR_ALL_MASK                  \
 +      (                                               \
 +              IMR(LINK_DOWN)          |               \
 +              IMR(HOT_RESET)          |               \
 +              IMR(CFG_PCIE_TIMEOUT)   |               \
 +              IMR(CFG_TIMEOUT)        |               \
 +              IMR(CORRECTABLE)        |               \
 +              IMR(NONFATAL)           |               \
 +              IMR(FATAL)              |               \
 +              IMR(CFG_ERR_POISON)     |               \
 +              IMR(PME_TO_ACK_RCVD)    |               \
 +              IMR(INTX)               |               \
 +              IMR(PM_PME_RCVD)        |               \
 +              IMR(SLV_UNSUPP)         |               \
 +              IMR(SLV_UNEXP)          |               \
 +              IMR(SLV_COMPL)          |               \
 +              IMR(SLV_ERRP)           |               \
 +              IMR(SLV_CMPABT)         |               \
 +              IMR(SLV_ILLBUR)         |               \
 +              IMR(MST_DECERR)         |               \
 +              IMR(MST_SLVERR)         |               \
 +              IMR(SLV_PCIE_TIMEOUT)                   \
 +      )
 +
 +#define XILINX_CPM_PCIE_IDR_ALL_MASK          0xFFFFFFFF
 +#define XILINX_CPM_PCIE_IDRN_MASK             GENMASK(19, 16)
 +#define XILINX_CPM_PCIE_IDRN_SHIFT            16
 +
 +/* Root Port Error FIFO Read Register definitions */
 +#define XILINX_CPM_PCIE_RPEFR_ERR_VALID               BIT(18)
 +#define XILINX_CPM_PCIE_RPEFR_REQ_ID          GENMASK(15, 0)
 +#define XILINX_CPM_PCIE_RPEFR_ALL_MASK                0xFFFFFFFF
 +
 +/* Root Port Status/control Register definitions */
 +#define XILINX_CPM_PCIE_REG_RPSC_BEN          BIT(0)
 +
 +/* Phy Status/Control Register definitions */
 +#define XILINX_CPM_PCIE_REG_PSCR_LNKUP                BIT(11)
 +
 +/**
 + * struct xilinx_cpm_pcie_port - PCIe port information
 + * @reg_base: Bridge Register Base
 + * @cpm_base: CPM System Level Control and Status Register(SLCR) Base
 + * @dev: Device pointer
 + * @intx_domain: Legacy IRQ domain pointer
 + * @cpm_domain: CPM IRQ domain pointer
 + * @cfg: Holds mappings of config space window
 + * @intx_irq: legacy interrupt number
 + * @irq: Error interrupt number
 + * @lock: lock protecting shared register access
 + */
 +struct xilinx_cpm_pcie_port {
 +      void __iomem                    *reg_base;
 +      void __iomem                    *cpm_base;
 +      struct device                   *dev;
 +      struct irq_domain               *intx_domain;
 +      struct irq_domain               *cpm_domain;
 +      struct pci_config_window        *cfg;
 +      int                             intx_irq;
 +      int                             irq;
 +      raw_spinlock_t                  lock;
 +};
 +
 +static u32 pcie_read(struct xilinx_cpm_pcie_port *port, u32 reg)
 +{
 +      return readl_relaxed(port->reg_base + reg);
 +}
 +
 +static void pcie_write(struct xilinx_cpm_pcie_port *port,
 +                     u32 val, u32 reg)
 +{
 +      writel_relaxed(val, port->reg_base + reg);
 +}
 +
 +static bool cpm_pcie_link_up(struct xilinx_cpm_pcie_port *port)
 +{
 +      return (pcie_read(port, XILINX_CPM_PCIE_REG_PSCR) &
 +              XILINX_CPM_PCIE_REG_PSCR_LNKUP);
 +}
 +
 +static void cpm_pcie_clear_err_interrupts(struct xilinx_cpm_pcie_port *port)
 +{
 +      unsigned long val = pcie_read(port, XILINX_CPM_PCIE_REG_RPEFR);
 +
 +      if (val & XILINX_CPM_PCIE_RPEFR_ERR_VALID) {
 +              dev_dbg(port->dev, "Requester ID %lu\n",
 +                      val & XILINX_CPM_PCIE_RPEFR_REQ_ID);
 +              pcie_write(port, XILINX_CPM_PCIE_RPEFR_ALL_MASK,
 +                         XILINX_CPM_PCIE_REG_RPEFR);
 +      }
 +}
 +
 +static void xilinx_cpm_mask_leg_irq(struct irq_data *data)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_data_get_irq_chip_data(data);
 +      unsigned long flags;
 +      u32 mask;
 +      u32 val;
 +
 +      mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
 +      raw_spin_lock_irqsave(&port->lock, flags);
 +      val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
 +      pcie_write(port, (val & (~mask)), XILINX_CPM_PCIE_REG_IDRN_MASK);
 +      raw_spin_unlock_irqrestore(&port->lock, flags);
 +}
 +
 +static void xilinx_cpm_unmask_leg_irq(struct irq_data *data)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_data_get_irq_chip_data(data);
 +      unsigned long flags;
 +      u32 mask;
 +      u32 val;
 +
 +      mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
 +      raw_spin_lock_irqsave(&port->lock, flags);
 +      val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
 +      pcie_write(port, (val | mask), XILINX_CPM_PCIE_REG_IDRN_MASK);
 +      raw_spin_unlock_irqrestore(&port->lock, flags);
 +}
 +
 +static struct irq_chip xilinx_cpm_leg_irq_chip = {
 +      .name           = "INTx",
 +      .irq_mask       = xilinx_cpm_mask_leg_irq,
 +      .irq_unmask     = xilinx_cpm_unmask_leg_irq,
 +};
 +
 +/**
 + * xilinx_cpm_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
 + * @domain: IRQ domain
 + * @irq: Virtual IRQ number
 + * @hwirq: HW interrupt number
 + *
 + * Return: Always returns 0.
 + */
 +static int xilinx_cpm_pcie_intx_map(struct irq_domain *domain,
 +                                  unsigned int irq, irq_hw_number_t hwirq)
 +{
 +      irq_set_chip_and_handler(irq, &xilinx_cpm_leg_irq_chip,
 +                               handle_level_irq);
 +      irq_set_chip_data(irq, domain->host_data);
 +      irq_set_status_flags(irq, IRQ_LEVEL);
 +
 +      return 0;
 +}
 +
 +/* INTx IRQ Domain operations */
 +static const struct irq_domain_ops intx_domain_ops = {
 +      .map = xilinx_cpm_pcie_intx_map,
 +};
 +
 +static void xilinx_cpm_pcie_intx_flow(struct irq_desc *desc)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_desc_get_handler_data(desc);
 +      struct irq_chip *chip = irq_desc_get_chip(desc);
 +      unsigned long val;
 +      int i;
 +
 +      chained_irq_enter(chip, desc);
 +
 +      val = FIELD_GET(XILINX_CPM_PCIE_IDRN_MASK,
 +                      pcie_read(port, XILINX_CPM_PCIE_REG_IDRN));
 +
 +      for_each_set_bit(i, &val, PCI_NUM_INTX)
 +              generic_handle_irq(irq_find_mapping(port->intx_domain, i));
 +
 +      chained_irq_exit(chip, desc);
 +}
 +
 +static void xilinx_cpm_mask_event_irq(struct irq_data *d)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_data_get_irq_chip_data(d);
 +      u32 val;
 +
 +      raw_spin_lock(&port->lock);
 +      val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
 +      val &= ~BIT(d->hwirq);
 +      pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
 +      raw_spin_unlock(&port->lock);
 +}
 +
 +static void xilinx_cpm_unmask_event_irq(struct irq_data *d)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_data_get_irq_chip_data(d);
 +      u32 val;
 +
 +      raw_spin_lock(&port->lock);
 +      val = pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
 +      val |= BIT(d->hwirq);
 +      pcie_write(port, val, XILINX_CPM_PCIE_REG_IMR);
 +      raw_spin_unlock(&port->lock);
 +}
 +
 +static struct irq_chip xilinx_cpm_event_irq_chip = {
 +      .name           = "RC-Event",
 +      .irq_mask       = xilinx_cpm_mask_event_irq,
 +      .irq_unmask     = xilinx_cpm_unmask_event_irq,
 +};
 +
 +static int xilinx_cpm_pcie_event_map(struct irq_domain *domain,
 +                                   unsigned int irq, irq_hw_number_t hwirq)
 +{
 +      irq_set_chip_and_handler(irq, &xilinx_cpm_event_irq_chip,
 +                               handle_level_irq);
 +      irq_set_chip_data(irq, domain->host_data);
 +      irq_set_status_flags(irq, IRQ_LEVEL);
 +      return 0;
 +}
 +
 +static const struct irq_domain_ops event_domain_ops = {
 +      .map = xilinx_cpm_pcie_event_map,
 +};
 +
 +static void xilinx_cpm_pcie_event_flow(struct irq_desc *desc)
 +{
 +      struct xilinx_cpm_pcie_port *port = irq_desc_get_handler_data(desc);
 +      struct irq_chip *chip = irq_desc_get_chip(desc);
 +      unsigned long val;
 +      int i;
 +
 +      chained_irq_enter(chip, desc);
 +      val =  pcie_read(port, XILINX_CPM_PCIE_REG_IDR);
 +      val &= pcie_read(port, XILINX_CPM_PCIE_REG_IMR);
 +      for_each_set_bit(i, &val, 32)
 +              generic_handle_irq(irq_find_mapping(port->cpm_domain, i));
 +      pcie_write(port, val, XILINX_CPM_PCIE_REG_IDR);
 +
 +      /*
 +       * XILINX_CPM_PCIE_MISC_IR_STATUS register is mapped to
 +       * CPM SLCR block.
 +       */
 +      val = readl_relaxed(port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
 +      if (val)
 +              writel_relaxed(val,
 +                             port->cpm_base + XILINX_CPM_PCIE_MISC_IR_STATUS);
 +
 +      chained_irq_exit(chip, desc);
 +}
 +
 +#define _IC(x, s)                              \
 +      [XILINX_CPM_PCIE_INTR_ ## x] = { __stringify(x), s }
 +
 +static const struct {
 +      const char      *sym;
 +      const char      *str;
 +} intr_cause[32] = {
 +      _IC(LINK_DOWN,          "Link Down"),
 +      _IC(HOT_RESET,          "Hot reset"),
 +      _IC(CFG_TIMEOUT,        "ECAM access timeout"),
 +      _IC(CORRECTABLE,        "Correctable error message"),
 +      _IC(NONFATAL,           "Non fatal error message"),
 +      _IC(FATAL,              "Fatal error message"),
 +      _IC(SLV_UNSUPP,         "Slave unsupported request"),
 +      _IC(SLV_UNEXP,          "Slave unexpected completion"),
 +      _IC(SLV_COMPL,          "Slave completion timeout"),
 +      _IC(SLV_ERRP,           "Slave Error Poison"),
 +      _IC(SLV_CMPABT,         "Slave Completer Abort"),
 +      _IC(SLV_ILLBUR,         "Slave Illegal Burst"),
 +      _IC(MST_DECERR,         "Master decode error"),
 +      _IC(MST_SLVERR,         "Master slave error"),
 +      _IC(CFG_PCIE_TIMEOUT,   "PCIe ECAM access timeout"),
 +      _IC(CFG_ERR_POISON,     "ECAM poisoned completion received"),
 +      _IC(PME_TO_ACK_RCVD,    "PME_TO_ACK message received"),
 +      _IC(PM_PME_RCVD,        "PM_PME message received"),
 +      _IC(SLV_PCIE_TIMEOUT,   "PCIe completion timeout received"),
 +};
 +
 +static irqreturn_t xilinx_cpm_pcie_intr_handler(int irq, void *dev_id)
 +{
 +      struct xilinx_cpm_pcie_port *port = dev_id;
 +      struct device *dev = port->dev;
 +      struct irq_data *d;
 +
 +      d = irq_domain_get_irq_data(port->cpm_domain, irq);
 +
 +      switch (d->hwirq) {
 +      case XILINX_CPM_PCIE_INTR_CORRECTABLE:
 +      case XILINX_CPM_PCIE_INTR_NONFATAL:
 +      case XILINX_CPM_PCIE_INTR_FATAL:
 +              cpm_pcie_clear_err_interrupts(port);
 +              fallthrough;
 +
 +      default:
 +              if (intr_cause[d->hwirq].str)
 +                      dev_warn(dev, "%s\n", intr_cause[d->hwirq].str);
 +              else
 +                      dev_warn(dev, "Unknown IRQ %ld\n", d->hwirq);
 +      }
 +
 +      return IRQ_HANDLED;
 +}
 +
 +static void xilinx_cpm_free_irq_domains(struct xilinx_cpm_pcie_port *port)
 +{
 +      if (port->intx_domain) {
 +              irq_domain_remove(port->intx_domain);
 +              port->intx_domain = NULL;
 +      }
 +
 +      if (port->cpm_domain) {
 +              irq_domain_remove(port->cpm_domain);
 +              port->cpm_domain = NULL;
 +      }
 +}
 +
 +/**
 + * xilinx_cpm_pcie_init_irq_domain - Initialize IRQ domain
 + * @port: PCIe port information
 + *
 + * Return: '0' on success and error value on failure
 + */
 +static int xilinx_cpm_pcie_init_irq_domain(struct xilinx_cpm_pcie_port *port)
 +{
 +      struct device *dev = port->dev;
 +      struct device_node *node = dev->of_node;
 +      struct device_node *pcie_intc_node;
 +
 +      /* Setup INTx */
 +      pcie_intc_node = of_get_next_child(node, NULL);
 +      if (!pcie_intc_node) {
 +              dev_err(dev, "No PCIe Intc node found\n");
 +              return -EINVAL;
 +      }
 +
 +      port->cpm_domain = irq_domain_add_linear(pcie_intc_node, 32,
 +                                               &event_domain_ops,
 +                                               port);
 +      if (!port->cpm_domain)
 +              goto out;
 +
 +      irq_domain_update_bus_token(port->cpm_domain, DOMAIN_BUS_NEXUS);
 +
 +      port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
 +                                                &intx_domain_ops,
 +                                                port);
 +      if (!port->intx_domain)
 +              goto out;
 +
 +      irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
 +
 +      of_node_put(pcie_intc_node);
 +      raw_spin_lock_init(&port->lock);
 +
 +      return 0;
 +out:
 +      xilinx_cpm_free_irq_domains(port);
 +      dev_err(dev, "Failed to allocate IRQ domains\n");
 +
 +      return -ENOMEM;
 +}
 +
 +static int xilinx_cpm_setup_irq(struct xilinx_cpm_pcie_port *port)
 +{
 +      struct device *dev = port->dev;
 +      struct platform_device *pdev = to_platform_device(dev);
 +      int i, irq;
 +
 +      port->irq = platform_get_irq(pdev, 0);
 +      if (port->irq < 0)
 +              return port->irq;
 +
 +      for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
 +              int err;
 +
 +              if (!intr_cause[i].str)
 +                      continue;
 +
 +              irq = irq_create_mapping(port->cpm_domain, i);
 +              if (!irq) {
 +                      dev_err(dev, "Failed to map interrupt\n");
 +                      return -ENXIO;
 +              }
 +
 +              err = devm_request_irq(dev, irq, xilinx_cpm_pcie_intr_handler,
 +                                     0, intr_cause[i].sym, port);
 +              if (err) {
 +                      dev_err(dev, "Failed to request IRQ %d\n", irq);
 +                      return err;
 +              }
 +      }
 +
 +      port->intx_irq = irq_create_mapping(port->cpm_domain,
 +                                          XILINX_CPM_PCIE_INTR_INTX);
 +      if (!port->intx_irq) {
 +              dev_err(dev, "Failed to map INTx interrupt\n");
 +              return -ENXIO;
 +      }
 +
 +      /* Plug the INTx chained handler */
 +      irq_set_chained_handler_and_data(port->intx_irq,
 +                                       xilinx_cpm_pcie_intx_flow, port);
 +
 +      /* Plug the main event chained handler */
 +      irq_set_chained_handler_and_data(port->irq,
 +                                       xilinx_cpm_pcie_event_flow, port);
 +
 +      return 0;
 +}
 +
 +/**
 + * xilinx_cpm_pcie_init_port - Initialize hardware
 + * @port: PCIe port information
 + */
 +static void xilinx_cpm_pcie_init_port(struct xilinx_cpm_pcie_port *port)
 +{
 +      if (cpm_pcie_link_up(port))
 +              dev_info(port->dev, "PCIe Link is UP\n");
 +      else
 +              dev_info(port->dev, "PCIe Link is DOWN\n");
 +
 +      /* Disable all interrupts */
 +      pcie_write(port, ~XILINX_CPM_PCIE_IDR_ALL_MASK,
 +                 XILINX_CPM_PCIE_REG_IMR);
 +
 +      /* Clear pending interrupts */
 +      pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_IDR) &
 +                 XILINX_CPM_PCIE_IMR_ALL_MASK,
 +                 XILINX_CPM_PCIE_REG_IDR);
 +
 +      /*
 +       * XILINX_CPM_PCIE_MISC_IR_ENABLE register is mapped to
 +       * CPM SLCR block.
 +       */
 +      writel(XILINX_CPM_PCIE_MISC_IR_LOCAL,
 +             port->cpm_base + XILINX_CPM_PCIE_MISC_IR_ENABLE);
 +      /* Enable the Bridge enable bit */
 +      pcie_write(port, pcie_read(port, XILINX_CPM_PCIE_REG_RPSC) |
 +                 XILINX_CPM_PCIE_REG_RPSC_BEN,
 +                 XILINX_CPM_PCIE_REG_RPSC);
 +}
 +
 +/**
 + * xilinx_cpm_pcie_parse_dt - Parse Device tree
 + * @port: PCIe port information
 + * @bus_range: Bus resource
 + *
 + * Return: '0' on success and error value on failure
 + */
 +static int xilinx_cpm_pcie_parse_dt(struct xilinx_cpm_pcie_port *port,
 +                                  struct resource *bus_range)
 +{
 +      struct device *dev = port->dev;
 +      struct platform_device *pdev = to_platform_device(dev);
 +      struct resource *res;
 +
 +      port->cpm_base = devm_platform_ioremap_resource_byname(pdev,
 +                                                             "cpm_slcr");
 +      if (IS_ERR(port->cpm_base))
 +              return PTR_ERR(port->cpm_base);
 +
 +      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
 +      if (!res)
 +              return -ENXIO;
 +
 +      port->cfg = pci_ecam_create(dev, res, bus_range,
 +                                  &pci_generic_ecam_ops);
 +      if (IS_ERR(port->cfg))
 +              return PTR_ERR(port->cfg);
 +
 +      port->reg_base = port->cfg->win;
 +
 +      return 0;
 +}
 +
 +static void xilinx_cpm_free_interrupts(struct xilinx_cpm_pcie_port *port)
 +{
 +      irq_set_chained_handler_and_data(port->intx_irq, NULL, NULL);
 +      irq_set_chained_handler_and_data(port->irq, NULL, NULL);
 +}
 +
 +/**
 + * xilinx_cpm_pcie_probe - Probe function
 + * @pdev: Platform device pointer
 + *
 + * Return: '0' on success and error value on failure
 + */
 +static int xilinx_cpm_pcie_probe(struct platform_device *pdev)
 +{
 +      struct xilinx_cpm_pcie_port *port;
 +      struct device *dev = &pdev->dev;
 +      struct pci_host_bridge *bridge;
-       err = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
-                                             &bridge->dma_ranges, &bus_range);
-       if (err) {
-               dev_err(dev, "Getting bridge resources failed\n");
-               return err;
-       }
++      struct resource_entry *bus;
 +      int err;
 +
 +      bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
 +      if (!bridge)
 +              return -ENODEV;
 +
 +      port = pci_host_bridge_priv(bridge);
 +
 +      port->dev = dev;
 +
-       err = xilinx_cpm_pcie_parse_dt(port, bus_range);
 +      err = xilinx_cpm_pcie_init_irq_domain(port);
 +      if (err)
 +              return err;
 +
++      bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS);
++      if (!bus)
++              return -ENODEV;
++
++      err = xilinx_cpm_pcie_parse_dt(port, bus->res);
 +      if (err) {
 +              dev_err(dev, "Parsing DT failed\n");
 +              goto err_parse_dt;
 +      }
 +
 +      xilinx_cpm_pcie_init_port(port);
 +
 +      err = xilinx_cpm_setup_irq(port);
 +      if (err) {
 +              dev_err(dev, "Failed to set up interrupts\n");
 +              goto err_setup_irq;
 +      }
 +
 +      bridge->dev.parent = dev;
 +      bridge->sysdata = port->cfg;
 +      bridge->busnr = port->cfg->busr.start;
 +      bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops;
 +      bridge->map_irq = of_irq_parse_and_map_pci;
 +      bridge->swizzle_irq = pci_common_swizzle;
 +
 +      err = pci_host_probe(bridge);
 +      if (err < 0)
 +              goto err_host_bridge;
 +
 +      return 0;
 +
 +err_host_bridge:
 +      xilinx_cpm_free_interrupts(port);
 +err_setup_irq:
 +      pci_ecam_free(port->cfg);
 +err_parse_dt:
 +      xilinx_cpm_free_irq_domains(port);
 +      return err;
 +}
 +
 +static const struct of_device_id xilinx_cpm_pcie_of_match[] = {
 +      { .compatible = "xlnx,versal-cpm-host-1.00", },
 +      {}
 +};
 +
 +static struct platform_driver xilinx_cpm_pcie_driver = {
 +      .driver = {
 +              .name = "xilinx-cpm-pcie",
 +              .of_match_table = xilinx_cpm_pcie_of_match,
 +              .suppress_bind_attrs = true,
 +      },
 +      .probe = xilinx_cpm_pcie_probe,
 +};
 +
 +builtin_platform_driver(xilinx_cpm_pcie_driver);
diff --combined drivers/pci/of.c
index 22727fc9558df8cb39deefb64210d86062a40544,8f478d92319625c9c37c98610b39310e4fa5312a..2ebc5e32e8a0c58ed5c2f9089c624678d09be398
@@@ -42,7 -42,7 +42,7 @@@ void pci_set_bus_of_node(struct pci_bu
        } else {
                node = of_node_get(bus->self->dev.of_node);
                if (node && of_property_read_bool(node, "external-facing"))
 -                      bus->self->untrusted = true;
 +                      bus->self->external_facing = true;
        }
  
        bus->dev.of_node = node;
@@@ -521,28 -521,26 +521,26 @@@ int of_irq_parse_and_map_pci(const stru
  EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
  #endif        /* CONFIG_OF_IRQ */
  
- int pci_parse_request_of_pci_ranges(struct device *dev,
-                                   struct list_head *resources,
-                                   struct list_head *ib_resources,
-                                   struct resource **bus_range)
+ static int pci_parse_request_of_pci_ranges(struct device *dev,
+                                          struct pci_host_bridge *bridge)
  {
        int err, res_valid = 0;
        resource_size_t iobase;
        struct resource_entry *win, *tmp;
  
-       INIT_LIST_HEAD(resources);
-       if (ib_resources)
-               INIT_LIST_HEAD(ib_resources);
-       err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, resources,
-                                                   ib_resources, &iobase);
+       INIT_LIST_HEAD(&bridge->windows);
+       INIT_LIST_HEAD(&bridge->dma_ranges);
+       err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &bridge->windows,
+                                                   &bridge->dma_ranges, &iobase);
        if (err)
                return err;
  
-       err = devm_request_pci_bus_resources(dev, resources);
+       err = devm_request_pci_bus_resources(dev, &bridge->windows);
        if (err)
-               goto out_release_res;
+               return err;
  
-       resource_list_for_each_entry_safe(win, tmp, resources) {
+       resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
                struct resource *res = win->res;
  
                switch (resource_type(res)) {
                case IORESOURCE_MEM:
                        res_valid |= !(res->flags & IORESOURCE_PREFETCH);
                        break;
-               case IORESOURCE_BUS:
-                       if (bus_range)
-                               *bus_range = res;
-                       break;
                }
        }
  
-       if (res_valid)
+       if (!res_valid)
+               dev_warn(dev, "non-prefetchable memory resource required\n");
+       return 0;
+ }
+ int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge)
+ {
+       if (!dev->of_node)
                return 0;
  
-       dev_err(dev, "non-prefetchable memory resource required\n");
-       err = -EINVAL;
+       bridge->swizzle_irq = pci_common_swizzle;
+       bridge->map_irq = of_irq_parse_and_map_pci;
  
-  out_release_res:
-       pci_free_resource_list(resources);
-       return err;
+       return pci_parse_request_of_pci_ranges(dev, bridge);
  }
- EXPORT_SYMBOL_GPL(pci_parse_request_of_pci_ranges);
  
  #endif /* CONFIG_PCI */
  
diff --combined drivers/pci/pci.h
index 42b95dba772a3c46aa3d7a27adc121d2d2772da2,56d67071e11618ee1679a3ea45f7fb08d659e567..fa12f7cbc1a095ea3e7e2cdca90ad511be4c3c00
@@@ -92,7 -92,6 +92,7 @@@ void pci_refresh_power_state(struct pci
  int pci_power_up(struct pci_dev *dev);
  void pci_disable_enabled_device(struct pci_dev *dev);
  int pci_finish_runtime_suspend(struct pci_dev *dev);
 +void pcie_clear_device_status(struct pci_dev *dev);
  void pcie_clear_root_pme_status(struct pci_dev *dev);
  bool pci_check_pme_status(struct pci_dev *dev);
  void pci_pme_wakeup_bus(struct pci_bus *bus);
@@@ -533,7 -532,7 +533,7 @@@ static inline resource_size_t pci_resou
        return resource_alignment(res);
  }
  
 -void pci_enable_acs(struct pci_dev *dev);
 +void pci_acs_init(struct pci_dev *dev);
  #ifdef CONFIG_PCI_QUIRKS
  int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
  int pci_dev_specific_enable_acs(struct pci_dev *dev);
@@@ -556,7 -555,7 +556,7 @@@ static inline int pci_dev_specific_disa
  
  /* PCI error reporting and recovery */
  pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
 -                      enum pci_channel_state state,
 +                      pci_channel_state_t state,
                        pci_ers_result_t (*reset_link)(struct pci_dev *pdev));
  
  bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
@@@ -628,6 -627,8 +628,8 @@@ void pci_release_of_node(struct pci_de
  void pci_set_bus_of_node(struct pci_bus *bus);
  void pci_release_bus_of_node(struct pci_bus *bus);
  
+ int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge);
  #else
  static inline int
  of_pci_parse_bus_range(struct device_node *node, struct resource *res)
@@@ -651,6 -652,12 +653,12 @@@ static inline void pci_set_of_node(stru
  static inline void pci_release_of_node(struct pci_dev *dev) { }
  static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
  static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
+ static inline int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge)
+ {
+       return 0;
+ }
  #endif /* CONFIG_OF */
  
  #ifdef CONFIG_PCIEAER
@@@ -659,6 -666,7 +667,6 @@@ void pci_aer_init(struct pci_dev *dev)
  void pci_aer_exit(struct pci_dev *dev);
  extern const struct attribute_group aer_stats_attr_group;
  void pci_aer_clear_fatal_status(struct pci_dev *dev);
 -void pci_aer_clear_device_status(struct pci_dev *dev);
  int pci_aer_clear_status(struct pci_dev *dev);
  int pci_aer_raw_clear_status(struct pci_dev *dev);
  #else
@@@ -666,6 -674,7 +674,6 @@@ static inline void pci_no_aer(void) { 
  static inline void pci_aer_init(struct pci_dev *d) { }
  static inline void pci_aer_exit(struct pci_dev *d) { }
  static inline void pci_aer_clear_fatal_status(struct pci_dev *dev) { }
 -static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
  static inline int pci_aer_clear_status(struct pci_dev *dev) { return -EINVAL; }
  static inline int pci_aer_raw_clear_status(struct pci_dev *dev) { return -EINVAL; }
  #endif
diff --combined drivers/pci/probe.c
index 494333df46af63fbfe20ff21ae92f8357955ac98,998f615cdb6d72a08b21e6bb55623c4e145762a1..03d37128a24f205602b7f6e9299dde8bb5fea81e
@@@ -628,11 -628,17 +628,17 @@@ struct pci_host_bridge *devm_pci_alloc_
        if (!bridge)
                return NULL;
  
+       bridge->dev.parent = dev;
        ret = devm_add_action_or_reset(dev, devm_pci_alloc_host_bridge_release,
                                       bridge);
        if (ret)
                return NULL;
  
+       ret = devm_of_pci_bridge_init(dev, bridge);
+       if (ret)
+               return NULL;
        return bridge;
  }
  EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
@@@ -1552,7 -1558,7 +1558,7 @@@ static void set_pcie_untrusted(struct p
         * untrusted as well.
         */
        parent = pci_upstream_bridge(dev);
 -      if (parent && parent->untrusted)
 +      if (parent && (parent->untrusted || parent->external_facing))
                dev->untrusted = true;
  }
  
@@@ -1802,6 -1808,9 +1808,6 @@@ int pci_setup_device(struct pci_dev *de
        dev->revision = class & 0xff;
        dev->class = class >> 8;                    /* upper 3 bytes */
  
 -      pci_info(dev, "[%04x:%04x] type %02x class %#08x\n",
 -                 dev->vendor, dev->device, dev->hdr_type, dev->class);
 -
        if (pci_early_dump)
                early_dump_pci_device(dev);
  
        /* Early fixups, before probing the BARs */
        pci_fixup_device(pci_fixup_early, dev);
  
 +      pci_info(dev, "[%04x:%04x] type %02x class %#08x\n",
 +               dev->vendor, dev->device, dev->hdr_type, dev->class);
 +
        /* Device class may be changed after fixup */
        class = dev->class >> 8;
  
@@@ -2390,7 -2396,7 +2396,7 @@@ static void pci_init_capabilities(struc
        pci_ats_init(dev);              /* Address Translation Services */
        pci_pri_init(dev);              /* Page Request Interface */
        pci_pasid_init(dev);            /* Process Address Space ID */
 -      pci_enable_acs(dev);            /* Enable ACS P2P upstream forwarding */
 +      pci_acs_init(dev);              /* Access Control Services */
        pci_ptm_init(dev);              /* Precision Time Measurement */
        pci_aer_init(dev);              /* Advanced Error Reporting */
        pci_dpc_init(dev);              /* Downstream Port Containment */
@@@ -3086,6 -3092,7 +3092,7 @@@ int pci_scan_root_bus_bridge(struct pci
  
        resource_list_for_each_entry(window, &bridge->windows)
                if (window->res->flags & IORESOURCE_BUS) {
+                       bridge->busnr = window->res->start;
                        found = true;
                        break;
                }
diff --combined include/linux/pci.h
index 6ebde53524dea20be9cb1e0493f08076d87cd663,2830799208fd01cdaaf8ec0a7f178cb5042c2129..ee49469bd2b591c77e682ef4599c241f324ef0a7
@@@ -179,7 -179,7 +179,7 @@@ static inline const char *pci_power_nam
   */
  typedef unsigned int __bitwise pci_channel_state_t;
  
 -enum pci_channel_state {
 +enum {
        /* I/O channel is in normal state */
        pci_channel_io_normal = (__force pci_channel_state_t) 1,
  
@@@ -432,12 -432,6 +432,12 @@@ struct pci_dev 
         * mappings to make sure they cannot access arbitrary memory.
         */
        unsigned int    untrusted:1;
 +      /*
 +       * Info from the platform, e.g., ACPI or device tree, may mark a
 +       * device as "external-facing".  An external-facing device is
 +       * itself internal but devices downstream from it are external.
 +       */
 +      unsigned int    external_facing:1;
        unsigned int    broken_intx_masking:1;  /* INTx masking can't be used */
        unsigned int    io_window_1k:1;         /* Intel bridge 1K I/O windows */
        unsigned int    irq_managed:1;
  #ifdef CONFIG_PCI_P2PDMA
        struct pci_p2pdma *p2pdma;
  #endif
 +      u16             acs_cap;        /* ACS Capability offset */
        phys_addr_t     rom;            /* Physical address if not from BAR */
        size_t          romlen;         /* Length if not from BAR */
        char            *driver_override; /* Driver name to force a match */
@@@ -792,7 -785,7 +792,7 @@@ enum pci_ers_result 
  struct pci_error_handlers {
        /* PCI bus error detected on this device */
        pci_ers_result_t (*error_detected)(struct pci_dev *dev,
 -                                         enum pci_channel_state error);
 +                                         pci_channel_state_t error);
  
        /* MMIO has been re-enabled, but not DMA */
        pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
@@@ -1060,6 -1053,13 +1060,6 @@@ void pci_sort_breadthfirst(void)
  
  /* Generic PCI functions exported to card drivers */
  
 -enum pci_lost_interrupt_reason {
 -      PCI_LOST_IRQ_NO_INFORMATION = 0,
 -      PCI_LOST_IRQ_DISABLE_MSI,
 -      PCI_LOST_IRQ_DISABLE_MSIX,
 -      PCI_LOST_IRQ_DISABLE_ACPI,
 -};
 -enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev);
  int pci_find_capability(struct pci_dev *dev, int cap);
  int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
  int pci_find_ext_capability(struct pci_dev *dev, int cap);
@@@ -2303,10 -2303,6 +2303,6 @@@ int pci_vpd_find_info_keyword(const u8 
  struct device_node;
  struct irq_domain;
  struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
- int pci_parse_request_of_pci_ranges(struct device *dev,
-                                   struct list_head *resources,
-                                   struct list_head *ib_resources,
-                                   struct resource **bus_range);
  
  /* Arch may override this (weak) */
  struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
  #else /* CONFIG_OF */
  static inline struct irq_domain *
  pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
- static inline int
- pci_parse_request_of_pci_ranges(struct device *dev,
-                               struct list_head *resources,
-                               struct list_head *ib_resources,
-                               struct resource **bus_range)
- {
-       return -EINVAL;
- }
  #endif  /* CONFIG_OF */
  
  static inline struct device_node *
This page took 0.192434 seconds and 4 git commands to generate.