summaryrefslogtreecommitdiff
path: root/drivers/pci/dwc/pci-imx6.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/dwc/pci-imx6.c')
-rw-r--r--drivers/pci/dwc/pci-imx6.c156
1 files changed, 74 insertions, 82 deletions
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c
index 54459b52f526..7855ded3102f 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/dwc/pci-imx6.c
@@ -70,19 +70,19 @@ struct imx_pcie {
u32 ctrl_id;
u32 cpu_base;
u32 hard_wired;
- int clkreq_gpio;
- int dis_gpio;
- int power_on_gpio;
- int reset_gpio;
+ struct gpio_desc *clkreq_gpiod;
+ struct gpio_desc *dis_gpiod;
+ struct gpio_desc *power_on_gpiod;
+ struct gpio_desc *reset_gpiod;
bool gpio_active_high;
struct clk *pcie_bus;
struct clk *pcie_phy;
struct clk *pcie_inbound_axi;
- struct clk *pcie_per;
struct clk *pcie;
+ struct clk *pcie_ext;
struct clk *pcie_ext_src;
struct regmap *iomuxc_gpr;
- enum imx_pcie_variants variant;
+ enum imx_pcie_variants variant;
u32 hsio_cfg;
u32 tx_deemph_gen1;
u32 tx_deemph_gen2_3p5db;
@@ -640,17 +640,8 @@ static int imx_pcie_enable_ref_clk(struct imx_pcie *imx_pcie)
case IMX8QXP:
case IMX8QM:
ret = clk_prepare_enable(imx_pcie->pcie_inbound_axi);
- if (ret) {
+ if (ret)
dev_err(dev, "unable to enable pcie_axi clock\n");
- break;
- }
- ret = clk_prepare_enable(imx_pcie->pcie_per);
- if (ret) {
- dev_err(dev, "unable to enable pcie_per clock\n");
- clk_disable_unprepare(imx_pcie->pcie_inbound_axi);
- break;
- }
-
break;
}
@@ -764,8 +755,15 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
}
}
- if (gpio_is_valid(imx_pcie->power_on_gpio))
- gpio_set_value_cansleep(imx_pcie->power_on_gpio, 1);
+ if (imx_pcie->power_on_gpiod)
+ gpiod_set_value_cansleep(imx_pcie->power_on_gpiod, 1);
+
+ if (imx_pcie->clkreq_gpiod)
+ gpiod_set_value_cansleep(imx_pcie->clkreq_gpiod, 1);
+
+ mdelay(2);
+ if (imx_pcie->dis_gpiod)
+ gpiod_set_value_cansleep(imx_pcie->dis_gpiod, 0);
ret = clk_prepare_enable(imx_pcie->pcie);
if (ret) {
@@ -782,6 +780,12 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
goto err_pcie_bus;
}
+ ret = clk_prepare_enable(imx_pcie->pcie_ext);
+ if (ret) {
+ dev_err(dev, "unable to enable pcie_ext clock\n");
+ goto err_pcie_bus;
+ }
+
ret = clk_prepare_enable(imx_pcie->pcie_phy);
if (ret) {
dev_err(dev, "unable to enable pcie_phy clock\n");
@@ -955,12 +959,12 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie)
}
/* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx_pcie->reset_gpio)) {
- gpio_set_value_cansleep(imx_pcie->reset_gpio,
- imx_pcie->gpio_active_high);
- mdelay(20);
- gpio_set_value_cansleep(imx_pcie->reset_gpio,
+ if (imx_pcie->reset_gpiod) {
+ gpiod_set_value_cansleep(imx_pcie->reset_gpiod,
!imx_pcie->gpio_active_high);
+ mdelay(100);
+ gpiod_set_value_cansleep(imx_pcie->reset_gpiod,
+ imx_pcie->gpio_active_high);
mdelay(20);
}
@@ -1495,7 +1499,6 @@ static void pci_imx_clk_disable(struct device *dev)
break;
case IMX8QXP:
case IMX8QM:
- clk_disable_unprepare(imx_pcie->pcie_per);
clk_disable_unprepare(imx_pcie->pcie_inbound_axi);
break;
}
@@ -2049,8 +2052,9 @@ static void pci_imx_pm_turn_off(struct imx_pcie *imx_pcie)
}
udelay(1000);
- if (gpio_is_valid(imx_pcie->reset_gpio))
- gpio_set_value_cansleep(imx_pcie->reset_gpio, 0);
+ if (imx_pcie->reset_gpiod)
+ gpiod_set_value_cansleep(imx_pcie->reset_gpiod,
+ !imx_pcie->gpio_active_high);
}
static int pci_imx_suspend_noirq(struct device *dev)
@@ -2074,6 +2078,8 @@ static int pci_imx_suspend_noirq(struct device *dev)
IMX6Q_GPR1_PCIE_TEST_PD,
IMX6Q_GPR1_PCIE_TEST_PD);
} else {
+ pm_runtime_put_sync(dev);
+
pci_imx_clk_disable(dev);
imx_pcie_phy_pwr_dn(imx_pcie);
@@ -2142,6 +2148,8 @@ static int pci_imx_resume_noirq(struct device *dev)
regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 0);
} else {
+ pm_runtime_get_sync(dev);
+
pci_imx_ltssm_disable(dev);
imx_pcie_assert_core_reset(imx_pcie);
imx_pcie_init_phy(imx_pcie);
@@ -2335,59 +2343,42 @@ static int imx_pcie_probe(struct platform_device *pdev)
}
/* Fetch GPIOs */
- imx_pcie->clkreq_gpio = of_get_named_gpio(node, "clkreq-gpio", 0);
- if (gpio_is_valid(imx_pcie->clkreq_gpio)) {
- ret = devm_gpio_request_one(&pdev->dev, imx_pcie->clkreq_gpio,
- GPIOF_OUT_INIT_LOW, "PCIe CLKREQ");
- if (ret) {
+ imx_pcie->clkreq_gpiod = devm_gpiod_get_optional(dev, "clkreq",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx_pcie->clkreq_gpiod)) {
+ ret = PTR_ERR(imx_pcie->clkreq_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "unable to get clkreq gpio\n");
- return ret;
- }
- } else if (imx_pcie->clkreq_gpio == -EPROBE_DEFER) {
- return imx_pcie->clkreq_gpio;
+ return ret;
}
- imx_pcie->dis_gpio = of_get_named_gpio(node, "disable-gpio", 0);
- if (gpio_is_valid(imx_pcie->dis_gpio)) {
- ret = devm_gpio_request_one(&pdev->dev, imx_pcie->dis_gpio,
- GPIOF_OUT_INIT_HIGH, "PCIe DIS");
- if (ret) {
+ imx_pcie->dis_gpiod = devm_gpiod_get_optional(dev, "disable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx_pcie->dis_gpiod)) {
+ ret = PTR_ERR(imx_pcie->dis_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "unable to get disable gpio\n");
- return ret;
- }
- } else if (imx_pcie->dis_gpio == -EPROBE_DEFER) {
- return imx_pcie->dis_gpio;
+ return ret;
}
- imx_pcie->power_on_gpio = of_get_named_gpio(node, "power-on-gpio", 0);
- if (gpio_is_valid(imx_pcie->power_on_gpio)) {
- ret = devm_gpio_request_one(&pdev->dev,
- imx_pcie->power_on_gpio,
- GPIOF_OUT_INIT_LOW,
- "PCIe power enable");
- if (ret) {
+ imx_pcie->power_on_gpiod = devm_gpiod_get_optional(dev, "power-on",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(imx_pcie->power_on_gpiod)) {
+ ret = PTR_ERR(imx_pcie->power_on_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev, "unable to get power-on gpio\n");
- return ret;
- }
- } else if (imx_pcie->power_on_gpio == -EPROBE_DEFER) {
- return imx_pcie->power_on_gpio;
- }
-
- imx_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
- imx_pcie->gpio_active_high = of_property_read_bool(node,
- "reset-gpio-active-high");
- if (gpio_is_valid(imx_pcie->reset_gpio)) {
- ret = devm_gpio_request_one(dev, imx_pcie->reset_gpio,
- imx_pcie->gpio_active_high ?
- GPIOF_OUT_INIT_HIGH :
- GPIOF_OUT_INIT_LOW,
- "PCIe reset");
- if (ret) {
+ return ret;
+ }
+
+ imx_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset",
+ imx_pcie->gpio_active_high ?
+ GPIOD_OUT_LOW :
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx_pcie->reset_gpiod)) {
+ ret = PTR_ERR(imx_pcie->reset_gpiod);
+ if (ret != -EPROBE_DEFER)
dev_err(dev, "unable to get reset gpio\n");
- return ret;
- }
- } else if (imx_pcie->reset_gpio == -EPROBE_DEFER) {
- return imx_pcie->reset_gpio;
+ return ret;
}
imx_pcie->epdev_on = devm_regulator_get(&pdev->dev, "epdev_on");
@@ -2418,15 +2409,18 @@ static int imx_pcie_probe(struct platform_device *pdev)
if (of_property_read_u32(node, "ext_osc", &imx_pcie->ext_osc) < 0)
imx_pcie->ext_osc = 0;
- if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP)) {
+ if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP ||
+ imx_pcie->variant == IMX8QM)) {
/* Change the pcie_bus clock to pcie external OSC */
- imx_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_ext");
- if (IS_ERR(imx_pcie->pcie_bus)) {
+ imx_pcie->pcie_ext = devm_clk_get(&pdev->dev, "pcie_ext");
+ if (IS_ERR(imx_pcie->pcie_ext)) {
dev_err(&pdev->dev,
- "pcie_bus clock source missing or invalid\n");
- return PTR_ERR(imx_pcie->pcie_bus);
+ "pcie_ext clock source missing or invalid\n");
+ return PTR_ERR(imx_pcie->pcie_ext);
}
+ }
+ if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP)) {
imx_pcie->pcie_ext_src = devm_clk_get(&pdev->dev,
"pcie_ext_src");
if (IS_ERR(imx_pcie->pcie_ext_src)) {
@@ -2502,12 +2496,6 @@ static int imx_pcie_probe(struct platform_device *pdev)
("fsl,imx6sx-iomuxc-gpr");
} else if (imx_pcie->variant == IMX8QM
|| imx_pcie->variant == IMX8QXP) {
- imx_pcie->pcie_per = devm_clk_get(dev, "pcie_per");
- if (IS_ERR(imx_pcie->pcie_per)) {
- dev_err(dev, "pcie_per clock source missing or invalid\n");
- return PTR_ERR(imx_pcie->pcie_per);
- }
-
imx_pcie->iomuxc_gpr =
syscon_regmap_lookup_by_phandle(node, "hsio");
imx_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev,
@@ -2823,6 +2811,8 @@ static int imx_pcie_probe(struct platform_device *pdev)
&& (imx_pcie->hard_wired == 0))
imx_pcie_regions_setup(&pdev->dev);
}
+ pm_runtime_get_sync(&pdev->dev);
+
return 0;
}
@@ -2833,6 +2823,8 @@ static void imx_pcie_shutdown(struct platform_device *pdev)
/* bring down link, so bootloader gets clean state in case of reboot */
if (imx_pcie->variant == IMX6Q)
imx_pcie_assert_core_reset(imx_pcie);
+
+ pm_runtime_put_sync(&pdev->dev);
}
static const struct of_device_id imx_pcie_of_match[] = {