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