diff options
author | 2020-03-21 12:53:24 +0000 | |
---|---|---|
committer | 2020-03-21 12:53:24 +0000 | |
commit | 6e71e8fef0cb29787f0854f56fd785082a977c2b (patch) | |
tree | e21b90961283050767c538171cded0962fa7c5c0 | |
parent | Instead of passing the flags as part of a struct that's supposed to be (diff) | |
download | wireguard-openbsd-6e71e8fef0cb29787f0854f56fd785082a977c2b.tar.xz wireguard-openbsd-6e71e8fef0cb29787f0854f56fd785082a977c2b.zip |
Add clock support for i.MX8MM. The CCM is based on the i.MX8MQ version,
so we can re-use the same mechanisms. It's not the same though, which
means that some code is duplicated. There's some room for refactoring.
The PLLs, on the other hand, work quite differently. This allows most
of our supported peripherals to work, including clock frequency scaling.
Feedback from and ok kettenis@
-rw-r--r-- | sys/dev/fdt/imxccm.c | 354 | ||||
-rw-r--r-- | sys/dev/fdt/imxccm_clocks.h | 119 |
2 files changed, 461 insertions, 12 deletions
diff --git a/sys/dev/fdt/imxccm.c b/sys/dev/fdt/imxccm.c index 26df53f7ffc..7fe69d26e82 100644 --- a/sys/dev/fdt/imxccm.c +++ b/sys/dev/fdt/imxccm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxccm.c,v 1.17 2020/03/20 17:32:25 patrick Exp $ */ +/* $OpenBSD: imxccm.c,v 1.18 2020/03/21 12:53:24 patrick Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> * @@ -127,10 +127,26 @@ #define CCM_ANALOG_PLL_ENET_POWERDOWN (1 << 12) /* i.MX6 */ #define CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ (1 << 10) /* i.MX7 */ +/* Int PLL */ +#define CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL 0x84 +#define CCM_14XX_IMX8M_ARM_PLL_DIV_CTL 0x88 +#define CCM_14XX_IMX8M_SYS_PLL1_GNRL_CTL 0x94 +#define CCM_14XX_IMX8M_SYS_PLL1_DIV_CTL 0x98 +#define CCM_INT_PLL_LOCK (1U << 31) +#define CCM_INT_PLL_LOCK_SEL (1 << 29) +#define CCM_INT_PLL_RST (1 << 9) +#define CCM_INT_PLL_BYPASS (1 << 4) +#define CCM_INT_PLL_MAIN_DIV_SHIFT 12 +#define CCM_INT_PLL_MAIN_DIV_MASK 0x3ff +#define CCM_INT_PLL_PRE_DIV_SHIFT 4 +#define CCM_INT_PLL_PRE_DIV_MASK 0x3f +#define CCM_INT_PLL_POST_DIV_SHIFT 0 +#define CCM_INT_PLL_POST_DIV_MASK 0x7 + /* Frac PLL */ #define CCM_FRAC_IMX8M_ARM_PLL0 0x28 #define CCM_FRAC_IMX8M_ARM_PLL1 0x2c -#define CCM_FRAC_PLL_LOCK (1 << 31) +#define CCM_FRAC_PLL_LOCK (1U << 31) #define CCM_FRAC_PLL_ENABLE (1 << 21) #define CCM_FRAC_PLL_POWERDOWN (1 << 19) #define CCM_FRAC_PLL_REFCLK_SEL_SHIFT 16 @@ -227,6 +243,10 @@ uint32_t imxccm_get_ahbclk(struct imxccm_softc *); uint32_t imxccm_get_ipgclk(struct imxccm_softc *); uint32_t imxccm_get_ipg_perclk(struct imxccm_softc *); uint32_t imxccm_get_uartclk(struct imxccm_softc *); +uint32_t imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t); +uint32_t imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t); +uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t); +uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t); uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t); uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t); uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t); @@ -249,6 +269,7 @@ imxccm_match(struct device *parent, void *match, void *aux) OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") || OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") || OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") || + OF_is_compatible(faa->fa_node, "fsl,imx8mm-ccm") || OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm")); } @@ -268,7 +289,18 @@ imxccm_attach(struct device *parent, struct device *self, void *aux) sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0); - if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) { + if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-ccm")) { + sc->sc_anatop = regmap_bycompatible("fsl,imx8mm-anatop"); + KASSERT(sc->sc_anatop != NULL); + sc->sc_gates = imx8mm_gates; + sc->sc_ngates = nitems(imx8mm_gates); + sc->sc_divs = imx8mm_divs; + sc->sc_ndivs = nitems(imx8mm_divs); + sc->sc_muxs = imx8mm_muxs; + sc->sc_nmuxs = nitems(imx8mm_muxs); + sc->sc_predivs = imx8mm_predivs; + sc->sc_npredivs = nitems(imx8mm_predivs); + } else if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) { sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop"); KASSERT(sc->sc_anatop != NULL); sc->sc_gates = imx8mq_gates; @@ -599,6 +631,214 @@ imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx) } uint32_t +imxccm_imx8mm_get_pll(struct imxccm_softc *sc, uint32_t idx) +{ + uint64_t main_div, pre_div, post_div, div; + uint32_t pll0, pll1; + uint64_t freq; + + switch (idx) { + case IMX8MM_ARM_PLL: + pll0 = regmap_read_4(sc->sc_anatop, + CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL); + pll1 = regmap_read_4(sc->sc_anatop, + CCM_14XX_IMX8M_ARM_PLL_DIV_CTL); + div = 1; + break; + default: + printf("%s: 0x%08x\n", __func__, idx); + return 0; + } + + freq = clock_get_frequency(sc->sc_node, "osc_24m"); + if (pll0 & CCM_INT_PLL_BYPASS) + return freq; + + main_div = (pll1 >> CCM_INT_PLL_MAIN_DIV_SHIFT) & + CCM_INT_PLL_MAIN_DIV_MASK; + pre_div = (pll1 >> CCM_INT_PLL_PRE_DIV_SHIFT) & + CCM_INT_PLL_PRE_DIV_MASK; + post_div = (pll1 >> CCM_INT_PLL_POST_DIV_SHIFT) & + CCM_INT_PLL_POST_DIV_MASK; + + freq = freq * main_div; + freq = freq / (pre_div * (1 << post_div) * div); + return freq; +} + +int +imxccm_imx8mm_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq) +{ + uint64_t main_div, pre_div, post_div; + uint32_t pll0, pll1, reg; + int i; + + switch (idx) { + case IMX8MM_ARM_PLL: + pre_div = 3; + switch (freq) { + case 1800000000U: + main_div = 225; + post_div = 0; + break; + case 1600000000U: + main_div = 200; + post_div = 0; + break; + case 1200000000U: + main_div = 300; + post_div = 1; + break; + case 1000000000U: + main_div = 250; + post_div = 1; + break; + case 800000000U: + main_div = 200; + post_div = 1; + break; + case 750000000U: + main_div = 250; + post_div = 2; + break; + case 700000000U: + main_div = 350; + post_div = 2; + break; + case 600000000U: + main_div = 300; + post_div = 2; + break; + default: + printf("%s: 0x%08x\n", __func__, idx); + return -1; + } + pll0 = CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL; + pll1 = CCM_14XX_IMX8M_ARM_PLL_DIV_CTL; + break; + default: + printf("%s: 0x%08x\n", __func__, idx); + return -1; + } + + regmap_write_4(sc->sc_anatop, pll0, + regmap_read_4(sc->sc_anatop, pll0) | + CCM_INT_PLL_LOCK_SEL); + regmap_write_4(sc->sc_anatop, pll0, + regmap_read_4(sc->sc_anatop, pll0) & + ~CCM_INT_PLL_RST); + regmap_write_4(sc->sc_anatop, pll1, + main_div << CCM_INT_PLL_MAIN_DIV_SHIFT | + pre_div << CCM_INT_PLL_PRE_DIV_SHIFT | + post_div << CCM_INT_PLL_POST_DIV_SHIFT); + delay(3); + regmap_write_4(sc->sc_anatop, pll0, + regmap_read_4(sc->sc_anatop, pll0) | + CCM_INT_PLL_RST); + for (i = 0; i < 5000; i++) { + reg = regmap_read_4(sc->sc_anatop, pll0); + if (reg & CCM_INT_PLL_LOCK) + break; + delay(10); + } + if (i == 5000) + printf("%s: timeout\n", __func__); + regmap_write_4(sc->sc_anatop, pll0, + regmap_read_4(sc->sc_anatop, pll0) & + ~CCM_INT_PLL_BYPASS); + + return 0; +} + +uint32_t +imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t idx) +{ + uint32_t mux; + + if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) + return 0; + + mux = HREAD4(sc, sc->sc_muxs[idx].reg); + mux >>= sc->sc_muxs[idx].shift; + mux &= sc->sc_muxs[idx].mask; + + switch (mux) { + case 0: + return clock_get_frequency(sc->sc_node, "osc_24m"); + case 1: + return 266 * 1000 * 1000; /* sys1_pll_266m */ + default: + printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); + return 0; + } +} + +uint32_t +imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t idx) +{ + uint32_t mux; + + if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) + return 0; + + mux = HREAD4(sc, sc->sc_muxs[idx].reg); + mux >>= sc->sc_muxs[idx].shift; + mux &= sc->sc_muxs[idx].mask; + + switch (mux) { + case 0: + return clock_get_frequency(sc->sc_node, "osc_24m"); + default: + printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); + return 0; + } +} + +uint32_t +imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t idx) +{ + uint32_t mux; + + if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) + return 0; + + mux = HREAD4(sc, sc->sc_muxs[idx].reg); + mux >>= sc->sc_muxs[idx].shift; + mux &= sc->sc_muxs[idx].mask; + + switch (mux) { + case 0: + return clock_get_frequency(sc->sc_node, "osc_24m"); + default: + printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); + return 0; + } +} + +uint32_t +imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx) +{ + uint32_t mux; + + if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) + return 0; + + mux = HREAD4(sc, sc->sc_muxs[idx].reg); + mux >>= sc->sc_muxs[idx].shift; + mux &= sc->sc_muxs[idx].mask; + + switch (mux) { + case 0: + return clock_get_frequency(sc->sc_node, "osc_24m"); + case 1: + return 400 * 1000 * 1000; /* sys1_pll_400m */ + default: + printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); + return 0; + } +} + +uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx) { uint32_t mux; @@ -1086,7 +1326,53 @@ imxccm_get_frequency(void *cookie, uint32_t *cells) return imxccm_get_frequency(sc, &parent) / (div + 1); } - if (sc->sc_gates == imx8mq_gates) { + if (sc->sc_gates == imx8mm_gates) { + switch (idx) { + case IMX8MM_CLK_ARM: + parent = IMX8MM_ARM_PLL; + return imxccm_get_frequency(sc, &parent); + case IMX8MM_ARM_PLL: + return imxccm_imx8mm_get_pll(sc, idx); + } + + /* These are composite clocks. */ + if (idx < sc->sc_ngates && sc->sc_gates[idx].reg && + idx < sc->sc_ndivs && sc->sc_divs[idx].reg && + idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) { + switch (idx) { + case IMX8MM_CLK_ENET_AXI: + freq = imxccm_imx8mm_enet(sc, idx); + break; + case IMX8MM_CLK_I2C1: + case IMX8MM_CLK_I2C2: + case IMX8MM_CLK_I2C3: + case IMX8MM_CLK_I2C4: + freq = imxccm_imx8mm_i2c(sc, idx); + break; + case IMX8MM_CLK_UART1: + case IMX8MM_CLK_UART2: + case IMX8MM_CLK_UART3: + case IMX8MM_CLK_UART4: + freq = imxccm_imx8mm_uart(sc, idx); + break; + case IMX8MM_CLK_USDHC1: + case IMX8MM_CLK_USDHC2: + case IMX8MM_CLK_USDHC3: + freq = imxccm_imx8mm_usdhc(sc, idx); + break; + default: + printf("%s: 0x%08x\n", __func__, idx); + return 0; + } + + reg = HREAD4(sc, sc->sc_divs[idx].reg); + div = reg >> sc->sc_divs[idx].shift; + div = div & sc->sc_divs[idx].mask; + pre = reg >> sc->sc_predivs[idx].shift; + pre = pre & sc->sc_predivs[idx].mask; + return ((freq / (pre + 1)) / (div + 1)); + } + } else if (sc->sc_gates == imx8mq_gates) { switch (idx) { case IMX8MQ_CLK_ARM: parent = IMX8MQ_ARM_PLL; @@ -1219,7 +1505,38 @@ imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) uint32_t pcells[2]; int ret; - if (sc->sc_divs == imx8mq_divs) { + if (sc->sc_divs == imx8mm_divs) { + switch (idx) { + case IMX8MM_CLK_ARM: + parent = IMX8MM_CLK_A53_SRC; + return imxccm_set_frequency(cookie, &parent, freq); + case IMX8MM_CLK_A53_SRC: + pcells[0] = sc->sc_phandle; + pcells[1] = IMX8MM_SYS_PLL1_800M; + ret = imxccm_set_parent(cookie, &idx, pcells); + if (ret) + return ret; + ret = imxccm_imx8mm_set_pll(sc, IMX8MM_ARM_PLL, freq); + pcells[0] = sc->sc_phandle; + pcells[1] = IMX8MM_ARM_PLL_OUT; + imxccm_set_parent(cookie, &idx, pcells); + return ret; + case IMX8MM_CLK_USDHC1_ROOT: + case IMX8MM_CLK_USDHC2_ROOT: + case IMX8MM_CLK_USDHC3_ROOT: + parent = sc->sc_gates[idx].parent; + return imxccm_set_frequency(sc, &parent, freq); + case IMX8MM_CLK_USDHC1: + case IMX8MM_CLK_USDHC2: + case IMX8MM_CLK_USDHC3: + imxccm_enable(cookie, &idx, 1); + HCLR4(sc, sc->sc_divs[idx].reg, + sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); + HCLR4(sc, sc->sc_predivs[idx].reg, + sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift); + return 0; + } + } else if (sc->sc_divs == imx8mq_divs) { switch (idx) { case IMX8MQ_CLK_ARM: parent = IMX8MQ_CLK_A53_SRC; @@ -1243,12 +1560,10 @@ imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) return 0; case IMX8MQ_CLK_USDHC1: imxccm_enable(cookie, &idx, 1); - reg = HREAD4(sc, sc->sc_divs[idx].reg); - reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); - HWRITE4(sc, sc->sc_divs[idx].reg, reg); - reg = HREAD4(sc, sc->sc_predivs[idx].reg); - reg &= ~(sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift); - HWRITE4(sc, sc->sc_predivs[idx].reg, reg); + HCLR4(sc, sc->sc_divs[idx].reg, + sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); + HCLR4(sc, sc->sc_predivs[idx].reg, + sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift); return 0; } } else if (sc->sc_divs == imx7d_divs) { @@ -1293,7 +1608,22 @@ imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) pidx = pcells[1]; - if (sc->sc_muxs == imx8mq_muxs) { + if (sc->sc_muxs == imx8mm_muxs) { + switch (idx) { + case IMX8MM_CLK_A53_SRC: + if (pidx != IMX8MM_ARM_PLL_OUT && + pidx != IMX8MM_SYS_PLL1_800M) + break; + mux = HREAD4(sc, sc->sc_muxs[idx].reg); + mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); + if (pidx == IMX8MM_ARM_PLL_OUT) + mux |= (0x1 << sc->sc_muxs[idx].shift); + if (pidx == IMX8MM_SYS_PLL1_800M) + mux |= (0x4 << sc->sc_muxs[idx].shift); + HWRITE4(sc, sc->sc_muxs[idx].reg, mux); + return 0; + } + } else if (sc->sc_muxs == imx8mq_muxs) { switch (idx) { case IMX8MQ_CLK_A53_SRC: if (pidx != IMX8MQ_ARM_PLL_OUT && diff --git a/sys/dev/fdt/imxccm_clocks.h b/sys/dev/fdt/imxccm_clocks.h index 404a672cd1b..06a641bdf6f 100644 --- a/sys/dev/fdt/imxccm_clocks.h +++ b/sys/dev/fdt/imxccm_clocks.h @@ -288,6 +288,125 @@ struct imxccm_mux imx7d_muxs[] = { }; /* + * i.MX8MM clocks. + */ + +#define IMX8MM_ARM_PLL 0x18 +#define IMX8MM_SYS_PLL1_800M 0x38 +#define IMX8MM_CLK_A53_SRC 0x42 +#define IMX8MM_ARM_PLL_OUT 0x2c +#define IMX8MM_CLK_A53_CG 0x47 +#define IMX8MM_CLK_A53_DIV 0x4c +#define IMX8MM_CLK_ENET_AXI 0x52 +#define IMX8MM_CLK_ENET_REF 0x74 +#define IMX8MM_CLK_ENET_TIMER 0x75 +#define IMX8MM_CLK_ENET_PHY_REF 0x76 +#define IMX8MM_CLK_USDHC1 0x79 +#define IMX8MM_CLK_USDHC2 0x7a +#define IMX8MM_CLK_I2C1 0x7b +#define IMX8MM_CLK_I2C2 0x7c +#define IMX8MM_CLK_I2C3 0x7d +#define IMX8MM_CLK_I2C4 0x7e +#define IMX8MM_CLK_UART1 0x7f +#define IMX8MM_CLK_UART2 0x80 +#define IMX8MM_CLK_UART3 0x81 +#define IMX8MM_CLK_UART4 0x82 +#define IMX8MM_CLK_USDHC3 0x91 +#define IMX8MM_CLK_ENET1_ROOT 0xa2 +#define IMX8MM_CLK_I2C1_ROOT 0xa4 +#define IMX8MM_CLK_I2C2_ROOT 0xa5 +#define IMX8MM_CLK_I2C3_ROOT 0xa6 +#define IMX8MM_CLK_I2C4_ROOT 0xa7 +#define IMX8MM_CLK_UART1_ROOT 0xbc +#define IMX8MM_CLK_UART2_ROOT 0xbd +#define IMX8MM_CLK_UART3_ROOT 0xbe +#define IMX8MM_CLK_UART4_ROOT 0xbf +#define IMX8MM_CLK_USDHC1_ROOT 0xc2 +#define IMX8MM_CLK_USDHC2_ROOT 0xc3 +#define IMX8MM_CLK_USDHC3_ROOT 0xd0 +#define IMX8MM_CLK_TMU_ROOT 0xd1 +#define IMX8MM_CLK_ARM 0xd7 + +struct imxccm_gate imx8mm_gates[] = { + [IMX8MM_CLK_A53_CG] = { 0x8000, 14 }, + [IMX8MM_CLK_ENET_AXI] = { 0x8880, 14 }, + [IMX8MM_CLK_ENET_REF] = { 0xa980, 14 }, + [IMX8MM_CLK_ENET_TIMER] = { 0xaa00, 14 }, + [IMX8MM_CLK_ENET_PHY_REF] = { 0xaa80, 14 }, + [IMX8MM_CLK_USDHC1] = { 0xac00, 14 }, + [IMX8MM_CLK_USDHC2] = { 0xac80, 14 }, + [IMX8MM_CLK_I2C1] = { 0xad00, 14 }, + [IMX8MM_CLK_I2C2] = { 0xad80, 14 }, + [IMX8MM_CLK_I2C3] = { 0xae00, 14 }, + [IMX8MM_CLK_I2C4] = { 0xae80, 14 }, + [IMX8MM_CLK_UART1] = { 0xaf00, 14 }, + [IMX8MM_CLK_UART2] = { 0xaf80, 14 }, + [IMX8MM_CLK_UART3] = { 0xb000, 14 }, + [IMX8MM_CLK_UART4] = { 0xb080, 14 }, + [IMX8MM_CLK_USDHC3] = { 0xbc80, 14 }, + [IMX8MM_CLK_ENET1_ROOT] = { 0x40a0, 0, IMX8MM_CLK_ENET_AXI }, + [IMX8MM_CLK_I2C1_ROOT] = { 0x4170, 0, IMX8MM_CLK_I2C1 }, + [IMX8MM_CLK_I2C2_ROOT] = { 0x4180, 0, IMX8MM_CLK_I2C2 }, + [IMX8MM_CLK_I2C3_ROOT] = { 0x4190, 0, IMX8MM_CLK_I2C3 }, + [IMX8MM_CLK_I2C4_ROOT] = { 0x41a0, 0, IMX8MM_CLK_I2C4 }, + [IMX8MM_CLK_UART1_ROOT] = { 0x4490, 0, IMX8MM_CLK_UART1 }, + [IMX8MM_CLK_UART2_ROOT] = { 0x44a0, 0, IMX8MM_CLK_UART2 }, + [IMX8MM_CLK_UART3_ROOT] = { 0x44b0, 0, IMX8MM_CLK_UART3 }, + [IMX8MM_CLK_UART4_ROOT] = { 0x44c0, 0, IMX8MM_CLK_UART4 }, + [IMX8MM_CLK_USDHC1_ROOT] = { 0x4510, 0, IMX8MM_CLK_USDHC1 }, + [IMX8MM_CLK_USDHC2_ROOT] = { 0x4520, 0, IMX8MM_CLK_USDHC2 }, + [IMX8MM_CLK_USDHC3_ROOT] = { 0x45e0, 0, IMX8MM_CLK_USDHC3 }, + [IMX8MM_CLK_TMU_ROOT] = { 0x4620, 0 }, +}; + +struct imxccm_divider imx8mm_divs[] = { + [IMX8MM_CLK_A53_DIV] = { 0x8000, 0, 0x7, IMX8MM_CLK_A53_CG }, + [IMX8MM_CLK_ENET_AXI] = { 0x8880, 0, 0x3f }, + [IMX8MM_CLK_USDHC1] = { 0xac00, 0, 0x3f }, + [IMX8MM_CLK_USDHC2] = { 0xac80, 0, 0x3f }, + [IMX8MM_CLK_I2C1] = { 0xad00, 0, 0x3f }, + [IMX8MM_CLK_I2C2] = { 0xad80, 0, 0x3f }, + [IMX8MM_CLK_I2C3] = { 0xae00, 0, 0x3f }, + [IMX8MM_CLK_I2C4] = { 0xae80, 0, 0x3f }, + [IMX8MM_CLK_UART1] = { 0xaf00, 0, 0x3f }, + [IMX8MM_CLK_UART2] = { 0xaf80, 0, 0x3f }, + [IMX8MM_CLK_UART3] = { 0xb000, 0, 0x3f }, + [IMX8MM_CLK_UART4] = { 0xb080, 0, 0x3f }, + [IMX8MM_CLK_USDHC3] = { 0xbc80, 0, 0x3f }, +}; + +struct imxccm_divider imx8mm_predivs[] = { + [IMX8MM_CLK_ENET_AXI] = { 0x8880, 16, 0x7 }, + [IMX8MM_CLK_USDHC1] = { 0xac00, 16, 0x7 }, + [IMX8MM_CLK_USDHC2] = { 0xac80, 16, 0x7 }, + [IMX8MM_CLK_I2C1] = { 0xad00, 16, 0x7 }, + [IMX8MM_CLK_I2C2] = { 0xad80, 16, 0x7 }, + [IMX8MM_CLK_I2C3] = { 0xae00, 16, 0x7 }, + [IMX8MM_CLK_I2C4] = { 0xae80, 16, 0x7 }, + [IMX8MM_CLK_UART1] = { 0xaf00, 16, 0x7 }, + [IMX8MM_CLK_UART2] = { 0xaf80, 16, 0x7 }, + [IMX8MM_CLK_UART3] = { 0xb000, 16, 0x7 }, + [IMX8MM_CLK_UART4] = { 0xb080, 16, 0x7 }, + [IMX8MM_CLK_USDHC3] = { 0xbc80, 16, 0x7 }, +}; + +struct imxccm_mux imx8mm_muxs[] = { + [IMX8MM_CLK_A53_SRC] = { 0x8000, 24, 0x7 }, + [IMX8MM_CLK_ENET_AXI] = { 0x8880, 24, 0x7 }, + [IMX8MM_CLK_USDHC1] = { 0xac00, 24, 0x7 }, + [IMX8MM_CLK_USDHC2] = { 0xac80, 24, 0x7 }, + [IMX8MM_CLK_I2C1] = { 0xad00, 24, 0x7 }, + [IMX8MM_CLK_I2C2] = { 0xad80, 24, 0x7 }, + [IMX8MM_CLK_I2C3] = { 0xae00, 24, 0x7 }, + [IMX8MM_CLK_I2C4] = { 0xae80, 24, 0x7 }, + [IMX8MM_CLK_UART1] = { 0xaf00, 24, 0x7 }, + [IMX8MM_CLK_UART2] = { 0xaf80, 24, 0x7 }, + [IMX8MM_CLK_UART3] = { 0xb000, 24, 0x7 }, + [IMX8MM_CLK_UART4] = { 0xb080, 24, 0x7 }, + [IMX8MM_CLK_USDHC3] = { 0xbc80, 24, 0x7 }, +}; + +/* * i.MX8MQ clocks. */ |