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

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.comSigned-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
...@@ -65,6 +65,7 @@ enum imx_pcie_variants { ...@@ -65,6 +65,7 @@ enum imx_pcie_variants {
IMX8MQ, IMX8MQ,
IMX8MM, IMX8MM,
IMX8MP, IMX8MP,
IMX8Q,
IMX95, IMX95,
IMX8MQ_EP, IMX8MQ_EP,
IMX8MM_EP, IMX8MM_EP,
...@@ -80,6 +81,7 @@ enum imx_pcie_variants { ...@@ -80,6 +81,7 @@ enum imx_pcie_variants {
#define IMX_PCIE_FLAG_HAS_PHY_RESET BIT(5) #define IMX_PCIE_FLAG_HAS_PHY_RESET BIT(5)
#define IMX_PCIE_FLAG_HAS_SERDES BIT(6) #define IMX_PCIE_FLAG_HAS_SERDES BIT(6)
#define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7) #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) #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) ...@@ -1010,6 +1012,22 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)
regulator_disable(imx_pcie->vpcie); 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 = { static const struct dw_pcie_host_ops imx_pcie_host_ops = {
.init = imx_pcie_host_init, .init = imx_pcie_host_init,
.deinit = imx_pcie_host_exit, .deinit = imx_pcie_host_exit,
...@@ -1018,6 +1036,7 @@ static const struct dw_pcie_host_ops imx_pcie_host_ops = { ...@@ -1018,6 +1036,7 @@ static const struct dw_pcie_host_ops imx_pcie_host_ops = {
static const struct dw_pcie_ops dw_pcie_ops = { static const struct dw_pcie_ops dw_pcie_ops = {
.start_link = imx_pcie_start_link, .start_link = imx_pcie_start_link,
.stop_link = imx_pcie_stop_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) 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"}; ...@@ -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 imx8mm_clks[] = {"pcie_bus", "pcie", "pcie_aux"};
static const char * const imx8mq_clks[] = {"pcie_bus", "pcie", "pcie_phy", "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 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[] = { static const struct imx_pcie_drvdata drvdata[] = {
[IMX6Q] = { [IMX6Q] = {
...@@ -1563,6 +1583,13 @@ static const struct imx_pcie_drvdata drvdata[] = { ...@@ -1563,6 +1583,13 @@ static const struct imx_pcie_drvdata drvdata[] = {
.mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
.enable_ref_clk = imx8mm_pcie_enable_ref_clk, .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] = { [IMX95] = {
.variant = IMX95, .variant = IMX95,
.flags = IMX_PCIE_FLAG_HAS_SERDES, .flags = IMX_PCIE_FLAG_HAS_SERDES,
...@@ -1640,6 +1667,7 @@ static const struct of_device_id imx_pcie_of_match[] = { ...@@ -1640,6 +1667,7 @@ static const struct of_device_id imx_pcie_of_match[] = {
{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], }, { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], }, { .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], }, { .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
{ .compatible = "fsl,imx8q-pcie", .data = &drvdata[IMX8Q], },
{ .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], }, { .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },
{ .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], }, { .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },
{ .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], }, { .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment