Commit beaba77c authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/host-imx6' into next

* pci/host-imx6:
  PCI: imx6: Add regulator support
parents 85e4b30a c26ebe98
...@@ -33,6 +33,10 @@ Optional properties: ...@@ -33,6 +33,10 @@ Optional properties:
- reset-gpio-active-high: If present then the reset sequence using the GPIO - reset-gpio-active-high: If present then the reset sequence using the GPIO
specified in the "reset-gpio" property is reversed (H=reset state, specified in the "reset-gpio" property is reversed (H=reset state,
L=operation state). L=operation state).
- vpcie-supply: Should specify the regulator in charge of PCIe port power.
The regulator will be enabled when initializing the PCIe host and
disabled either as part of the init process or when shutting down the
host.
Additional required properties for imx6sx-pcie: Additional required properties for imx6sx-pcie:
- clock names: Must include the following additional entries: - clock names: Must include the following additional entries:
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -59,6 +60,7 @@ struct imx6_pcie { ...@@ -59,6 +60,7 @@ struct imx6_pcie {
u32 tx_swing_full; u32 tx_swing_full;
u32 tx_swing_low; u32 tx_swing_low;
int link_gen; int link_gen;
struct regulator *vpcie;
}; };
/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
...@@ -284,6 +286,8 @@ static int imx6q_pcie_abort_handler(unsigned long addr, ...@@ -284,6 +286,8 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
{ {
struct device *dev = imx6_pcie->pci->dev;
switch (imx6_pcie->variant) { switch (imx6_pcie->variant) {
case IMX7D: case IMX7D:
reset_control_assert(imx6_pcie->pciephy_reset); reset_control_assert(imx6_pcie->pciephy_reset);
...@@ -310,6 +314,14 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) ...@@ -310,6 +314,14 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
break; break;
} }
if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
int ret = regulator_disable(imx6_pcie->vpcie);
if (ret)
dev_err(dev, "failed to disable vpcie regulator: %d\n",
ret);
}
} }
static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
...@@ -376,10 +388,19 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) ...@@ -376,10 +388,19 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
struct device *dev = pci->dev; struct device *dev = pci->dev;
int ret; int ret;
if (imx6_pcie->vpcie && !regulator_is_enabled(imx6_pcie->vpcie)) {
ret = regulator_enable(imx6_pcie->vpcie);
if (ret) {
dev_err(dev, "failed to enable vpcie regulator: %d\n",
ret);
return;
}
}
ret = clk_prepare_enable(imx6_pcie->pcie_phy); ret = clk_prepare_enable(imx6_pcie->pcie_phy);
if (ret) { if (ret) {
dev_err(dev, "unable to enable pcie_phy clock\n"); dev_err(dev, "unable to enable pcie_phy clock\n");
return; goto err_pcie_phy;
} }
ret = clk_prepare_enable(imx6_pcie->pcie_bus); ret = clk_prepare_enable(imx6_pcie->pcie_bus);
...@@ -439,6 +460,13 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) ...@@ -439,6 +460,13 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
clk_disable_unprepare(imx6_pcie->pcie_bus); clk_disable_unprepare(imx6_pcie->pcie_bus);
err_pcie_bus: err_pcie_bus:
clk_disable_unprepare(imx6_pcie->pcie_phy); clk_disable_unprepare(imx6_pcie->pcie_phy);
err_pcie_phy:
if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
ret = regulator_disable(imx6_pcie->vpcie);
if (ret)
dev_err(dev, "failed to disable vpcie regulator: %d\n",
ret);
}
} }
static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
...@@ -802,6 +830,13 @@ static int imx6_pcie_probe(struct platform_device *pdev) ...@@ -802,6 +830,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
if (ret) if (ret)
imx6_pcie->link_gen = 1; imx6_pcie->link_gen = 1;
imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
if (IS_ERR(imx6_pcie->vpcie)) {
if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
return -EPROBE_DEFER;
imx6_pcie->vpcie = NULL;
}
platform_set_drvdata(pdev, imx6_pcie); platform_set_drvdata(pdev, imx6_pcie);
ret = imx6_add_pcie_port(imx6_pcie, pdev); ret = imx6_add_pcie_port(imx6_pcie, pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment