]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'pci/host-exynos' into next
authorBjorn Helgaas <bhelgaas@google.com>
Tue, 21 Feb 2017 21:13:30 +0000 (15:13 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 21 Feb 2017 21:13:30 +0000 (15:13 -0600)
* pci/host-exynos:
  PCI: exynos: Support the PHY generic framework
  Documentation: binding: Modify the exynos5440 PCIe binding
  phy: phy-exynos-pcie: Add support for Exynos PCIe PHY
  Documentation: samsung-phy: Add exynos-pcie-phy binding
  PCI: exynos: Refactor to make it easier to support other SoCs
  PCI: exynos: Remove duplicated code
  PCI: exynos: Use the bitops BIT() macro to build bitmasks
  PCI: exynos: Remove unnecessary local variables
  PCI: exynos: Replace the *_blk/*_phy/*_elb accessors
  PCI: exynos: Rename all pointer names from "exynos_pcie" to "ep"

Conflicts:
drivers/pci/dwc/pci-exynos.c

1  2 
drivers/pci/dwc/pci-exynos.c

index 0295ec96f3d016218bb5003615033ae5ecfb41f2,c86961feaa6f46a29903b6c6fae1a462b91b6e33..001c91a945aa64401d9ae3ec428aae4d1492cd26
  
  #include "pcie-designware.h"
  
 -#define to_exynos_pcie(x)     container_of(x, struct exynos_pcie, pp)
 +#define to_exynos_pcie(x)     dev_get_drvdata((x)->dev)
  
- struct exynos_pcie {
-       struct dw_pcie          *pci;
-       void __iomem            *elbi_base;     /* DT 0th resource */
-       void __iomem            *phy_base;      /* DT 1st resource */
-       void __iomem            *block_base;    /* DT 2nd resource */
-       int                     reset_gpio;
-       struct clk              *clk;
-       struct clk              *bus_clk;
- };
  /* PCIe ELBI registers */
  #define PCIE_IRQ_PULSE                        0x000
- #define IRQ_INTA_ASSERT                       (0x1 << 0)
- #define IRQ_INTB_ASSERT                       (0x1 << 2)
- #define IRQ_INTC_ASSERT                       (0x1 << 4)
- #define IRQ_INTD_ASSERT                       (0x1 << 6)
+ #define IRQ_INTA_ASSERT                       BIT(0)
+ #define IRQ_INTB_ASSERT                       BIT(2)
+ #define IRQ_INTC_ASSERT                       BIT(4)
+ #define IRQ_INTD_ASSERT                       BIT(6)
  #define PCIE_IRQ_LEVEL                        0x004
  #define PCIE_IRQ_SPECIAL              0x008
  #define PCIE_IRQ_EN_PULSE             0x00c
  #define PCIE_PHY_TRSV3_EMP_LVL                0x2c4
  #define PCIE_PHY_TRSV3_RXCDR          0x2ec
  #define PCIE_PHY_TRSV3_POWER          0x304
- #define PCIE_PHY_TRSV3_PD_TSV         (0x1 << 7)
+ #define PCIE_PHY_TRSV3_PD_TSV         BIT(7)
  #define PCIE_PHY_TRSV3_LVCC           0x31c
  
- static void exynos_elb_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
+ struct exynos_pcie_mem_res {
+       void __iomem *elbi_base;   /* DT 0th resource: PCIe CTRL */
+       void __iomem *phy_base;    /* DT 1st resource: PHY CTRL */
+       void __iomem *block_base;  /* DT 2nd resource: PHY ADDITIONAL CTRL */
+ };
+ struct exynos_pcie_clk_res {
+       struct clk *clk;
+       struct clk *bus_clk;
+ };
+ struct exynos_pcie {
 -      struct pcie_port                pp;
++      struct dw_pcie                  *pci;
+       struct exynos_pcie_mem_res      *mem_res;
+       struct exynos_pcie_clk_res      *clk_res;
+       const struct exynos_pcie_ops    *ops;
+       int                             reset_gpio;
+       /* For Generic PHY Framework */
+       bool                            using_phy;
+       struct phy                      *phy;
+ };
+ struct exynos_pcie_ops {
+       int (*get_mem_resources)(struct platform_device *pdev,
+                       struct exynos_pcie *ep);
+       int (*get_clk_resources)(struct exynos_pcie *ep);
+       int (*init_clk_resources)(struct exynos_pcie *ep);
+       void (*deinit_clk_resources)(struct exynos_pcie *ep);
+ };
+ static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev,
+                                            struct exynos_pcie *ep)
  {
-       writel(val, exynos_pcie->elbi_base + reg);
++      struct dw_pcie *pci = ep->pci;
++      struct device *dev = pci->dev;
+       struct resource *res;
 -      struct device *dev = ep->pp.dev;
+       /* If using the PHY framework, doesn't need to get other resource */
+       if (ep->using_phy)
+               return 0;
+       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);
+       if (IS_ERR(ep->mem_res->elbi_base))
+               return PTR_ERR(ep->mem_res->elbi_base);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       ep->mem_res->phy_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ep->mem_res->phy_base))
+               return PTR_ERR(ep->mem_res->phy_base);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       ep->mem_res->block_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ep->mem_res->block_base))
+               return PTR_ERR(ep->mem_res->block_base);
+       return 0;
  }
  
- static u32 exynos_elb_readl(struct exynos_pcie *exynos_pcie, u32 reg)
+ static int exynos5440_pcie_get_clk_resources(struct exynos_pcie *ep)
  {
-       return readl(exynos_pcie->elbi_base + reg);
 -      struct device *dev = ep->pp.dev;
++      struct dw_pcie *pci = ep->pci;
++      struct device *dev = pci->dev;
+       ep->clk_res = devm_kzalloc(dev, sizeof(*ep->clk_res), GFP_KERNEL);
+       if (!ep->clk_res)
+               return -ENOMEM;
+       ep->clk_res->clk = devm_clk_get(dev, "pcie");
+       if (IS_ERR(ep->clk_res->clk)) {
+               dev_err(dev, "Failed to get pcie rc clock\n");
+               return PTR_ERR(ep->clk_res->clk);
+       }
+       ep->clk_res->bus_clk = devm_clk_get(dev, "pcie_bus");
+       if (IS_ERR(ep->clk_res->bus_clk)) {
+               dev_err(dev, "Failed to get pcie bus clock\n");
+               return PTR_ERR(ep->clk_res->bus_clk);
+       }
+       return 0;
  }
  
- static void exynos_phy_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
+ static int exynos5440_pcie_init_clk_resources(struct exynos_pcie *ep)
  {
-       writel(val, exynos_pcie->phy_base + reg);
 -      struct device *dev = ep->pp.dev;
++      struct dw_pcie *pci = ep->pci;
++      struct device *dev = pci->dev;
+       int ret;
+       ret = clk_prepare_enable(ep->clk_res->clk);
+       if (ret) {
+               dev_err(dev, "cannot enable pcie rc clock");
+               return ret;
+       }
+       ret = clk_prepare_enable(ep->clk_res->bus_clk);
+       if (ret) {
+               dev_err(dev, "cannot enable pcie bus clock");
+               goto err_bus_clk;
+       }
+       return 0;
+ err_bus_clk:
+       clk_disable_unprepare(ep->clk_res->clk);
+       return ret;
  }
  
- static u32 exynos_phy_readl(struct exynos_pcie *exynos_pcie, u32 reg)
+ static void exynos5440_pcie_deinit_clk_resources(struct exynos_pcie *ep)
  {
-       return readl(exynos_pcie->phy_base + reg);
+       clk_disable_unprepare(ep->clk_res->bus_clk);
+       clk_disable_unprepare(ep->clk_res->clk);
  }
  
- static void exynos_blk_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
+ static const struct exynos_pcie_ops exynos5440_pcie_ops = {
+       .get_mem_resources      = exynos5440_pcie_get_mem_resources,
+       .get_clk_resources      = exynos5440_pcie_get_clk_resources,
+       .init_clk_resources     = exynos5440_pcie_init_clk_resources,
+       .deinit_clk_resources   = exynos5440_pcie_deinit_clk_resources,
+ };
+ static void exynos_pcie_writel(void __iomem *base, u32 val, u32 reg)
  {
-       writel(val, exynos_pcie->block_base + reg);
+       writel(val, base + reg);
  }
  
- static u32 exynos_blk_readl(struct exynos_pcie *exynos_pcie, u32 reg)
+ static u32 exynos_pcie_readl(void __iomem *base, u32 reg)
  {
-       return readl(exynos_pcie->block_base + reg);
+       return readl(base + reg);
  }
  
- static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *exynos_pcie,
-                                           bool on)
+ static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool on)
  {
        u32 val;
  
@@@ -236,83 -324,82 +327,83 @@@ static void exynos_pcie_power_off_phy(s
  {
        u32 val;
  
-       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
+       val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER);
        val |= PCIE_PHY_COMMON_PD_CMN;
-       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
+       exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER);
  
-       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
+       val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER);
        val |= PCIE_PHY_TRSV0_PD_TSV;
-       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
+       exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER);
  
-       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
+       val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER);
        val |= PCIE_PHY_TRSV1_PD_TSV;
-       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
+       exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER);
  
-       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
+       val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER);
        val |= PCIE_PHY_TRSV2_PD_TSV;
-       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
+       exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER);
  
-       val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
+       val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER);
        val |= PCIE_PHY_TRSV3_PD_TSV;
-       exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
+       exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER);
  }
  
- static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie)
+ static void exynos_pcie_init_phy(struct exynos_pcie *ep)
  {
        /* DCC feedback control off */
-       exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK);
  
        /* set TX/RX impedance */
-       exynos_phy_writel(exynos_pcie, 0xd5, PCIE_PHY_IMPEDANCE);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE);
  
        /* set 50Mhz PHY clock */
-       exynos_phy_writel(exynos_pcie, 0x14, PCIE_PHY_PLL_DIV_0);
-       exynos_phy_writel(exynos_pcie, 0x12, PCIE_PHY_PLL_DIV_1);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1);
  
        /* set TX Differential output for lane 0 */
-       exynos_phy_writel(exynos_pcie, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
  
        /* set TX Pre-emphasis Level Control for lane 0 to minimum */
-       exynos_phy_writel(exynos_pcie, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
  
        /* set RX clock and data recovery bandwidth */
-       exynos_phy_writel(exynos_pcie, 0xe7, PCIE_PHY_PLL_BIAS);
-       exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV0_RXCDR);
-       exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV1_RXCDR);
-       exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV2_RXCDR);
-       exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV3_RXCDR);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR);
  
        /* change TX Pre-emphasis Level Control for lanes */
-       exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
-       exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
-       exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
-       exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
  
        /* set LVCC */
-       exynos_phy_writel(exynos_pcie, 0x20, PCIE_PHY_TRSV0_LVCC);
-       exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV1_LVCC);
-       exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV2_LVCC);
-       exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC);
+       exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC);
  }
  
- static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
+ static void exynos_pcie_assert_reset(struct exynos_pcie *ep)
  {
-       struct dw_pcie *pci = exynos_pcie->pci;
 -      struct pcie_port *pp = &ep->pp;
 -      struct device *dev = pp->dev;
++      struct dw_pcie *pci = ep->pci;
 +      struct device *dev = pci->dev;
  
-       if (exynos_pcie->reset_gpio >= 0)
-               devm_gpio_request_one(dev, exynos_pcie->reset_gpio,
+       if (ep->reset_gpio >= 0)
+               devm_gpio_request_one(dev, ep->reset_gpio,
                                GPIOF_OUT_INIT_HIGH, "RESET");
  }
  
- static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
+ static int exynos_pcie_establish_link(struct exynos_pcie *ep)
  {
-       struct dw_pcie *pci = exynos_pcie->pci;
 -      struct pcie_port *pp = &ep->pp;
 -      struct device *dev = pp->dev;
++      struct dw_pcie *pci = ep->pci;
 +      struct pcie_port *pp = &pci->pp;
 +      struct device *dev = pci->dev;
        u32 val;
  
 -      if (dw_pcie_link_up(pp)) {
 +      if (dw_pcie_link_up(pci)) {
                dev_err(dev, "Link already up\n");
                return 0;
        }
                          PCIE_APP_LTSSM_ENABLE);
  
        /* check if the link is up or not */
 -      if (!dw_pcie_wait_for_link(pp))
 +      if (!dw_pcie_wait_for_link(pci))
                return 0;
  
-       while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) {
-               val = exynos_blk_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED);
+       if (ep->using_phy) {
+               phy_power_off(ep->phy);
+               return -ETIMEDOUT;
+       }
+       while (exynos_pcie_readl(ep->mem_res->phy_base,
+                               PCIE_PHY_PLL_LOCKED) == 0) {
+               val = exynos_pcie_readl(ep->mem_res->block_base,
+                               PCIE_PHY_PLL_LOCKED);
                dev_info(dev, "PLL Locked: 0x%x\n", val);
        }
-       exynos_pcie_power_off_phy(exynos_pcie);
+       exynos_pcie_power_off_phy(ep);
        return -ETIMEDOUT;
  }
  
@@@ -376,87 -488,83 +492,87 @@@ static irqreturn_t exynos_pcie_irq_hand
  
  static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
  {
-       struct exynos_pcie *exynos_pcie = arg;
-       struct dw_pcie *pci = exynos_pcie->pci;
+       struct exynos_pcie *ep = arg;
 -      struct pcie_port *pp = &ep->pp;
++      struct dw_pcie *pci = ep->pci;
 +      struct pcie_port *pp = &pci->pp;
  
        return dw_handle_msi_irq(pp);
  }
  
- static void exynos_pcie_msi_init(struct exynos_pcie *exynos_pcie)
+ static void exynos_pcie_msi_init(struct exynos_pcie *ep)
  {
-       struct dw_pcie *pci = exynos_pcie->pci;
 -      struct pcie_port *pp = &ep->pp;
++      struct dw_pcie *pci = ep->pci;
 +      struct pcie_port *pp = &pci->pp;
        u32 val;
  
        dw_pcie_msi_init(pp);
  
        /* enable MSI interrupt */
-       val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL);
+       val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_IRQ_EN_LEVEL);
        val |= IRQ_MSI_ENABLE;
-       exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL);
+       exynos_pcie_writel(ep->mem_res->elbi_base, val, PCIE_IRQ_EN_LEVEL);
  }
  
- static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
+ static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep)
  {
-       exynos_pcie_enable_irq_pulse(exynos_pcie);
+       exynos_pcie_enable_irq_pulse(ep);
  
        if (IS_ENABLED(CONFIG_PCI_MSI))
-               exynos_pcie_msi_init(exynos_pcie);
+               exynos_pcie_msi_init(ep);
  }
  
 -static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
 +static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
  {
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
        u32 val;
  
-       exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
+       exynos_pcie_sideband_dbi_r_mode(ep, true);
 -      val = readl(pp->dbi_base + reg);
 +      val = readl(pci->dbi_base + reg);
-       exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
+       exynos_pcie_sideband_dbi_r_mode(ep, false);
        return val;
  }
  
 -static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
 +static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
  {
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
  
-       exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
+       exynos_pcie_sideband_dbi_w_mode(ep, true);
 -      writel(val, pp->dbi_base + reg);
 +      writel(val, pci->dbi_base + reg);
-       exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
+       exynos_pcie_sideband_dbi_w_mode(ep, false);
  }
  
  static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
                                u32 *val)
  {
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
 +      struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
        int ret;
  
-       exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
+       exynos_pcie_sideband_dbi_r_mode(ep, true);
 -      ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
 +      ret = dw_pcie_read(pci->dbi_base + where, size, val);
-       exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
+       exynos_pcie_sideband_dbi_r_mode(ep, false);
        return ret;
  }
  
  static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
                                u32 val)
  {
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
 +      struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
        int ret;
  
-       exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
+       exynos_pcie_sideband_dbi_w_mode(ep, true);
 -      ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
 +      ret = dw_pcie_write(pci->dbi_base + where, size, val);
-       exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
+       exynos_pcie_sideband_dbi_w_mode(ep, false);
        return ret;
  }
  
 -static int exynos_pcie_link_up(struct pcie_port *pp)
 +static int exynos_pcie_link_up(struct dw_pcie *pci)
  {
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
        u32 val;
  
-       val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
+       val = exynos_pcie_readl(ep->mem_res->elbi_base, PCIE_ELBI_RDLH_LINKUP);
        if (val == PCIE_ELBI_LTSSM_ENABLE)
                return 1;
  
  
  static void exynos_pcie_host_init(struct pcie_port *pp)
  {
 -      struct exynos_pcie *ep = to_exynos_pcie(pp);
 +      struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
-       struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
++      struct exynos_pcie *ep = to_exynos_pcie(pci);
  
-       exynos_pcie_establish_link(exynos_pcie);
-       exynos_pcie_enable_interrupts(exynos_pcie);
+       exynos_pcie_establish_link(ep);
+       exynos_pcie_enable_interrupts(ep);
  }
  
 -static struct pcie_host_ops exynos_pcie_host_ops = {
 -      .readl_rc = exynos_pcie_readl_rc,
 -      .writel_rc = exynos_pcie_writel_rc,
 +static struct dw_pcie_host_ops exynos_pcie_host_ops = {
        .rd_own_conf = exynos_pcie_rd_own_conf,
        .wr_own_conf = exynos_pcie_wr_own_conf,
 -      .link_up = exynos_pcie_link_up,
        .host_init = exynos_pcie_host_init,
  };
  
- static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie,
+ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
                                       struct platform_device *pdev)
  {
-       struct dw_pcie *pci = exynos_pcie->pci;
 -      struct pcie_port *pp = &ep->pp;
 -      struct device *dev = pp->dev;
++      struct dw_pcie *pci = ep->pci;
 +      struct pcie_port *pp = &pci->pp;
 +      struct device *dev = &pdev->dev;
        int ret;
  
        pp->irq = platform_get_irq(pdev, 1);
@@@ -536,79 -639,62 +652,67 @@@ static const struct dw_pcie_ops dw_pcie
  static int __init exynos_pcie_probe(struct platform_device *pdev)
  {
        struct device *dev = &pdev->dev;
-       struct exynos_pcie *exynos_pcie;
 +      struct dw_pcie *pci;
 -      struct pcie_port *pp;
+       struct exynos_pcie *ep;
        struct device_node *np = dev->of_node;
-       struct resource *elbi_base;
-       struct resource *phy_base;
-       struct resource *block_base;
        int ret;
  
-       exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
-       if (!exynos_pcie)
+       ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
+       if (!ep)
                return -ENOMEM;
  
 -      pp = &ep->pp;
 -      pp->dev = dev;
 +      pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
 +      if (!pci)
 +              return -ENOMEM;
 +
 +      pci->dev = dev;
 +      pci->ops = &dw_pcie_ops;
  
-       exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+       ep->ops = (const struct exynos_pcie_ops *)
+               of_device_get_match_data(dev);
  
-       exynos_pcie->clk = devm_clk_get(dev, "pcie");
-       if (IS_ERR(exynos_pcie->clk)) {
-               dev_err(dev, "Failed to get pcie rc clock\n");
-               return PTR_ERR(exynos_pcie->clk);
-       }
-       ret = clk_prepare_enable(exynos_pcie->clk);
-       if (ret)
-               return ret;
+       ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
  
-       exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
-       if (IS_ERR(exynos_pcie->bus_clk)) {
-               dev_err(dev, "Failed to get pcie bus clock\n");
-               ret = PTR_ERR(exynos_pcie->bus_clk);
-               goto fail_clk;
-       }
-       ret = clk_prepare_enable(exynos_pcie->bus_clk);
-       if (ret)
-               goto fail_clk;
-       elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       exynos_pcie->elbi_base = devm_ioremap_resource(dev, elbi_base);
-       if (IS_ERR(exynos_pcie->elbi_base)) {
-               ret = PTR_ERR(exynos_pcie->elbi_base);
-               goto fail_bus_clk;
-       }
+       /* Assume that controller doesn't use the PHY framework */
+       ep->using_phy = false;
  
-       phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       exynos_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
-       if (IS_ERR(exynos_pcie->phy_base)) {
-               ret = PTR_ERR(exynos_pcie->phy_base);
-               goto fail_bus_clk;
+       ep->phy = devm_of_phy_get(dev, np, NULL);
+       if (IS_ERR(ep->phy)) {
+               if (PTR_ERR(ep->phy) == -EPROBE_DEFER)
+                       return PTR_ERR(ep->phy);
+               dev_warn(dev, "Use the 'phy' property. Current DT of pci-exynos was deprecated!!\n");
+       } else
+               ep->using_phy = true;
+       if (ep->ops && ep->ops->get_mem_resources) {
+               ret = ep->ops->get_mem_resources(pdev, ep);
+               if (ret)
+                       return ret;
        }
  
-       block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       exynos_pcie->block_base = devm_ioremap_resource(dev, block_base);
-       if (IS_ERR(exynos_pcie->block_base)) {
-               ret = PTR_ERR(exynos_pcie->block_base);
-               goto fail_bus_clk;
+       if (ep->ops && ep->ops->get_clk_resources) {
+               ret = ep->ops->get_clk_resources(ep);
+               if (ret)
+                       return ret;
+               ret = ep->ops->init_clk_resources(ep);
+               if (ret)
+                       return ret;
        }
  
-       platform_set_drvdata(pdev, exynos_pcie);
++      platform_set_drvdata(pdev, ep);
 +
-       ret = exynos_add_pcie_port(exynos_pcie, pdev);
+       ret = exynos_add_pcie_port(ep, pdev);
        if (ret < 0)
-               goto fail_bus_clk;
+               goto fail_probe;
  
 -      platform_set_drvdata(pdev, ep);
        return 0;
  
- fail_bus_clk:
-       clk_disable_unprepare(exynos_pcie->bus_clk);
- fail_clk:
-       clk_disable_unprepare(exynos_pcie->clk);
+ fail_probe:
+       if (ep->using_phy)
+               phy_exit(ep->phy);
+       if (ep->ops && ep->ops->deinit_clk_resources)
+               ep->ops->deinit_clk_resources(ep);
        return ret;
  }