]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: imx6: Add i.MX8Q PCIe Root Complex (RC) support
authorRichard Zhu <hongxing.zhu@nxp.com>
Mon, 29 Jul 2024 20:18:18 +0000 (16:18 -0400)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 11 Sep 2024 14:04:18 +0000 (09:04 -0500)
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: Richard Zhu <hongxing.zhu@nxp.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Krzysztof WilczyƄski <kwilczynski@kernel.org>
[bhelgaas: check resource_list_first_type() for NULL]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/dwc/pci-imx6.c

index f99d65a281caa0d5e41f1def5638b31db559d26a..5a40cd7f29d4afdfa54cea30c28f5ae952242454 100644 (file)
@@ -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], },