* [PATCH v7 0/4] i.MX7 PCI support @ 2017-03-21 13:41 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:41 UTC (permalink / raw) To: linux-pci Cc: Andrey Smirnov, yurovsky, Lucas Stach, Fabio Estevam, Dong Aisheng, Bjorn Helgaas, Rob Herring, linux-arm-kernel, linux-kernel Hello, everyone: This is a seventh iteration of the code that adds PCI-subsystem bits necessary for enabling PCI support on i.MX7. NOTE: To test this patchset with real i.MX7 hardware, additional patches, that are being upstreamed via different trees, are needed. Full working tree is availible at: https://github.com/ndreys/linux/tree/imx7d/pcie-support-v7 Changes since v6 (can be found at [version6]): - Rebased against latest changes in 'next' of PCI subsystem git tree Chagnes since v5 (can be found at [version5]): - Collected ACKs from Lee and Rob Changes since v4 (can be found at [version4]): - Dropped typo-fix patch (originally patch #1 of the series). - Added patch with workaround to address speed change false failures (I kept it as a separate patch to better document exchange with NXP/Freescale that lead to that patch) - Added patch to avoid speed change on links configured Gen1 only (Let me know if that is a terrible idea) - Addressed section mismatch problem by moving call to hook_fault_code to happend before driver registration. Changes since v3 (can be found at [version3]): - Move all of the reset_control_assert's into imx6_pcie_assert_core_reset - Documented required reset and power domain DT bindings Changes since v2 (can be found at [version2]): - Collected Reviewed-by for patch #2 from Lucas - Reset logic implementation moved out into a reset controller driver (see [reset1]) - Removed unused leftover code Changes since v1 (can be found at [version1]): - All GPC related code moved into a separate driver (see [gpc1]) - Removed GPIO probe deferral logging - Fixed section mismatch warning - Minor reformatting of fsl,imx6q-pcie.txt(as per Rob Herring's request) [version6] https://lkml.org/lkml/2017/3/14/584 [version5] https://lkml.org/lkml/2017/2/20/376 [version4] https://lkml.org/lkml/2017/2/7/478 [version3] https://lkml.org/lkml/2017/2/6/565 [version2] https://lkml.org/lkml/2017/2/1/510 [version1] https://lkml.org/lkml/2017/1/19/488 [gpc1] https://lkml.org/lkml/2017/2/6/551 [reset1] https://lkml.org/lkml/2017/2/6/554 Andrey Smirnov (4): PCI: imx6: Add code to support i.MX7D PCI: imx6: Allow probe deferal by reset GPIO PCI: imx6: Do not wait for speed change on i.MX7 PCI: imx6: Do not switch speed if Gen2 is disabled .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 13 +- drivers/pci/dwc/pci-imx6.c | 198 +++++++++++++++------ include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 4 + 3 files changed, 160 insertions(+), 55 deletions(-) -- 2.9.3 ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 0/4] i.MX7 PCI support @ 2017-03-21 13:41 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:41 UTC (permalink / raw) To: linux-arm-kernel Hello, everyone: This is a seventh iteration of the code that adds PCI-subsystem bits necessary for enabling PCI support on i.MX7. NOTE: To test this patchset with real i.MX7 hardware, additional patches, that are being upstreamed via different trees, are needed. Full working tree is availible at: https://github.com/ndreys/linux/tree/imx7d/pcie-support-v7 Changes since v6 (can be found at [version6]): - Rebased against latest changes in 'next' of PCI subsystem git tree Chagnes since v5 (can be found at [version5]): - Collected ACKs from Lee and Rob Changes since v4 (can be found at [version4]): - Dropped typo-fix patch (originally patch #1 of the series). - Added patch with workaround to address speed change false failures (I kept it as a separate patch to better document exchange with NXP/Freescale that lead to that patch) - Added patch to avoid speed change on links configured Gen1 only (Let me know if that is a terrible idea) - Addressed section mismatch problem by moving call to hook_fault_code to happend before driver registration. Changes since v3 (can be found at [version3]): - Move all of the reset_control_assert's into imx6_pcie_assert_core_reset - Documented required reset and power domain DT bindings Changes since v2 (can be found at [version2]): - Collected Reviewed-by for patch #2 from Lucas - Reset logic implementation moved out into a reset controller driver (see [reset1]) - Removed unused leftover code Changes since v1 (can be found at [version1]): - All GPC related code moved into a separate driver (see [gpc1]) - Removed GPIO probe deferral logging - Fixed section mismatch warning - Minor reformatting of fsl,imx6q-pcie.txt(as per Rob Herring's request) [version6] https://lkml.org/lkml/2017/3/14/584 [version5] https://lkml.org/lkml/2017/2/20/376 [version4] https://lkml.org/lkml/2017/2/7/478 [version3] https://lkml.org/lkml/2017/2/6/565 [version2] https://lkml.org/lkml/2017/2/1/510 [version1] https://lkml.org/lkml/2017/1/19/488 [gpc1] https://lkml.org/lkml/2017/2/6/551 [reset1] https://lkml.org/lkml/2017/2/6/554 Andrey Smirnov (4): PCI: imx6: Add code to support i.MX7D PCI: imx6: Allow probe deferal by reset GPIO PCI: imx6: Do not wait for speed change on i.MX7 PCI: imx6: Do not switch speed if Gen2 is disabled .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 13 +- drivers/pci/dwc/pci-imx6.c | 198 +++++++++++++++------ include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 4 + 3 files changed, 160 insertions(+), 55 deletions(-) -- 2.9.3 ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 0/4] i.MX7 PCI support @ 2017-03-21 13:41 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:41 UTC (permalink / raw) To: linux-pci Cc: Dong Aisheng, Andrey Smirnov, linux-kernel, Bjorn Helgaas, Rob Herring, Fabio Estevam, yurovsky, linux-arm-kernel, Lucas Stach Hello, everyone: This is a seventh iteration of the code that adds PCI-subsystem bits necessary for enabling PCI support on i.MX7. NOTE: To test this patchset with real i.MX7 hardware, additional patches, that are being upstreamed via different trees, are needed. Full working tree is availible at: https://github.com/ndreys/linux/tree/imx7d/pcie-support-v7 Changes since v6 (can be found at [version6]): - Rebased against latest changes in 'next' of PCI subsystem git tree Chagnes since v5 (can be found at [version5]): - Collected ACKs from Lee and Rob Changes since v4 (can be found at [version4]): - Dropped typo-fix patch (originally patch #1 of the series). - Added patch with workaround to address speed change false failures (I kept it as a separate patch to better document exchange with NXP/Freescale that lead to that patch) - Added patch to avoid speed change on links configured Gen1 only (Let me know if that is a terrible idea) - Addressed section mismatch problem by moving call to hook_fault_code to happend before driver registration. Changes since v3 (can be found at [version3]): - Move all of the reset_control_assert's into imx6_pcie_assert_core_reset - Documented required reset and power domain DT bindings Changes since v2 (can be found at [version2]): - Collected Reviewed-by for patch #2 from Lucas - Reset logic implementation moved out into a reset controller driver (see [reset1]) - Removed unused leftover code Changes since v1 (can be found at [version1]): - All GPC related code moved into a separate driver (see [gpc1]) - Removed GPIO probe deferral logging - Fixed section mismatch warning - Minor reformatting of fsl,imx6q-pcie.txt(as per Rob Herring's request) [version6] https://lkml.org/lkml/2017/3/14/584 [version5] https://lkml.org/lkml/2017/2/20/376 [version4] https://lkml.org/lkml/2017/2/7/478 [version3] https://lkml.org/lkml/2017/2/6/565 [version2] https://lkml.org/lkml/2017/2/1/510 [version1] https://lkml.org/lkml/2017/1/19/488 [gpc1] https://lkml.org/lkml/2017/2/6/551 [reset1] https://lkml.org/lkml/2017/2/6/554 Andrey Smirnov (4): PCI: imx6: Add code to support i.MX7D PCI: imx6: Allow probe deferal by reset GPIO PCI: imx6: Do not wait for speed change on i.MX7 PCI: imx6: Do not switch speed if Gen2 is disabled .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 13 +- drivers/pci/dwc/pci-imx6.c | 198 +++++++++++++++------ include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 4 + 3 files changed, 160 insertions(+), 55 deletions(-) -- 2.9.3 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 1/4] PCI: imx6: Add code to support i.MX7D 2017-03-21 13:41 ` Andrey Smirnov @ 2017-03-21 13:42 ` Andrey Smirnov -1 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-pci Cc: Andrey Smirnov, yurovsky, Lucas Stach, Bjorn Helgaas, Rob Herring, Mark Rutland, Lee Jones, Fabio Estevam, Dong Aisheng, linux-arm-kernel, devicetree, linux-kernel Add various bits of code needed to support i.MX7D variant of the IP. Cc: yurovsky@gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Lee Jones <lee.jones@linaro.org> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 13 ++- drivers/pci/dwc/pci-imx6.c | 120 ++++++++++++++++----- include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 4 + 3 files changed, 111 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt index 83aeb1f..11db2ab 100644 --- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt @@ -4,7 +4,11 @@ This PCIe host controller is based on the Synopsis Designware PCIe IP and thus inherits all the common properties defined in designware-pcie.txt. Required properties: -- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie", "fsl,imx6qp-pcie" +- compatible: + - "fsl,imx6q-pcie" + - "fsl,imx6sx-pcie", + - "fsl,imx6qp-pcie" + - "fsl,imx7d-pcie" - reg: base address and length of the PCIe controller - interrupts: A list of interrupt outputs of the controller. Must contain an entry for each entry in the interrupt-names property. @@ -34,6 +38,13 @@ Additional required properties for imx6sx-pcie: - clock names: Must include the following additional entries: - "pcie_inbound_axi" +Additional required properties for imx7d-pcie: +- power-domains: Must be set to a phandle pointing to PCIE_PHY power domain +- resets: Must contain phandles to PCIE related reset lines exposed by SRC IP block +- reset-names: Must contain the following entires: + - "pciephy" + - "apps" + Example: pcie@0x01000000 { diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 801e46c..e0c36d6 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/mfd/syscon/imx7-iomuxc-gpr.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/of_device.h> @@ -27,6 +28,7 @@ #include <linux/signal.h> #include <linux/types.h> #include <linux/interrupt.h> +#include <linux/reset.h> #include "pcie-designware.h" @@ -36,6 +38,7 @@ enum imx6_pcie_variants { IMX6Q, IMX6SX, IMX6QP, + IMX7D, }; struct imx6_pcie { @@ -47,6 +50,8 @@ struct imx6_pcie { struct clk *pcie_inbound_axi; struct clk *pcie; struct regmap *iomuxc_gpr; + struct reset_control *pciephy_reset; + struct reset_control *apps_reset; enum imx6_pcie_variants variant; u32 tx_deemph_gen1; u32 tx_deemph_gen2_3p5db; @@ -56,6 +61,11 @@ struct imx6_pcie { int link_gen; }; +/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ +#define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000 +#define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50 +#define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200 + /* PCIe Root Complex registers (memory-mapped) */ #define PCIE_RC_LCR 0x7c #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 @@ -248,6 +258,10 @@ static int imx6q_pcie_abort_handler(unsigned long addr, static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { switch (imx6_pcie->variant) { + case IMX7D: + reset_control_assert(imx6_pcie->pciephy_reset); + reset_control_assert(imx6_pcie->apps_reset); + break; case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, @@ -303,11 +317,32 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); break; + case IMX7D: + break; } return ret; } +static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie) +{ + u32 val; + unsigned int retries; + struct device *dev = imx6_pcie->pci->dev; + + for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) { + regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val); + + if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED) + return; + + usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN, + PHY_PLL_LOCK_WAIT_USLEEP_MAX); + } + + dev_err(dev, "PCIe PLL lock timeout\n"); +} + static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) { struct dw_pcie *pci = imx6_pcie->pci; @@ -351,6 +386,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) } switch (imx6_pcie->variant) { + case IMX7D: + reset_control_deassert(imx6_pcie->pciephy_reset); + imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); + break; case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); @@ -377,35 +416,44 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) { - if (imx6_pcie->variant == IMX6SX) + switch (imx6_pcie->variant) { + case IMX7D: + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); + break; + case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_RX_EQ_MASK, IMX6SX_GPR12_PCIE_RX_EQ_2); + /* FALLTHROUGH */ + default: + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); + /* configure constant input signal to the pcie ctrl and phy */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_LOS_LEVEL, 9 << 4); + + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN1, + imx6_pcie->tx_deemph_gen1 << 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, + imx6_pcie->tx_deemph_gen2_3p5db << 6); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, + imx6_pcie->tx_deemph_gen2_6db << 12); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_SWING_FULL, + imx6_pcie->tx_swing_full << 18); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_SWING_LOW, + imx6_pcie->tx_swing_low << 25); + break; + } - /* configure constant input signal to the pcie ctrl and phy */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_LOS_LEVEL, 9 << 4); - - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN1, - imx6_pcie->tx_deemph_gen1 << 0); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, - imx6_pcie->tx_deemph_gen2_3p5db << 6); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, - imx6_pcie->tx_deemph_gen2_6db << 12); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_SWING_FULL, - imx6_pcie->tx_swing_full << 18); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_SWING_LOW, - imx6_pcie->tx_swing_low << 25); } static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) @@ -469,8 +517,11 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); /* Start LTSSM. */ - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); + if (imx6_pcie->variant == IMX7D) + reset_control_deassert(imx6_pcie->apps_reset); + else + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); ret = imx6_pcie_wait_for_link(imx6_pcie); if (ret) @@ -653,13 +704,31 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) return PTR_ERR(imx6_pcie->pcie); } - if (imx6_pcie->variant == IMX6SX) { + switch (imx6_pcie->variant) { + case IMX6SX: imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, "pcie_inbound_axi"); if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { dev_err(dev, "pcie_inbound_axi clock missing or invalid\n"); return PTR_ERR(imx6_pcie->pcie_inbound_axi); } + break; + case IMX7D: + imx6_pcie->pciephy_reset = devm_reset_control_get(dev, + "pciephy"); + if (IS_ERR(imx6_pcie->pciephy_reset)) { + dev_err(dev, "Failed to get PCIEPHY reset contol\n"); + return PTR_ERR(imx6_pcie->pciephy_reset); + } + + imx6_pcie->apps_reset = devm_reset_control_get(dev, "apps"); + if (IS_ERR(imx6_pcie->apps_reset)) { + dev_err(dev, "Failed to get PCIE APPS reset contol\n"); + return PTR_ERR(imx6_pcie->apps_reset); + } + break; + default: + break; } /* Grab GPR config register range */ @@ -718,6 +787,7 @@ static const struct of_device_id imx6_pcie_of_match[] = { { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, }, { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, + { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, }, {}, }; diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h index 4585d61..abbd524 100644 --- a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h @@ -44,4 +44,8 @@ #define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI (0x1 << 4) +#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5) + +#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31) + #endif /* __LINUX_IMX7_IOMUXC_GPR_H */ -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 1/4] PCI: imx6: Add code to support i.MX7D @ 2017-03-21 13:42 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-arm-kernel Add various bits of code needed to support i.MX7D variant of the IP. Cc: yurovsky at gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Lee Jones <lee.jones@linaro.org> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel at lists.infradead.org Cc: devicetree at vger.kernel.org Cc: linux-kernel at vger.kernel.org Acked-by: Lee Jones <lee.jones@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- .../devicetree/bindings/pci/fsl,imx6q-pcie.txt | 13 ++- drivers/pci/dwc/pci-imx6.c | 120 ++++++++++++++++----- include/linux/mfd/syscon/imx7-iomuxc-gpr.h | 4 + 3 files changed, 111 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt index 83aeb1f..11db2ab 100644 --- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt @@ -4,7 +4,11 @@ This PCIe host controller is based on the Synopsis Designware PCIe IP and thus inherits all the common properties defined in designware-pcie.txt. Required properties: -- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie", "fsl,imx6qp-pcie" +- compatible: + - "fsl,imx6q-pcie" + - "fsl,imx6sx-pcie", + - "fsl,imx6qp-pcie" + - "fsl,imx7d-pcie" - reg: base address and length of the PCIe controller - interrupts: A list of interrupt outputs of the controller. Must contain an entry for each entry in the interrupt-names property. @@ -34,6 +38,13 @@ Additional required properties for imx6sx-pcie: - clock names: Must include the following additional entries: - "pcie_inbound_axi" +Additional required properties for imx7d-pcie: +- power-domains: Must be set to a phandle pointing to PCIE_PHY power domain +- resets: Must contain phandles to PCIE related reset lines exposed by SRC IP block +- reset-names: Must contain the following entires: + - "pciephy" + - "apps" + Example: pcie at 0x01000000 { diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 801e46c..e0c36d6 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/mfd/syscon/imx7-iomuxc-gpr.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/of_device.h> @@ -27,6 +28,7 @@ #include <linux/signal.h> #include <linux/types.h> #include <linux/interrupt.h> +#include <linux/reset.h> #include "pcie-designware.h" @@ -36,6 +38,7 @@ enum imx6_pcie_variants { IMX6Q, IMX6SX, IMX6QP, + IMX7D, }; struct imx6_pcie { @@ -47,6 +50,8 @@ struct imx6_pcie { struct clk *pcie_inbound_axi; struct clk *pcie; struct regmap *iomuxc_gpr; + struct reset_control *pciephy_reset; + struct reset_control *apps_reset; enum imx6_pcie_variants variant; u32 tx_deemph_gen1; u32 tx_deemph_gen2_3p5db; @@ -56,6 +61,11 @@ struct imx6_pcie { int link_gen; }; +/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ +#define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000 +#define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50 +#define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200 + /* PCIe Root Complex registers (memory-mapped) */ #define PCIE_RC_LCR 0x7c #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 @@ -248,6 +258,10 @@ static int imx6q_pcie_abort_handler(unsigned long addr, static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { switch (imx6_pcie->variant) { + case IMX7D: + reset_control_assert(imx6_pcie->pciephy_reset); + reset_control_assert(imx6_pcie->apps_reset); + break; case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, @@ -303,11 +317,32 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); break; + case IMX7D: + break; } return ret; } +static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie) +{ + u32 val; + unsigned int retries; + struct device *dev = imx6_pcie->pci->dev; + + for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) { + regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val); + + if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED) + return; + + usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN, + PHY_PLL_LOCK_WAIT_USLEEP_MAX); + } + + dev_err(dev, "PCIe PLL lock timeout\n"); +} + static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) { struct dw_pcie *pci = imx6_pcie->pci; @@ -351,6 +386,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) } switch (imx6_pcie->variant) { + case IMX7D: + reset_control_deassert(imx6_pcie->pciephy_reset); + imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie); + break; case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5, IMX6SX_GPR5_PCIE_BTNRST_RESET, 0); @@ -377,35 +416,44 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) { - if (imx6_pcie->variant == IMX6SX) + switch (imx6_pcie->variant) { + case IMX7D: + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0); + break; + case IMX6SX: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_RX_EQ_MASK, IMX6SX_GPR12_PCIE_RX_EQ_2); + /* FALLTHROUGH */ + default: + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); + /* configure constant input signal to the pcie ctrl and phy */ + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_LOS_LEVEL, 9 << 4); + + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN1, + imx6_pcie->tx_deemph_gen1 << 0); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, + imx6_pcie->tx_deemph_gen2_3p5db << 6); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, + imx6_pcie->tx_deemph_gen2_6db << 12); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_SWING_FULL, + imx6_pcie->tx_swing_full << 18); + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, + IMX6Q_GPR8_TX_SWING_LOW, + imx6_pcie->tx_swing_low << 25); + break; + } - /* configure constant input signal to the pcie ctrl and phy */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_LOS_LEVEL, 9 << 4); - - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN1, - imx6_pcie->tx_deemph_gen1 << 0); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, - imx6_pcie->tx_deemph_gen2_3p5db << 6); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, - imx6_pcie->tx_deemph_gen2_6db << 12); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_SWING_FULL, - imx6_pcie->tx_swing_full << 18); - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, - IMX6Q_GPR8_TX_SWING_LOW, - imx6_pcie->tx_swing_low << 25); } static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) @@ -469,8 +517,11 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); /* Start LTSSM. */ - regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, - IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); + if (imx6_pcie->variant == IMX7D) + reset_control_deassert(imx6_pcie->apps_reset); + else + regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, + IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); ret = imx6_pcie_wait_for_link(imx6_pcie); if (ret) @@ -653,13 +704,31 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) return PTR_ERR(imx6_pcie->pcie); } - if (imx6_pcie->variant == IMX6SX) { + switch (imx6_pcie->variant) { + case IMX6SX: imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, "pcie_inbound_axi"); if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { dev_err(dev, "pcie_inbound_axi clock missing or invalid\n"); return PTR_ERR(imx6_pcie->pcie_inbound_axi); } + break; + case IMX7D: + imx6_pcie->pciephy_reset = devm_reset_control_get(dev, + "pciephy"); + if (IS_ERR(imx6_pcie->pciephy_reset)) { + dev_err(dev, "Failed to get PCIEPHY reset contol\n"); + return PTR_ERR(imx6_pcie->pciephy_reset); + } + + imx6_pcie->apps_reset = devm_reset_control_get(dev, "apps"); + if (IS_ERR(imx6_pcie->apps_reset)) { + dev_err(dev, "Failed to get PCIE APPS reset contol\n"); + return PTR_ERR(imx6_pcie->apps_reset); + } + break; + default: + break; } /* Grab GPR config register range */ @@ -718,6 +787,7 @@ static const struct of_device_id imx6_pcie_of_match[] = { { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, }, { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, + { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, }, {}, }; diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h index 4585d61..abbd524 100644 --- a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h +++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h @@ -44,4 +44,8 @@ #define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI (0x1 << 4) +#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5) + +#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31) + #endif /* __LINUX_IMX7_IOMUXC_GPR_H */ -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO 2017-03-21 13:41 ` Andrey Smirnov (?) @ 2017-03-21 13:42 ` Andrey Smirnov -1 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-pci Cc: Andrey Smirnov, yurovsky, Lucas Stach, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel Some designs implement reset GPIO via a GPIO expander connected to a peripheral bus. One such example would be i.MX7 Sabre board where said GPIO is provided by SPI shift register connected to a bitbanged SPI bus. In order to support such designs allow reset GPIO request to defer probing of the driver. Cc: yurovsky@gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index e0c36d6..64de9bb 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { .host_init = imx6_pcie_host_init, }; -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, - struct platform_device *pdev) +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, + struct platform_device *pdev) { struct dw_pcie *pci = imx6_pcie->pci; struct pcie_port *pp = &pci->pp; @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { .link_up = imx6_pcie_link_up, }; -static int __init imx6_pcie_probe(struct platform_device *pdev) +static int imx6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dw_pcie *pci; @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) imx6_pcie->variant = (enum imx6_pcie_variants)of_device_get_match_data(dev); - /* Added for PCI abort handling */ - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, - "imprecise external abort"); - dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); pci->dbi_base = devm_ioremap_resource(dev, dbi_base); if (IS_ERR(pci->dbi_base)) @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) dev_err(dev, "unable to get reset gpio\n"); return ret; } + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { + return imx6_pcie->reset_gpio; } /* Fetch clocks */ @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { .name = "imx6q-pcie", .of_match_table = imx6_pcie_of_match, }, + .probe = imx6_pcie_probe, .shutdown = imx6_pcie_shutdown, }; static int __init imx6_pcie_init(void) { - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); + /* + * Since probe() can be deferred we need to make sure that + * hook_fault_code is not called after __init memory is freed + * by kernel and since imx6q_pcie_abort_handler() is a no-op + * we can install the handler here without risking it + * accessing some unitialized driver state + */ + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, + "imprecise external abort"); + + return platform_driver_register(&imx6_pcie_driver); } device_initcall(imx6_pcie_init); -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO @ 2017-03-21 13:42 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-arm-kernel Some designs implement reset GPIO via a GPIO expander connected to a peripheral bus. One such example would be i.MX7 Sabre board where said GPIO is provided by SPI shift register connected to a bitbanged SPI bus. In order to support such designs allow reset GPIO request to defer probing of the driver. Cc: yurovsky at gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel at lists.infradead.org Cc: linux-kernel at vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index e0c36d6..64de9bb 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { .host_init = imx6_pcie_host_init, }; -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, - struct platform_device *pdev) +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, + struct platform_device *pdev) { struct dw_pcie *pci = imx6_pcie->pci; struct pcie_port *pp = &pci->pp; @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { .link_up = imx6_pcie_link_up, }; -static int __init imx6_pcie_probe(struct platform_device *pdev) +static int imx6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dw_pcie *pci; @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) imx6_pcie->variant = (enum imx6_pcie_variants)of_device_get_match_data(dev); - /* Added for PCI abort handling */ - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, - "imprecise external abort"); - dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); pci->dbi_base = devm_ioremap_resource(dev, dbi_base); if (IS_ERR(pci->dbi_base)) @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) dev_err(dev, "unable to get reset gpio\n"); return ret; } + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { + return imx6_pcie->reset_gpio; } /* Fetch clocks */ @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { .name = "imx6q-pcie", .of_match_table = imx6_pcie_of_match, }, + .probe = imx6_pcie_probe, .shutdown = imx6_pcie_shutdown, }; static int __init imx6_pcie_init(void) { - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); + /* + * Since probe() can be deferred we need to make sure that + * hook_fault_code is not called after __init memory is freed + * by kernel and since imx6q_pcie_abort_handler() is a no-op + * we can install the handler here without risking it + * accessing some unitialized driver state + */ + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, + "imprecise external abort"); + + return platform_driver_register(&imx6_pcie_driver); } device_initcall(imx6_pcie_init); -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO @ 2017-03-21 13:42 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-pci Cc: Dong Aisheng, Andrey Smirnov, linux-kernel, Fabio Estevam, Bjorn Helgaas, yurovsky, linux-arm-kernel, Lucas Stach Some designs implement reset GPIO via a GPIO expander connected to a peripheral bus. One such example would be i.MX7 Sabre board where said GPIO is provided by SPI shift register connected to a bitbanged SPI bus. In order to support such designs allow reset GPIO request to defer probing of the driver. Cc: yurovsky@gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index e0c36d6..64de9bb 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { .host_init = imx6_pcie_host_init, }; -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, - struct platform_device *pdev) +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, + struct platform_device *pdev) { struct dw_pcie *pci = imx6_pcie->pci; struct pcie_port *pp = &pci->pp; @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { .link_up = imx6_pcie_link_up, }; -static int __init imx6_pcie_probe(struct platform_device *pdev) +static int imx6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dw_pcie *pci; @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) imx6_pcie->variant = (enum imx6_pcie_variants)of_device_get_match_data(dev); - /* Added for PCI abort handling */ - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, - "imprecise external abort"); - dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); pci->dbi_base = devm_ioremap_resource(dev, dbi_base); if (IS_ERR(pci->dbi_base)) @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) dev_err(dev, "unable to get reset gpio\n"); return ret; } + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { + return imx6_pcie->reset_gpio; } /* Fetch clocks */ @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { .name = "imx6q-pcie", .of_match_table = imx6_pcie_of_match, }, + .probe = imx6_pcie_probe, .shutdown = imx6_pcie_shutdown, }; static int __init imx6_pcie_init(void) { - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); + /* + * Since probe() can be deferred we need to make sure that + * hook_fault_code is not called after __init memory is freed + * by kernel and since imx6q_pcie_abort_handler() is a no-op + * we can install the handler here without risking it + * accessing some unitialized driver state + */ + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, + "imprecise external abort"); + + return platform_driver_register(&imx6_pcie_driver); } device_initcall(imx6_pcie_init); -- 2.9.3 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO 2017-03-21 13:42 ` Andrey Smirnov (?) @ 2017-03-21 13:49 ` Lucas Stach -1 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:49 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pci, yurovsky, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Some designs implement reset GPIO via a GPIO expander connected to a > peripheral bus. One such example would be i.MX7 Sabre board where said > GPIO is provided by SPI shift register connected to a bitbanged SPI > bus. In order to support such designs allow reset GPIO request to defer > probing of the driver. > > Cc: yurovsky@gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index e0c36d6..64de9bb 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { > .host_init = imx6_pcie_host_init, > }; > > -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > - struct platform_device *pdev) > +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > + struct platform_device *pdev) > { > struct dw_pcie *pci = imx6_pcie->pci; > struct pcie_port *pp = &pci->pp; > @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { > .link_up = imx6_pcie_link_up, > }; > > -static int __init imx6_pcie_probe(struct platform_device *pdev) > +static int imx6_pcie_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > struct dw_pcie *pci; > @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > imx6_pcie->variant = > (enum imx6_pcie_variants)of_device_get_match_data(dev); > > - /* Added for PCI abort handling */ > - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > - "imprecise external abort"); > - > dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); > pci->dbi_base = devm_ioremap_resource(dev, dbi_base); > if (IS_ERR(pci->dbi_base)) > @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > dev_err(dev, "unable to get reset gpio\n"); > return ret; > } > + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { > + return imx6_pcie->reset_gpio; > } > > /* Fetch clocks */ > @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { > .name = "imx6q-pcie", > .of_match_table = imx6_pcie_of_match, > }, > + .probe = imx6_pcie_probe, > .shutdown = imx6_pcie_shutdown, > }; > > static int __init imx6_pcie_init(void) > { > - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); > + /* > + * Since probe() can be deferred we need to make sure that > + * hook_fault_code is not called after __init memory is freed > + * by kernel and since imx6q_pcie_abort_handler() is a no-op > + * we can install the handler here without risking it > + * accessing some unitialized driver state > + */ > + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > + "imprecise external abort"); > + > + return platform_driver_register(&imx6_pcie_driver); > } > device_initcall(imx6_pcie_init); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO @ 2017-03-21 13:49 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:49 UTC (permalink / raw) To: linux-arm-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Some designs implement reset GPIO via a GPIO expander connected to a > peripheral bus. One such example would be i.MX7 Sabre board where said > GPIO is provided by SPI shift register connected to a bitbanged SPI > bus. In order to support such designs allow reset GPIO request to defer > probing of the driver. > > Cc: yurovsky at gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel at lists.infradead.org > Cc: linux-kernel at vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index e0c36d6..64de9bb 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { > .host_init = imx6_pcie_host_init, > }; > > -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > - struct platform_device *pdev) > +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > + struct platform_device *pdev) > { > struct dw_pcie *pci = imx6_pcie->pci; > struct pcie_port *pp = &pci->pp; > @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { > .link_up = imx6_pcie_link_up, > }; > > -static int __init imx6_pcie_probe(struct platform_device *pdev) > +static int imx6_pcie_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > struct dw_pcie *pci; > @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > imx6_pcie->variant = > (enum imx6_pcie_variants)of_device_get_match_data(dev); > > - /* Added for PCI abort handling */ > - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > - "imprecise external abort"); > - > dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); > pci->dbi_base = devm_ioremap_resource(dev, dbi_base); > if (IS_ERR(pci->dbi_base)) > @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > dev_err(dev, "unable to get reset gpio\n"); > return ret; > } > + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { > + return imx6_pcie->reset_gpio; > } > > /* Fetch clocks */ > @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { > .name = "imx6q-pcie", > .of_match_table = imx6_pcie_of_match, > }, > + .probe = imx6_pcie_probe, > .shutdown = imx6_pcie_shutdown, > }; > > static int __init imx6_pcie_init(void) > { > - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); > + /* > + * Since probe() can be deferred we need to make sure that > + * hook_fault_code is not called after __init memory is freed > + * by kernel and since imx6q_pcie_abort_handler() is a no-op > + * we can install the handler here without risking it > + * accessing some unitialized driver state > + */ > + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > + "imprecise external abort"); > + > + return platform_driver_register(&imx6_pcie_driver); > } > device_initcall(imx6_pcie_init); ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO @ 2017-03-21 13:49 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:49 UTC (permalink / raw) To: Andrey Smirnov Cc: Dong Aisheng, linux-pci, linux-kernel, Fabio Estevam, Bjorn Helgaas, linux-arm-kernel, yurovsky Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Some designs implement reset GPIO via a GPIO expander connected to a > peripheral bus. One such example would be i.MX7 Sabre board where said > GPIO is provided by SPI shift register connected to a bitbanged SPI > bus. In order to support such designs allow reset GPIO request to defer > probing of the driver. > > Cc: yurovsky@gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index e0c36d6..64de9bb 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -595,8 +595,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = { > .host_init = imx6_pcie_host_init, > }; > > -static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > - struct platform_device *pdev) > +static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, > + struct platform_device *pdev) > { > struct dw_pcie *pci = imx6_pcie->pci; > struct pcie_port *pp = &pci->pp; > @@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = { > .link_up = imx6_pcie_link_up, > }; > > -static int __init imx6_pcie_probe(struct platform_device *pdev) > +static int imx6_pcie_probe(struct platform_device *pdev) > { > struct device *dev = &pdev->dev; > struct dw_pcie *pci; > @@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > imx6_pcie->variant = > (enum imx6_pcie_variants)of_device_get_match_data(dev); > > - /* Added for PCI abort handling */ > - hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > - "imprecise external abort"); > - > dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); > pci->dbi_base = devm_ioremap_resource(dev, dbi_base); > if (IS_ERR(pci->dbi_base)) > @@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) > dev_err(dev, "unable to get reset gpio\n"); > return ret; > } > + } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) { > + return imx6_pcie->reset_gpio; > } > > /* Fetch clocks */ > @@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = { > .name = "imx6q-pcie", > .of_match_table = imx6_pcie_of_match, > }, > + .probe = imx6_pcie_probe, > .shutdown = imx6_pcie_shutdown, > }; > > static int __init imx6_pcie_init(void) > { > - return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); > + /* > + * Since probe() can be deferred we need to make sure that > + * hook_fault_code is not called after __init memory is freed > + * by kernel and since imx6q_pcie_abort_handler() is a no-op > + * we can install the handler here without risking it > + * accessing some unitialized driver state > + */ > + hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, > + "imprecise external abort"); > + > + return platform_driver_register(&imx6_pcie_driver); > } > device_initcall(imx6_pcie_init); _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 2017-03-21 13:41 ` Andrey Smirnov @ 2017-03-21 13:42 ` Andrey Smirnov -1 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-pci Cc: Andrey Smirnov, yurovsky, Lucas Stach, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel As can be seen from [1]: "...the different behavior between iMX6Q PCIe and iMX7D PCIe maybe caused by the different controller version. Regarding to the DOC description, the DIRECT_SPEED_CHANGE should be cleared after the speed change from GEN1 to GEN2. Unfortunately, when GEN1 device is used, the behavior is not documented. So, IC design guys run the simulation and find out the following behaviors: 1. DIRECT_SPEED_CHANGE will be cleared in 7D after speed change from GEN1 to GEN2. This matches doc’s description 2. set MAX link speed(PCIE_CAP_TARGET_LINK_SPEED=0x01) as GEN1 and re-run the simulation, DIRECT_SPEED_CHANGE will not be cleared; remain as 1, this matches your result, but function test is passed, so this bit should not affect the normal PCIe function. ..." imx6_pcie_wait_for_speed_change will report false failures for Gen1 -> Gen1 speed transition, so avoid doing that check and just rely on imx6_pcie_wait_for_link only. [1] https://community.nxp.com/message/867943 Cc: yurovsky@gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 64de9bb..c731e41 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -545,10 +545,21 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) tmp |= PORT_LOGIC_SPEED_CHANGE; dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); - if (ret) { - dev_err(dev, "Failed to bring link up!\n"); - goto err_reset_phy; + if (imx6_pcie->variant != IMX7D) { + /* + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently + * from i.MX6 family when no link speed transition + * occurs and we go Gen1 -> yep, Gen1. The difference + * is that, in such case, it will not be cleared by HW + * which will cause the following code to report false + * failure. + */ + + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + if (ret) { + dev_err(dev, "Failed to bring link up!\n"); + goto err_reset_phy; + } } /* Make sure link training is finished as well! */ -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 @ 2017-03-21 13:42 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-arm-kernel As can be seen from [1]: "...the different behavior between iMX6Q PCIe and iMX7D PCIe maybe caused by the different controller version. Regarding to the DOC description, the DIRECT_SPEED_CHANGE should be cleared after the speed change from GEN1 to GEN2. Unfortunately, when GEN1 device is used, the behavior is not documented. So, IC design guys run the simulation and find out the following behaviors: 1. DIRECT_SPEED_CHANGE will be cleared in 7D after speed change from GEN1 to GEN2. This matches doc?s description 2. set MAX link speed(PCIE_CAP_TARGET_LINK_SPEED=0x01) as GEN1 and re-run the simulation, DIRECT_SPEED_CHANGE will not be cleared; remain as 1, this matches your result, but function test is passed, so this bit should not affect the normal PCIe function. ..." imx6_pcie_wait_for_speed_change will report false failures for Gen1 -> Gen1 speed transition, so avoid doing that check and just rely on imx6_pcie_wait_for_link only. [1] https://community.nxp.com/message/867943 Cc: yurovsky at gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel at lists.infradead.org Cc: linux-kernel at vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 64de9bb..c731e41 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -545,10 +545,21 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) tmp |= PORT_LOGIC_SPEED_CHANGE; dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); - if (ret) { - dev_err(dev, "Failed to bring link up!\n"); - goto err_reset_phy; + if (imx6_pcie->variant != IMX7D) { + /* + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently + * from i.MX6 family when no link speed transition + * occurs and we go Gen1 -> yep, Gen1. The difference + * is that, in such case, it will not be cleared by HW + * which will cause the following code to report false + * failure. + */ + + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + if (ret) { + dev_err(dev, "Failed to bring link up!\n"); + goto err_reset_phy; + } } /* Make sure link training is finished as well! */ -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 2017-03-21 13:42 ` Andrey Smirnov (?) @ 2017-03-21 13:50 ` Lucas Stach -1 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:50 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pci, yurovsky, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > As can be seen from [1]: > > "...the different behavior between iMX6Q PCIe and iMX7D PCIe maybe > caused by the different controller version. > > Regarding to the DOC description, the DIRECT_SPEED_CHANGE should be > cleared after the speed change from GEN1 to GEN2. Unfortunately, when > GEN1 device is used, the behavior is not documented. > > So, IC design guys run the simulation and > find out the following behaviors: > > 1. DIRECT_SPEED_CHANGE will be cleared in 7D after speed change > from GEN1 to GEN2. This matches doc’s description > > 2. set MAX link speed(PCIE_CAP_TARGET_LINK_SPEED=0x01) as GEN1 and > re-run the simulation, DIRECT_SPEED_CHANGE will not be cleared; > remain as 1, this matches your result, but function test is > passed, so this bit should not affect the normal PCIe function. > ..." > > imx6_pcie_wait_for_speed_change will report false failures for Gen1 -> > Gen1 speed transition, so avoid doing that check and just rely on > imx6_pcie_wait_for_link only. > > [1] https://community.nxp.com/message/867943 > > Cc: yurovsky@gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 19 +++++++++++++++---- > 1 file changed, 15 insertions(+), 4 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index 64de9bb..c731e41 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -545,10 +545,21 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) > tmp |= PORT_LOGIC_SPEED_CHANGE; > dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > > - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > - if (ret) { > - dev_err(dev, "Failed to bring link up!\n"); > - goto err_reset_phy; > + if (imx6_pcie->variant != IMX7D) { > + /* > + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > + * from i.MX6 family when no link speed transition > + * occurs and we go Gen1 -> yep, Gen1. The difference > + * is that, in such case, it will not be cleared by HW > + * which will cause the following code to report false > + * failure. > + */ > + > + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + if (ret) { > + dev_err(dev, "Failed to bring link up!\n"); > + goto err_reset_phy; > + } > } > > /* Make sure link training is finished as well! */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 @ 2017-03-21 13:50 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:50 UTC (permalink / raw) To: linux-arm-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > As can be seen from [1]: > > "...the different behavior between iMX6Q PCIe and iMX7D PCIe maybe > caused by the different controller version. > > Regarding to the DOC description, the DIRECT_SPEED_CHANGE should be > cleared after the speed change from GEN1 to GEN2. Unfortunately, when > GEN1 device is used, the behavior is not documented. > > So, IC design guys run the simulation and > find out the following behaviors: > > 1. DIRECT_SPEED_CHANGE will be cleared in 7D after speed change > from GEN1 to GEN2. This matches doc?s description > > 2. set MAX link speed(PCIE_CAP_TARGET_LINK_SPEED=0x01) as GEN1 and > re-run the simulation, DIRECT_SPEED_CHANGE will not be cleared; > remain as 1, this matches your result, but function test is > passed, so this bit should not affect the normal PCIe function. > ..." > > imx6_pcie_wait_for_speed_change will report false failures for Gen1 -> > Gen1 speed transition, so avoid doing that check and just rely on > imx6_pcie_wait_for_link only. > > [1] https://community.nxp.com/message/867943 > > Cc: yurovsky at gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel at lists.infradead.org > Cc: linux-kernel at vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 19 +++++++++++++++---- > 1 file changed, 15 insertions(+), 4 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index 64de9bb..c731e41 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -545,10 +545,21 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) > tmp |= PORT_LOGIC_SPEED_CHANGE; > dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > > - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > - if (ret) { > - dev_err(dev, "Failed to bring link up!\n"); > - goto err_reset_phy; > + if (imx6_pcie->variant != IMX7D) { > + /* > + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > + * from i.MX6 family when no link speed transition > + * occurs and we go Gen1 -> yep, Gen1. The difference > + * is that, in such case, it will not be cleared by HW > + * which will cause the following code to report false > + * failure. > + */ > + > + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + if (ret) { > + dev_err(dev, "Failed to bring link up!\n"); > + goto err_reset_phy; > + } > } > > /* Make sure link training is finished as well! */ ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 @ 2017-03-21 13:50 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:50 UTC (permalink / raw) To: Andrey Smirnov Cc: Dong Aisheng, linux-pci, linux-kernel, Fabio Estevam, Bjorn Helgaas, linux-arm-kernel, yurovsky QW0gRGllbnN0YWcsIGRlbiAyMS4wMy4yMDE3LCAwNjo0MiAtMDcwMCBzY2hyaWViIEFuZHJleSBT bWlybm92Ogo+IEFzIGNhbiBiZSBzZWVuIGZyb20gWzFdOgo+IAo+ICIuLi50aGUgZGlmZmVyZW50 IGJlaGF2aW9yIGJldHdlZW4gaU1YNlEgUENJZSBhbmQgaU1YN0QgUENJZSBtYXliZQo+IGNhdXNl ZCBieSB0aGUgZGlmZmVyZW50IGNvbnRyb2xsZXIgdmVyc2lvbi4KPiAKPiBSZWdhcmRpbmcgdG8g dGhlIERPQyBkZXNjcmlwdGlvbiwgdGhlIERJUkVDVF9TUEVFRF9DSEFOR0Ugc2hvdWxkIGJlCj4g Y2xlYXJlZCBhZnRlciB0aGUgc3BlZWQgY2hhbmdlIGZyb20gR0VOMSB0byBHRU4yLiBVbmZvcnR1 bmF0ZWx5LCB3aGVuCj4gR0VOMSBkZXZpY2UgaXMgdXNlZCwgdGhlIGJlaGF2aW9yIGlzIG5vdCBk b2N1bWVudGVkLgo+IAo+IFNvLCBJQyBkZXNpZ24gZ3V5cyBydW4gdGhlIHNpbXVsYXRpb24gYW5k Cj4gZmluZCBvdXQgdGhlIGZvbGxvd2luZyBiZWhhdmlvcnM6Cj4gCj4gICAgICAxLiBESVJFQ1Rf U1BFRURfQ0hBTkdFIHdpbGwgYmUgY2xlYXJlZCBpbiA3RCBhZnRlciBzcGVlZCBjaGFuZ2UKPiAg ICAgIAlmcm9tIEdFTjEgdG8gR0VOMi4gVGhpcyBtYXRjaGVzIGRvY+KAmXMgZGVzY3JpcHRpb24K PiAKPiAgICAgIDIuIHNldCBNQVggbGluayBzcGVlZChQQ0lFX0NBUF9UQVJHRVRfTElOS19TUEVF RD0weDAxKSBhcyBHRU4xIGFuZAo+ICAgICAgCXJlLXJ1biB0aGUgc2ltdWxhdGlvbiwgRElSRUNU X1NQRUVEX0NIQU5HRSB3aWxsIG5vdCBiZSBjbGVhcmVkOwo+ICAgICAgCXJlbWFpbiBhcyAxLCB0 aGlzIG1hdGNoZXMgeW91ciByZXN1bHQsIGJ1dCBmdW5jdGlvbiB0ZXN0IGlzCj4gICAgICAJcGFz c2VkLCBzbyB0aGlzIGJpdCBzaG91bGQgbm90IGFmZmVjdCB0aGUgbm9ybWFsIFBDSWUgZnVuY3Rp b24uCj4gLi4uIgo+IAo+IGlteDZfcGNpZV93YWl0X2Zvcl9zcGVlZF9jaGFuZ2Ugd2lsbCByZXBv cnQgZmFsc2UgZmFpbHVyZXMgZm9yIEdlbjEgLT4KPiBHZW4xIHNwZWVkIHRyYW5zaXRpb24sIHNv IGF2b2lkIGRvaW5nIHRoYXQgY2hlY2sgYW5kIGp1c3QgcmVseSBvbgo+IGlteDZfcGNpZV93YWl0 X2Zvcl9saW5rIG9ubHkuCj4gCj4gWzFdIGh0dHBzOi8vY29tbXVuaXR5Lm54cC5jb20vbWVzc2Fn ZS84Njc5NDMKPiAKPiBDYzogeXVyb3Zza3lAZ21haWwuY29tCj4gQ2M6IEx1Y2FzIFN0YWNoIDxs LnN0YWNoQHBlbmd1dHJvbml4LmRlPgo+IENjOiBCam9ybiBIZWxnYWFzIDxiaGVsZ2Fhc0Bnb29n bGUuY29tPgo+IENjOiBGYWJpbyBFc3RldmFtIDxmYWJpby5lc3RldmFtQG54cC5jb20+Cj4gQ2M6 IERvbmcgQWlzaGVuZyA8ZG9uZ2FzODZAZ21haWwuY29tPgo+IENjOiBsaW51eC1hcm0ta2VybmVs QGxpc3RzLmluZnJhZGVhZC5vcmcKPiBDYzogbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZwo+ IFNpZ25lZC1vZmYtYnk6IEFuZHJleSBTbWlybm92IDxhbmRyZXcuc21pcm5vdkBnbWFpbC5jb20+ CgpSZXZpZXdlZC1ieTogTHVjYXMgU3RhY2ggPGwuc3RhY2hAcGVuZ3V0cm9uaXguZGU+Cgo+IC0t LQo+ICBkcml2ZXJzL3BjaS9kd2MvcGNpLWlteDYuYyB8IDE5ICsrKysrKysrKysrKysrKy0tLS0K PiAgMSBmaWxlIGNoYW5nZWQsIDE1IGluc2VydGlvbnMoKyksIDQgZGVsZXRpb25zKC0pCj4gCj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGNpL2R3Yy9wY2ktaW14Ni5jIGIvZHJpdmVycy9wY2kvZHdj L3BjaS1pbXg2LmMKPiBpbmRleCA2NGRlOWJiLi5jNzMxZTQxIDEwMDY0NAo+IC0tLSBhL2RyaXZl cnMvcGNpL2R3Yy9wY2ktaW14Ni5jCj4gKysrIGIvZHJpdmVycy9wY2kvZHdjL3BjaS1pbXg2LmMK PiBAQCAtNTQ1LDEwICs1NDUsMjEgQEAgc3RhdGljIGludCBpbXg2X3BjaWVfZXN0YWJsaXNoX2xp bmsoc3RydWN0IGlteDZfcGNpZSAqaW14Nl9wY2llKQo+ICAJdG1wIHw9IFBPUlRfTE9HSUNfU1BF RURfQ0hBTkdFOwo+ICAJZHdfcGNpZV93cml0ZWxfZGJpKHBjaSwgUENJRV9MSU5LX1dJRFRIX1NQ RUVEX0NPTlRST0wsIHRtcCk7Cj4gIAo+IC0JcmV0ID0gaW14Nl9wY2llX3dhaXRfZm9yX3NwZWVk X2NoYW5nZShpbXg2X3BjaWUpOwo+IC0JaWYgKHJldCkgewo+IC0JCWRldl9lcnIoZGV2LCAiRmFp bGVkIHRvIGJyaW5nIGxpbmsgdXAhXG4iKTsKPiAtCQlnb3RvIGVycl9yZXNldF9waHk7Cj4gKwlp ZiAoaW14Nl9wY2llLT52YXJpYW50ICE9IElNWDdEKSB7Cj4gKwkJLyoKPiArCQkgKiBPbiBpLk1Y NywgRElSRUNUX1NQRUVEX0NIQU5HRSBiZWhhdmVzIGRpZmZlcmVudGx5Cj4gKwkJICogZnJvbSBp Lk1YNiBmYW1pbHkgd2hlbiBubyBsaW5rIHNwZWVkIHRyYW5zaXRpb24KPiArCQkgKiBvY2N1cnMg YW5kIHdlIGdvIEdlbjEgLT4geWVwLCBHZW4xLiBUaGUgZGlmZmVyZW5jZQo+ICsJCSAqIGlzIHRo YXQsIGluIHN1Y2ggY2FzZSwgaXQgd2lsbCBub3QgYmUgY2xlYXJlZCBieSBIVwo+ICsJCSAqIHdo aWNoIHdpbGwgY2F1c2UgdGhlIGZvbGxvd2luZyBjb2RlIHRvIHJlcG9ydCBmYWxzZQo+ICsJCSAq IGZhaWx1cmUuCj4gKwkJICovCj4gKwo+ICsJCXJldCA9IGlteDZfcGNpZV93YWl0X2Zvcl9zcGVl ZF9jaGFuZ2UoaW14Nl9wY2llKTsKPiArCQlpZiAocmV0KSB7Cj4gKwkJCWRldl9lcnIoZGV2LCAi RmFpbGVkIHRvIGJyaW5nIGxpbmsgdXAhXG4iKTsKPiArCQkJZ290byBlcnJfcmVzZXRfcGh5Owo+ ICsJCX0KPiAgCX0KPiAgCj4gIAkvKiBNYWtlIHN1cmUgbGluayB0cmFpbmluZyBpcyBmaW5pc2hl ZCBhcyB3ZWxsISAqLwoKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxp c3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1hcm0ta2VybmVsCg== ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled 2017-03-21 13:41 ` Andrey Smirnov @ 2017-03-21 13:42 ` Andrey Smirnov -1 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-pci Cc: Andrey Smirnov, yurovsky, Lucas Stach, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel Save a bit of time and avoid going through link speed change procedure in configuration where link max speed is limited to Gen1 in DT. Cc: yurovsky@gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index c731e41..9407c03 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -533,40 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); - } else { - dev_info(dev, "Link: Gen2 disabled\n"); - } - - /* - * Start Directed Speed Change so the best possible speed both link - * partners support can be negotiated. - */ - tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); - tmp |= PORT_LOGIC_SPEED_CHANGE; - dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); - if (imx6_pcie->variant != IMX7D) { /* - * On i.MX7, DIRECT_SPEED_CHANGE behaves differently - * from i.MX6 family when no link speed transition - * occurs and we go Gen1 -> yep, Gen1. The difference - * is that, in such case, it will not be cleared by HW - * which will cause the following code to report false - * failure. + * Start Directed Speed Change so the best possible + * speed both link partners support can be negotiated. */ + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp |= PORT_LOGIC_SPEED_CHANGE; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); + + if (imx6_pcie->variant != IMX7D) { + /* + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently + * from i.MX6 family when no link speed transition + * occurs and we go Gen1 -> yep, Gen1. The difference + * is that, in such case, it will not be cleared by HW + * which will cause the following code to report false + * failure. + */ + + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + if (ret) { + dev_err(dev, "Failed to bring link up!\n"); + goto err_reset_phy; + } + } - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + /* Make sure link training is finished as well! */ + ret = imx6_pcie_wait_for_link(imx6_pcie); if (ret) { dev_err(dev, "Failed to bring link up!\n"); goto err_reset_phy; } - } - - /* Make sure link training is finished as well! */ - ret = imx6_pcie_wait_for_link(imx6_pcie); - if (ret) { - dev_err(dev, "Failed to bring link up!\n"); - goto err_reset_phy; + } else { + dev_info(dev, "Link: Gen2 disabled\n"); } tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled @ 2017-03-21 13:42 ` Andrey Smirnov 0 siblings, 0 replies; 21+ messages in thread From: Andrey Smirnov @ 2017-03-21 13:42 UTC (permalink / raw) To: linux-arm-kernel Save a bit of time and avoid going through link speed change procedure in configuration where link max speed is limited to Gen1 in DT. Cc: yurovsky at gmail.com Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Dong Aisheng <dongas86@gmail.com> Cc: linux-arm-kernel at lists.infradead.org Cc: linux-kernel at vger.kernel.org Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> --- drivers/pci/dwc/pci-imx6.c | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index c731e41..9407c03 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -533,40 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); - } else { - dev_info(dev, "Link: Gen2 disabled\n"); - } - - /* - * Start Directed Speed Change so the best possible speed both link - * partners support can be negotiated. - */ - tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); - tmp |= PORT_LOGIC_SPEED_CHANGE; - dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); - if (imx6_pcie->variant != IMX7D) { /* - * On i.MX7, DIRECT_SPEED_CHANGE behaves differently - * from i.MX6 family when no link speed transition - * occurs and we go Gen1 -> yep, Gen1. The difference - * is that, in such case, it will not be cleared by HW - * which will cause the following code to report false - * failure. + * Start Directed Speed Change so the best possible + * speed both link partners support can be negotiated. */ + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp |= PORT_LOGIC_SPEED_CHANGE; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); + + if (imx6_pcie->variant != IMX7D) { + /* + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently + * from i.MX6 family when no link speed transition + * occurs and we go Gen1 -> yep, Gen1. The difference + * is that, in such case, it will not be cleared by HW + * which will cause the following code to report false + * failure. + */ + + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + if (ret) { + dev_err(dev, "Failed to bring link up!\n"); + goto err_reset_phy; + } + } - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); + /* Make sure link training is finished as well! */ + ret = imx6_pcie_wait_for_link(imx6_pcie); if (ret) { dev_err(dev, "Failed to bring link up!\n"); goto err_reset_phy; } - } - - /* Make sure link training is finished as well! */ - ret = imx6_pcie_wait_for_link(imx6_pcie); - if (ret) { - dev_err(dev, "Failed to bring link up!\n"); - goto err_reset_phy; + } else { + dev_info(dev, "Link: Gen2 disabled\n"); } tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); -- 2.9.3 ^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled 2017-03-21 13:42 ` Andrey Smirnov (?) @ 2017-03-21 13:51 ` Lucas Stach -1 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:51 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pci, yurovsky, Bjorn Helgaas, Fabio Estevam, Dong Aisheng, linux-arm-kernel, linux-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Save a bit of time and avoid going through link speed change procedure > in configuration where link max speed is limited to Gen1 in DT. > > Cc: yurovsky@gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 52 +++++++++++++++++++++++----------------------- > 1 file changed, 26 insertions(+), 26 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index c731e41..9407c03 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -533,40 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) > tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; > tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; > dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); > - } else { > - dev_info(dev, "Link: Gen2 disabled\n"); > - } > - > - /* > - * Start Directed Speed Change so the best possible speed both link > - * partners support can be negotiated. > - */ > - tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > - tmp |= PORT_LOGIC_SPEED_CHANGE; > - dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > > - if (imx6_pcie->variant != IMX7D) { > /* > - * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > - * from i.MX6 family when no link speed transition > - * occurs and we go Gen1 -> yep, Gen1. The difference > - * is that, in such case, it will not be cleared by HW > - * which will cause the following code to report false > - * failure. > + * Start Directed Speed Change so the best possible > + * speed both link partners support can be negotiated. > */ > + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > + tmp |= PORT_LOGIC_SPEED_CHANGE; > + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > + > + if (imx6_pcie->variant != IMX7D) { > + /* > + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > + * from i.MX6 family when no link speed transition > + * occurs and we go Gen1 -> yep, Gen1. The difference > + * is that, in such case, it will not be cleared by HW > + * which will cause the following code to report false > + * failure. > + */ > + > + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + if (ret) { > + dev_err(dev, "Failed to bring link up!\n"); > + goto err_reset_phy; > + } > + } > > - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + /* Make sure link training is finished as well! */ > + ret = imx6_pcie_wait_for_link(imx6_pcie); > if (ret) { > dev_err(dev, "Failed to bring link up!\n"); > goto err_reset_phy; > } > - } > - > - /* Make sure link training is finished as well! */ > - ret = imx6_pcie_wait_for_link(imx6_pcie); > - if (ret) { > - dev_err(dev, "Failed to bring link up!\n"); > - goto err_reset_phy; > + } else { > + dev_info(dev, "Link: Gen2 disabled\n"); > } > > tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); ^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled @ 2017-03-21 13:51 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:51 UTC (permalink / raw) To: linux-arm-kernel Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Save a bit of time and avoid going through link speed change procedure > in configuration where link max speed is limited to Gen1 in DT. > > Cc: yurovsky at gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel at lists.infradead.org > Cc: linux-kernel at vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 52 +++++++++++++++++++++++----------------------- > 1 file changed, 26 insertions(+), 26 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index c731e41..9407c03 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -533,40 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) > tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; > tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; > dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); > - } else { > - dev_info(dev, "Link: Gen2 disabled\n"); > - } > - > - /* > - * Start Directed Speed Change so the best possible speed both link > - * partners support can be negotiated. > - */ > - tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > - tmp |= PORT_LOGIC_SPEED_CHANGE; > - dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > > - if (imx6_pcie->variant != IMX7D) { > /* > - * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > - * from i.MX6 family when no link speed transition > - * occurs and we go Gen1 -> yep, Gen1. The difference > - * is that, in such case, it will not be cleared by HW > - * which will cause the following code to report false > - * failure. > + * Start Directed Speed Change so the best possible > + * speed both link partners support can be negotiated. > */ > + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > + tmp |= PORT_LOGIC_SPEED_CHANGE; > + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > + > + if (imx6_pcie->variant != IMX7D) { > + /* > + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > + * from i.MX6 family when no link speed transition > + * occurs and we go Gen1 -> yep, Gen1. The difference > + * is that, in such case, it will not be cleared by HW > + * which will cause the following code to report false > + * failure. > + */ > + > + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + if (ret) { > + dev_err(dev, "Failed to bring link up!\n"); > + goto err_reset_phy; > + } > + } > > - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + /* Make sure link training is finished as well! */ > + ret = imx6_pcie_wait_for_link(imx6_pcie); > if (ret) { > dev_err(dev, "Failed to bring link up!\n"); > goto err_reset_phy; > } > - } > - > - /* Make sure link training is finished as well! */ > - ret = imx6_pcie_wait_for_link(imx6_pcie); > - if (ret) { > - dev_err(dev, "Failed to bring link up!\n"); > - goto err_reset_phy; > + } else { > + dev_info(dev, "Link: Gen2 disabled\n"); > } > > tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled @ 2017-03-21 13:51 ` Lucas Stach 0 siblings, 0 replies; 21+ messages in thread From: Lucas Stach @ 2017-03-21 13:51 UTC (permalink / raw) To: Andrey Smirnov Cc: Dong Aisheng, linux-pci, linux-kernel, Fabio Estevam, Bjorn Helgaas, linux-arm-kernel, yurovsky Am Dienstag, den 21.03.2017, 06:42 -0700 schrieb Andrey Smirnov: > Save a bit of time and avoid going through link speed change procedure > in configuration where link max speed is limited to Gen1 in DT. > > Cc: yurovsky@gmail.com > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Bjorn Helgaas <bhelgaas@google.com> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Dong Aisheng <dongas86@gmail.com> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> > --- > drivers/pci/dwc/pci-imx6.c | 52 +++++++++++++++++++++++----------------------- > 1 file changed, 26 insertions(+), 26 deletions(-) > > diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c > index c731e41..9407c03 100644 > --- a/drivers/pci/dwc/pci-imx6.c > +++ b/drivers/pci/dwc/pci-imx6.c > @@ -533,40 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) > tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; > tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; > dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); > - } else { > - dev_info(dev, "Link: Gen2 disabled\n"); > - } > - > - /* > - * Start Directed Speed Change so the best possible speed both link > - * partners support can be negotiated. > - */ > - tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > - tmp |= PORT_LOGIC_SPEED_CHANGE; > - dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > > - if (imx6_pcie->variant != IMX7D) { > /* > - * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > - * from i.MX6 family when no link speed transition > - * occurs and we go Gen1 -> yep, Gen1. The difference > - * is that, in such case, it will not be cleared by HW > - * which will cause the following code to report false > - * failure. > + * Start Directed Speed Change so the best possible > + * speed both link partners support can be negotiated. > */ > + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); > + tmp |= PORT_LOGIC_SPEED_CHANGE; > + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); > + > + if (imx6_pcie->variant != IMX7D) { > + /* > + * On i.MX7, DIRECT_SPEED_CHANGE behaves differently > + * from i.MX6 family when no link speed transition > + * occurs and we go Gen1 -> yep, Gen1. The difference > + * is that, in such case, it will not be cleared by HW > + * which will cause the following code to report false > + * failure. > + */ > + > + ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + if (ret) { > + dev_err(dev, "Failed to bring link up!\n"); > + goto err_reset_phy; > + } > + } > > - ret = imx6_pcie_wait_for_speed_change(imx6_pcie); > + /* Make sure link training is finished as well! */ > + ret = imx6_pcie_wait_for_link(imx6_pcie); > if (ret) { > dev_err(dev, "Failed to bring link up!\n"); > goto err_reset_phy; > } > - } > - > - /* Make sure link training is finished as well! */ > - ret = imx6_pcie_wait_for_link(imx6_pcie); > - if (ret) { > - dev_err(dev, "Failed to bring link up!\n"); > - goto err_reset_phy; > + } else { > + dev_info(dev, "Link: Gen2 disabled\n"); > } > > tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2017-03-21 14:27 UTC | newest] Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-03-21 13:41 [PATCH v7 0/4] i.MX7 PCI support Andrey Smirnov 2017-03-21 13:41 ` Andrey Smirnov 2017-03-21 13:41 ` Andrey Smirnov 2017-03-21 13:42 ` [PATCH v7 1/4] PCI: imx6: Add code to support i.MX7D Andrey Smirnov 2017-03-21 13:42 ` Andrey Smirnov 2017-03-21 13:42 ` [PATCH v7 2/4] PCI: imx6: Allow probe deferal by reset GPIO Andrey Smirnov 2017-03-21 13:42 ` Andrey Smirnov 2017-03-21 13:42 ` Andrey Smirnov 2017-03-21 13:49 ` Lucas Stach 2017-03-21 13:49 ` Lucas Stach 2017-03-21 13:49 ` Lucas Stach 2017-03-21 13:42 ` [PATCH v7 3/4] PCI: imx6: Do not wait for speed change on i.MX7 Andrey Smirnov 2017-03-21 13:42 ` Andrey Smirnov 2017-03-21 13:50 ` Lucas Stach 2017-03-21 13:50 ` Lucas Stach 2017-03-21 13:50 ` Lucas Stach 2017-03-21 13:42 ` [PATCH v7 4/4] PCI: imx6: Do not switch speed if Gen2 is disabled Andrey Smirnov 2017-03-21 13:42 ` Andrey Smirnov 2017-03-21 13:51 ` Lucas Stach 2017-03-21 13:51 ` Lucas Stach 2017-03-21 13:51 ` Lucas Stach
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.