diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/fdt/dwpcie.c | 116 |
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; |