From 8b6f0330b5f9a7543356bfa9e76d580f03aa2c1e Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:05:57 +0200 Subject: PCI: qcom: Add missing ipq806x clocks in PCIe driver Aux and Ref clk are missing in PCIe qcom driver. Add support for this optional clks for ipq8064/apq8064 SoC. Link: https://lore.kernel.org/r/20200615210608.21469-2-ansuelsmth@gmail.com Fixes: 82a823833f4e ("PCI: qcom: Add Qualcomm PCIe controller driver") Signed-off-by: Sham Muthayyan Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 138e1a2d21cc..fa0bf652ce0b 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -88,6 +88,8 @@ struct qcom_pcie_resources_2_1_0 { struct clk *iface_clk; struct clk *core_clk; struct clk *phy_clk; + struct clk *aux_clk; + struct clk *ref_clk; struct reset_control *pci_reset; struct reset_control *axi_reset; struct reset_control *ahb_reset; @@ -246,6 +248,14 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (IS_ERR(res->phy_clk)) return PTR_ERR(res->phy_clk); + res->aux_clk = devm_clk_get_optional(dev, "aux"); + if (IS_ERR(res->aux_clk)) + return PTR_ERR(res->aux_clk); + + res->ref_clk = devm_clk_get_optional(dev, "ref"); + if (IS_ERR(res->ref_clk)) + return PTR_ERR(res->ref_clk); + res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); if (IS_ERR(res->pci_reset)) return PTR_ERR(res->pci_reset); @@ -278,6 +288,8 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) clk_disable_unprepare(res->iface_clk); clk_disable_unprepare(res->core_clk); clk_disable_unprepare(res->phy_clk); + clk_disable_unprepare(res->aux_clk); + clk_disable_unprepare(res->ref_clk); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -307,16 +319,28 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) goto err_assert_ahb; } + ret = clk_prepare_enable(res->core_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable core clock\n"); + goto err_clk_core; + } + ret = clk_prepare_enable(res->phy_clk); if (ret) { dev_err(dev, "cannot prepare/enable phy clock\n"); goto err_clk_phy; } - ret = clk_prepare_enable(res->core_clk); + ret = clk_prepare_enable(res->aux_clk); if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_core; + dev_err(dev, "cannot prepare/enable aux clock\n"); + goto err_clk_aux; + } + + ret = clk_prepare_enable(res->ref_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable ref clock\n"); + goto err_clk_ref; } ret = reset_control_deassert(res->ahb_reset); @@ -372,10 +396,14 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) return 0; err_deassert_ahb: - clk_disable_unprepare(res->core_clk); -err_clk_core: + clk_disable_unprepare(res->ref_clk); +err_clk_ref: + clk_disable_unprepare(res->aux_clk); +err_clk_aux: clk_disable_unprepare(res->phy_clk); err_clk_phy: + clk_disable_unprepare(res->core_clk); +err_clk_core: clk_disable_unprepare(res->iface_clk); err_assert_ahb: regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); -- cgit v1.2.3 From dd58318c019f10bc94db36df66af6c55d4c0cbba Mon Sep 17 00:00:00 2001 From: Abhishek Sahu Date: Mon, 15 Jun 2020 23:05:59 +0200 Subject: PCI: qcom: Change duplicate PCI reset to phy reset The deinit issues reset_control_assert for PCI twice and does not contain phy reset. Link: https://lore.kernel.org/r/20200615210608.21469-4-ansuelsmth@gmail.com Signed-off-by: Abhishek Sahu Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index fa0bf652ce0b..bae5158a9854 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -280,14 +280,14 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; + clk_disable_unprepare(res->phy_clk); reset_control_assert(res->pci_reset); reset_control_assert(res->axi_reset); reset_control_assert(res->ahb_reset); reset_control_assert(res->por_reset); - reset_control_assert(res->pci_reset); + reset_control_assert(res->phy_reset); clk_disable_unprepare(res->iface_clk); clk_disable_unprepare(res->core_clk); - clk_disable_unprepare(res->phy_clk); clk_disable_unprepare(res->aux_clk); clk_disable_unprepare(res->ref_clk); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); @@ -325,12 +325,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) goto err_clk_core; } - ret = clk_prepare_enable(res->phy_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_clk_phy; - } - ret = clk_prepare_enable(res->aux_clk); if (ret) { dev_err(dev, "cannot prepare/enable aux clock\n"); @@ -383,6 +377,12 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) return ret; } + ret = clk_prepare_enable(res->phy_clk); + if (ret) { + dev_err(dev, "cannot prepare/enable phy clock\n"); + goto err_deassert_ahb; + } + /* wait for clock acquisition */ usleep_range(1000, 1500); @@ -400,8 +400,6 @@ err_deassert_ahb: err_clk_ref: clk_disable_unprepare(res->aux_clk); err_clk_aux: - clk_disable_unprepare(res->phy_clk); -err_clk_phy: clk_disable_unprepare(res->core_clk); err_clk_core: clk_disable_unprepare(res->iface_clk); -- cgit v1.2.3 From ee367e2cdd2202b5714982739e684543cd2cee0e Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:00 +0200 Subject: PCI: qcom: Add missing reset for ipq806x Add missing ext reset used by ipq8064 SoC in PCIe qcom driver. Link: https://lore.kernel.org/r/20200615210608.21469-5-ansuelsmth@gmail.com Fixes: 82a823833f4e ("PCI: qcom: Add Qualcomm PCIe controller driver") Signed-off-by: Sham Muthayyan Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Reviewed-by: Philipp Zabel Acked-by: Stanimir Varbanov Cc: stable@vger.kernel.org # v4.5+ --- drivers/pci/controller/dwc/pcie-qcom.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index bae5158a9854..fcd265067f34 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -95,6 +95,7 @@ struct qcom_pcie_resources_2_1_0 { struct reset_control *ahb_reset; struct reset_control *por_reset; struct reset_control *phy_reset; + struct reset_control *ext_reset; struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY]; }; @@ -272,6 +273,10 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (IS_ERR(res->por_reset)) return PTR_ERR(res->por_reset); + res->ext_reset = devm_reset_control_get_optional_exclusive(dev, "ext"); + if (IS_ERR(res->ext_reset)) + return PTR_ERR(res->ext_reset); + res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); return PTR_ERR_OR_ZERO(res->phy_reset); } @@ -285,6 +290,7 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) reset_control_assert(res->axi_reset); reset_control_assert(res->ahb_reset); reset_control_assert(res->por_reset); + reset_control_assert(res->ext_reset); reset_control_assert(res->phy_reset); clk_disable_unprepare(res->iface_clk); clk_disable_unprepare(res->core_clk); @@ -343,6 +349,12 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) goto err_deassert_ahb; } + ret = reset_control_deassert(res->ext_reset); + if (ret) { + dev_err(dev, "cannot deassert ext reset\n"); + goto err_deassert_ahb; + } + /* enable PCIe clocks and resets */ val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); val &= ~BIT(0); -- cgit v1.2.3 From 6a114526af4689938863bf34976c83bfd279f517 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:02 +0200 Subject: PCI: qcom: Use bulk clk api and assert on error Rework 2.1.0 revision to use bulk clk api and fix missing assert on reset_control_deassert error. Link: https://lore.kernel.org/r/20200615210608.21469-7-ansuelsmth@gmail.com Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 131 ++++++++++++--------------------- 1 file changed, 46 insertions(+), 85 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index fcd265067f34..8cb36cbcde46 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -84,12 +84,9 @@ #define DEVICE_TYPE_RC 0x4 #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 +#define QCOM_PCIE_2_1_0_MAX_CLOCKS 5 struct qcom_pcie_resources_2_1_0 { - struct clk *iface_clk; - struct clk *core_clk; - struct clk *phy_clk; - struct clk *aux_clk; - struct clk *ref_clk; + struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS]; struct reset_control *pci_reset; struct reset_control *axi_reset; struct reset_control *ahb_reset; @@ -237,25 +234,21 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (ret) return ret; - res->iface_clk = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface_clk)) - return PTR_ERR(res->iface_clk); - - res->core_clk = devm_clk_get(dev, "core"); - if (IS_ERR(res->core_clk)) - return PTR_ERR(res->core_clk); - - res->phy_clk = devm_clk_get(dev, "phy"); - if (IS_ERR(res->phy_clk)) - return PTR_ERR(res->phy_clk); + res->clks[0].id = "iface"; + res->clks[1].id = "core"; + res->clks[2].id = "phy"; + res->clks[3].id = "aux"; + res->clks[4].id = "ref"; - res->aux_clk = devm_clk_get_optional(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); + /* iface, core, phy are required */ + ret = devm_clk_bulk_get(dev, 3, res->clks); + if (ret < 0) + return ret; - res->ref_clk = devm_clk_get_optional(dev, "ref"); - if (IS_ERR(res->ref_clk)) - return PTR_ERR(res->ref_clk); + /* aux, ref are optional */ + ret = devm_clk_bulk_get_optional(dev, 2, res->clks + 3); + if (ret < 0) + return ret; res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); if (IS_ERR(res->pci_reset)) @@ -285,17 +278,13 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; - clk_disable_unprepare(res->phy_clk); + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); reset_control_assert(res->pci_reset); reset_control_assert(res->axi_reset); reset_control_assert(res->ahb_reset); reset_control_assert(res->por_reset); reset_control_assert(res->ext_reset); reset_control_assert(res->phy_reset); - clk_disable_unprepare(res->iface_clk); - clk_disable_unprepare(res->core_clk); - clk_disable_unprepare(res->aux_clk); - clk_disable_unprepare(res->ref_clk); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -313,36 +302,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) return ret; } - ret = reset_control_assert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot assert ahb reset\n"); - goto err_assert_ahb; - } - - ret = clk_prepare_enable(res->iface_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_assert_ahb; - } - - ret = clk_prepare_enable(res->core_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_core; - } - - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; - } - - ret = clk_prepare_enable(res->ref_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ref clock\n"); - goto err_clk_ref; - } - ret = reset_control_deassert(res->ahb_reset); if (ret) { dev_err(dev, "cannot deassert ahb reset\n"); @@ -352,48 +311,46 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) ret = reset_control_deassert(res->ext_reset); if (ret) { dev_err(dev, "cannot deassert ext reset\n"); - goto err_deassert_ahb; + goto err_deassert_ext; } - /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); - - /* enable external reference clock */ - val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); - val |= BIT(16); - writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); - ret = reset_control_deassert(res->phy_reset); if (ret) { dev_err(dev, "cannot deassert phy reset\n"); - return ret; + goto err_deassert_phy; } ret = reset_control_deassert(res->pci_reset); if (ret) { dev_err(dev, "cannot deassert pci reset\n"); - return ret; + goto err_deassert_pci; } ret = reset_control_deassert(res->por_reset); if (ret) { dev_err(dev, "cannot deassert por reset\n"); - return ret; + goto err_deassert_por; } ret = reset_control_deassert(res->axi_reset); if (ret) { dev_err(dev, "cannot deassert axi reset\n"); - return ret; + goto err_deassert_axi; } - ret = clk_prepare_enable(res->phy_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_deassert_ahb; - } + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); + if (ret) + goto err_clks; + + /* enable PCIe clocks and resets */ + val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); + val &= ~BIT(0); + writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + + /* enable external reference clock */ + val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); + val |= BIT(16); + writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); /* wait for clock acquisition */ usleep_range(1000, 1500); @@ -407,15 +364,19 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) return 0; +err_clks: + reset_control_assert(res->axi_reset); +err_deassert_axi: + reset_control_assert(res->por_reset); +err_deassert_por: + reset_control_assert(res->pci_reset); +err_deassert_pci: + reset_control_assert(res->phy_reset); +err_deassert_phy: + reset_control_assert(res->ext_reset); +err_deassert_ext: + reset_control_assert(res->ahb_reset); err_deassert_ahb: - clk_disable_unprepare(res->ref_clk); -err_clk_ref: - clk_disable_unprepare(res->aux_clk); -err_clk_aux: - clk_disable_unprepare(res->core_clk); -err_clk_core: - clk_disable_unprepare(res->iface_clk); -err_assert_ahb: regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); return ret; -- cgit v1.2.3 From 5149901e9e6deca487c01cc434a3ac4125c7b00b Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:03 +0200 Subject: PCI: qcom: Define some PARF params needed for ipq8064 SoC Set some specific value for Tx De-Emphasis, Tx Swing and Rx equalization needed on some ipq8064 based device (Netgear R7800 for example). Without this the system locks on kernel load. Link: https://lore.kernel.org/r/20200615210608.21469-8-ansuelsmth@gmail.com Fixes: 82a823833f4e ("PCI: qcom: Add Qualcomm PCIe controller driver") Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Stanimir Varbanov Cc: stable@vger.kernel.org # v4.5+ --- drivers/pci/controller/dwc/pcie-qcom.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 8cb36cbcde46..69c7b119e81a 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -77,6 +77,18 @@ #define DBI_RO_WR_EN 1 #define PERST_DELAY_US 1000 +/* PARF registers */ +#define PCIE20_PARF_PCS_DEEMPH 0x34 +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) ((x) << 16) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) ((x) << 8) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) ((x) << 0) + +#define PCIE20_PARF_PCS_SWING 0x38 +#define PCS_SWING_TX_SWING_FULL(x) ((x) << 8) +#define PCS_SWING_TX_SWING_LOW(x) ((x) << 0) + +#define PCIE20_PARF_CONFIG_BITS 0x50 +#define PHY_RX0_EQ(x) ((x) << 24) #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358 #define SLV_ADDR_SPACE_SZ 0x10000000 @@ -293,6 +305,7 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; + struct device_node *node = dev->of_node; u32 val; int ret; @@ -347,6 +360,17 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) val &= ~BIT(0); writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) { + writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) | + PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(24) | + PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(34), + pcie->parf + PCIE20_PARF_PCS_DEEMPH); + writel(PCS_SWING_TX_SWING_FULL(120) | + PCS_SWING_TX_SWING_LOW(120), + pcie->parf + PCIE20_PARF_PCS_SWING); + writel(PHY_RX0_EQ(4), pcie->parf + PCIE20_PARF_CONFIG_BITS); + } + /* enable external reference clock */ val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); val |= BIT(16); -- cgit v1.2.3 From de3c4bf648975ea0b1d344d811e9b0748907b47c Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:04 +0200 Subject: PCI: qcom: Add support for tx term offset for rev 2.1.0 Add tx term offset support to pcie qcom driver need in some revision of the ipq806x SoC. Ipq8064 needs tx term offset set to 7. Link: https://lore.kernel.org/r/20200615210608.21469-9-ansuelsmth@gmail.com Fixes: 82a823833f4e ("PCI: qcom: Add Qualcomm PCIe controller driver") Signed-off-by: Sham Muthayyan Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Acked-by: Stanimir Varbanov Cc: stable@vger.kernel.org # v4.5+ --- drivers/pci/controller/dwc/pcie-qcom.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 69c7b119e81a..34d961e492fd 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -45,7 +45,13 @@ #define PCIE_CAP_CPL_TIMEOUT_DISABLE 0x10 #define PCIE20_PARF_PHY_CTRL 0x40 +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK GENMASK(20, 16) +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) ((x) << 16) + #define PCIE20_PARF_PHY_REFCLK 0x4C +#define PHY_REFCLK_SSP_EN BIT(16) +#define PHY_REFCLK_USE_PAD BIT(12) + #define PCIE20_PARF_DBI_BASE_ADDR 0x168 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174 @@ -371,9 +377,18 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) writel(PHY_RX0_EQ(4), pcie->parf + PCIE20_PARF_CONFIG_BITS); } + if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) { + /* set TX termination offset */ + val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); + val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK; + val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(7); + writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + } + /* enable external reference clock */ val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); - val |= BIT(16); + val &= ~PHY_REFCLK_USE_PAD; + val |= PHY_REFCLK_SSP_EN; writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); /* wait for clock acquisition */ -- cgit v1.2.3 From 8df093fe2ae1717389df0dcdc620c02cc35abb21 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:05 +0200 Subject: PCI: qcom: Add ipq8064 rev2 variant Ipq8064-v2 have tx term offset set to 0. Introduce this variant to permit different offset based on the revision. Link: https://lore.kernel.org/r/20200615210608.21469-10-ansuelsmth@gmail.com Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 34d961e492fd..6f37ab914fa3 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -366,7 +366,8 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) val &= ~BIT(0); writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); - if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) { + if (of_device_is_compatible(node, "qcom,pcie-ipq8064") || + of_device_is_compatible(node, "qcom,pcie-ipq8064-v2")) { writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) | PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(24) | PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(34), @@ -1464,6 +1465,7 @@ err_pm_runtime_put: static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-apq8084", .data = &ops_1_0_0 }, { .compatible = "qcom,pcie-ipq8064", .data = &ops_2_1_0 }, + { .compatible = "qcom,pcie-ipq8064-v2", .data = &ops_2_1_0 }, { .compatible = "qcom,pcie-apq8064", .data = &ops_2_1_0 }, { .compatible = "qcom,pcie-msm8996", .data = &ops_2_3_2 }, { .compatible = "qcom,pcie-ipq8074", .data = &ops_2_3_3 }, -- cgit v1.2.3 From 51ed2c2b60265006bde7531d10993cf24def0aee Mon Sep 17 00:00:00 2001 From: Sham Muthayyan Date: Mon, 15 Jun 2020 23:06:07 +0200 Subject: PCI: qcom: Support pci speed set for ipq806x Some SoC based on ipq8064/5 needs to be limited to pci GEN1 speed due to some hardware limitations. Add support for speed setting defined by the max-link-speed binding. If not defined the max speed is set to GEN2 by default. Link: https://lore.kernel.org/r/20200615210608.21469-12-ansuelsmth@gmail.com Signed-off-by: Sham Muthayyan Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Reviewed-by: Rob Herring Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 6f37ab914fa3..17498e66e2df 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -27,6 +27,7 @@ #include #include +#include "../../pci.h" #include "pcie-designware.h" #define PCIE20_PARF_SYS_CTRL 0x00 @@ -99,6 +100,8 @@ #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358 #define SLV_ADDR_SPACE_SZ 0x10000000 +#define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xa0 + #define DEVICE_TYPE_RC 0x4 #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 @@ -195,6 +198,7 @@ struct qcom_pcie { struct phy *phy; struct gpio_desc *reset; const struct qcom_pcie_ops *ops; + int gen; }; #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) @@ -395,6 +399,11 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) /* wait for clock acquisition */ usleep_range(1000, 1500); + if (pcie->gen == 1) { + val = readl(pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); + val |= PCI_EXP_LNKSTA_CLS_2_5GB; + writel(val, pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); + } /* Set the Max TLP size to 2K, instead of using default of 4K */ writel(CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K, @@ -1397,6 +1406,10 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_pm_runtime_put; } + pcie->gen = of_pci_get_max_link_speed(pdev->dev.of_node); + if (pcie->gen < 0) + pcie->gen = 2; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); pcie->parf = devm_ioremap_resource(dev, res); if (IS_ERR(pcie->parf)) { -- cgit v1.2.3 From 824001cb64c007129cd8bb95649a3eea9542e870 Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Mon, 15 Jun 2020 23:06:08 +0200 Subject: PCI: qcom: Replace define with standard value Lots of define are actually already defined in pci_regs.h, directly use the standard defines. Link: https://lore.kernel.org/r/20200615210608.21469-13-ansuelsmth@gmail.com Signed-off-by: Ansuel Smith Signed-off-by: Lorenzo Pieralisi Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-qcom.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 17498e66e2df..73d4eed26f65 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -40,11 +40,6 @@ #define L23_CLK_RMV_DIS BIT(2) #define L1_CLK_RMV_DIS BIT(1) -#define PCIE20_COMMAND_STATUS 0x04 -#define CMD_BME_VAL 0x4 -#define PCIE20_DEVICE_CONTROL2_STATUS2 0x98 -#define PCIE_CAP_CPL_TIMEOUT_DISABLE 0x10 - #define PCIE20_PARF_PHY_CTRL 0x40 #define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK GENMASK(20, 16) #define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) ((x) << 16) @@ -73,8 +68,8 @@ #define CFG_BRIDGE_SB_INIT BIT(0) #define PCIE20_CAP 0x70 -#define PCIE20_CAP_LINK_CAPABILITIES (PCIE20_CAP + 0xC) -#define PCIE20_CAP_ACTIVE_STATE_LINK_PM_SUPPORT (BIT(10) | BIT(11)) +#define PCIE20_DEVICE_CONTROL2_STATUS2 (PCIE20_CAP + PCI_EXP_DEVCTL2) +#define PCIE20_CAP_LINK_CAPABILITIES (PCIE20_CAP + PCI_EXP_LNKCAP) #define PCIE20_CAP_LINK_1 (PCIE20_CAP + 0x14) #define PCIE_CAP_LINK1_VAL 0x2FD7F @@ -1095,15 +1090,15 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) pcie->parf + PCIE20_PARF_SYS_CTRL); writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); - writel(CMD_BME_VAL, pci->dbi_base + PCIE20_COMMAND_STATUS); + writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND); writel(DBI_RO_WR_EN, pci->dbi_base + PCIE20_MISC_CONTROL_1_REG); writel(PCIE_CAP_LINK1_VAL, pci->dbi_base + PCIE20_CAP_LINK_1); val = readl(pci->dbi_base + PCIE20_CAP_LINK_CAPABILITIES); - val &= ~PCIE20_CAP_ACTIVE_STATE_LINK_PM_SUPPORT; + val &= ~PCI_EXP_LNKCAP_ASPMS; writel(val, pci->dbi_base + PCIE20_CAP_LINK_CAPABILITIES); - writel(PCIE_CAP_CPL_TIMEOUT_DISABLE, pci->dbi_base + + writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + PCIE20_DEVICE_CONTROL2_STATUS2); return 0; -- cgit v1.2.3 From 936fa5cd7b8e3e2a21b434d0f3ac29784ac69791 Mon Sep 17 00:00:00 2001 From: Dejin Zheng Date: Thu, 9 Jul 2020 00:40:13 +0800 Subject: PCI: dwc: Convert to devm_platform_ioremap_resource_byname() Use devm_platform_ioremap_resource_byname() to simplify the code since it contains platform_get_resource_byname() and devm_ioremap_resource() respectively. Link: https://lore.kernel.org/r/20200708164013.5076-1-zhengdejin5@gmail.com Signed-off-by: Dejin Zheng Signed-off-by: Lorenzo Pieralisi Reviewed-by: Gustavo Pimentel Reviewed-by: Rob Herring --- drivers/pci/controller/dwc/pci-dra7xx.c | 11 ++++------- drivers/pci/controller/dwc/pci-keystone.c | 3 +-- drivers/pci/controller/dwc/pcie-artpec6.c | 12 ++++-------- drivers/pci/controller/dwc/pcie-designware-plat.c | 3 +-- drivers/pci/controller/dwc/pcie-histb.c | 7 ++----- drivers/pci/controller/dwc/pcie-intel-gw.c | 7 ++----- drivers/pci/controller/dwc/pcie-kirin.c | 17 ++++++----------- drivers/pci/controller/dwc/pcie-qcom.c | 6 ++---- drivers/pci/controller/dwc/pcie-uniphier.c | 3 +-- 9 files changed, 23 insertions(+), 46 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index 6184ebc9392d..e5d0c7ac09b9 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -593,13 +593,12 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, ep = &pci->ep; ep->ops = &pcie_ep_ops; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ep_dbics"); - pci->dbi_base = devm_ioremap_resource(dev, res); + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "ep_dbics"); if (IS_ERR(pci->dbi_base)) return PTR_ERR(pci->dbi_base); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ep_dbics2"); - pci->dbi_base2 = devm_ioremap_resource(dev, res); + pci->dbi_base2 = + devm_platform_ioremap_resource_byname(pdev, "ep_dbics2"); if (IS_ERR(pci->dbi_base2)) return PTR_ERR(pci->dbi_base2); @@ -626,7 +625,6 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, struct dw_pcie *pci = dra7xx->pci; struct pcie_port *pp = &pci->pp; struct device *dev = pci->dev; - struct resource *res; pp->irq = platform_get_irq(pdev, 1); if (pp->irq < 0) { @@ -638,8 +636,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, if (ret < 0) return ret; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics"); - pci->dbi_base = devm_ioremap_resource(dev, res); + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "rc_dbics"); if (IS_ERR(pci->dbi_base)) return PTR_ERR(pci->dbi_base); diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index 790679fdfa48..00279002102e 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -1323,8 +1323,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev) } if (pci->version >= 0x480A) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu"); - atu_base = devm_ioremap_resource(dev, res); + atu_base = devm_platform_ioremap_resource_byname(pdev, "atu"); if (IS_ERR(atu_base)) { ret = PTR_ERR(atu_base); goto err_get_sync; diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c index 28d5a1095200..7d2cfa288b01 100644 --- a/drivers/pci/controller/dwc/pcie-artpec6.c +++ b/drivers/pci/controller/dwc/pcie-artpec6.c @@ -455,8 +455,7 @@ static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie, ep = &pci->ep; ep->ops = &pcie_ep_ops; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2"); - pci->dbi_base2 = devm_ioremap_resource(dev, res); + pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2"); if (IS_ERR(pci->dbi_base2)) return PTR_ERR(pci->dbi_base2); @@ -481,8 +480,6 @@ static int artpec6_pcie_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct dw_pcie *pci; struct artpec6_pcie *artpec6_pcie; - struct resource *dbi_base; - struct resource *phy_base; int ret; const struct of_device_id *match; const struct artpec_pcie_of_data *data; @@ -512,13 +509,12 @@ static int artpec6_pcie_probe(struct platform_device *pdev) artpec6_pcie->variant = variant; artpec6_pcie->mode = mode; - dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi"); if (IS_ERR(pci->dbi_base)) return PTR_ERR(pci->dbi_base); - phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); - artpec6_pcie->phy_base = devm_ioremap_resource(dev, phy_base); + artpec6_pcie->phy_base = + devm_platform_ioremap_resource_byname(pdev, "phy"); if (IS_ERR(artpec6_pcie->phy_base)) return PTR_ERR(artpec6_pcie->phy_base); diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c index 73646b677aff..712456f6ce36 100644 --- a/drivers/pci/controller/dwc/pcie-designware-plat.c +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c @@ -153,8 +153,7 @@ static int dw_plat_add_pcie_ep(struct dw_plat_pcie *dw_plat_pcie, ep = &pci->ep; ep->ops = &pcie_ep_ops; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2"); - pci->dbi_base2 = devm_ioremap_resource(dev, res); + pci->dbi_base2 = devm_platform_ioremap_resource_byname(pdev, "dbi2"); if (IS_ERR(pci->dbi_base2)) return PTR_ERR(pci->dbi_base2); diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c index 811b5c6d62ea..6d3524c39a9b 100644 --- a/drivers/pci/controller/dwc/pcie-histb.c +++ b/drivers/pci/controller/dwc/pcie-histb.c @@ -304,7 +304,6 @@ static int histb_pcie_probe(struct platform_device *pdev) struct histb_pcie *hipcie; struct dw_pcie *pci; struct pcie_port *pp; - struct resource *res; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; enum of_gpio_flags of_flags; @@ -324,15 +323,13 @@ static int histb_pcie_probe(struct platform_device *pdev) pci->dev = dev; pci->ops = &dw_pcie_ops; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); - hipcie->ctrl = devm_ioremap_resource(dev, res); + hipcie->ctrl = devm_platform_ioremap_resource_byname(pdev, "control"); if (IS_ERR(hipcie->ctrl)) { dev_err(dev, "cannot get control reg base\n"); return PTR_ERR(hipcie->ctrl); } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc-dbi"); - pci->dbi_base = devm_ioremap_resource(dev, res); + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "rc-dbi"); if (IS_ERR(pci->dbi_base)) { dev_err(dev, "cannot get rc-dbi base\n"); return PTR_ERR(pci->dbi_base); diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 2d8dbb318087..c3b3a1d162b5 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -253,11 +253,9 @@ static int intel_pcie_get_resources(struct platform_device *pdev) struct intel_pcie_port *lpp = platform_get_drvdata(pdev); struct dw_pcie *pci = &lpp->pci; struct device *dev = pci->dev; - struct resource *res; int ret; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - pci->dbi_base = devm_ioremap_resource(dev, res); + pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "dbi"); if (IS_ERR(pci->dbi_base)) return PTR_ERR(pci->dbi_base); @@ -291,8 +289,7 @@ static int intel_pcie_get_resources(struct platform_device *pdev) ret = of_pci_get_max_link_speed(dev->of_node); lpp->link_gen = ret < 0 ? 0 : ret; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app"); - lpp->app_base = devm_ioremap_resource(dev, res); + lpp->app_base = devm_platform_ioremap_resource_byname(pdev, "app"); if (IS_ERR(lpp->app_base)) return PTR_ERR(lpp->app_base); diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c index c19617a912bd..e5e765038686 100644 --- a/drivers/pci/controller/dwc/pcie-kirin.c +++ b/drivers/pci/controller/dwc/pcie-kirin.c @@ -147,23 +147,18 @@ static long kirin_pcie_get_clk(struct kirin_pcie *kirin_pcie, static long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct resource *apb; - struct resource *phy; - struct resource *dbi; - - apb = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb"); - kirin_pcie->apb_base = devm_ioremap_resource(dev, apb); + kirin_pcie->apb_base = + devm_platform_ioremap_resource_byname(pdev, "apb"); if (IS_ERR(kirin_pcie->apb_base)) return PTR_ERR(kirin_pcie->apb_base); - phy = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); - kirin_pcie->phy_base = devm_ioremap_resource(dev, phy); + kirin_pcie->phy_base = + devm_platform_ioremap_resource_byname(pdev, "phy"); if (IS_ERR(kirin_pcie->phy_base)) return PTR_ERR(kirin_pcie->phy_base); - dbi = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - kirin_pcie->pci->dbi_base = devm_ioremap_resource(dev, dbi); + kirin_pcie->pci->dbi_base = + devm_platform_ioremap_resource_byname(pdev, "dbi"); if (IS_ERR(kirin_pcie->pci->dbi_base)) return PTR_ERR(kirin_pcie->pci->dbi_base); diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 73d4eed26f65..b79f7878c993 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1405,8 +1405,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) if (pcie->gen < 0) pcie->gen = 2; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); - pcie->parf = devm_ioremap_resource(dev, res); + pcie->parf = devm_platform_ioremap_resource_byname(pdev, "parf"); if (IS_ERR(pcie->parf)) { ret = PTR_ERR(pcie->parf); goto err_pm_runtime_put; @@ -1419,8 +1418,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_pm_runtime_put; } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); - pcie->elbi = devm_ioremap_resource(dev, res); + pcie->elbi = devm_platform_ioremap_resource_byname(pdev, "elbi"); if (IS_ERR(pcie->elbi)) { ret = PTR_ERR(pcie->elbi); goto err_pm_runtime_put; diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c index a5401a0b1e58..3a7f403b57b8 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier.c +++ b/drivers/pci/controller/dwc/pcie-uniphier.c @@ -416,8 +416,7 @@ static int uniphier_pcie_probe(struct platform_device *pdev) if (IS_ERR(priv->pci.dbi_base)) return PTR_ERR(priv->pci.dbi_base); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "link"); - priv->base = devm_ioremap_resource(dev, res); + priv->base = devm_platform_ioremap_resource_byname(pdev, "link"); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); -- cgit v1.2.3 From c2fa6cf76d204e296e2e295d821500e0b291697d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 24 Jul 2020 16:42:04 -0600 Subject: PCI: dwc: hisi: Remove non-ECAM HiSilicon hip05/hip06 driver The HiSilicon non-ECAM PCIe has been broken since March 2016 commit 7e57fd1444bf ("PCI: designware: Move Root Complex setup code to dw_pcie_setup_rc()"). The reason is this commit moved the iATU setup code from dw_pcie_host_init() to dw_pcie_setup_rc(), but the hisi driver never calls dw_pcie_setup_rc(). The result is the PCI memory space is never configured and the driver can't work. It's also clear it has an iATU as the config space accesses use it. There's also no dts file using either "hisilicon,hip05-pcie" or "hisilicon,hip06-pcie". Link: https://lore.kernel.org/r/20200724224204.3249055-1-robh@kernel.org Signed-off-by: Rob Herring Signed-off-by: Lorenzo Pieralisi Cc: Zhou Wang Cc: Lorenzo Pieralisi Cc: Bjorn Helgaas --- drivers/pci/controller/dwc/pcie-hisi.c | 219 --------------------------------- 1 file changed, 219 deletions(-) (limited to 'drivers/pci') diff --git a/drivers/pci/controller/dwc/pcie-hisi.c b/drivers/pci/controller/dwc/pcie-hisi.c index 0ad4e07dd4c2..5ca86796d43a 100644 --- a/drivers/pci/controller/dwc/pcie-hisi.c +++ b/drivers/pci/controller/dwc/pcie-hisi.c @@ -10,15 +10,10 @@ */ #include #include -#include -#include -#include #include -#include #include #include #include -#include #include "../../pci.h" #if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) @@ -118,220 +113,6 @@ const struct pci_ecam_ops hisi_pcie_ops = { #ifdef CONFIG_PCI_HISI -#include "pcie-designware.h" - -#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818 -#define PCIE_HIP06_CTRL_OFF 0x1000 -#define PCIE_SYS_STATE4 (PCIE_HIP06_CTRL_OFF + 0x31c) -#define PCIE_LTSSM_LINKUP_STATE 0x11 -#define PCIE_LTSSM_STATE_MASK 0x3F - -#define to_hisi_pcie(x) dev_get_drvdata((x)->dev) - -struct hisi_pcie; - -struct pcie_soc_ops { - int (*hisi_pcie_link_up)(struct hisi_pcie *hisi_pcie); -}; - -struct hisi_pcie { - struct dw_pcie *pci; - struct regmap *subctrl; - u32 port_id; - const struct pcie_soc_ops *soc_ops; -}; - -/* HipXX PCIe host only supports 32-bit config access */ -static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, - u32 *val) -{ - u32 reg; - u32 reg_val; - void *walker = ®_val; - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - - walker += (where & 0x3); - reg = where & ~0x3; - reg_val = dw_pcie_readl_dbi(pci, reg); - - if (size == 1) - *val = *(u8 __force *) walker; - else if (size == 2) - *val = *(u16 __force *) walker; - else if (size == 4) - *val = reg_val; - else - return PCIBIOS_BAD_REGISTER_NUMBER; - - return PCIBIOS_SUCCESSFUL; -} - -/* HipXX PCIe host only supports 32-bit config access */ -static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, - u32 val) -{ - u32 reg_val; - u32 reg; - void *walker = ®_val; - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - - walker += (where & 0x3); - reg = where & ~0x3; - if (size == 4) - dw_pcie_writel_dbi(pci, reg, val); - else if (size == 2) { - reg_val = dw_pcie_readl_dbi(pci, reg); - *(u16 __force *) walker = val; - dw_pcie_writel_dbi(pci, reg, reg_val); - } else if (size == 1) { - reg_val = dw_pcie_readl_dbi(pci, reg); - *(u8 __force *) walker = val; - dw_pcie_writel_dbi(pci, reg, reg_val); - } else - return PCIBIOS_BAD_REGISTER_NUMBER; - - return PCIBIOS_SUCCESSFUL; -} - -static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie) -{ - u32 val; - - regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG + - 0x100 * hisi_pcie->port_id, &val); - - return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); -} - -static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie) -{ - struct dw_pcie *pci = hisi_pcie->pci; - u32 val; - - val = dw_pcie_readl_dbi(pci, PCIE_SYS_STATE4); - - return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); -} - -static int hisi_pcie_link_up(struct dw_pcie *pci) -{ - struct hisi_pcie *hisi_pcie = to_hisi_pcie(pci); - - return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie); -} - -static const struct dw_pcie_host_ops hisi_pcie_host_ops = { - .rd_own_conf = hisi_pcie_cfg_read, - .wr_own_conf = hisi_pcie_cfg_write, -}; - -static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie, - struct platform_device *pdev) -{ - struct dw_pcie *pci = hisi_pcie->pci; - struct pcie_port *pp = &pci->pp; - struct device *dev = &pdev->dev; - int ret; - u32 port_id; - - if (of_property_read_u32(dev->of_node, "port-id", &port_id)) { - dev_err(dev, "failed to read port-id\n"); - return -EINVAL; - } - if (port_id > 3) { - dev_err(dev, "Invalid port-id: %d\n", port_id); - return -EINVAL; - } - hisi_pcie->port_id = port_id; - - pp->ops = &hisi_pcie_host_ops; - - ret = dw_pcie_host_init(pp); - if (ret) { - dev_err(dev, "failed to initialize host\n"); - return ret; - } - - return 0; -} - -static const struct dw_pcie_ops dw_pcie_ops = { - .link_up = hisi_pcie_link_up, -}; - -static int hisi_pcie_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct dw_pcie *pci; - struct hisi_pcie *hisi_pcie; - struct resource *reg; - int ret; - - hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL); - if (!hisi_pcie) - return -ENOMEM; - - pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); - if (!pci) - return -ENOMEM; - - pci->dev = dev; - pci->ops = &dw_pcie_ops; - - hisi_pcie->pci = pci; - - hisi_pcie->soc_ops = of_device_get_match_data(dev); - - hisi_pcie->subctrl = - syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl"); - if (IS_ERR(hisi_pcie->subctrl)) { - dev_err(dev, "cannot get subctrl base\n"); - return PTR_ERR(hisi_pcie->subctrl); - } - - reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi"); - pci->dbi_base = devm_pci_remap_cfg_resource(dev, reg); - if (IS_ERR(pci->dbi_base)) - return PTR_ERR(pci->dbi_base); - platform_set_drvdata(pdev, hisi_pcie); - - ret = hisi_add_pcie_port(hisi_pcie, pdev); - if (ret) - return ret; - - return 0; -} - -static struct pcie_soc_ops hip05_ops = { - &hisi_pcie_link_up_hip05 -}; - -static struct pcie_soc_ops hip06_ops = { - &hisi_pcie_link_up_hip06 -}; - -static const struct of_device_id hisi_pcie_of_match[] = { - { - .compatible = "hisilicon,hip05-pcie", - .data = (void *) &hip05_ops, - }, - { - .compatible = "hisilicon,hip06-pcie", - .data = (void *) &hip06_ops, - }, - {}, -}; - -static struct platform_driver hisi_pcie_driver = { - .probe = hisi_pcie_probe, - .driver = { - .name = "hisi-pcie", - .of_match_table = hisi_pcie_of_match, - .suppress_bind_attrs = true, - }, -}; -builtin_platform_driver(hisi_pcie_driver); - static int hisi_pcie_platform_init(struct pci_config_window *cfg) { struct device *dev = cfg->parent; -- cgit v1.2.3