aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2014-07-08 13:15:26 +0100
committerAndrey Konovalov <andrey.konovalov@linaro.org>2014-10-08 21:04:55 +0400
commit477c93b5836f335742e48671025e2dfc40abd61e (patch)
treea2bf1d6096a6bf895607beb3ddd62d3b72835bbd
parentfc2c5c23b597f57c57b93ea433bae8a57d999039 (diff)
pci: qcom: Add regulator support
This patch adds regulator support to the driver. There are 3 regulators VDD, AVDD and V3P3_PCIECLK which are necessary for pci IP to work. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-rw-r--r--drivers/pci/host/pci-qcom.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-qcom.c b/drivers/pci/host/pci-qcom.c
index 9b0d48b3e02e..665943baed4e 100644
--- a/drivers/pci/host/pci-qcom.c
+++ b/drivers/pci/host/pci-qcom.c
@@ -19,6 +19,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/reset.h>
@@ -107,6 +108,7 @@ struct qcom_pcie {
void __iomem *parf_base;
void __iomem *dwc_base;
void __iomem *cfg_base;
+ struct device *dev;
int reset_gpio;
struct clk *iface_clk;
struct clk *bus_clk;
@@ -121,6 +123,11 @@ struct qcom_pcie {
struct resource conf;
struct resource io;
struct resource mem;
+
+ struct regulator *vdd_supply;
+ struct regulator *avdd_supply;
+ struct regulator *pcie_clk_supply;
+
};
static int qcom_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
@@ -422,6 +429,32 @@ static void qcom_pcie_config_controller(struct qcom_pcie *dev)
wmb();
}
+static int qcom_pcie_vreg_on(struct qcom_pcie *qcom_pcie)
+{
+ int err;
+ /* enable regulators */
+ err = regulator_enable(qcom_pcie->vdd_supply);
+ if (err < 0) {
+ dev_err(qcom_pcie->dev, "failed to enable VDD regulator\n");
+ return err;
+ }
+
+ err = regulator_enable(qcom_pcie->pcie_clk_supply);
+ if (err < 0) {
+ dev_err(qcom_pcie->dev, "failed to enable pcie-clk regulator\n");
+ return err;
+ }
+
+ err = regulator_enable(qcom_pcie->avdd_supply);
+ if (err < 0) {
+ dev_err(qcom_pcie->dev, "failed to enable AVDD regulator\n");
+ return err;
+ }
+
+ return err;
+
+}
+
static int qcom_pcie_parse_dt(struct qcom_pcie *qcom_pcie,
struct platform_device *pdev)
{
@@ -473,6 +506,24 @@ static int qcom_pcie_parse_dt(struct qcom_pcie *qcom_pcie,
}
}
+ qcom_pcie->vdd_supply = devm_regulator_get(&pdev->dev, "vdd");
+ if (IS_ERR(qcom_pcie->vdd_supply)) {
+ dev_err(&pdev->dev, "Failed to get vdd supply\n");
+ return PTR_ERR(qcom_pcie->vdd_supply);
+ }
+
+ qcom_pcie->pcie_clk_supply = devm_regulator_get(&pdev->dev, "pcie-clk");
+ if (IS_ERR(qcom_pcie->pcie_clk_supply)) {
+ dev_err(&pdev->dev, "Failed to get pcie clk supply\n");
+ return PTR_ERR(qcom_pcie->pcie_clk_supply);
+ }
+ qcom_pcie->avdd_supply = devm_regulator_get(&pdev->dev, "avdd");
+ if (IS_ERR(qcom_pcie->avdd_supply)) {
+ dev_err(&pdev->dev, "Failed to get avdd supply\n");
+ return PTR_ERR(qcom_pcie->avdd_supply);
+ }
+
+
qcom_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
if (!gpio_is_valid(qcom_pcie->reset_gpio)) {
dev_err(&pdev->dev, "pcie reset gpio is not valid\n");
@@ -558,6 +609,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no memory for qcom_pcie\n");
return -ENOMEM;
}
+ qcom_pcie->dev = &pdev->dev;
ret = qcom_pcie_parse_dt(qcom_pcie, pdev);
if (IS_ERR_VALUE(ret))
@@ -573,6 +625,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
gpio_set_value(qcom_pcie->reset_gpio, 0);
usleep_range(10000, 15000);
+ /* enable power */
+ qcom_pcie_vreg_on(qcom_pcie);
/* assert PCIe PARF reset while powering the core */
reset_control_assert(qcom_pcie->ahb_reset);