Unverified Commit 256867b7 authored by Frank Li's avatar Frank Li Committed by Krzysztof Wilczyński
Browse files

PCI: imx6: Introduce SoC specific callbacks for controlling REFCLK

Instead of using the switch case statement to enable/disable the
reference clock handled by this driver itself, let's introduce a new
callback enable_ref_clk() and define it for platforms that require it.

This simplifies the code.

Link: https://lore.kernel.org/linux-pci/20240729-pci2_upstream-v8-5-b68ee5ef2b4d@nxp.com


Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
[kwilczynski: commit log]
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
parent d657ea28
Loading
Loading
Loading
Loading
+51 −60
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ struct imx_pcie_drvdata {
	const u32 mode_mask[IMX_PCIE_MAX_INSTANCES];
	const struct pci_epc_features *epc_features;
	int (*init_phy)(struct imx_pcie *pcie);
	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);
};

struct imx_pcie {
@@ -582,21 +583,20 @@ static int imx_pcie_attach_pd(struct device *dev)
	return 0;
}

static int imx_pcie_enable_ref_clk(struct imx_pcie *imx_pcie)
static int imx6sx_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
	unsigned int offset;
	int ret = 0;
	if (enable)
		regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
				  IMX6SX_GPR12_PCIE_TEST_POWERDOWN);

	switch (imx_pcie->drvdata->variant) {
	case IMX6SX:
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
		break;
	case IMX6QP:
	case IMX6Q:
	return 0;
}

static int imx6q_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
	if (enable) {
		/* power up core phy and enable ref clock */
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
				   IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
		regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
		/*
		 * the async reset input need ref clock to sync internally,
		 * when the ref clock comes after reset, internal synced
@@ -604,55 +604,33 @@ static int imx_pcie_enable_ref_clk(struct imx_pcie *imx_pcie)
		 * add one ~10us delay here.
		 */
		usleep_range(10, 100);
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
		break;
	case IMX7D:
	case IMX95:
	case IMX95_EP:
		break;
	case IMX8MM:
	case IMX8MM_EP:
	case IMX8MQ:
	case IMX8MQ_EP:
	case IMX8MP:
	case IMX8MP_EP:
		offset = imx_pcie_grp_offset(imx_pcie);
		/*
		 * Set the over ride low and enabled
		 * make sure that REF_CLK is turned on.
		 */
		regmap_update_bits(imx_pcie->iomuxc_gpr, offset,
				   IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE,
				   0);
		regmap_update_bits(imx_pcie->iomuxc_gpr, offset,
				   IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN,
				   IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN);
		break;
		regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
	} else {
		regmap_clear_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_REF_CLK_EN);
		regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD);
	}

	return ret;
	return 0;
}

static void imx_pcie_disable_ref_clk(struct imx_pcie *imx_pcie)
static int imx8mm_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
	switch (imx_pcie->drvdata->variant) {
	case IMX6QP:
	case IMX6Q:
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
				IMX6Q_GPR1_PCIE_REF_CLK_EN, 0);
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1,
				IMX6Q_GPR1_PCIE_TEST_PD,
				IMX6Q_GPR1_PCIE_TEST_PD);
		break;
	case IMX7D:
		regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,
				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
		break;
	default:
		break;
	int offset = imx_pcie_grp_offset(imx_pcie);

	if (enable) {
		regmap_clear_bits(imx_pcie->iomuxc_gpr, offset, IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE);
		regmap_set_bits(imx_pcie->iomuxc_gpr, offset, IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN);
	}

	return 0;
}

static int imx7d_pcie_enable_ref_clk(struct imx_pcie *imx_pcie, bool enable)
{
	if (!enable)
		regmap_set_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR12,
				IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
	return 0;
}

static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)
@@ -665,11 +643,13 @@ static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)
	if (ret)
		return ret;

	ret = imx_pcie_enable_ref_clk(imx_pcie);
	if (imx_pcie->drvdata->enable_ref_clk) {
		ret = imx_pcie->drvdata->enable_ref_clk(imx_pcie, true);
		if (ret) {
		dev_err(dev, "unable to enable pcie ref clock\n");
			dev_err(dev, "Failed to enable PCIe REFCLK\n");
			goto err_ref_clk;
		}
	}

	/* allow the clocks to stabilize */
	usleep_range(200, 500);
@@ -683,7 +663,8 @@ static int imx_pcie_clk_enable(struct imx_pcie *imx_pcie)

static void imx_pcie_clk_disable(struct imx_pcie *imx_pcie)
{
	imx_pcie_disable_ref_clk(imx_pcie);
	if (imx_pcie->drvdata->enable_ref_clk)
		imx_pcie->drvdata->enable_ref_clk(imx_pcie, false);
	clk_bulk_disable_unprepare(imx_pcie->drvdata->clks_cnt, imx_pcie->clks);
}

@@ -1459,6 +1440,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.init_phy = imx_pcie_init_phy,
		.enable_ref_clk = imx6q_pcie_enable_ref_clk,
	},
	[IMX6SX] = {
		.variant = IMX6SX,
@@ -1473,6 +1455,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.init_phy = imx6sx_pcie_init_phy,
		.enable_ref_clk = imx6sx_pcie_enable_ref_clk,
	},
	[IMX6QP] = {
		.variant = IMX6QP,
@@ -1488,6 +1471,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.init_phy = imx_pcie_init_phy,
		.enable_ref_clk = imx6q_pcie_enable_ref_clk,
	},
	[IMX7D] = {
		.variant = IMX7D,
@@ -1500,6 +1484,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.init_phy = imx7d_pcie_init_phy,
		.enable_ref_clk = imx7d_pcie_enable_ref_clk,
	},
	[IMX8MQ] = {
		.variant = IMX8MQ,
@@ -1513,6 +1498,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[1] = IOMUXC_GPR12,
		.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
		.init_phy = imx8mq_pcie_init_phy,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX8MM] = {
		.variant = IMX8MM,
@@ -1524,6 +1510,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.clks_cnt = ARRAY_SIZE(imx8mm_clks),
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX8MP] = {
		.variant = IMX8MP,
@@ -1535,6 +1522,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.clks_cnt = ARRAY_SIZE(imx8mm_clks),
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX95] = {
		.variant = IMX95,
@@ -1561,6 +1549,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
		.epc_features = &imx8m_pcie_epc_features,
		.init_phy = imx8mq_pcie_init_phy,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX8MM_EP] = {
		.variant = IMX8MM_EP,
@@ -1573,6 +1562,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.epc_features = &imx8m_pcie_epc_features,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX8MP_EP] = {
		.variant = IMX8MP_EP,
@@ -1585,6 +1575,7 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_off[0] = IOMUXC_GPR12,
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.epc_features = &imx8m_pcie_epc_features,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX95_EP] = {
		.variant = IMX95_EP,