summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/dwpcie.c116
1 files changed, 98 insertions, 18 deletions
diff --git a/sys/dev/fdt/dwpcie.c b/sys/dev/fdt/dwpcie.c
index 64428b02a8e..f10a654dc7b 100644
--- a/sys/dev/fdt/dwpcie.c
+++ b/sys/dev/fdt/dwpcie.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwpcie.c,v 1.17 2020/04/23 19:50:52 patrick Exp $ */
+/* $OpenBSD: dwpcie.c,v 1.18 2020/04/26 15:17:21 patrick Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
*
@@ -119,6 +119,24 @@
#define IMX8MQ_GPR_PCIE_REF_USE_PAD (1 << 9)
#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE_EN (1 << 10)
#define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE (1 << 11)
+#define IMX8MM_GPR_PCIE_SSC_EN (1 << 16)
+#define IMX8MM_GPR_PCIE_POWER_OFF (1 << 17)
+#define IMX8MM_GPR_PCIE_CMN_RST (1 << 18)
+#define IMX8MM_GPR_PCIE_AUX_EN (1 << 19)
+#define IMX8MM_GPR_PCIE_REF_CLK_MASK (0x3 << 24)
+#define IMX8MM_GPR_PCIE_REF_CLK_PLL (0x3 << 24)
+#define IMX8MM_GPR_PCIE_REF_CLK_EXT (0x2 << 24)
+
+#define IMX8MM_PCIE_PHY_CMN_REG62 0x188
+#define IMX8MM_PCIE_PHY_CMN_REG62_PLL_CLK_OUT 0x08
+#define IMX8MM_PCIE_PHY_CMN_REG64 0x190
+#define IMX8MM_PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM 0x8c
+#define IMX8MM_PCIE_PHY_CMN_REG75 0x1d4
+#define IMX8MM_PCIE_PHY_CMN_REG75_PLL_DONE 0x3
+#define IMX8MM_PCIE_PHY_TRSV_REG5 0x414
+#define IMX8MM_PCIE_PHY_TRSV_REG5_GEN1_DEEMP 0x2d
+#define IMX8MM_PCIE_PHY_TRSV_REG6 0x418
+#define IMX8MM_PCIE_PHY_TRSV_REG6_GEN2_DEEMP 0xf
#define ANATOP_PLLOUT_CTL 0x74
#define ANATOP_PLLOUT_CTL_CKE (1 << 4)
@@ -199,6 +217,7 @@ dwpcie_match(struct device *parent, void *match, void *aux)
struct fdt_attach_args *faa = aux;
return (OF_is_compatible(faa->fa_node, "marvell,armada8k-pcie") ||
+ OF_is_compatible(faa->fa_node, "fsl,imx8mm-pcie") ||
OF_is_compatible(faa->fa_node, "fsl,imx8mq-pcie"));
}
@@ -340,7 +359,8 @@ dwpcie_attach(struct device *parent, struct device *self, void *aux)
if (OF_is_compatible(sc->sc_node, "marvell,armada8k-pcie"))
dwpcie_armada8k_init(sc);
- if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-pcie"))
+ if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie") ||
+ OF_is_compatible(sc->sc_node, "fsl,imx8mq-pcie"))
dwpcie_imx8mq_init(sc);
if (HREAD4(sc, IATU_VIEWPORT) == 0xffffffff) {
@@ -599,12 +619,19 @@ dwpcie_imx8mq_init(struct dwpcie_softc *sc)
{
uint32_t *clkreq_gpio, *disable_gpio, *reset_gpio;
ssize_t clkreq_gpiolen, disable_gpiolen, reset_gpiolen;
- struct regmap *anatop, *gpr;
+ struct regmap *anatop, *gpr, *phy;
uint32_t off, reg;
int timo;
- anatop = regmap_bycompatible("fsl,imx8mq-anatop");
- gpr = regmap_bycompatible("fsl,imx8mq-iomuxc-gpr");
+ if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
+ anatop = regmap_bycompatible("fsl,imx8mm-anatop");
+ gpr = regmap_bycompatible("fsl,imx8mm-iomuxc-gpr");
+ phy = regmap_bycompatible("fsl,imx7d-pcie-phy");
+ KASSERT(phy != NULL);
+ } else {
+ anatop = regmap_bycompatible("fsl,imx8mq-anatop");
+ gpr = regmap_bycompatible("fsl,imx8mq-iomuxc-gpr");
+ }
KASSERT(anatop != NULL);
KASSERT(gpr != NULL);
@@ -652,20 +679,62 @@ dwpcie_imx8mq_init(struct dwpcie_softc *sc)
}
regmap_write_4(gpr, IOMUXC_GPR12, reg);
- if (OF_getproplen(sc->sc_node, "ext_osc") == 0 ||
- OF_getpropint(sc->sc_node, "ext_osc", 0)) {
- reg = regmap_read_4(gpr, off);
- reg |= IMX8MQ_GPR_PCIE_REF_USE_PAD;
- regmap_write_4(gpr, off, reg);
+ if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
+ if (OF_getproplen(sc->sc_node, "ext_osc") == 0 ||
+ OF_getpropint(sc->sc_node, "ext_osc", 0)) {
+ reg = regmap_read_4(gpr, off);
+ reg &= ~(IMX8MQ_GPR_PCIE_REF_USE_PAD |
+ IMX8MM_GPR_PCIE_SSC_EN |
+ IMX8MM_GPR_PCIE_POWER_OFF |
+ IMX8MM_GPR_PCIE_REF_CLK_MASK);
+ reg |= (IMX8MM_GPR_PCIE_AUX_EN |
+ IMX8MM_GPR_PCIE_REF_CLK_EXT);
+ regmap_write_4(gpr, off, reg);
+ delay(100);
+ reg = regmap_read_4(gpr, off);
+ reg |= IMX8MM_GPR_PCIE_CMN_RST;
+ regmap_write_4(gpr, off, reg);
+ delay(200);
+ } else {
+ reg = regmap_read_4(gpr, off);
+ reg &= ~(IMX8MQ_GPR_PCIE_REF_USE_PAD |
+ IMX8MM_GPR_PCIE_SSC_EN |
+ IMX8MM_GPR_PCIE_POWER_OFF |
+ IMX8MM_GPR_PCIE_REF_CLK_MASK);
+ reg |= (IMX8MM_GPR_PCIE_AUX_EN |
+ IMX8MM_GPR_PCIE_REF_CLK_PLL);
+ regmap_write_4(gpr, off, reg);
+ delay(100);
+ regmap_write_4(phy, IMX8MM_PCIE_PHY_CMN_REG62,
+ IMX8MM_PCIE_PHY_CMN_REG62_PLL_CLK_OUT);
+ regmap_write_4(phy, IMX8MM_PCIE_PHY_CMN_REG64,
+ IMX8MM_PCIE_PHY_CMN_REG64_AUX_RX_TX_TERM);
+ reg = regmap_read_4(gpr, off);
+ reg |= IMX8MM_GPR_PCIE_CMN_RST;
+ regmap_write_4(gpr, off, reg);
+ delay(200);
+ regmap_write_4(phy, IMX8MM_PCIE_PHY_TRSV_REG5,
+ IMX8MM_PCIE_PHY_TRSV_REG5_GEN1_DEEMP);
+ regmap_write_4(phy, IMX8MM_PCIE_PHY_TRSV_REG6,
+ IMX8MM_PCIE_PHY_TRSV_REG6_GEN2_DEEMP);
+ }
} else {
- reg = regmap_read_4(gpr, off);
- reg &= ~IMX8MQ_GPR_PCIE_REF_USE_PAD;
- regmap_write_4(gpr, off, reg);
-
- regmap_write_4(anatop, ANATOP_PLLOUT_CTL,
- ANATOP_PLLOUT_CTL_CKE | ANATOP_PLLOUT_CTL_SEL_SYSPLL1);
- regmap_write_4(anatop, ANATOP_PLLOUT_DIV,
- ANATOP_PLLOUT_DIV_SYSPLL1);
+ if (OF_getproplen(sc->sc_node, "ext_osc") == 0 ||
+ OF_getpropint(sc->sc_node, "ext_osc", 0)) {
+ reg = regmap_read_4(gpr, off);
+ reg |= IMX8MQ_GPR_PCIE_REF_USE_PAD;
+ regmap_write_4(gpr, off, reg);
+ } else {
+ reg = regmap_read_4(gpr, off);
+ reg &= ~IMX8MQ_GPR_PCIE_REF_USE_PAD;
+ regmap_write_4(gpr, off, reg);
+
+ regmap_write_4(anatop, ANATOP_PLLOUT_CTL,
+ ANATOP_PLLOUT_CTL_CKE |
+ ANATOP_PLLOUT_CTL_SEL_SYSPLL1);
+ regmap_write_4(anatop, ANATOP_PLLOUT_DIV,
+ ANATOP_PLLOUT_DIV_SYSPLL1);
+ }
}
clock_enable(sc->sc_node, "pcie_phy");
@@ -685,6 +754,17 @@ dwpcie_imx8mq_init(struct dwpcie_softc *sc)
reset_deassert(sc->sc_node, "pciephy");
+ if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-pcie")) {
+ for (timo = 2000; timo > 0; timo--) {
+ if (regmap_read_4(phy, IMX8MM_PCIE_PHY_CMN_REG75) ==
+ IMX8MM_PCIE_PHY_CMN_REG75_PLL_DONE)
+ break;
+ delay(10);
+ }
+ if (timo == 0)
+ printf("%s:%d: timeout\n", __func__, __LINE__);
+ }
+
reg = HREAD4(sc, 0x100000 + PCIE_RC_LCR);
reg &= ~PCIE_RC_LCR_L1EL_MASK;
reg |= PCIE_RC_LCR_L1EL_64US;