IMX8QM,
IMX8QXP,
IMX8MQ,
+ IMX8MM,
};
/*
#define PCIE_PHY_CMN_REG26 0x98
#define PCIE_PHY_CMN_REG26_ATT_MODE 0xBC
+#define PCIE_PHY_CMN_REG62 0x188
+#define PCIE_PHY_CMN_REG62_PLL_CLK_OUT 0x08
+#define PCIE_PHY_CMN_REG64 0x190
+#define PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM 0x8C
+#define PCIE_PHY_CMN_REG75 0x1D4
+#define PCIE_PHY_CMN_REG75_PLL_DONE 0x3
+
/* iMX8 HSIO registers */
#define IMX8QM_LPCG_PHYX2_OFFSET 0x00000
#define IMX8QM_LPCG_PHYX1_OFFSET 0x10000
#define IMX8MQ_SRC_PCIEPHY_RCR_OFFSET 0x2C
#define IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET 0x48
+#define IMX8MQ_PCIEPHY_DOMAIN_EN (BIT(31) | (0xF << 24))
#define IMX8MQ_PCIEPHY_PWR_ON_RST BIT(0)
#define IMX8MQ_PCIEPHY_G_RST BIT(1)
#define IMX8MQ_PCIEPHY_BTN BIT(2)
#define IMX8MQ_GPC_PGC_PCIE2_BIT_OFFSET 12
#define IMX8MQ_GPC_PCG_PCIE_CTRL_PCR BIT(0)
#define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9)
+#define IMX8MM_GPR_PCIE_REF_CLK_SEL (0x3 << 24)
+#define IMX8MM_GPR_PCIE_REF_CLK_PLL (0x3 << 24)
+#define IMX8MM_GPR_PCIE_REF_CLK_EXT (0x2 << 24)
+#define IMX8MM_GPR_PCIE_AUX_EN BIT(19)
+#define IMX8MM_GPR_PCIE_CMN_RST BIT(18)
+#define IMX8MM_GPR_PCIE_POWER_OFF BIT(17)
+#define IMX8MM_GPR_PCIE_SSC_EN BIT(16)
static int pcie_phy_poll_ack(struct imx_pcie *imx_pcie, int exp_val)
{
}
break;
case IMX8MQ:
+ case IMX8MM:
if (imx_pcie->ctrl_id == 0)
val = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET;
else
val = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET;
/* Do RSTs */
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIEPHY_BTN,
- IMX8MQ_PCIEPHY_BTN);
+ IMX8MQ_PCIEPHY_BTN | IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_BTN | IMX8MQ_PCIEPHY_DOMAIN_EN);
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIEPHY_G_RST,
- IMX8MQ_PCIEPHY_G_RST);
+ IMX8MQ_PCIEPHY_G_RST |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_G_RST |
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
}
if (imx_pcie->vpcie && regulator_is_enabled(imx_pcie->vpcie) > 0) {
break;
case IMX7D:
case IMX8MQ:
+ case IMX8MM:
break;
case IMX8QXP:
case IMX8QM:
struct dw_pcie *pci = imx_pcie->pci;
struct device *dev = pci->dev;
- for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) {
- if (imx_pcie->hsio_cfg == PCIEAX2SATA) {
- regmap_read(imx_pcie->iomuxc_gpr,
- IMX8QM_CSR_PHYX2_OFFSET + 0x4,
- &tmp);
- if (imx_pcie->ctrl_id == 0) /* pciea 1 lanes */
- orig = IMX8QM_STTS0_LANE0_TX_PLL_LOCK;
- else /* pcieb 1 lanes */
- orig = IMX8QM_STTS0_LANE1_TX_PLL_LOCK;
- tmp &= orig;
- if (tmp == orig) {
- regmap_update_bits(imx_pcie->iomuxc_gpr,
- IMX8QM_LPCG_PHYX2_OFFSET,
- IMX8QM_LPCG_PHY_PCG0
- | IMX8QM_LPCG_PHY_PCG1,
- IMX8QM_LPCG_PHY_PCG0
- | IMX8QM_LPCG_PHY_PCG1);
+ if (imx_pcie->variant == IMX8MM) {
+ tmp = readl(imx_pcie->phy_base + PCIE_PHY_CMN_REG75);
+ for (retries = 0; retries < 100; retries++) {
+ if (tmp == PCIE_PHY_CMN_REG75_PLL_DONE)
break;
- }
+ udelay(10);
}
-
- if (imx_pcie->hsio_cfg == PCIEAX1PCIEBX1SATA) {
- regmap_read(imx_pcie->iomuxc_gpr,
- IMX8QM_CSR_PHYX2_OFFSET + 0x4,
- &tmp);
- tmp &= IMX8QM_STTS0_LANE0_TX_PLL_LOCK;
- if (tmp == IMX8QM_STTS0_LANE0_TX_PLL_LOCK) {
- regmap_update_bits(imx_pcie->iomuxc_gpr,
- IMX8QM_LPCG_PHYX2_OFFSET,
- IMX8QM_LPCG_PHY_PCG0,
- IMX8QM_LPCG_PHY_PCG0);
- break;
+ } else if (imx_pcie->variant == IMX8QXP
+ || imx_pcie->variant == IMX8QM) {
+ for (retries = 0; retries < 100; retries++) {
+ if (imx_pcie->hsio_cfg == PCIEAX1PCIEBX1SATA) {
+ regmap_read(imx_pcie->iomuxc_gpr,
+ IMX8QM_CSR_PHYX2_OFFSET + 0x4,
+ &tmp);
+ if (imx_pcie->ctrl_id == 0) /* pciea 1 lanes */
+ orig = IMX8QM_STTS0_LANE0_TX_PLL_LOCK;
+ else /* pcieb 1 lanes */
+ orig = IMX8QM_STTS0_LANE1_TX_PLL_LOCK;
+ tmp &= orig;
+ if (tmp == orig) {
+ regmap_update_bits(imx_pcie->iomuxc_gpr,
+ IMX8QM_LPCG_PHYX2_OFFSET,
+ IMX8QM_LPCG_PHY_PCG0
+ | IMX8QM_LPCG_PHY_PCG1,
+ IMX8QM_LPCG_PHY_PCG0
+ | IMX8QM_LPCG_PHY_PCG1);
+ break;
+ }
}
- }
- if (imx_pcie->hsio_cfg == PCIEAX2PCIEBX1) {
- val = IMX8QM_CSR_PHYX2_OFFSET
- + imx_pcie->ctrl_id * SZ_64K;
- regmap_read(imx_pcie->iomuxc_gpr,
- val + IMX8QM_CSR_PHYX_STTS0_OFFSET,
- &tmp);
- orig = IMX8QM_STTS0_LANE0_TX_PLL_LOCK;
- if (imx_pcie->ctrl_id == 0) /* pciea 2 lanes */
- orig |= IMX8QM_STTS0_LANE1_TX_PLL_LOCK;
- tmp &= orig;
- if (tmp == orig) {
+ if (imx_pcie->hsio_cfg == PCIEAX2PCIEBX1) {
val = IMX8QM_CSR_PHYX2_OFFSET
+ imx_pcie->ctrl_id * SZ_64K;
- regmap_update_bits(imx_pcie->iomuxc_gpr,
- val, IMX8QM_LPCG_PHY_PCG0,
- IMX8QM_LPCG_PHY_PCG0);
- break;
+ regmap_read(imx_pcie->iomuxc_gpr,
+ val + IMX8QM_CSR_PHYX_STTS0_OFFSET,
+ &tmp);
+ orig = IMX8QM_STTS0_LANE0_TX_PLL_LOCK;
+ if (imx_pcie->ctrl_id == 0) /* pciea 2 lanes */
+ orig |= IMX8QM_STTS0_LANE1_TX_PLL_LOCK;
+ tmp &= orig;
+ if (tmp == orig) {
+ val = IMX8QM_CSR_PHYX2_OFFSET
+ + imx_pcie->ctrl_id * SZ_64K;
+ regmap_update_bits(imx_pcie->iomuxc_gpr,
+ val, IMX8QM_LPCG_PHY_PCG0,
+ IMX8QM_LPCG_PHY_PCG0);
+ break;
+ }
}
+ udelay(10);
}
- udelay(10);
}
if (retries >= PHY_PLL_LOCK_WAIT_MAX_RETRIES) {
dw_pcie_writel_dbi(pci, PCIE_MISC_CTRL,
PCIE_MISC_DBI_RO_WR_EN);
break;
+ case IMX8MM:
case IMX8MQ:
/* wait for more than 10us to release phy g_rst and btnrst */
udelay(10);
else
val = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET;
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIEPHY_BTN, 0);
+ IMX8MQ_PCIEPHY_BTN |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIEPHY_G_RST, 0);
+ IMX8MQ_PCIEPHY_G_RST |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
+
+ udelay(100);
+ /* wait for phy pll lock firstly. */
+ if (imx8_pcie_wait_for_phy_pll_lock(imx_pcie)) {
+ ret = -ENODEV;
+ break;
+ }
+
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIE_CTRL_APPS_EN, 0);
+ IMX8MQ_PCIE_CTRL_APPS_EN |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
break;
-
}
/* Some boards don't have PCIe reset GPIO. */
unsigned long timeout = jiffies + msecs_to_jiffies(500);
struct device *dev = imx_pcie->pci->dev;
- if (imx_pcie->variant != IMX8MQ)
+ if ((imx_pcie->variant != IMX8MQ) && (imx_pcie->variant != IMX8MM))
return;
/*
* Power up PHY.
unsigned long timeout = jiffies + msecs_to_jiffies(500);
struct device *dev = imx_pcie->pci->dev;
- if (imx_pcie->variant != IMX8MQ)
+ if ((imx_pcie->variant != IMX8MQ) && (imx_pcie->variant != IMX8MM))
return;
/*
* Power up PHY.
| IMX8QM_CSR_MISC_IOB_A_0_M1M0_2);
}
- } else if (imx_pcie->variant == IMX8MQ) {
+ } else if (imx_pcie->variant == IMX8MQ || imx_pcie->variant == IMX8MM) {
imx_pcie_phy_pwr_up(imx_pcie);
if (imx_pcie->ctrl_id == 0)
else
val = IOMUXC_GPR16;
- regmap_update_bits(imx_pcie->iomuxc_gpr, val,
- IMX8MQ_GPR_PCIE_REF_USE_PAD,
- IMX8MQ_GPR_PCIE_REF_USE_PAD);
+ if (imx_pcie->ext_osc) {
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MQ_GPR_PCIE_REF_USE_PAD,
+ IMX8MQ_GPR_PCIE_REF_USE_PAD);
+ if (imx_pcie->variant == IMX8MM) {
+ dev_info(imx_pcie->pci->dev,
+ "Initialize PHY with EXT REfCLK!.\n");
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MQ_GPR_PCIE_REF_USE_PAD,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_AUX_EN,
+ IMX8MM_GPR_PCIE_AUX_EN);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_POWER_OFF,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_SSC_EN,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL,
+ IMX8MM_GPR_PCIE_REF_CLK_EXT);
+ udelay(100);
+ /* Do the PHY common block reset */
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_CMN_RST,
+ IMX8MM_GPR_PCIE_CMN_RST);
+ udelay(200);
+ dev_info(imx_pcie->pci->dev,
+ "PHY Initialization End!.\n");
+ }
+ } else {
+ if (imx_pcie->variant == IMX8MM) {
+ /* Configure the internal PLL as REF clock */
+ dev_info(imx_pcie->pci->dev,
+ "Initialize PHY with PLL REfCLK!.\n");
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MQ_GPR_PCIE_REF_USE_PAD,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_AUX_EN,
+ IMX8MM_GPR_PCIE_AUX_EN);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_POWER_OFF,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_SSC_EN,
+ 0);
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_REF_CLK_SEL,
+ IMX8MM_GPR_PCIE_REF_CLK_PLL);
+ udelay(100);
+ /* Configure the PHY */
+ writel(PCIE_PHY_CMN_REG62_PLL_CLK_OUT,
+ imx_pcie->phy_base + PCIE_PHY_CMN_REG62);
+ writel(PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM,
+ imx_pcie->phy_base + PCIE_PHY_CMN_REG64);
+
+ /* Do the PHY common block reset */
+ regmap_update_bits(imx_pcie->iomuxc_gpr, val,
+ IMX8MM_GPR_PCIE_CMN_RST,
+ IMX8MM_GPR_PCIE_CMN_RST);
+ udelay(200);
+ dev_info(imx_pcie->pci->dev,
+ "PHY Initialization End!.\n");
+ } else {
+ dev_err(imx_pcie->pci->dev,
+ "Don't support internal PLL.\n");
+ }
+ }
} else if (imx_pcie->variant == IMX7D) {
/* Enable PCIe PHY 1P0D */
regulator_set_voltage(imx_pcie->pcie_phy_regulator,
BIT(5), BIT(5));
break;
case IMX8MQ:
+ case IMX8MM:
if (imx_pcie->ctrl_id == 0)
val = IOMUXC_GPR14;
else
break;
case IMX7D:
case IMX8MQ:
+ case IMX8MM:
if (imx_pcie->ctrl_id == 0)
val = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET;
else
val = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET;
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIE_CTRL_APPS_EN,
- IMX8MQ_PCIE_CTRL_APPS_EN);
+ IMX8MQ_PCIE_CTRL_APPS_EN |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIE_CTRL_APPS_EN |
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
break;
case IMX8QXP:
case IMX8QM:
if (!IS_ENABLED(CONFIG_PCI_IMX6_COMPLIANCE_TEST)) {
pci_imx_clk_disable(dev);
- if ((imx_pcie->variant == IMX7D)
- || (imx_pcie->variant == IMX8MQ)
- || (imx_pcie->variant == IMX8QM)
- || (imx_pcie->variant == IMX8QXP))
- pm_runtime_put_sync(pci->dev);
- if (imx_pcie->variant == IMX8MQ)
- imx_pcie_phy_pwr_dn(imx_pcie);
+ pm_runtime_put_sync(pci->dev);
+ imx_pcie_phy_pwr_dn(imx_pcie);
if (imx_pcie->pcie_phy_regulator != NULL)
regulator_disable(imx_pcie->pcie_phy_regulator);
if (imx_pcie->pcie_bus_regulator != NULL)
struct imx_pcie *imx_pcie = to_imx_pcie(pci);
/* enable disp_mix power domain */
- if ((imx_pcie->variant == IMX7D)
- || (imx_pcie->variant == IMX8MQ)
- || (imx_pcie->variant == IMX8QM)
- || (imx_pcie->variant == IMX8QXP))
- pm_runtime_get_sync(pci->dev);
+ pm_runtime_get_sync(pci->dev);
imx_pcie_assert_core_reset(imx_pcie);
imx_pcie_init_phy(imx_pcie);
case IMX8QM:
case IMX8QXP:
case IMX8MQ:
+ case IMX8MM:
/*
* RPMSG reserved 4Mbytes, but only used up to 2Mbytes.
* The left 2Mbytes can be used here.
break;
case IMX7D:
case IMX8MQ:
+ case IMX8MM:
if (imx_pcie->ctrl_id == 0)
dst = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET;
else
dst = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET;
regmap_update_bits(imx_pcie->reg_src, dst,
- IMX8MQ_PCIE_CTRL_APPS_TURNOFF,
- IMX8MQ_PCIE_CTRL_APPS_TURNOFF);
+ IMX8MQ_PCIE_CTRL_APPS_TURNOFF |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIE_CTRL_APPS_TURNOFF |
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
regmap_update_bits(imx_pcie->reg_src, dst,
- IMX8MQ_PCIE_CTRL_APPS_TURNOFF,
- 0);
+ IMX8MQ_PCIE_CTRL_APPS_TURNOFF |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
break;
case IMX8QXP:
case IMX8QM:
} else {
pci_imx_clk_disable(dev);
- if (imx_pcie->variant == IMX8MQ)
- imx_pcie_phy_pwr_dn(imx_pcie);
+ imx_pcie_phy_pwr_dn(imx_pcie);
/* Power down PCIe PHY. */
if (imx_pcie->pcie_phy_regulator != NULL)
regulator_disable(imx_pcie->pcie_phy_regulator);
break;
case IMX7D:
case IMX8MQ:
+ case IMX8MM:
if (imx_pcie->ctrl_id == 0)
val = IMX8MQ_SRC_PCIEPHY_RCR_OFFSET;
else
val = IMX8MQ_SRC_PCIE2PHY_RCR_OFFSET;
regmap_update_bits(imx_pcie->reg_src, val,
- IMX8MQ_PCIE_CTRL_APPS_EN,
- 0);
+ IMX8MQ_PCIE_CTRL_APPS_EN |
+ IMX8MQ_PCIEPHY_DOMAIN_EN,
+ IMX8MQ_PCIEPHY_DOMAIN_EN);
break;
case IMX8QXP:
case IMX8QM:
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct imx_pcie *imx_pcie;
- struct device_node *np;
struct resource *res;
struct device_node *node = dev->of_node;
int ret;
return -EINVAL;
}
- np = of_find_compatible_node(NULL, NULL, "fsl,imx-pcie-phy");
- if (np != NULL) {
- imx_pcie->phy_base = of_iomap(np, 0);
- WARN_ON(!imx_pcie->phy_base);
- } else {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+ if (res)
+ imx_pcie->phy_base = devm_ioremap_resource(dev, res);
+ else
imx_pcie->phy_base = NULL;
- }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
if (res)
}
imx_pcie->pcie_phy_regulator = devm_regulator_get(&pdev->dev,
"pcie-phy");
- } else if (imx_pcie->variant == IMX8MQ) {
+ } else if (imx_pcie->variant == IMX8MQ || imx_pcie->variant == IMX8MM) {
imx_pcie->iomuxc_gpr =
syscon_regmap_lookup_by_compatible
- ("fsl,imx8mq-iomuxc-gpr");
+ ("fsl,imx7d-iomuxc-gpr");
imx_pcie->reg_src =
syscon_regmap_lookup_by_compatible("fsl,imx8mq-src");
if (IS_ERR(imx_pcie->reg_src)) {
{ .compatible = "fsl,imx8qm-pcie", .data = (void *)IMX8QM, },
{ .compatible = "fsl,imx8qxp-pcie", .data = (void *)IMX8QXP, },
{ .compatible = "fsl,imx8mq-pcie", .data = (void *)IMX8MQ, },
+ { .compatible = "fsl,imx8mm-pcie", .data = (void *)IMX8MM, },
{},
};