diff options
author | Jaehoon Chung <jh80.chung@samsung.com> | 2017-02-13 03:26:13 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-02-21 08:48:47 -0500 |
commit | e7cd7ef58e1fedb09b16720919869a81d7a2b867 (patch) | |
tree | 7228e210f079a1b19f89eeb77075ca864c9f5601 | |
parent | 34f80c7ddfffe262bf04fb03e198e64de4cec7fc (diff) |
PCI: exynos: Support the PHY generic framework
Switch the pci-exynos driver to generic PHY framework. At the same time
backward compatibility is preserved: Warning will be printed for old DTB.
Refer to the binding file:
- Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Jingoo Han <jingoohan1@gmail.com>
-rw-r--r-- | drivers/pci/host/pci-exynos.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index ab9e67465b9b..c86961feaa6f 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/of_gpio.h> | 21 | #include <linux/of_gpio.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/phy/phy.h> | ||
24 | #include <linux/resource.h> | 25 | #include <linux/resource.h> |
25 | #include <linux/signal.h> | 26 | #include <linux/signal.h> |
26 | #include <linux/types.h> | 27 | #include <linux/types.h> |
@@ -110,6 +111,10 @@ struct exynos_pcie { | |||
110 | struct exynos_pcie_clk_res *clk_res; | 111 | struct exynos_pcie_clk_res *clk_res; |
111 | const struct exynos_pcie_ops *ops; | 112 | const struct exynos_pcie_ops *ops; |
112 | int reset_gpio; | 113 | int reset_gpio; |
114 | |||
115 | /* For Generic PHY Framework */ | ||
116 | bool using_phy; | ||
117 | struct phy *phy; | ||
113 | }; | 118 | }; |
114 | 119 | ||
115 | struct exynos_pcie_ops { | 120 | struct exynos_pcie_ops { |
@@ -126,6 +131,10 @@ static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev, | |||
126 | struct resource *res; | 131 | struct resource *res; |
127 | struct device *dev = ep->pp.dev; | 132 | struct device *dev = ep->pp.dev; |
128 | 133 | ||
134 | /* If using the PHY framework, doesn't need to get other resource */ | ||
135 | if (ep->using_phy) | ||
136 | return 0; | ||
137 | |||
129 | ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); | 138 | ep->mem_res = devm_kzalloc(dev, sizeof(*ep->mem_res), GFP_KERNEL); |
130 | if (!ep->mem_res) | 139 | if (!ep->mem_res) |
131 | return -ENOMEM; | 140 | return -ENOMEM; |
@@ -396,10 +405,28 @@ static int exynos_pcie_establish_link(struct exynos_pcie *ep) | |||
396 | } | 405 | } |
397 | 406 | ||
398 | exynos_pcie_assert_core_reset(ep); | 407 | exynos_pcie_assert_core_reset(ep); |
399 | exynos_pcie_assert_phy_reset(ep); | 408 | |
400 | exynos_pcie_deassert_phy_reset(ep); | 409 | if (ep->using_phy) { |
401 | exynos_pcie_power_on_phy(ep); | 410 | phy_reset(ep->phy); |
402 | exynos_pcie_init_phy(ep); | 411 | |
412 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, | ||
413 | PCIE_PWR_RESET); | ||
414 | |||
415 | phy_power_on(ep->phy); | ||
416 | phy_init(ep->phy); | ||
417 | } else { | ||
418 | exynos_pcie_assert_phy_reset(ep); | ||
419 | exynos_pcie_deassert_phy_reset(ep); | ||
420 | exynos_pcie_power_on_phy(ep); | ||
421 | exynos_pcie_init_phy(ep); | ||
422 | |||
423 | /* pulse for common reset */ | ||
424 | exynos_pcie_writel(ep->mem_res->block_base, 1, | ||
425 | PCIE_PHY_COMMON_RESET); | ||
426 | udelay(500); | ||
427 | exynos_pcie_writel(ep->mem_res->block_base, 0, | ||
428 | PCIE_PHY_COMMON_RESET); | ||
429 | } | ||
403 | 430 | ||
404 | /* pulse for common reset */ | 431 | /* pulse for common reset */ |
405 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_COMMON_RESET); | 432 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_COMMON_RESET); |
@@ -418,6 +445,11 @@ static int exynos_pcie_establish_link(struct exynos_pcie *ep) | |||
418 | if (!dw_pcie_wait_for_link(pp)) | 445 | if (!dw_pcie_wait_for_link(pp)) |
419 | return 0; | 446 | return 0; |
420 | 447 | ||
448 | if (ep->using_phy) { | ||
449 | phy_power_off(ep->phy); | ||
450 | return -ETIMEDOUT; | ||
451 | } | ||
452 | |||
421 | while (exynos_pcie_readl(ep->mem_res->phy_base, | 453 | while (exynos_pcie_readl(ep->mem_res->phy_base, |
422 | PCIE_PHY_PLL_LOCKED) == 0) { | 454 | PCIE_PHY_PLL_LOCKED) == 0) { |
423 | val = exynos_pcie_readl(ep->mem_res->block_base, | 455 | val = exynos_pcie_readl(ep->mem_res->block_base, |
@@ -624,6 +656,17 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
624 | 656 | ||
625 | ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | 657 | ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); |
626 | 658 | ||
659 | /* Assume that controller doesn't use the PHY framework */ | ||
660 | ep->using_phy = false; | ||
661 | |||
662 | ep->phy = devm_of_phy_get(dev, np, NULL); | ||
663 | if (IS_ERR(ep->phy)) { | ||
664 | if (PTR_ERR(ep->phy) == -EPROBE_DEFER) | ||
665 | return PTR_ERR(ep->phy); | ||
666 | dev_warn(dev, "Use the 'phy' property. Current DT of pci-exynos was deprecated!!\n"); | ||
667 | } else | ||
668 | ep->using_phy = true; | ||
669 | |||
627 | if (ep->ops && ep->ops->get_mem_resources) { | 670 | if (ep->ops && ep->ops->get_mem_resources) { |
628 | ret = ep->ops->get_mem_resources(pdev, ep); | 671 | ret = ep->ops->get_mem_resources(pdev, ep); |
629 | if (ret) | 672 | if (ret) |
@@ -647,6 +690,9 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
647 | return 0; | 690 | return 0; |
648 | 691 | ||
649 | fail_probe: | 692 | fail_probe: |
693 | if (ep->using_phy) | ||
694 | phy_exit(ep->phy); | ||
695 | |||
650 | if (ep->ops && ep->ops->deinit_clk_resources) | 696 | if (ep->ops && ep->ops->deinit_clk_resources) |
651 | ep->ops->deinit_clk_resources(ep); | 697 | ep->ops->deinit_clk_resources(ep); |
652 | return ret; | 698 | return ret; |