Commit 47f54a90 authored by Richard Zhu's avatar Richard Zhu Committed by Manivannan Sadhasivam
Browse files

PCI: imx6: Toggle the core reset for i.MX95 PCIe



Add toggling core reset for i.MX95 to align with PHY's power-up sequence.
Note that the register is named as IMX95_PCIE_COLD_RST in hardware, though
it is used to reset the PCIe core.

Signed-off-by: default avatarRichard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[mani: subject and description rewording]
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20250416081314.3929794-4-hongxing.zhu@nxp.com
parent 4a4be0c0
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -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,43 @@ 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)
{
	u32 val;

	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_set_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
				IMX95_PCIE_COLD_RST);
		/*
		 * Make sure the write to IMX95_PCIE_RST_CTRL is flushed to the
		 * hardware by doing a read. Otherwise, there is no guarantee
		 * that the write has reached the hardware before udelay().
		 */
		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
				     &val);
		udelay(15);
		regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
				  IMX95_PCIE_COLD_RST);
		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL,
				     &val);
		udelay(10);
	}

	return 0;
}

static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)
{
	reset_control_assert(imx_pcie->pciephy_reset);
@@ -1739,6 +1779,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] = {
@@ -1792,6 +1833,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,
	},