Commit c2699778 authored by Richard Zhu's avatar Richard Zhu Committed by Bjorn Helgaas
Browse files

PCI: imx6: Add i.MX8Q PCIe Root Complex (RC) support

Implement i.MX8Q (i.MX8QM, i.MX8QXP, and i.MX8DXL) PCIe Root Complex
(RC) support. While the controller resembles that of i.MX8MP, the PHY
differs significantly. Also, there's a distinction between PCI bus
addresses and CPU addresses.

Introduce IMX_PCIE_FLAG_CPU_ADDR_FIXUP in drvdata::flags to indicate driver
need the cpu_addr_fixup() callback to facilitate CPU address to PCI bus
address conversion according to "ranges" property.

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


Signed-off-by: default avatarRichard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
Signed-off-by: default avatarKrzysztof Wilczyński <kwilczynski@kernel.org>
[bhelgaas: check resource_list_first_type() for NULL]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
parent 8026f2d8
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ enum imx_pcie_variants {
	IMX8MQ,
	IMX8MM,
	IMX8MP,
	IMX8Q,
	IMX95,
	IMX8MQ_EP,
	IMX8MM_EP,
@@ -80,6 +81,7 @@ enum imx_pcie_variants {
#define IMX_PCIE_FLAG_HAS_PHY_RESET		BIT(5)
#define IMX_PCIE_FLAG_HAS_SERDES		BIT(6)
#define IMX_PCIE_FLAG_SUPPORT_64BIT		BIT(7)
#define IMX_PCIE_FLAG_CPU_ADDR_FIXUP		BIT(8)

#define imx_check_flag(pci, val)	(pci->drvdata->flags & val)

@@ -1010,6 +1012,22 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
		regulator_disable(imx_pcie->vpcie);
}

static u64 imx_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
{
	struct imx_pcie *imx_pcie = to_imx_pcie(pcie);
	struct dw_pcie_rp *pp = &pcie->pp;
	struct resource_entry *entry;

	if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_CPU_ADDR_FIXUP))
		return cpu_addr;

	entry = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM);
	if (!entry)
		return cpu_addr;

	return cpu_addr - entry->offset;
}

static const struct dw_pcie_host_ops imx_pcie_host_ops = {
	.init = imx_pcie_host_init,
	.deinit = imx_pcie_host_exit,
@@ -1018,6 +1036,7 @@ static const struct dw_pcie_host_ops imx_pcie_host_ops = {
static const struct dw_pcie_ops dw_pcie_ops = {
	.start_link = imx_pcie_start_link,
	.stop_link = imx_pcie_stop_link,
	.cpu_addr_fixup = imx_pcie_cpu_addr_fixup,
};

static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
@@ -1460,6 +1479,7 @@ static const char * const imx6q_clks[] = {"pcie_bus", "pcie", "pcie_phy"};
static const char * const imx8mm_clks[] = {"pcie_bus", "pcie", "pcie_aux"};
static const char * const imx8mq_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_aux"};
static const char * const imx6sx_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_inbound_axi"};
static const char * const imx8q_clks[] = {"mstr", "slv", "dbi"};

static const struct imx_pcie_drvdata drvdata[] = {
	[IMX6Q] = {
@@ -1563,6 +1583,13 @@ static const struct imx_pcie_drvdata drvdata[] = {
		.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
		.enable_ref_clk = imx8mm_pcie_enable_ref_clk,
	},
	[IMX8Q] = {
		.variant = IMX8Q,
		.flags = IMX_PCIE_FLAG_HAS_PHYDRV |
			 IMX_PCIE_FLAG_CPU_ADDR_FIXUP,
		.clk_names = imx8q_clks,
		.clks_cnt = ARRAY_SIZE(imx8q_clks),
	},
	[IMX95] = {
		.variant = IMX95,
		.flags = IMX_PCIE_FLAG_HAS_SERDES,
@@ -1640,6 +1667,7 @@ static const struct of_device_id imx_pcie_of_match[] = {
	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
	{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
	{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
	{ .compatible = "fsl,imx8q-pcie", .data = &drvdata[IMX8Q], },
	{ .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },
	{ .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },
	{ .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },