aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Schulz <quentin.schulz@free-electrons.com>2017-06-08 04:07:42 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-07-02 19:43:39 -0400
commitc26ebe98a103479dae9284fe0a86a95af4a5cd46 (patch)
tree5af5b1c5aa475d9d3c7f35e86c210c4940bc5f18
parent769b461fc0c0451bacf75826d5830fc07c5a57e4 (diff)
PCI: imx6: Add regulator support
Some boards might require to control a regulator to power the PCIe port. Add support for an optional regulator defined in Device Tree linked in the PCIe controller under `vpcie-supply`. If present, the regulator will be disabled and then enabled as part of the PCIe host initialization process and will be disabled when shutting down. Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com> [bhelgaas: use dev_err() instead of pr_err() in imx6_pcie_assert_core_reset()] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rob Herring <robh@kernel.org> Acked-by: Richard Zhu <hongxing.zhu@nxp.com>
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt4
-rw-r--r--drivers/pci/dwc/pci-imx6.c37
2 files changed, 40 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
index e3d5680875b1..cf92d3ba5a26 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
@@ -33,6 +33,10 @@ Optional properties:
33- reset-gpio-active-high: If present then the reset sequence using the GPIO 33- reset-gpio-active-high: If present then the reset sequence using the GPIO
34 specified in the "reset-gpio" property is reversed (H=reset state, 34 specified in the "reset-gpio" property is reversed (H=reset state,
35 L=operation state). 35 L=operation state).
36- vpcie-supply: Should specify the regulator in charge of PCIe port power.
37 The regulator will be enabled when initializing the PCIe host and
38 disabled either as part of the init process or when shutting down the
39 host.
36 40
37Additional required properties for imx6sx-pcie: 41Additional required properties for imx6sx-pcie:
38- clock names: Must include the following additional entries: 42- clock names: Must include the following additional entries:
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c
index a98cba55c7f0..9717ef71e71b 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/dwc/pci-imx6.c
@@ -24,6 +24,7 @@
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/regmap.h> 26#include <linux/regmap.h>
27#include <linux/regulator/consumer.h>
27#include <linux/resource.h> 28#include <linux/resource.h>
28#include <linux/signal.h> 29#include <linux/signal.h>
29#include <linux/types.h> 30#include <linux/types.h>
@@ -59,6 +60,7 @@ struct imx6_pcie {
59 u32 tx_swing_full; 60 u32 tx_swing_full;
60 u32 tx_swing_low; 61 u32 tx_swing_low;
61 int link_gen; 62 int link_gen;
63 struct regulator *vpcie;
62}; 64};
63 65
64/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ 66/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
@@ -257,6 +259,8 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
257 259
258static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) 260static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
259{ 261{
262 struct device *dev = imx6_pcie->pci->dev;
263
260 switch (imx6_pcie->variant) { 264 switch (imx6_pcie->variant) {
261 case IMX7D: 265 case IMX7D:
262 reset_control_assert(imx6_pcie->pciephy_reset); 266 reset_control_assert(imx6_pcie->pciephy_reset);
@@ -283,6 +287,14 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
283 IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); 287 IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
284 break; 288 break;
285 } 289 }
290
291 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
292 int ret = regulator_disable(imx6_pcie->vpcie);
293
294 if (ret)
295 dev_err(dev, "failed to disable vpcie regulator: %d\n",
296 ret);
297 }
286} 298}
287 299
288static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) 300static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
@@ -349,10 +361,19 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
349 struct device *dev = pci->dev; 361 struct device *dev = pci->dev;
350 int ret; 362 int ret;
351 363
364 if (imx6_pcie->vpcie && !regulator_is_enabled(imx6_pcie->vpcie)) {
365 ret = regulator_enable(imx6_pcie->vpcie);
366 if (ret) {
367 dev_err(dev, "failed to enable vpcie regulator: %d\n",
368 ret);
369 return;
370 }
371 }
372
352 ret = clk_prepare_enable(imx6_pcie->pcie_phy); 373 ret = clk_prepare_enable(imx6_pcie->pcie_phy);
353 if (ret) { 374 if (ret) {
354 dev_err(dev, "unable to enable pcie_phy clock\n"); 375 dev_err(dev, "unable to enable pcie_phy clock\n");
355 return; 376 goto err_pcie_phy;
356 } 377 }
357 378
358 ret = clk_prepare_enable(imx6_pcie->pcie_bus); 379 ret = clk_prepare_enable(imx6_pcie->pcie_bus);
@@ -412,6 +433,13 @@ err_pcie:
412 clk_disable_unprepare(imx6_pcie->pcie_bus); 433 clk_disable_unprepare(imx6_pcie->pcie_bus);
413err_pcie_bus: 434err_pcie_bus:
414 clk_disable_unprepare(imx6_pcie->pcie_phy); 435 clk_disable_unprepare(imx6_pcie->pcie_phy);
436err_pcie_phy:
437 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
438 ret = regulator_disable(imx6_pcie->vpcie);
439 if (ret)
440 dev_err(dev, "failed to disable vpcie regulator: %d\n",
441 ret);
442 }
415} 443}
416 444
417static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) 445static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
@@ -775,6 +803,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
775 if (ret) 803 if (ret)
776 imx6_pcie->link_gen = 1; 804 imx6_pcie->link_gen = 1;
777 805
806 imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
807 if (IS_ERR(imx6_pcie->vpcie)) {
808 if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
809 return -EPROBE_DEFER;
810 imx6_pcie->vpcie = NULL;
811 }
812
778 platform_set_drvdata(pdev, imx6_pcie); 813 platform_set_drvdata(pdev, imx6_pcie);
779 814
780 ret = imx6_add_pcie_port(imx6_pcie, pdev); 815 ret = imx6_add_pcie_port(imx6_pcie, pdev);