summaryrefslogtreecommitdiff
path: root/drivers/pci/controller/dwc/pci-imx6.c
diff options
context:
space:
mode:
authorRichard Zhu <hongxing.zhu@nxp.com>2020-05-14 17:04:18 +0800
committerRichard Zhu <hongxing.zhu@nxp.com>2020-06-11 10:06:33 +0800
commit112ade807b909b5bb44dd16eca0313a2085b4c0c (patch)
treeaecf6d7623c65adad6eb53967967ff4396355277 /drivers/pci/controller/dwc/pci-imx6.c
parentaba962ef8b93c537d9ca1c0d862050d806ba756c (diff)
MLK-24012-12 pci: imx: add the imx8qxp ep support
Add the PCIe EP mode on iMX8QXP, and verify EP mode on iMX8QXP MEK board Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com> Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
Diffstat (limited to 'drivers/pci/controller/dwc/pci-imx6.c')
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c790
1 files changed, 194 insertions, 596 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c655d9de144e..4c958b4811d2 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -84,6 +84,7 @@ enum imx6_pcie_variants {
IMX8QM,
IMX8QXP,
IMX8MP,
+ IMX8QXP_EP,
};
#define IMX6_PCIE_FLAG_IMX6_PHY BIT(0)
@@ -94,6 +95,7 @@ enum imx6_pcie_variants {
struct imx6_pcie_drvdata {
enum imx6_pcie_variants variant;
+ enum dw_pcie_device_mode mode;
u32 flags;
int dbi_length;
};
@@ -115,7 +117,6 @@ struct imx6_pcie {
struct clk *phy_per;
struct clk *misc_per;
struct regmap *iomuxc_gpr;
- struct regmap *hsiomix;
u32 controller_id;
struct reset_control *pciephy_reset;
struct reset_control *pciephy_perst;
@@ -130,8 +131,6 @@ struct imx6_pcie {
u32 hsio_cfg;
u32 ext_osc;
u32 local_addr;
- u32 hard_wired;
- u32 dma_unroll_offset;
int link_gen;
struct regulator *vpcie;
void __iomem *phy_base;
@@ -187,35 +186,6 @@ struct imx6_pcie {
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
-/* DMA registers */
-#define MAX_PCIE_DMA_CHANNELS 8
-#define DMA_UNROLL_CDM_OFFSET (0x7 << 19)
-#define DMA_REG_OFFSET 0x970
-#define DMA_CTRL_VIEWPORT_OFF (DMA_REG_OFFSET + 0x8)
-#define DMA_WRITE_ENGINE_EN_OFF (DMA_REG_OFFSET + 0xC)
-#define DMA_WRITE_ENGINE_EN BIT(0)
-#define DMA_WRITE_DOORBELL (DMA_REG_OFFSET + 0x10)
-#define DMA_READ_ENGINE_EN_OFF (DMA_REG_OFFSET + 0x2C)
-#define DMA_READ_ENGINE_EN BIT(0)
-#define DMA_READ_DOORBELL (DMA_REG_OFFSET + 0x30)
-#define DMA_WRITE_INT_STS (DMA_REG_OFFSET + 0x4C)
-#define DMA_WRITE_INT_MASK (DMA_REG_OFFSET + 0x54)
-#define DMA_WRITE_INT_CLR (DMA_REG_OFFSET + 0x58)
-#define DMA_READ_INT_STS (DMA_REG_OFFSET + 0xA0)
-#define DMA_READ_INT_MASK (DMA_REG_OFFSET + 0xA8)
-#define DMA_READ_INT_CLR (DMA_REG_OFFSET + 0xAC)
-#define DMA_DONE_INT_STS 0xFF
-#define DMA_ABORT_INT_STS (0xFF << 16)
-#define DMA_VIEWPOT_SEL_OFF (DMA_REG_OFFSET + 0xFC)
-#define DMA_CHANNEL_CTRL_1 (DMA_REG_OFFSET + 0x100)
-#define DMA_CHANNEL_CTRL_1_LIE BIT(3)
-#define DMA_CHANNEL_CTRL_2 (DMA_REG_OFFSET + 0x104)
-#define DMA_TRANSFER_SIZE (DMA_REG_OFFSET + 0x108)
-#define DMA_SAR_LOW (DMA_REG_OFFSET + 0x10C)
-#define DMA_SAR_HIGH (DMA_REG_OFFSET + 0x110)
-#define DMA_DAR_LOW (DMA_REG_OFFSET + 0x114)
-#define DMA_DAR_HIGH (DMA_REG_OFFSET + 0x118)
-
/* PHY registers (not memory-mapped) */
#define PCIE_PHY_ATEOVRD 0x10
#define PCIE_PHY_ATEOVRD_EN BIT(2)
@@ -227,19 +197,11 @@ struct imx6_pcie {
#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f
#define PCIE_PHY_MPLL_MULTIPLIER_OVRD BIT(9)
-#define PCIE_PHY_RX_ASIC_OUT 0x100D
-#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
-
/* iMX7 PCIe PHY registers */
#define PCIE_PHY_CMN_REG4 0x14
/* These are probably the bits that *aren't* DCC_FB_EN */
#define PCIE_PHY_CMN_REG4_DCC_FB_EN 0x29
-#define PCIE_PHY_CMN_REG15 0x54
-#define PCIE_PHY_CMN_REG15_DLY_4 BIT(2)
-#define PCIE_PHY_CMN_REG15_PLL_PD BIT(5)
-#define PCIE_PHY_CMN_REG15_OVRD_PLL_PD BIT(7)
-
#define PCIE_PHY_CMN_REG24 0x90
#define PCIE_PHY_CMN_REG24_RX_EQ BIT(6)
#define PCIE_PHY_CMN_REG24_RX_EQ_SEL BIT(3)
@@ -288,7 +250,7 @@ struct imx6_pcie {
#define IMX8QM_STTS0_LANE0_TX_PLL_LOCK BIT(4)
#define IMX8QM_STTS0_LANE1_TX_PLL_LOCK BIT(12)
-#define IMX8QM_PCIE_TYPE_MASK (0xF << 24)
+#define IMX8QM_PCIE_TYPE_MASK GENMASK(27, 24)
#define IMX8QM_PHYX2_CTRL0_APB_MASK 0x3
#define IMX8QM_PHY_APB_RSTN_0 BIT(0)
@@ -316,24 +278,13 @@ struct imx6_pcie {
static void imx6_pcie_ltssm_disable(struct device *dev);
-/*
- * The default value of the reserved ddr memory
- * used to verify EP/RC memory space access operations.
- * The layout of the 1G ddr on SD boards
- * [imx6qdl-sd-ard boards]0x1000_0000 ~ 0x4FFF_FFFF
- * [imx6sx,imx7d platforms]0x8000_0000 ~ 0xBFFF_FFFF
- *
- */
-static u32 ddr_test_region = 0, test_region_size = SZ_2M;
-static bool dma_w_end, dma_r_end, dma_en;
-
static bool imx6_pcie_readable_reg(struct device *dev, unsigned int reg)
{
enum imx6_pcie_variants variant;
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
variant = imx6_pcie->drvdata->variant;
- if (variant == IMX8QXP) {
+ if (variant == IMX8QXP || variant == IMX8QXP_EP) {
switch (reg) {
case IMX8QM_CSR_PHYX1_OFFSET:
case IMX8QM_CSR_PCIEB_OFFSET:
@@ -376,7 +327,7 @@ static bool imx6_pcie_writeable_reg(struct device *dev, unsigned int reg)
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
variant = imx6_pcie->drvdata->variant;
- if (variant == IMX8QXP) {
+ if (variant == IMX8QXP || variant == IMX8QXP_EP) {
switch (reg) {
case IMX8QM_CSR_PHYX1_OFFSET:
case IMX8QM_CSR_PCIEB_OFFSET:
@@ -713,6 +664,7 @@ static int imx6_pcie_attach_pd(struct device *dev)
}
/* fall through */
case IMX8QXP:
+ case IMX8QXP_EP:
pd_dev = dev_pm_domain_attach_by_name(dev, "hsio_gpio");
if (IS_ERR(pd_dev)) {
ret = PTR_ERR(pd_dev);
@@ -807,6 +759,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
if (ret) {
@@ -908,6 +861,7 @@ static void imx8_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
break;
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES;
retries++) {
@@ -1016,6 +970,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
}
/* fall through */
case IMX8QXP:
+ case IMX8QXP_EP:
clk_disable_unprepare(imx6_pcie->pcie_per);
clk_disable_unprepare(imx6_pcie->pcie_inbound_axi);
clk_disable_unprepare(imx6_pcie->phy_per);
@@ -1063,6 +1018,7 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
imx6_pcie_clk_enable(imx6_pcie);
/*
* Set the over ride low and enabled
@@ -1160,6 +1116,7 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
switch (imx6_pcie->drvdata->variant) {
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
case IMX8MP:
/* ClKs had been enabled */
@@ -1173,7 +1130,7 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpio_set_value_cansleep(imx6_pcie->reset_gpio,
imx6_pcie->gpio_active_high);
- msleep(100);
+ msleep(20);
gpio_set_value_cansleep(imx6_pcie->reset_gpio,
!imx6_pcie->gpio_active_high);
}
@@ -1190,6 +1147,7 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
IMX8QM_PHYX2_LPCG_PCLK1_MASK);
/* fall through */
case IMX8QXP:
+ case IMX8QXP_EP:
val = IMX8QM_CSR_PCIEA_OFFSET
+ imx6_pcie->controller_id * SZ_64K;
/* bit19 PM_REQ_CORE_RST of pciex#_stts0 should be cleared. */
@@ -1334,53 +1292,47 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
{
- unsigned int mask, val;
+ unsigned int addr, mask, val, mode;
+ unsigned int variant = imx6_pcie->drvdata->variant;
+ struct dw_pcie *pci = imx6_pcie->pci;
+ struct device *dev = pci->dev;
- if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
- && (imx6_pcie->hard_wired == 0)) {
- if (imx6_pcie->drvdata->variant == IMX8QM
- || imx6_pcie->drvdata->variant == IMX8QXP) {
- val = IMX8QM_CSR_PCIEA_OFFSET
- + imx6_pcie->controller_id * SZ_64K;
- regmap_update_bits(imx6_pcie->iomuxc_gpr,
- val, IMX8QM_PCIE_TYPE_MASK,
- PCI_EXP_TYPE_ENDPOINT << 24);
- } else {
- if (unlikely(imx6_pcie->controller_id))
- /* iMX8MQ second PCIE */
- regmap_update_bits(imx6_pcie->iomuxc_gpr,
- IOMUXC_GPR12,
- IMX6Q_GPR12_DEVICE_TYPE >> 4,
- PCI_EXP_TYPE_ENDPOINT << 8);
- else
- regmap_update_bits(imx6_pcie->iomuxc_gpr,
- IOMUXC_GPR12,
- IMX6Q_GPR12_DEVICE_TYPE,
- PCI_EXP_TYPE_ENDPOINT << 12);
- }
- } else {
- if (imx6_pcie->drvdata->variant == IMX8QM ||
- imx6_pcie->drvdata->variant == IMX8QXP) {
- val = IMX8QM_CSR_PCIEA_OFFSET
- + imx6_pcie->controller_id * SZ_64K;
- regmap_update_bits(imx6_pcie->iomuxc_gpr,
- val, IMX8QM_PCIE_TYPE_MASK,
- PCI_EXP_TYPE_ROOT_PORT << 24);
- } else if (imx6_pcie->drvdata->variant == IMX8MQ &&
- imx6_pcie->controller_id == 1) {
- mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE;
- val = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
- PCI_EXP_TYPE_ROOT_PORT);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- mask, val);
+ mode = imx6_pcie->drvdata->mode;
+ switch (mode) {
+ case DW_PCIE_RC_TYPE:
+ mode = PCI_EXP_TYPE_ROOT_PORT;
+ break;
+ case DW_PCIE_EP_TYPE:
+ mode = PCI_EXP_TYPE_ENDPOINT;
+ break;
+ default:
+ dev_err(dev, "INVALID device type %d\n", mode);
+ }
+
+ switch (variant) {
+ case IMX8QM:
+ case IMX8QXP:
+ case IMX8QXP_EP:
+ if (imx6_pcie->controller_id)
+ addr = IMX8QM_CSR_PCIEB_OFFSET;
+ else
+ addr = IMX8QM_CSR_PCIEA_OFFSET;
+ mask = IMX8QM_PCIE_TYPE_MASK;
+ val = FIELD_PREP(IMX8QM_PCIE_TYPE_MASK, mode);
+ break;
+ default:
+ if (variant == IMX8MQ && imx6_pcie->controller_id == 1) {
+ addr = IOMUXC_GPR12;
+ mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE;
+ val = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, mode);
} else {
+ addr = IOMUXC_GPR12;
mask = IMX6Q_GPR12_DEVICE_TYPE;
- val = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE,
- PCI_EXP_TYPE_ROOT_PORT);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- mask, val);
+ val = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, mode);
}
+ break;
}
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, addr, mask, val);
}
static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
@@ -1390,6 +1342,7 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
switch (imx6_pcie->drvdata->variant) {
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
if (imx6_pcie->hsio_cfg == PCIEAX2SATA) {
/*
@@ -1743,6 +1696,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev)
reset_control_deassert(imx6_pcie->apps_reset);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
/* Bit4 of the CTRL2 */
val = IMX8QM_CSR_PCIEA_OFFSET
@@ -1854,6 +1808,7 @@ static void pci_imx_set_msi_en(struct pcie_port *pp)
val = dw_pcie_readw_dbi(pci, PCIE_RC_IMX6_MSI_CAP +
PCI_MSI_FLAGS);
val |= PCI_MSI_FLAGS_ENABLE;
+ val &= ~PCI_MSI_FLAGS_64BIT;
dw_pcie_writew_dbi(pci, PCIE_RC_IMX6_MSI_CAP + PCI_MSI_FLAGS,
val);
dw_pcie_dbi_ro_wr_dis(pci);
@@ -1868,20 +1823,13 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
if (gpio_is_valid(imx6_pcie->dis_gpio))
gpio_set_value_cansleep(imx6_pcie->dis_gpio, 1);
- imx6_pcie_assert_core_reset(imx6_pcie);
- imx6_pcie_init_phy(imx6_pcie);
- imx6_pcie_deassert_core_reset(imx6_pcie);
- imx6_setup_phy_mpll(imx6_pcie);
- if (!(IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
- && (imx6_pcie->hard_wired == 0))) {
- dw_pcie_setup_rc(pp);
- pci_imx_set_msi_en(pp);
- if (imx6_pcie_establish_link(imx6_pcie))
- return -ENODEV;
+ dw_pcie_setup_rc(pp);
+ pci_imx_set_msi_en(pp);
+ if (imx6_pcie_establish_link(imx6_pcie))
+ return -ENODEV;
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
- }
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ dw_pcie_msi_init(pp);
return 0;
}
@@ -1917,283 +1865,143 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
return 0;
}
+static int imx6_pcie_start_link(struct dw_pcie *pci)
+{
+ struct device *dev = pci->dev;
+
+ if (dw_pcie_link_up(pci)) {
+ dev_dbg(dev, "link is already up\n");
+ return 0;
+ }
+
+ /* Start LTSSM. */
+ imx6_pcie_ltssm_enable(dev);
+
+ return 0;
+}
+
+static void imx6_pcie_stop_link(struct dw_pcie *pci)
+{
+ struct device *dev = pci->dev;
+
+ /* turn off pcie ltssm */
+ imx6_pcie_ltssm_disable(dev);
+}
+
static u64 imx6_pcie_cpu_addr_fixup(struct dw_pcie *pcie, u64 cpu_addr)
{
+ unsigned int offset;
+ struct dw_pcie_ep *ep = &pcie->ep;
struct pcie_port *pp = &pcie->pp;
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pcie);
+ if (imx6_pcie->drvdata->mode == DW_PCIE_RC_TYPE)
+ offset = pp->mem_base;
+ else
+ offset = ep->phys_base;
+
if (imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_CPU_ADDR_FIXUP)
- return (cpu_addr + imx6_pcie->local_addr - pp->mem_base);
+ return (cpu_addr + imx6_pcie->local_addr - offset);
else
return cpu_addr;
}
static const struct dw_pcie_ops dw_pcie_ops = {
- /* No special ops needed, but pcie-designware still expects this struct */
+ .start_link = imx6_pcie_start_link,
+ .stop_link = imx6_pcie_stop_link,
.cpu_addr_fixup = imx6_pcie_cpu_addr_fixup,
};
-static ssize_t ep_bar0_addr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static void imx_pcie_ep_init(struct dw_pcie_ep *ep)
{
- struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- struct dw_pcie *pci = imx6_pcie->pci;
+ enum pci_barno bar;
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
- return sprintf(buf, "imx-pcie-bar0-addr-info start 0x%08x\n",
- readl(pci->dbi_base + PCI_BASE_ADDRESS_0));
+ for (bar = BAR_0; bar <= BAR_5; bar++)
+ dw_pcie_ep_reset_bar(pci, bar);
}
-static ssize_t ep_bar0_addr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
+static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
+ enum pci_epc_irq_type type,
+ u16 interrupt_num)
{
- u32 bar_start;
- struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- struct dw_pcie *pci = imx6_pcie->pci;
-
- if (sscanf(buf, "%x\n", &bar_start) != 1)
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+ switch (type) {
+ case PCI_EPC_IRQ_LEGACY:
+ return dw_pcie_ep_raise_legacy_irq(ep, func_no);
+ case PCI_EPC_IRQ_MSI:
+ return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
+ case PCI_EPC_IRQ_MSIX:
+ return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
+ default:
+ dev_err(pci->dev, "UNKNOWN IRQ type\n");
return -EINVAL;
- writel(bar_start, pci->dbi_base + PCI_BASE_ADDRESS_0);
-
- return count;
-}
-
-static void imx6_pcie_regions_setup(struct device *dev)
-{
- struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
- struct dw_pcie *pci = imx6_pcie->pci;
- struct pcie_port *pp = &pci->pp;
-
- dw_pcie_dbi_ro_wr_en(pci);
-
- switch (imx6_pcie->drvdata->variant) {
- case IMX8QM:
- case IMX8QXP:
- case IMX8MQ:
- case IMX8MM:
- case IMX8MP:
- /*
- * RPMSG reserved 4Mbytes, but only used up to 2Mbytes.
- * The left 2Mbytes can be used here.
- */
- if (ddr_test_region == 0)
- dev_err(dev, "invalid ddr test region.\n");
- break;
- case IMX6SX:
- case IMX7D:
- ddr_test_region = 0xb0000000;
- break;
-
- case IMX6Q:
- case IMX6QP:
- ddr_test_region = 0x40000000;
- break;
}
- dev_info(dev, "ddr_test_region is 0x%08x.\n", ddr_test_region);
- dw_pcie_prog_outbound_atu(pci, 0, 0, pp->mem_base,
- ddr_test_region, test_region_size);
+ return 0;
}
-static DEVICE_ATTR_RW(ep_bar0_addr);
-
-static struct attribute *imx6_pcie_ep_attrs[] = {
- &dev_attr_ep_bar0_addr.attr,
- NULL
+/*
+ * iMX8QM/iMXQXP: Bar1/3/5 are reserved.
+ */
+static const struct pci_epc_features imx8q_pcie_epc_features = {
+ .linkup_notifier = false,
+ .msi_capable = true,
+ .msix_capable = false,
+ .reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
};
-static struct attribute_group imx6_pcie_attrgroup = {
- .attrs = imx6_pcie_ep_attrs,
+static const struct pci_epc_features*
+imx_pcie_ep_get_features(struct dw_pcie_ep *ep)
+{
+ return &imx8q_pcie_epc_features;
+}
+
+static const struct dw_pcie_ep_ops pcie_ep_ops = {
+ .ep_init = imx_pcie_ep_init,
+ .raise_irq = imx_pcie_ep_raise_irq,
+ .get_features = imx_pcie_ep_get_features,
};
-static void imx6_pcie_setup_ep(struct dw_pcie *pci, unsigned int bar_offset)
+static int __init imx_add_pcie_ep(struct imx6_pcie *imx6_pcie,
+ struct platform_device *pdev)
{
int ret;
- u32 val;
- u32 lanes;
- struct device_node *np = pci->dev->of_node;
+ unsigned int pcie_dbi2_offset;
+ struct dw_pcie_ep *ep;
+ struct resource *res;
+ struct dw_pcie *pci = imx6_pcie->pci;
+ struct device *dev = pci->dev;
- ret = of_property_read_u32(np, "num-lanes", &lanes);
- if (ret)
- lanes = 0;
-
- /* set the number of lanes */
- val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
- val &= ~PORT_LINK_MODE_MASK;
- switch (lanes) {
- case 1:
- val |= PORT_LINK_MODE_1_LANES;
+ ep = &pci->ep;
+ ep->ops = &pcie_ep_ops;
+
+ switch (imx6_pcie->drvdata->variant) {
+ case IMX8MQ:
+ case IMX8MM:
+ case IMX8MP:
+ pcie_dbi2_offset = SZ_1M;
break;
default:
- dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes);
- return;
- }
- dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
-
- /* set link width speed control register */
- val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
- val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
- switch (lanes) {
- case 1:
- val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
+ pcie_dbi2_offset = SZ_4K;
break;
- default:
- dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes);
- return;
- }
- dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
-
- /* get iATU unroll support */
- val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
- if (val == 0xffffffff) {
- pci->iatu_unroll_enabled = 1;
- if (!pci->atu_base)
- pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
}
- dev_info(pci->dev, "iATU unroll: %s\n",
- pci->iatu_unroll_enabled ? "enabled" : "disabled");
-
- /* CMD reg:I/O space, MEM space, and Bus Master Enable */
- writel(readl(pci->dbi_base + PCI_COMMAND)
- | PCI_COMMAND_IO
- | PCI_COMMAND_MEMORY
- | PCI_COMMAND_MASTER,
- pci->dbi_base + PCI_COMMAND);
-
- /*
- * configure the class_rev(emaluate one memory ram ep device),
- * bar0 and bar1 of ep
- */
- writel(0xdeadbeaf, pci->dbi_base + PCI_VENDOR_ID);
- writel((readl(pci->dbi_base + PCI_CLASS_REVISION) & 0xFFFF)
- | (PCI_CLASS_MEMORY_RAM << 16),
- pci->dbi_base + PCI_CLASS_REVISION);
- writel(0xdeadbeaf, pci->dbi_base
- + PCI_SUBSYSTEM_VENDOR_ID);
-
- /* 32bit none-prefetchable 8M bytes memory on bar0 */
- writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_0);
- writel(SZ_8M - 1, pci->dbi_base + bar_offset
- + PCI_BASE_ADDRESS_0);
-
- /* None used bar1 */
- writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1);
- writel(0, pci->dbi_base + bar_offset + PCI_BASE_ADDRESS_1);
-
- /* 4K bytes IO on bar2 */
- writel(0x1, pci->dbi_base + PCI_BASE_ADDRESS_2);
- writel(SZ_4K - 1, pci->dbi_base + bar_offset +
- PCI_BASE_ADDRESS_2);
-
- /*
- * 32bit prefetchable 1M bytes memory on bar3
- * FIXME BAR MASK3 is not changeable, the size
- * is fixed to 256 bytes.
- */
- writel(0x8, pci->dbi_base + PCI_BASE_ADDRESS_3);
- writel(SZ_1M - 1, pci->dbi_base + bar_offset
- + PCI_BASE_ADDRESS_3);
-
- /*
- * 64bit prefetchable 1M bytes memory on bar4-5.
- * FIXME BAR4,5 are not enabled yet
- */
- writel(0xc, pci->dbi_base + PCI_BASE_ADDRESS_4);
- writel(SZ_1M - 1, pci->dbi_base + bar_offset
- + PCI_BASE_ADDRESS_4);
- writel(0, pci->dbi_base + bar_offset + PCI_BASE_ADDRESS_5);
-}
-
-static irqreturn_t imx6_pcie_dma_isr(int irq, void *param)
-{
- u32 irqs, offset;
- struct pcie_port *pp = (struct pcie_port *)param;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
-
- offset = imx6_pcie->dma_unroll_offset;
-
- /* check write isr */
- irqs = readl(pci->dbi_base + offset + DMA_WRITE_INT_STS);
- if (irqs & DMA_DONE_INT_STS) {
- /* write 1 clear */
- writel(irqs & DMA_DONE_INT_STS,
- pci->dbi_base + offset + DMA_WRITE_INT_CLR);
- dma_w_end = 1;
- } else if (irqs & DMA_ABORT_INT_STS) {
- pr_info("imx pcie dma write error 0x%0x.\n", irqs);
- }
- /* check read isr */
- irqs = readl(pci->dbi_base + offset + DMA_READ_INT_STS);
- if (irqs & DMA_DONE_INT_STS) {
- /* write 1 clear */
- writel(irqs & DMA_DONE_INT_STS,
- pci->dbi_base + offset + DMA_READ_INT_CLR);
- dma_r_end = 1;
- } else if (irqs & DMA_ABORT_INT_STS) {
- pr_info("imx pcie dma read error 0x%0x.", irqs);
- }
- return IRQ_HANDLED;
-}
-
-/**
- * imx6_pcie_local_dma_start - Start one local iMX PCIE DMA.
- * @pp: the port start the dma transmission.
- * @dir: direction of the dma, 1 read, 0 write;
- * @chl: the channel num of the iMX PCIE DMA(0 - 7).
- * @src: source DMA address.
- * @dst: destination DMA address.
- * @len: transfer length.
- */
-static int imx6_pcie_local_dma_start(struct pcie_port *pp, bool dir,
- unsigned int chl, dma_addr_t src, dma_addr_t dst,
- unsigned int len)
-{
- u32 offset, doorbell, unroll_cal;
- struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
- struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
-
- if (pp == NULL)
- return -EINVAL;
- if (chl > MAX_PCIE_DMA_CHANNELS)
+ pci->dbi_base2 = pci->dbi_base + pcie_dbi2_offset;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
+ if (!res)
return -EINVAL;
- offset = imx6_pcie->dma_unroll_offset;
- /* enable dma engine, dir 1:read. 0:write. */
- if (dir)
- writel(DMA_READ_ENGINE_EN,
- pci->dbi_base + offset
- + DMA_READ_ENGINE_EN_OFF);
- else
- writel(DMA_WRITE_ENGINE_EN,
- pci->dbi_base + offset
- + DMA_WRITE_ENGINE_EN_OFF);
- writel(0x0, pci->dbi_base + offset + DMA_WRITE_INT_MASK);
- writel(0x0, pci->dbi_base + offset + DMA_READ_INT_MASK);
- /* ch dir and ch num */
- if (offset == 0) {
- writel((dir << 31) | chl, pci->dbi_base + DMA_VIEWPOT_SEL_OFF);
- writel(DMA_CHANNEL_CTRL_1_LIE,
- pci->dbi_base + DMA_CHANNEL_CTRL_1);
- writel(0x0, pci->dbi_base + DMA_CHANNEL_CTRL_2);
- writel(len, pci->dbi_base + DMA_TRANSFER_SIZE);
- writel((u32)src, pci->dbi_base + DMA_SAR_LOW);
- writel(0x0, pci->dbi_base + DMA_SAR_HIGH);
- writel((u32)dst, pci->dbi_base + DMA_DAR_LOW);
- writel(0x0, pci->dbi_base + DMA_DAR_HIGH);
- } else {
- unroll_cal = DMA_UNROLL_CDM_OFFSET
- + 0x200 * (chl + 1) + 0x100 * dir;
- writel(DMA_CHANNEL_CTRL_1_LIE, pci->dbi_base + unroll_cal);
- writel(0x0, pci->dbi_base + unroll_cal + 0x4);
- writel(len, pci->dbi_base + unroll_cal + 0x8);
- writel((u32)src, pci->dbi_base + unroll_cal + 0xc);
- writel(0x0, pci->dbi_base + unroll_cal + 0x10);
- writel((u32)dst, pci->dbi_base + unroll_cal + 0x14);
- writel(0x0, pci->dbi_base + unroll_cal + 0x18);
- }
+ ep->phys_base = res->start;
+ ep->addr_size = resource_size(res);
- doorbell = dir ? DMA_READ_DOORBELL : DMA_WRITE_DOORBELL;
- writel(chl, pci->dbi_base + offset + doorbell);
+ ret = dw_pcie_ep_init(ep);
+ if (ret) {
+ dev_err(dev, "failed to initialize endpoint\n");
+ return ret;
+ }
+ /* Start LTSSM. */
+ imx6_pcie_ltssm_enable(dev);
return 0;
}
@@ -2216,6 +2024,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev)
reset_control_assert(imx6_pcie->apps_reset);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
/* Bit4 of the CTRL2 */
val = IMX8QM_CSR_PCIEA_OFFSET
@@ -2263,6 +2072,7 @@ static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
IMX6SX_GPR12_PCIE_PM_TURN_OFF, 0);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
case IMX8QM:
dst = IMX8QM_CSR_PCIEA_OFFSET + imx6_pcie->controller_id * SZ_64K;
regmap_update_bits(imx6_pcie->iomuxc_gpr,
@@ -2447,24 +2257,8 @@ static int imx6_pcie_probe(struct platform_device *pdev)
imx6_pcie->hsio_cfg = 0;
if (of_property_read_u32(node, "ext_osc", &imx6_pcie->ext_osc) < 0)
imx6_pcie->ext_osc = 0;
-
if (of_property_read_u32(node, "local-addr", &imx6_pcie->local_addr))
imx6_pcie->local_addr = 0;
- if (of_property_read_u32(node, "hard-wired", &imx6_pcie->hard_wired))
- imx6_pcie->hard_wired = 0;
-
- np = of_parse_phandle(node, "reserved-region", 0);
- if (np) {
- struct resource res;
-
- if (of_address_to_resource(np, 0, &res)) {
- dev_err(dev, "failed to get reserved region address\n");
- of_node_put(np);
- return -EINVAL;
- }
- ddr_test_region = res.start + SZ_2M;
- of_node_put(np);
- }
/* Fetch GPIOs */
imx6_pcie->clkreq_gpio = of_get_named_gpio(node, "clkreq-gpio", 0);
@@ -2486,12 +2280,9 @@ static int imx6_pcie_probe(struct platform_device *pdev)
} else if (imx6_pcie->dis_gpio == -EPROBE_DEFER) {
return imx6_pcie->dis_gpio;
}
-
- imx6_pcie->epdev_on = devm_regulator_get(&pdev->dev,
- "epdev_on");
+ imx6_pcie->epdev_on = devm_regulator_get(&pdev->dev, "epdev_on");
if (IS_ERR(imx6_pcie->epdev_on))
return -EPROBE_DEFER;
-
imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
imx6_pcie->gpio_active_high = of_property_read_bool(node,
"reset-gpio-active-high");
@@ -2574,6 +2365,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
break;
case IMX8QM:
case IMX8QXP:
+ case IMX8QXP_EP:
if (dbi_base->start == IMX8_HSIO_PCIEB_BASE_ADDR)
imx6_pcie->controller_id = 1;
@@ -2652,7 +2444,6 @@ static int imx6_pcie_probe(struct platform_device *pdev)
return PTR_ERR(imx6_pcie->clkreq_reset);
}
-
/* Grab GPR config register range */
if (imx6_pcie->iomuxc_gpr == NULL) {
imx6_pcie->iomuxc_gpr =
@@ -2709,229 +2500,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
goto err_ret;
}
- if (IS_ENABLED(CONFIG_EP_MODE_IN_EP_RC_SYS)
- && (imx6_pcie->hard_wired == 0)) {
- int i = 0, irq;
- u32 val, tv_count1, tv_count2;
- dma_addr_t test_reg1_dma, test_reg2_dma;
- void *test_reg1, *test_reg2;
- void __iomem *pcie_arb_base_addr;
- struct timespec64 tv1s, tv1e, tv2s, tv2e;
- struct resource_entry *win, *tmp;
- LIST_HEAD(res);
- struct pcie_port *pp = &pci->pp;
- unsigned long timeout = jiffies + msecs_to_jiffies(300000);
-
- /* add attributes for device */
- imx6_pcie_attrgroup.attrs = imx6_pcie_ep_attrs;
- ret = sysfs_create_group(&pdev->dev.kobj, &imx6_pcie_attrgroup);
- if (ret)
- return -EINVAL;
-
- ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
- &pp->io_base);
- if (ret)
- return ret;
-
- ret = devm_request_pci_bus_resources(&pdev->dev, &res);
- if (ret) {
- dev_err(dev, "missing ranges property\n");
- pci_free_resource_list(&res);
- return ret;
- }
-
- /* Get the I/O and memory ranges from DT */
- resource_list_for_each_entry_safe(win, tmp, &res) {
- switch (resource_type(win->res)) {
- case IORESOURCE_MEM:
- pp->mem = win->res;
- pp->mem->name = "MEM";
- pp->mem_size = resource_size(pp->mem);
- pp->mem_bus_addr = pp->mem->start - win->offset;
- break;
- }
- }
-
- pp->mem_base = pp->mem->start;
- pp->ops = &imx6_pcie_host_ops;
- dev_info(dev, " try to initialize pcie ep.\n");
- ret = imx6_pcie_host_init(pp);
- if (ret) {
- dev_info(dev, " fail to initialize pcie ep.\n");
- return ret;
- }
-
- dw_pcie_dbi_ro_wr_en(pci);
- switch (imx6_pcie->drvdata->variant) {
- case IMX8MQ:
- case IMX8MM:
- case IMX8MP:
- imx6_pcie_setup_ep(pci, SZ_1M);
- break;
- default:
- imx6_pcie_setup_ep(pci, SZ_4K);
- break;
- }
- pci_imx_set_msi_en(pp);
- platform_set_drvdata(pdev, imx6_pcie);
- imx6_pcie_regions_setup(dev);
-
- /*
- * iMX6SX PCIe has the stand-alone power domain.
- * refer to the initialization for iMX6SX PCIe,
- * release the PCIe PHY reset here,
- * before LTSSM enable is set.
- */
- if (imx6_pcie->drvdata->variant == IMX6SX)
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
- BIT(19), 0 << 19);
-
- /* assert LTSSM enable */
- imx6_pcie_ltssm_enable(dev);
-
- dev_info(dev, "PCIe EP: waiting for link up...\n");
- /* link is indicated by the bit4 of DB_R1 register */
- do {
- usleep_range(10, 20);
- if (time_after(jiffies, timeout)) {
- dev_info(dev, "PCIe EP: link down.\n");
- return 0;
- }
- val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
- } while ((val & 0x10) == 0);
-
- /* self io test */
- /* Check the DMA INT exist or not */
- irq = platform_get_irq_byname(pdev, "dma");
- if (irq > 0)
- dma_en = 1;
- else
- dma_en = 0;
- if (dma_en) {
- /* configure the DMA INT ISR */
- ret = request_irq(irq, imx6_pcie_dma_isr,
- IRQF_SHARED, "imx-pcie-dma", pp);
- if (ret) {
- pr_err("register interrupt %d failed, rc %d\n",
- irq, ret);
- dma_en = 0;
- }
- test_reg1 = dma_alloc_coherent(dev, test_region_size,
- &test_reg1_dma, GFP_KERNEL);
- test_reg2 = dma_alloc_coherent(dev, test_region_size,
- &test_reg2_dma, GFP_KERNEL);
- if (!(test_reg1 && test_reg2))
- dma_en = 0; /* Roll back to PIO. */
- dma_r_end = dma_w_end = 0;
-
- val = readl(pci->dbi_base + DMA_CTRL_VIEWPORT_OFF);
- if (val == 0xffffffff)
- imx6_pcie->dma_unroll_offset =
- DMA_UNROLL_CDM_OFFSET - DMA_REG_OFFSET;
- else
- imx6_pcie->dma_unroll_offset = 0;
- }
-
- if (unlikely(dma_en == 0)) {
- test_reg1 = devm_kzalloc(&pdev->dev,
- test_region_size, GFP_KERNEL);
- if (!test_reg1) {
- ret = -ENOMEM;
- return ret;
- }
-
- test_reg2 = devm_kzalloc(&pdev->dev,
- test_region_size, GFP_KERNEL);
- if (!test_reg2) {
- ret = -ENOMEM;
- return ret;
- }
- }
-
- pcie_arb_base_addr = ioremap_nocache(pp->mem_base,
- test_region_size);
- if (!pcie_arb_base_addr) {
- dev_err(dev, "ioremap error in ep io test\n");
- ret = -ENOMEM;
- return ret;
- }
-
- for (i = 0; i < test_region_size; i = i + 4) {
- writel(0xE6600D00 + i, test_reg1 + i);
- writel(0xDEADBEAF, test_reg2 + i);
- }
-
- /* PCIe EP start the data transfer after link up */
- dev_info(dev, "pcie ep: Starting data transfer...\n");
- ktime_get_real_ts64(&tv1s);
-
-
- /* EP write the test region to remote RC's DDR memory */
- if (dma_en) {
- imx6_pcie_local_dma_start(pp, 0, 0, test_reg1_dma,
- imx6_pcie_cpu_addr_fixup(imx6_pcie->pci, pp->mem_base),
- test_region_size);
- timeout = jiffies + msecs_to_jiffies(300);
- do {
- udelay(1);
- if (time_after(jiffies, timeout)) {
- dev_info(dev, "dma write no end ...\n");
- break;
- }
- } while (!dma_w_end);
- } else {
- memcpy((unsigned int *)pcie_arb_base_addr,
- (unsigned int *)test_reg1,
- test_region_size);
- }
-
- ktime_get_real_ts64(&tv1e);
-
- ktime_get_real_ts64(&tv2s);
- /* EP read the test region back from remote RC's DDR memory */
- if (dma_en) {
- imx6_pcie_local_dma_start(pp, 1, 0,
- imx6_pcie_cpu_addr_fixup(imx6_pcie->pci, pp->mem_base),
- test_reg2_dma, test_region_size);
- timeout = jiffies + msecs_to_jiffies(300);
- do {
- udelay(1);
- if (time_after(jiffies, timeout)) {
- dev_info(dev, "dma read no end\n");
- break;
- }
- } while (!dma_r_end);
- } else {
- memcpy((unsigned int *)test_reg2,
- (unsigned int *)pcie_arb_base_addr,
- test_region_size);
- }
+ imx6_pcie_assert_core_reset(imx6_pcie);
+ imx6_pcie_init_phy(imx6_pcie);
+ imx6_pcie_deassert_core_reset(imx6_pcie);
+ imx6_setup_phy_mpll(imx6_pcie);
- ktime_get_real_ts64(&tv2e);
- if (memcmp(test_reg2, test_reg1, test_region_size) == 0) {
- tv_count1 = (tv1e.tv_sec - tv1s.tv_sec)
- * USEC_PER_SEC
- + (tv1e.tv_nsec - tv1s.tv_nsec) / 1000;
- tv_count2 = (tv2e.tv_sec - tv2s.tv_sec)
- * USEC_PER_SEC
- + (tv2e.tv_nsec - tv2s.tv_nsec) / 1000;
-
- dev_info(dev, "ep: Data %s transfer is successful.\n",
- dma_en ? "DMA" : "PIO");
- dev_info(dev, "ep: Data write %dus speed:%ldMB/s.\n",
- tv_count1,
- ((test_region_size/1024)
- * MSEC_PER_SEC)
- /(tv_count1));
- dev_info(dev, "ep: Data read %dus speed:%ldMB/s.\n",
- tv_count2,
- ((test_region_size/1024)
- * MSEC_PER_SEC)
- /(tv_count2));
- } else {
- dev_info(dev, "ep: Data transfer is failed.\n");
- } /* end of self io test. */
- } else {
+ switch (imx6_pcie->drvdata->mode) {
+ case DW_PCIE_RC_TYPE:
ret = imx6_add_pcie_port(imx6_pcie, pdev);
if (ret < 0) {
if (IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) {
@@ -2945,10 +2520,6 @@ static int imx6_pcie_probe(struct platform_device *pdev)
}
pci_imx_set_msi_en(&imx6_pcie->pci->pp);
- if (IS_ENABLED(CONFIG_RC_MODE_IN_EP_RC_SYS)
- && (imx6_pcie->hard_wired == 0))
- imx6_pcie_regions_setup(&pdev->dev);
-
/*
* If the L1SS is enabled, disable the over ride after link up.
* Let the the CLK_REQ# controlled by HW L1SS automatically.
@@ -2965,6 +2536,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
0);
break;
case IMX8QXP:
+ case IMX8QXP_EP:
regmap_update_bits(imx6_pcie->iomuxc_gpr,
IMX8QM_CSR_MISC_OFFSET,
IMX8QM_MISC_CLKREQ_OVERRIDE_EN_1,
@@ -2983,6 +2555,17 @@ static int imx6_pcie_probe(struct platform_device *pdev)
break;
};
}
+ break;
+ case DW_PCIE_EP_TYPE:
+ if (!IS_ENABLED(CONFIG_PCI_IMX_EP))
+ ret = -ENODEV;
+
+ ret = imx_add_pcie_ep(imx6_pcie, pdev);
+ if (ret < 0)
+ goto err_ret;
+ break;
+ default:
+ dev_err(dev, "INVALID device type.\n");
}
return 0;
@@ -3003,6 +2586,7 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
static const struct imx6_pcie_drvdata drvdata[] = {
[IMX6Q] = {
.variant = IMX6Q,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_IMX6_PHY |
IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
@@ -3010,44 +2594,57 @@ static const struct imx6_pcie_drvdata drvdata[] = {
},
[IMX6SX] = {
.variant = IMX6SX,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_IMX6_PHY |
IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |
IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
},
[IMX6QP] = {
.variant = IMX6QP,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_IMX6_PHY |
IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |
IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
},
[IMX7D] = {
.variant = IMX7D,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
},
[IMX8MQ] = {
.variant = IMX8MQ,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
IMX6_PCIE_FLAG_SUPPORTS_L1SS,
},
[IMX8MM] = {
.variant = IMX8MM,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
IMX6_PCIE_FLAG_SUPPORTS_L1SS,
},
[IMX8QM] = {
.variant = IMX8QM,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
IMX6_PCIE_FLAG_IMX6_CPU_ADDR_FIXUP,
},
[IMX8QXP] = {
.variant = IMX8QXP,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
IMX6_PCIE_FLAG_IMX6_CPU_ADDR_FIXUP,
},
[IMX8MP] = {
.variant = IMX8MP,
+ .mode = DW_PCIE_RC_TYPE,
.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
},
+ [IMX8QXP_EP] = {
+ .variant = IMX8QXP_EP,
+ .mode = DW_PCIE_EP_TYPE,
+ .flags = IMX6_PCIE_FLAG_IMX6_CPU_ADDR_FIXUP,
+ },
};
static const struct of_device_id imx6_pcie_of_match[] = {
@@ -3060,6 +2657,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
{ .compatible = "fsl,imx8qm-pcie", .data = &drvdata[IMX8QM], },
{ .compatible = "fsl,imx8qxp-pcie", .data = &drvdata[IMX8QXP], },
{ .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
+ { .compatible = "fsl,imx8qxp-pcie-ep", .data = &drvdata[IMX8QXP_EP], },
{},
};