[PATCH] pci: pcie-rcar: add regulators support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Andrey Gusakov <andrey.gusakov@xxxxxxxxxxxxxxxxxx>

Add PCIe regulators for KingFisher board.

Signed-off-by: Meng Li <Meng.Li@xxxxxxxxxxxxx>
---
 arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 47 +++++++++++++++++
 drivers/pci/controller/pcie-rcar-host.c  | 64 ++++++++++++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
index 8986a7e6e099..82e463c32a37 100644
--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
@@ -50,6 +50,25 @@
 		startup-delay-us = <70000>;
 		enable-active-high;
 	};
+
+	mpcie_3v3: regulator-mpcie_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "mPCIe 3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio_exp_77 14 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	mpcie_1v8: regulator-mpcie_1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "mPCIe 1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio_exp_77 15 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <200000>;
+		enable-active-high;
+	};
 };
 
 &can0 {
@@ -241,6 +260,31 @@
 		interrupt-controller;
 		interrupt-parent = <&gpio5>;
 		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+
+		mpcie_wake {
+			gpio-hog;
+			gpios = <0 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "mPCIe WAKE#";
+		};
+		mpcie_wdisable {
+			gpio-hog;
+			gpios = <1 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "mPCIe W_DISABLE";
+		};
+		mpcie_clreq {
+			gpio-hog;
+			gpios = <2 GPIO_ACTIVE_HIGH>;
+			input;
+			line-name = "mPCIe CLKREQ#";
+		};
+		mpcie_ovc {
+			gpio-hog;
+			gpios = <3 GPIO_ACTIVE_HIGH>;
+			input;
+			line-name = "mPCIe OVC";
+		};
 	};
 };
 
@@ -259,6 +303,9 @@
 
 &pciec1 {
 	status = "okay";
+
+	pcie3v3-supply = <&mpcie_3v3>;
+	pcie1v8-supply = <&mpcie_1v8>;
 };
 
 &pfc {
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
index cdc0963f154e..bf1e4007876e 100644
--- a/drivers/pci/controller/pcie-rcar-host.c
+++ b/drivers/pci/controller/pcie-rcar-host.c
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
+#include <linux/regulator/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -54,6 +55,8 @@ struct rcar_pcie_host {
 	struct rcar_pcie	pcie;
 	struct phy		*phy;
 	struct clk		*bus_clk;
+	struct regulator	*pcie3v3; /* 3.3V power supply */
+	struct regulator	*pcie1v8; /* 1.8V power supply */
 	struct			rcar_msi msi;
 	int			(*phy_init_fn)(struct rcar_pcie_host *host);
 };
@@ -893,6 +896,36 @@ static const struct of_device_id rcar_pcie_of_match[] = {
 	{},
 };
 
+static int rcar_pcie_set_vpcie(struct rcar_pcie_host *host)
+{
+	struct device *dev = host->pcie.dev;
+	int err;
+
+	if (!IS_ERR(host->pcie3v3)) {
+		err = regulator_enable(host->pcie3v3);
+		if (err) {
+			dev_err(dev, "fail to enable vpcie3v3 regulator\n");
+			goto err_out;
+		}
+	}
+
+	if (!IS_ERR(host->pcie1v8)) {
+		err = regulator_enable(host->pcie1v8);
+		if (err) {
+			dev_err(dev, "fail to enable vpcie1v8 regulator\n");
+			goto err_disable_3v3;
+		}
+	}
+
+	return 0;
+
+err_disable_3v3:
+	if (!IS_ERR(host->pcie3v3))
+		regulator_disable(host->pcie3v3);
+err_out:
+	return err;
+}
+
 static int rcar_pcie_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -911,6 +944,31 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	pcie->dev = dev;
 	platform_set_drvdata(pdev, host);
 
+	host->pcie3v3 = devm_regulator_get_optional(dev, "pcie3v3");
+	if (IS_ERR(host->pcie3v3)) {
+		if (PTR_ERR(host->pcie3v3) == -EPROBE_DEFER) {
+			pci_free_host_bridge(bridge);
+			return -EPROBE_DEFER;
+		}
+		dev_info(dev, "no pcie3v3 regulator found\n");
+	}
+
+	host->pcie1v8 = devm_regulator_get_optional(dev, "pcie1v8");
+	if (IS_ERR(host->pcie1v8)) {
+		if (PTR_ERR(host->pcie1v8) == -EPROBE_DEFER) {
+			pci_free_host_bridge(bridge);
+			return -EPROBE_DEFER;
+		}
+		dev_info(dev, "no pcie1v8 regulator found\n");
+	}
+
+	err = rcar_pcie_set_vpcie(host);
+	if (err) {
+		dev_err(dev, "failed to set pcie regulators\n");
+		pci_free_host_bridge(bridge);
+		return err;
+	}
+
 	pm_runtime_enable(pcie->dev);
 	err = pm_runtime_get_sync(pcie->dev);
 	if (err < 0) {
@@ -985,6 +1043,12 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 	irq_dispose_mapping(host->msi.irq1);
 
 err_pm_put:
+	if(!IS_ERR(host->pcie3v3))
+		if (regulator_is_enabled(host->pcie3v3))
+			regulator_disable(host->pcie3v3);
+	if(!IS_ERR(host->pcie1v8))
+		if (regulator_is_enabled(host->pcie1v8))
+			regulator_disable(host->pcie1v8);
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
 
-- 
2.17.1




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux