aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/controller/pcie-rcar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/controller/pcie-rcar.c')
-rw-r--r--drivers/pci/controller/pcie-rcar.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
index 759c6542c5c8..a9dd563c6b40 100644
--- a/drivers/pci/controller/pcie-rcar.c
+++ b/drivers/pci/controller/pcie-rcar.c
@@ -14,6 +14,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
@@ -152,6 +153,8 @@ struct rcar_pcie {
struct list_head resources;
int root_bus_nr;
struct clk *bus_clk;
+ struct regulator *pcie3v3; /* 3.3V power supply */
+ struct regulator *pcie1v8; /* 1.8V power supply */
struct rcar_msi msi;
};
@@ -1110,6 +1113,36 @@ static const struct of_device_id rcar_pcie_of_match[] = {
{},
};
+static int rcar_pcie_set_vpcie(struct rcar_pcie *pcie)
+{
+ struct device *dev = pcie->dev;
+ int err;
+
+ if (!IS_ERR(pcie->pcie3v3)) {
+ err = regulator_enable(pcie->pcie3v3);
+ if (err) {
+ dev_err(dev, "fail to enable vpcie3v3 regulator\n");
+ goto err_out;
+ }
+ }
+
+ if (!IS_ERR(pcie->pcie1v8)) {
+ err = regulator_enable(pcie->pcie1v8);
+ if (err) {
+ dev_err(dev, "fail to enable vpcie1v8 regulator\n");
+ goto err_disable_3v3;
+ }
+ }
+
+ return 0;
+
+err_disable_3v3:
+ if (!IS_ERR(pcie->pcie3v3))
+ regulator_disable(pcie->pcie3v3);
+err_out:
+ return err;
+}
+
static int rcar_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1128,6 +1161,31 @@ static int rcar_pcie_probe(struct platform_device *pdev)
pcie->dev = dev;
platform_set_drvdata(pdev, pcie);
+ pcie->pcie3v3 = devm_regulator_get_optional(dev, "pcie3v3");
+ if (IS_ERR(pcie->pcie3v3)) {
+ if (PTR_ERR(pcie->pcie3v3) == -EPROBE_DEFER) {
+ pci_free_host_bridge(bridge);
+ return -EPROBE_DEFER;
+ }
+ dev_info(dev, "no pcie3v3 regulator found\n");
+ }
+
+ pcie->pcie1v8 = devm_regulator_get_optional(dev, "pcie1v8");
+ if (IS_ERR(pcie->pcie1v8)) {
+ if (PTR_ERR(pcie->pcie1v8) == -EPROBE_DEFER) {
+ pci_free_host_bridge(bridge);
+ return -EPROBE_DEFER;
+ }
+ dev_info(dev, "no pcie1v8 regulator found\n");
+ }
+
+ err = rcar_pcie_set_vpcie(pcie);
+ if (err) {
+ dev_err(dev, "failed to set pcie regulators\n");
+ pci_free_host_bridge(bridge);
+ return err;
+ }
+
err = pci_parse_request_of_pci_ranges(dev, &pcie->resources,
&bridge->dma_ranges, NULL);
if (err)
@@ -1214,6 +1272,12 @@ err_pm_disable:
pci_free_resource_list(&pcie->resources);
err_free_bridge:
+ if(!IS_ERR(pcie->pcie3v3))
+ if (regulator_is_enabled(pcie->pcie3v3))
+ regulator_disable(pcie->pcie3v3);
+ if(!IS_ERR(pcie->pcie1v8))
+ if (regulator_is_enabled(pcie->pcie1v8))
+ regulator_disable(pcie->pcie1v8);
pci_free_host_bridge(bridge);
return err;