* [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe
@ 2025-03-24 6:26 Richard Zhu
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel
Add some enhancements for i.MX95 PCIe.
- Refine the link procedure to speed up link training.
- Add two ERRATA SW workarounds of i.MX95 PCIe.
- Beside Power On reset, add COLD reset for i.MX95 PCIe.
- Save/retore the LUT table in supend/resume callbacks.
[PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not
[PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
[PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23
[PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s
[PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95
drivers/pci/controller/dwc/pci-imx6.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 135 insertions(+), 20 deletions(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
@ 2025-03-24 6:26 ` Richard Zhu
2025-03-24 7:48 ` Hongxing Zhu
2025-03-24 13:05 ` Ilpo Järvinen
2025-03-24 6:26 ` [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe Richard Zhu
` (3 subsequent siblings)
4 siblings, 2 replies; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu
The current link setup procedure is more like one workaround to detect
the device behind PCIe switches on some i.MX6 platforms.
To describe more accurately, change the flag name from
IMX_PCIE_FLAG_IMX_SPEED_CHANGE to IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.
Then, start PCIe link directly when this flag is not set on i.MX7 or
later paltforms to simple and speed up link training.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c1f7904e3600..aa5c3f235995 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -91,7 +91,7 @@ enum imx_pcie_variants {
};
#define IMX_PCIE_FLAG_IMX_PHY BIT(0)
-#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE BIT(1)
+#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND BIT(1)
#define IMX_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2)
#define IMX_PCIE_FLAG_HAS_PHYDRV BIT(3)
#define IMX_PCIE_FLAG_HAS_APP_RESET BIT(4)
@@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
u32 tmp;
int ret;
+ if (!(imx_pcie->drvdata->flags &
+ IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
+ imx_pcie_ltssm_enable(dev);
+ return 0;
+ }
+
/*
* Force Gen1 operation when starting the link. In case the link is
* started in Gen2 mode, there is a possibility the devices on the
@@ -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
dw_pcie_dbi_ro_wr_dis(pci);
- if (imx_pcie->drvdata->flags &
- IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
-
- /*
- * 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 = imx_pcie_wait_for_speed_change(imx_pcie);
- if (ret) {
- dev_err(dev, "Failed to bring link up!\n");
- goto err_reset_phy;
- }
+ ret = imx_pcie_wait_for_speed_change(imx_pcie);
+ if (ret) {
+ dev_err(dev, "Failed to bring link up!\n");
+ goto err_reset_phy;
}
/* Make sure link training is finished as well! */
@@ -1665,7 +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6Q] = {
.variant = IMX6Q,
.flags = IMX_PCIE_FLAG_IMX_PHY |
- IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+ IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
IMX_PCIE_FLAG_BROKEN_SUSPEND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.dbi_length = 0x200,
@@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6SX] = {
.variant = IMX6SX,
.flags = IMX_PCIE_FLAG_IMX_PHY |
- IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+ IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.gpr = "fsl,imx6q-iomuxc-gpr",
.ltssm_off = IOMUXC_GPR12,
@@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
[IMX6QP] = {
.variant = IMX6QP,
.flags = IMX_PCIE_FLAG_IMX_PHY |
- IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
+ IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
.dbi_length = 0x200,
.gpr = "fsl,imx6q-iomuxc-gpr",
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
@ 2025-03-24 6:26 ` Richard Zhu
2025-03-24 19:00 ` Frank Li
2025-03-24 6:26 ` [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready Richard Zhu
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu
Beside the power-on reset, add the cold reset toggle for i.MX95 PCIe.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 31 +++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index aa5c3f235995..0f42ab63f5ad 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -71,6 +71,9 @@
#define IMX95_SID_MASK GENMASK(5, 0)
#define IMX95_MAX_LUT 32
+#define IMX95_PCIE_RST_CTRL 0x3010
+#define IMX95_PCIE_COLD_RST BIT(0)
+
#define to_imx_pcie(x) dev_get_drvdata((x)->dev)
enum imx_pcie_variants {
@@ -773,6 +776,32 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
return 0;
}
+static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
+{
+ if (assert) {
+ /*
+ * From i.MX95 PCIe PHY perspective, the COLD reset toggle
+ * should be complete after power-up by the following sequence.
+ * > 10us(at power-up)
+ * > 10ns(warm reset)
+ * |<------------>|
+ * ______________
+ * phy_reset ____/ \________________
+ * ____________
+ * ref_clk_en_______________________/
+ * Toggle COLD reset aligned with this sequence for i.MX95 PCIe.
+ */
+ regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
+ IMX95_PCIE_COLD_RST, IMX95_PCIE_COLD_RST);
+ udelay(15);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
+ IMX95_PCIE_COLD_RST, 0);
+ udelay(10);
+ }
+
+ return 0;
+}
+
static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
{
reset_control_assert(imx_pcie->pciephy_reset);
@@ -1762,6 +1791,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
.ltssm_mask = IMX95_PCIE_LTSSM_EN,
.mode_off[0] = IMX95_PE0_GEN_CTRL_1,
.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+ .core_reset = imx95_pcie_core_reset,
.init_phy = imx95_pcie_init_phy,
},
[IMX8MQ_EP] = {
@@ -1815,6 +1845,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
.mode_off[0] = IMX95_PE0_GEN_CTRL_1,
.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
.init_phy = imx95_pcie_init_phy,
+ .core_reset = imx95_pcie_core_reset,
.epc_features = &imx95_pcie_epc_features,
.mode = DW_PCIE_EP_TYPE,
},
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
2025-03-24 6:26 ` [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe Richard Zhu
@ 2025-03-24 6:26 ` Richard Zhu
2025-03-24 19:14 ` Frank Li
2025-03-24 6:26 ` [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN Richard Zhu
2025-03-24 6:26 ` [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe Richard Zhu
4 siblings, 1 reply; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu
Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23
Ready Through Beacon or PERST# De-assertion
When the auxiliary power is not available, the controller cannot exit
from L23 Ready with beacon or PERST# de-assertion when main power is not
removed.
Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 0f42ab63f5ad..52aa8bd66cde 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -48,6 +48,8 @@
#define IMX95_PCIE_SS_RW_REG_0 0xf0
#define IMX95_PCIE_REF_CLKEN BIT(23)
#define IMX95_PCIE_PHY_CR_PARA_SEL BIT(9)
+#define IMX95_PCIE_SS_RW_REG_1 0xf4
+#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
#define IMX95_PE0_GEN_CTRL_1 0x1050
#define IMX95_PCIE_DEVICE_TYPE GENMASK(3, 0)
@@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
{
+ /*
+ * Workaround for ERR051624: The Controller Without Vaux Cannot
+ * Exit L23 Ready Through Beacon or PERST# De-assertion
+ *
+ * When the auxiliary power is not available, the controller
+ * cannot exit from L23 Ready with beacon or PERST# de-assertion
+ * when main power is not removed.
+ *
+ * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
+ */
+ regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
+ IMX95_PCIE_SYS_AUX_PWR_DET, IMX95_PCIE_SYS_AUX_PWR_DET);
+
regmap_update_bits(imx_pcie->iomuxc_gpr,
IMX95_PCIE_SS_RW_REG_0,
IMX95_PCIE_PHY_CR_PARA_SEL,
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
` (2 preceding siblings ...)
2025-03-24 6:26 ` [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready Richard Zhu
@ 2025-03-24 6:26 ` Richard Zhu
2025-03-24 19:18 ` Frank Li
2025-03-24 6:26 ` [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe Richard Zhu
4 siblings, 1 reply; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu
Workaround for ERR051586: Compliance with 8GT/s Receiver Impedance ECN.
The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is 1 which
makes receiver non-compliant with the ZRX-DC parameter for 2.5 GT/s when
operating at 8 GT/s or higher. It causes unnecessary timeout in L1.
Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 29 +++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 52aa8bd66cde..dda3eed99bb8 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -131,6 +131,7 @@ struct imx_pcie_drvdata {
int (*init_phy)(struct imx_pcie *pcie);
int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
int (*core_reset)(struct imx_pcie *pcie, bool assert);
+ void (*post_config)(struct imx_pcie *pcie);
const struct dw_pcie_host_ops *ops;
};
@@ -1158,6 +1159,29 @@ static void imx_pcie_disable_device(struct pci_host_bridge *bridge,
imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev));
}
+static void imx95_pcie_post_config(struct imx_pcie *imx_pcie)
+{
+ u32 val;
+ struct dw_pcie *pci = imx_pcie->pci;
+
+ /*
+ * Workaround for ERR051586: Compliance with 8GT/s Receiver
+ * Impedance ECN
+ *
+ * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is
+ * 1 which makes receiver non-compliant with the ZRX-DC
+ * parameter for 2.5 GT/s when operating at 8 GT/s or higher. It
+ * causes unnecessary timeout in L1.
+ *
+ * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
+ */
+ dw_pcie_dbi_ro_wr_en(pci);
+ val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
+ val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
+ dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
+ dw_pcie_dbi_ro_wr_dis(pci);
+}
+
static int imx_pcie_host_init(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -1222,6 +1246,9 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
imx_setup_phy_mpll(imx_pcie);
+ if (imx_pcie->drvdata->post_config)
+ imx_pcie->drvdata->post_config(imx_pcie);
+
return 0;
err_phy_off:
@@ -1808,6 +1835,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
.core_reset = imx95_pcie_core_reset,
.init_phy = imx95_pcie_init_phy,
+ .post_config = imx95_pcie_post_config,
},
[IMX8MQ_EP] = {
.variant = IMX8MQ_EP,
@@ -1863,6 +1891,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
.core_reset = imx95_pcie_core_reset,
.epc_features = &imx95_pcie_epc_features,
.mode = DW_PCIE_EP_TYPE,
+ .post_config = imx95_pcie_post_config,
},
};
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
` (3 preceding siblings ...)
2025-03-24 6:26 ` [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN Richard Zhu
@ 2025-03-24 6:26 ` Richard Zhu
2025-03-24 19:22 ` Frank Li
4 siblings, 1 reply; 13+ messages in thread
From: Richard Zhu @ 2025-03-24 6:26 UTC (permalink / raw)
To: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, imx, linux-kernel, Richard Zhu
LUT(look up table) setting would be lost during PCIe suspend on i.MX95.
To let i.MX95 PCIe PM work fine, save and restore the LUT setting in
suspend and resume operations.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 46 +++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index dda3eed99bb8..a3a032cbaa3c 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -135,6 +135,11 @@ struct imx_pcie_drvdata {
const struct dw_pcie_host_ops *ops;
};
+struct imx_lut_data {
+ u32 data1;
+ u32 data2;
+};
+
struct imx_pcie {
struct dw_pcie *pci;
struct gpio_desc *reset_gpiod;
@@ -154,6 +159,8 @@ struct imx_pcie {
struct regulator *vph;
void __iomem *phy_base;
+ /* LUT data for pcie */
+ struct imx_lut_data luts[IMX95_MAX_LUT];
/* power domain for pcie */
struct device *pd_pcie;
/* power domain for pcie phy */
@@ -1468,6 +1475,41 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
}
}
+static void imx_pcie_lut_save_restore(struct imx_pcie *imx_pcie, bool save)
+{
+ int i;
+ u32 data1, data2;
+
+ for (i = 0; i < IMX95_MAX_LUT; i++) {
+ if (save) {
+ regmap_write(imx_pcie->iomuxc_gpr,
+ IMX95_PE0_LUT_ACSCTRL,
+ IMX95_PEO_LUT_RWA | i);
+ regmap_read(imx_pcie->iomuxc_gpr,
+ IMX95_PE0_LUT_DATA1, &data1);
+ regmap_read(imx_pcie->iomuxc_gpr,
+ IMX95_PE0_LUT_DATA2, &data2);
+ if (data1 & IMX95_PE0_LUT_VLD) {
+ imx_pcie->luts[i].data1 = data1;
+ imx_pcie->luts[i].data2 = data2;
+ } else {
+ imx_pcie->luts[i].data1 = 0;
+ imx_pcie->luts[i].data2 = 0;
+ }
+ } else {
+ if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0)
+ continue;
+
+ regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1,
+ imx_pcie->luts[i].data1);
+ regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2,
+ imx_pcie->luts[i].data2);
+ regmap_write(imx_pcie->iomuxc_gpr,
+ IMX95_PE0_LUT_ACSCTRL, i);
+ }
+ }
+}
+
static int imx_pcie_suspend_noirq(struct device *dev)
{
struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
@@ -1476,6 +1518,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)
return 0;
imx_pcie_msi_save_restore(imx_pcie, true);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_save_restore(imx_pcie, true);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
/*
* The minimum for a workaround would be to set PERST# and to
@@ -1520,6 +1564,8 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (ret)
return ret;
}
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_save_restore(imx_pcie, false);
imx_pcie_msi_save_restore(imx_pcie, false);
return 0;
--
2.37.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* RE: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
@ 2025-03-24 7:48 ` Hongxing Zhu
2025-03-24 13:05 ` Ilpo Järvinen
1 sibling, 0 replies; 13+ messages in thread
From: Hongxing Zhu @ 2025-03-24 7:48 UTC (permalink / raw)
To: Frank Li, l.stach@pengutronix.de, lpieralisi@kernel.org,
kw@linux.com, manivannan.sadhasivam@linaro.org, robh@kernel.org,
bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de,
kernel@pengutronix.de, festevam@gmail.com
Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
imx@lists.linux.dev, linux-kernel@vger.kernel.org
> -----Original Message-----
> From: Hongxing Zhu <hongxing.zhu@nxp.com>
> Sent: 2025年3月24日 14:27
> To: Frank Li <frank.li@nxp.com>; l.stach@pengutronix.de;
> lpieralisi@kernel.org; kw@linux.com; manivannan.sadhasivam@linaro.org;
> robh@kernel.org; bhelgaas@google.com; shawnguo@kernel.org;
> s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com
> Cc: linux-pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> imx@lists.linux.dev; linux-kernel@vger.kernel.org; Hongxing Zhu
> <hongxing.zhu@nxp.com>
> Subject: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not
> required
>
> The current link setup procedure is more like one workaround to detect the
> device behind PCIe switches on some i.MX6 platforms.
>
> To describe more accurately, change the flag name from
> IMX_PCIE_FLAG_IMX_SPEED_CHANGE to
> IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.
>
> Then, start PCIe link directly when this flag is not set on i.MX7 or later
> paltforms to simple and speed up link training.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
> 1 file changed, 14 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> b/drivers/pci/controller/dwc/pci-imx6.c
> index c1f7904e3600..aa5c3f235995 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -91,7 +91,7 @@ enum imx_pcie_variants { };
>
> #define IMX_PCIE_FLAG_IMX_PHY BIT(0)
> -#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE BIT(1)
> +#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND BIT(1)
WORDAROUND/s/WORKAROUND
Sorry to find this typo error after patch-set is issued.
Would correct them all in next version.
Best Regards
Richard Zhu
> #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2)
> #define IMX_PCIE_FLAG_HAS_PHYDRV BIT(3)
> #define IMX_PCIE_FLAG_HAS_APP_RESET BIT(4)
> @@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
> u32 tmp;
> int ret;
>
> + if (!(imx_pcie->drvdata->flags &
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
> + imx_pcie_ltssm_enable(dev);
> + return 0;
> + }
> +
> /*
> * Force Gen1 operation when starting the link. In case the link is
> * started in Gen2 mode, there is a possibility the devices on the @@
> -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
> dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL,
> tmp);
> dw_pcie_dbi_ro_wr_dis(pci);
>
> - if (imx_pcie->drvdata->flags &
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
> -
> - /*
> - * 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 = imx_pcie_wait_for_speed_change(imx_pcie);
> - if (ret) {
> - dev_err(dev, "Failed to bring link up!\n");
> - goto err_reset_phy;
> - }
> + ret = imx_pcie_wait_for_speed_change(imx_pcie);
> + if (ret) {
> + dev_err(dev, "Failed to bring link up!\n");
> + goto err_reset_phy;
> }
>
> /* Make sure link training is finished as well! */ @@ -1665,7
> +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6Q] = {
> .variant = IMX6Q,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_BROKEN_SUSPEND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .dbi_length = 0x200,
> @@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6SX] = {
> .variant = IMX6SX,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .gpr = "fsl,imx6q-iomuxc-gpr",
> .ltssm_off = IOMUXC_GPR12,
> @@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6QP] = {
> .variant = IMX6QP,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .dbi_length = 0x200,
> .gpr = "fsl,imx6q-iomuxc-gpr",
> --
> 2.37.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
2025-03-24 7:48 ` Hongxing Zhu
@ 2025-03-24 13:05 ` Ilpo Järvinen
1 sibling, 0 replies; 13+ messages in thread
From: Ilpo Järvinen @ 2025-03-24 13:05 UTC (permalink / raw)
To: Richard Zhu
Cc: frank.li, l.stach, lpieralisi, kw, manivannan.sadhasivam, robh,
bhelgaas, shawnguo, s.hauer, kernel, festevam, linux-pci,
linux-arm-kernel, imx, LKML
On Mon, 24 Mar 2025, Richard Zhu wrote:
> The current link setup procedure is more like one workaround to detect
> the device behind PCIe switches on some i.MX6 platforms.
>
> To describe more accurately, change the flag name from
> IMX_PCIE_FLAG_IMX_SPEED_CHANGE to IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND.
>
> Then, start PCIe link directly when this flag is not set on i.MX7 or
> later paltforms to simple and speed up link training.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 34 +++++++++++----------------
> 1 file changed, 14 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index c1f7904e3600..aa5c3f235995 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -91,7 +91,7 @@ enum imx_pcie_variants {
> };
>
> #define IMX_PCIE_FLAG_IMX_PHY BIT(0)
> -#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE BIT(1)
> +#define IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND BIT(1)
WORDaround ?? :-)
--
i.
> #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND BIT(2)
> #define IMX_PCIE_FLAG_HAS_PHYDRV BIT(3)
> #define IMX_PCIE_FLAG_HAS_APP_RESET BIT(4)
> @@ -860,6 +860,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
> u32 tmp;
> int ret;
>
> + if (!(imx_pcie->drvdata->flags &
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND)) {
> + imx_pcie_ltssm_enable(dev);
> + return 0;
> + }
> +
> /*
> * Force Gen1 operation when starting the link. In case the link is
> * started in Gen2 mode, there is a possibility the devices on the
> @@ -896,22 +902,10 @@ static int imx_pcie_start_link(struct dw_pcie *pci)
> dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
> dw_pcie_dbi_ro_wr_dis(pci);
>
> - if (imx_pcie->drvdata->flags &
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE) {
> -
> - /*
> - * 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 = imx_pcie_wait_for_speed_change(imx_pcie);
> - if (ret) {
> - dev_err(dev, "Failed to bring link up!\n");
> - goto err_reset_phy;
> - }
> + ret = imx_pcie_wait_for_speed_change(imx_pcie);
> + if (ret) {
> + dev_err(dev, "Failed to bring link up!\n");
> + goto err_reset_phy;
> }
>
> /* Make sure link training is finished as well! */
> @@ -1665,7 +1659,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6Q] = {
> .variant = IMX6Q,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_BROKEN_SUSPEND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .dbi_length = 0x200,
> @@ -1681,7 +1675,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6SX] = {
> .variant = IMX6SX,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .gpr = "fsl,imx6q-iomuxc-gpr",
> .ltssm_off = IOMUXC_GPR12,
> @@ -1696,7 +1690,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> [IMX6QP] = {
> .variant = IMX6QP,
> .flags = IMX_PCIE_FLAG_IMX_PHY |
> - IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
> + IMX_PCIE_FLAG_SPEED_CHANGE_WORDAROUND |
> IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
> .dbi_length = 0x200,
> .gpr = "fsl,imx6q-iomuxc-gpr",
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe
2025-03-24 6:26 ` [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe Richard Zhu
@ 2025-03-24 19:00 ` Frank Li
0 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2025-03-24 19:00 UTC (permalink / raw)
To: Richard Zhu
Cc: l.stach, lpieralisi, kw, manivannan.sadhasivam, robh, bhelgaas,
shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel,
imx, linux-kernel
On Mon, Mar 24, 2025 at 02:26:44PM +0800, Richard Zhu wrote:
> Beside the power-on reset, add the cold reset toggle for i.MX95 PCIe.
Add the code reset toggle for i.MX95 PCIe to align PHY's power on sequency.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 31 +++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index aa5c3f235995..0f42ab63f5ad 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -71,6 +71,9 @@
> #define IMX95_SID_MASK GENMASK(5, 0)
> #define IMX95_MAX_LUT 32
>
> +#define IMX95_PCIE_RST_CTRL 0x3010
> +#define IMX95_PCIE_COLD_RST BIT(0)
> +
> #define to_imx_pcie(x) dev_get_drvdata((x)->dev)
>
> enum imx_pcie_variants {
> @@ -773,6 +776,32 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
> return 0;
> }
>
> +static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)
> +{
> + if (assert) {
> + /*
> + * From i.MX95 PCIe PHY perspective, the COLD reset toggle
> + * should be complete after power-up by the following sequence.
> + * > 10us(at power-up)
> + * > 10ns(warm reset)
> + * |<------------>|
> + * ______________
> + * phy_reset ____/ \________________
> + * ____________
> + * ref_clk_en_______________________/
> + * Toggle COLD reset aligned with this sequence for i.MX95 PCIe.
> + */
> + regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
> + IMX95_PCIE_COLD_RST, IMX95_PCIE_COLD_RST);
regmap_set_bits()
> + udelay(15);
udelay may not use MMIO. It cause delay time less than 15us. Need read one
register before udelay(15);
> + regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
> + IMX95_PCIE_COLD_RST, 0);
regmap_clr_bits();
Frank
> + udelay(10);
> + }
> +
> + return 0;
> +}
> +
> static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
> {
> reset_control_assert(imx_pcie->pciephy_reset);
> @@ -1762,6 +1791,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> .ltssm_mask = IMX95_PCIE_LTSSM_EN,
> .mode_off[0] = IMX95_PE0_GEN_CTRL_1,
> .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
> + .core_reset = imx95_pcie_core_reset,
> .init_phy = imx95_pcie_init_phy,
> },
> [IMX8MQ_EP] = {
> @@ -1815,6 +1845,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> .mode_off[0] = IMX95_PE0_GEN_CTRL_1,
> .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
> .init_phy = imx95_pcie_init_phy,
> + .core_reset = imx95_pcie_core_reset,
> .epc_features = &imx95_pcie_epc_features,
> .mode = DW_PCIE_EP_TYPE,
> },
> --
> 2.37.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready
2025-03-24 6:26 ` [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready Richard Zhu
@ 2025-03-24 19:14 ` Frank Li
2025-03-25 8:08 ` Hongxing Zhu
0 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2025-03-24 19:14 UTC (permalink / raw)
To: Richard Zhu
Cc: l.stach, lpieralisi, kw, manivannan.sadhasivam, robh, bhelgaas,
shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel,
imx, linux-kernel
On Mon, Mar 24, 2025 at 02:26:45PM +0800, Richard Zhu wrote:
> Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23
provide a errata link here.
ERR051624: ...
The words after ERR051624 is descript errata itself, not workaround.
> Ready Through Beacon or PERST# De-assertion
>
> When the auxiliary power is not available, the controller cannot exit
> from L23 Ready with beacon or PERST# de-assertion when main power is not
> removed.
>
> Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 0f42ab63f5ad..52aa8bd66cde 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -48,6 +48,8 @@
> #define IMX95_PCIE_SS_RW_REG_0 0xf0
> #define IMX95_PCIE_REF_CLKEN BIT(23)
> #define IMX95_PCIE_PHY_CR_PARA_SEL BIT(9)
> +#define IMX95_PCIE_SS_RW_REG_1 0xf4
> +#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
>
> #define IMX95_PE0_GEN_CTRL_1 0x1050
> #define IMX95_PCIE_DEVICE_TYPE GENMASK(3, 0)
> @@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)
>
> static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)
> {
> + /*
> + * Workaround for ERR051624: The Controller Without Vaux Cannot
> + * Exit L23 Ready Through Beacon or PERST# De-assertion
> + *
> + * When the auxiliary power is not available, the controller
> + * cannot exit from L23 Ready with beacon or PERST# de-assertion
> + * when main power is not removed.
> + *
> + * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> + */
> + regmap_update_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1,
> + IMX95_PCIE_SYS_AUX_PWR_DET, IMX95_PCIE_SYS_AUX_PWR_DET);
regmap_set_bits()
Frank
> +
> regmap_update_bits(imx_pcie->iomuxc_gpr,
> IMX95_PCIE_SS_RW_REG_0,
> IMX95_PCIE_PHY_CR_PARA_SEL,
> --
> 2.37.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN
2025-03-24 6:26 ` [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN Richard Zhu
@ 2025-03-24 19:18 ` Frank Li
0 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2025-03-24 19:18 UTC (permalink / raw)
To: Richard Zhu
Cc: l.stach, lpieralisi, kw, manivannan.sadhasivam, robh, bhelgaas,
shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel,
imx, linux-kernel
On Mon, Mar 24, 2025 at 02:26:46PM +0800, Richard Zhu wrote:
> Workaround for ERR051586: Compliance with 8GT/s Receiver Impedance ECN.
>
> The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is 1 which
> makes receiver non-compliant with the ZRX-DC parameter for 2.5 GT/s when
> operating at 8 GT/s or higher. It causes unnecessary timeout in L1.
>
> Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 29 +++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 52aa8bd66cde..dda3eed99bb8 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -131,6 +131,7 @@ struct imx_pcie_drvdata {
> int (*init_phy)(struct imx_pcie *pcie);
> int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
> int (*core_reset)(struct imx_pcie *pcie, bool assert);
> + void (*post_config)(struct imx_pcie *pcie);
> const struct dw_pcie_host_ops *ops;
> };
>
> @@ -1158,6 +1159,29 @@ static void imx_pcie_disable_device(struct pci_host_bridge *bridge,
> imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev));
> }
>
> +static void imx95_pcie_post_config(struct imx_pcie *imx_pcie)
There are already have post_init in dwc dw_pcie_host_ops
struct dw_pcie_host_ops {
int (*init)(struct dw_pcie_rp *pp);
void (*deinit)(struct dw_pcie_rp *pp);
void (*post_init)(struct dw_pcie_rp *pp);
int (*msi_init)(struct dw_pcie_rp *pp);
void (*pme_turn_off)(struct dw_pcie_rp *pp);
};
Can you use it directly?
Frank
> +{
> + u32 val;
> + struct dw_pcie *pci = imx_pcie->pci;
struct dw_pcie *pci = imx_pcie->pci;
u32 val;
> +
> + /*
> + * Workaround for ERR051586: Compliance with 8GT/s Receiver
> + * Impedance ECN
> + *
> + * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] is
> + * 1 which makes receiver non-compliant with the ZRX-DC
> + * parameter for 2.5 GT/s when operating at 8 GT/s or higher. It
> + * causes unnecessary timeout in L1.
> + *
> + * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] to 0.
> + */
> + dw_pcie_dbi_ro_wr_en(pci);
> + val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
> + val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
> + dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val);
> + dw_pcie_dbi_ro_wr_dis(pci);
> +}
> +
> static int imx_pcie_host_init(struct dw_pcie_rp *pp)
> {
> struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> @@ -1222,6 +1246,9 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>
> imx_setup_phy_mpll(imx_pcie);
>
> + if (imx_pcie->drvdata->post_config)
> + imx_pcie->drvdata->post_config(imx_pcie);
> +
> return 0;
>
> err_phy_off:
> @@ -1808,6 +1835,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
> .core_reset = imx95_pcie_core_reset,
> .init_phy = imx95_pcie_init_phy,
> + .post_config = imx95_pcie_post_config,
> },
> [IMX8MQ_EP] = {
> .variant = IMX8MQ_EP,
> @@ -1863,6 +1891,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
> .core_reset = imx95_pcie_core_reset,
> .epc_features = &imx95_pcie_epc_features,
> .mode = DW_PCIE_EP_TYPE,
> + .post_config = imx95_pcie_post_config,
> },
> };
>
> --
> 2.37.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe
2025-03-24 6:26 ` [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe Richard Zhu
@ 2025-03-24 19:22 ` Frank Li
0 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2025-03-24 19:22 UTC (permalink / raw)
To: Richard Zhu
Cc: l.stach, lpieralisi, kw, manivannan.sadhasivam, robh, bhelgaas,
shawnguo, s.hauer, kernel, festevam, linux-pci, linux-arm-kernel,
imx, linux-kernel
On Mon, Mar 24, 2025 at 02:26:47PM +0800, Richard Zhu wrote:
> LUT(look up table) setting would be lost during PCIe suspend on i.MX95.
>
> To let i.MX95 PCIe PM work fine, save and restore the LUT setting in
> suspend and resume operations.
>
> Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> ---
> drivers/pci/controller/dwc/pci-imx6.c | 46 +++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index dda3eed99bb8..a3a032cbaa3c 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -135,6 +135,11 @@ struct imx_pcie_drvdata {
> const struct dw_pcie_host_ops *ops;
> };
>
> +struct imx_lut_data {
> + u32 data1;
> + u32 data2;
> +};
> +
> struct imx_pcie {
> struct dw_pcie *pci;
> struct gpio_desc *reset_gpiod;
> @@ -154,6 +159,8 @@ struct imx_pcie {
> struct regulator *vph;
> void __iomem *phy_base;
>
> + /* LUT data for pcie */
> + struct imx_lut_data luts[IMX95_MAX_LUT];
> /* power domain for pcie */
> struct device *pd_pcie;
> /* power domain for pcie phy */
> @@ -1468,6 +1475,41 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)
> }
> }
>
> +static void imx_pcie_lut_save_restore(struct imx_pcie *imx_pcie, bool save)
> +{
> + int i;
> + u32 data1, data2;
Reverse Christmas order.
> +
> + for (i = 0; i < IMX95_MAX_LUT; i++) {
> + if (save) {
> + regmap_write(imx_pcie->iomuxc_gpr,
> + IMX95_PE0_LUT_ACSCTRL,
> + IMX95_PEO_LUT_RWA | i);
> + regmap_read(imx_pcie->iomuxc_gpr,
> + IMX95_PE0_LUT_DATA1, &data1);
> + regmap_read(imx_pcie->iomuxc_gpr,
> + IMX95_PE0_LUT_DATA2, &data2);
> + if (data1 & IMX95_PE0_LUT_VLD) {
> + imx_pcie->luts[i].data1 = data1;
> + imx_pcie->luts[i].data2 = data2;
> + } else {
> + imx_pcie->luts[i].data1 = 0;
> + imx_pcie->luts[i].data2 = 0;
> + }
Almost no shared part between save and restore. Suggest use two helper
function imx_pcie_lut_save() and imx_pcie_lut_restore().
Frank
> + } else {
> + if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0)
> + continue;
> +
> + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1,
> + imx_pcie->luts[i].data1);
> + regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2,
> + imx_pcie->luts[i].data2);
> + regmap_write(imx_pcie->iomuxc_gpr,
> + IMX95_PE0_LUT_ACSCTRL, i);
> + }
> + }
> +}
> +
> static int imx_pcie_suspend_noirq(struct device *dev)
> {
> struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
> @@ -1476,6 +1518,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)
> return 0;
>
> imx_pcie_msi_save_restore(imx_pcie, true);
> + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> + imx_pcie_lut_save_restore(imx_pcie, true);
> if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
> /*
> * The minimum for a workaround would be to set PERST# and to
> @@ -1520,6 +1564,8 @@ static int imx_pcie_resume_noirq(struct device *dev)
> if (ret)
> return ret;
> }
> + if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
> + imx_pcie_lut_save_restore(imx_pcie, false);
> imx_pcie_msi_save_restore(imx_pcie, false);
>
> return 0;
> --
> 2.37.1
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready
2025-03-24 19:14 ` Frank Li
@ 2025-03-25 8:08 ` Hongxing Zhu
0 siblings, 0 replies; 13+ messages in thread
From: Hongxing Zhu @ 2025-03-25 8:08 UTC (permalink / raw)
To: Frank Li
Cc: l.stach@pengutronix.de, lpieralisi@kernel.org, kw@linux.com,
manivannan.sadhasivam@linaro.org, robh@kernel.org,
bhelgaas@google.com, shawnguo@kernel.org, s.hauer@pengutronix.de,
kernel@pengutronix.de, festevam@gmail.com,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
imx@lists.linux.dev, linux-kernel@vger.kernel.org
> -----Original Message-----
> From: Frank Li <frank.li@nxp.com>
> Sent: 2025年3月25日 3:14
> To: Hongxing Zhu <hongxing.zhu@nxp.com>
> Cc: l.stach@pengutronix.de; lpieralisi@kernel.org; kw@linux.com;
> manivannan.sadhasivam@linaro.org; robh@kernel.org;
> bhelgaas@google.com; shawnguo@kernel.org; s.hauer@pengutronix.de;
> kernel@pengutronix.de; festevam@gmail.com; linux-pci@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; imx@lists.linux.dev;
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit
> L23 ready
>
> On Mon, Mar 24, 2025 at 02:26:45PM +0800, Richard Zhu wrote:
> > Workaround for ERR051624: The Controller Without Vaux Cannot Exit L23
>
> provide a errata link here.
Up to now, I only get the following document updates information.
" This is being converted to Docs update and will be added to init sequence
in Reference Manual."
Would add the errata link after I find it.
Thanks.
Best Regards
Richard Zhu
>
> ERR051624: ...
>
> The words after ERR051624 is descript errata itself, not workaround.
>
> > Ready Through Beacon or PERST# De-assertion
> >
> > When the auxiliary power is not available, the controller cannot exit
> > from L23 Ready with beacon or PERST# de-assertion when main power is
> > not removed.
> >
> > Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> >
> > Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
> > ---
> > drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++++++++++
> > 1 file changed, 15 insertions(+)
> >
> > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > b/drivers/pci/controller/dwc/pci-imx6.c
> > index 0f42ab63f5ad..52aa8bd66cde 100644
> > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > @@ -48,6 +48,8 @@
> > #define IMX95_PCIE_SS_RW_REG_0 0xf0
> > #define IMX95_PCIE_REF_CLKEN BIT(23)
> > #define IMX95_PCIE_PHY_CR_PARA_SEL BIT(9)
> > +#define IMX95_PCIE_SS_RW_REG_1 0xf4
> > +#define IMX95_PCIE_SYS_AUX_PWR_DET BIT(31)
> >
> > #define IMX95_PE0_GEN_CTRL_1 0x1050
> > #define IMX95_PCIE_DEVICE_TYPE GENMASK(3, 0)
> > @@ -227,6 +229,19 @@ static unsigned int imx_pcie_grp_offset(const
> > struct imx_pcie *imx_pcie)
> >
> > static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie) {
> > + /*
> > + * Workaround for ERR051624: The Controller Without Vaux Cannot
> > + * Exit L23 Ready Through Beacon or PERST# De-assertion
> > + *
> > + * When the auxiliary power is not available, the controller
> > + * cannot exit from L23 Ready with beacon or PERST# de-assertion
> > + * when main power is not removed.
> > + *
> > + * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1.
> > + */
> > + regmap_update_bits(imx_pcie->iomuxc_gpr,
> IMX95_PCIE_SS_RW_REG_1,
> > + IMX95_PCIE_SYS_AUX_PWR_DET,
> IMX95_PCIE_SYS_AUX_PWR_DET);
>
> regmap_set_bits()
>
> Frank
> > +
> > regmap_update_bits(imx_pcie->iomuxc_gpr,
> > IMX95_PCIE_SS_RW_REG_0,
> > IMX95_PCIE_PHY_CR_PARA_SEL,
> > --
> > 2.37.1
> >
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-03-25 8:11 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-24 6:26 [PATCH v1 0/5] Add some enhancements for i.MX95 PCIe Richard Zhu
2025-03-24 6:26 ` [PATCH v1 1/5] PCI: imx6: Start link directly when workaround is not required Richard Zhu
2025-03-24 7:48 ` Hongxing Zhu
2025-03-24 13:05 ` Ilpo Järvinen
2025-03-24 6:26 ` [PATCH v1 2/5] PCI: imx6: Toggle the cold reset for i.MX95 PCIe Richard Zhu
2025-03-24 19:00 ` Frank Li
2025-03-24 6:26 ` [PATCH v1 3/5] PCI: imx6: Workaround i.MX95 PCIe may not exit L23 ready Richard Zhu
2025-03-24 19:14 ` Frank Li
2025-03-25 8:08 ` Hongxing Zhu
2025-03-24 6:26 ` [PATCH v1 4/5] PCI: imx6: Let i.MX95 PCIe compliance with 8GT/s Receiver Impedance ECN Richard Zhu
2025-03-24 19:18 ` Frank Li
2025-03-24 6:26 ` [PATCH v1 5/5] PCI: imx6: Save and restore the LUT setting for i.MX95 PCIe Richard Zhu
2025-03-24 19:22 ` Frank Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).