xref: /openbsd-src/sys/dev/fdt/imxccm.c (revision 15572fcf8c6bfa0588565cd23f393a5a1499ea57)
1 /* $OpenBSD: imxccm.c,v 1.23 2020/11/07 21:42:47 patrick Exp $ */
2 /*
3  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/queue.h>
21 #include <sys/malloc.h>
22 #include <sys/sysctl.h>
23 #include <sys/device.h>
24 #include <sys/evcount.h>
25 #include <sys/socket.h>
26 #include <sys/timeout.h>
27 
28 #include <machine/intr.h>
29 #include <machine/bus.h>
30 #include <machine/fdt.h>
31 
32 #include <dev/ofw/openfirm.h>
33 #include <dev/ofw/ofw_clock.h>
34 #include <dev/ofw/ofw_misc.h>
35 #include <dev/ofw/ofw_regulator.h>
36 #include <dev/ofw/fdt.h>
37 
38 #include <dev/fdt/imxanatopvar.h>
39 
40 /* registers */
41 #define CCM_CCR		0x00
42 #define CCM_CCDR	0x04
43 #define CCM_CSR		0x08
44 #define CCM_CCSR	0x0c
45 #define CCM_CACRR	0x10
46 #define CCM_CBCDR	0x14
47 #define CCM_CBCMR	0x18
48 #define CCM_CSCMR1	0x1c
49 #define CCM_CSCMR2	0x20
50 #define CCM_CSCDR1	0x24
51 #define CCM_CS1CDR	0x28
52 #define CCM_CS2CDR	0x2c
53 #define CCM_CDCDR	0x30
54 #define CCM_CHSCCDR	0x34
55 #define CCM_CSCDR2	0x38
56 #define CCM_CSCDR3	0x3c
57 #define CCM_CSCDR4	0x40
58 #define CCM_CDHIPR	0x48
59 #define CCM_CDCR	0x4c
60 #define CCM_CTOR	0x50
61 #define CCM_CLPCR	0x54
62 #define CCM_CISR	0x58
63 #define CCM_CIMR	0x5c
64 #define CCM_CCOSR	0x60
65 #define CCM_CGPR	0x64
66 #define CCM_CCGR0	0x68
67 #define CCM_CCGR1	0x6c
68 #define CCM_CCGR2	0x70
69 #define CCM_CCGR3	0x74
70 #define CCM_CCGR4	0x78
71 #define CCM_CCGR5	0x7c
72 #define CCM_CCGR6	0x80
73 #define CCM_CCGR7	0x84
74 #define CCM_CMEOR	0x88
75 
76 /* bits and bytes */
77 #define CCM_CCSR_PLL3_SW_CLK_SEL		(1 << 0)
78 #define CCM_CCSR_PLL2_SW_CLK_SEL		(1 << 1)
79 #define CCM_CCSR_PLL1_SW_CLK_SEL		(1 << 2)
80 #define CCM_CCSR_STEP_SEL			(1 << 8)
81 #define CCM_CBCDR_IPG_PODF_SHIFT		8
82 #define CCM_CBCDR_IPG_PODF_MASK			0x3
83 #define CCM_CBCDR_AHB_PODF_SHIFT		10
84 #define CCM_CBCDR_AHB_PODF_MASK			0x7
85 #define CCM_CBCDR_PERIPH_CLK_SEL_SHIFT		25
86 #define CCM_CBCDR_PERIPH_CLK_SEL_MASK		0x1
87 #define CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT		12
88 #define CCM_CBCMR_PERIPH_CLK2_SEL_MASK		0x3
89 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT	18
90 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK	0x3
91 #define CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)	((x) + 15)
92 #define CCM_CSCDR1_USDHCx_CLK_SEL_MASK		0x1
93 #define CCM_CSCDR1_USDHCx_PODF_MASK		0x7
94 #define CCM_CSCDR1_UART_PODF_MASK		0x7
95 #define CCM_CSCDR2_ECSPI_PODF_SHIFT		19
96 #define CCM_CSCDR2_ECSPI_PODF_MASK		0x7
97 #define CCM_CCGR1_ENET				(3 << 10)
98 #define CCM_CCGR4_125M_PCIE			(3 << 0)
99 #define CCM_CCGR5_100M_SATA			(3 << 4)
100 #define CCM_CSCMR1_PERCLK_CLK_PODF_MASK		0x1f
101 #define CCM_CSCMR1_PERCLK_CLK_SEL_MASK		(1 << 6)
102 
103 /* Analog registers */
104 #define CCM_ANALOG_PLL_USB1			0x0010
105 #define CCM_ANALOG_PLL_USB1_SET			0x0014
106 #define CCM_ANALOG_PLL_USB1_CLR			0x0018
107 #define  CCM_ANALOG_PLL_USB1_LOCK		(1U << 31)
108 #define  CCM_ANALOG_PLL_USB1_BYPASS		(1 << 16)
109 #define  CCM_ANALOG_PLL_USB1_ENABLE		(1 << 13)
110 #define  CCM_ANALOG_PLL_USB1_POWER		(1 << 12)
111 #define  CCM_ANALOG_PLL_USB1_EN_USB_CLKS	(1 << 6)
112 #define CCM_ANALOG_PLL_USB2			0x0020
113 #define CCM_ANALOG_PLL_USB2_SET			0x0024
114 #define CCM_ANALOG_PLL_USB2_CLR			0x0028
115 #define  CCM_ANALOG_PLL_USB2_LOCK		(1U << 31)
116 #define  CCM_ANALOG_PLL_USB2_BYPASS		(1 << 16)
117 #define  CCM_ANALOG_PLL_USB2_ENABLE		(1 << 13)
118 #define  CCM_ANALOG_PLL_USB2_POWER		(1 << 12)
119 #define  CCM_ANALOG_PLL_USB2_EN_USB_CLKS	(1 << 6)
120 #define CCM_ANALOG_PLL_ENET			0x00e0
121 #define CCM_ANALOG_PLL_ENET_SET			0x00e4
122 #define CCM_ANALOG_PLL_ENET_CLR			0x00e8
123 #define  CCM_ANALOG_PLL_ENET_LOCK		(1U << 31)
124 #define  CCM_ANALOG_PLL_ENET_ENABLE_100M	(1 << 20) /* i.MX6 */
125 #define  CCM_ANALOG_PLL_ENET_BYPASS		(1 << 16)
126 #define  CCM_ANALOG_PLL_ENET_ENABLE		(1 << 13) /* i.MX6 */
127 #define  CCM_ANALOG_PLL_ENET_POWERDOWN		(1 << 12) /* i.MX6 */
128 #define  CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ	(1 << 10) /* i.MX7 */
129 
130 /* Int PLL */
131 #define CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL		0x84
132 #define CCM_14XX_IMX8M_ARM_PLL_DIV_CTL		0x88
133 #define CCM_14XX_IMX8M_SYS_PLL1_GNRL_CTL	0x94
134 #define CCM_14XX_IMX8M_SYS_PLL1_DIV_CTL		0x98
135 #define  CCM_INT_PLL_LOCK				(1U << 31)
136 #define  CCM_INT_PLL_LOCK_SEL				(1 << 29)
137 #define  CCM_INT_PLL_RST				(1 << 9)
138 #define  CCM_INT_PLL_BYPASS				(1 << 4)
139 #define  CCM_INT_PLL_MAIN_DIV_SHIFT			12
140 #define  CCM_INT_PLL_MAIN_DIV_MASK			0x3ff
141 #define  CCM_INT_PLL_PRE_DIV_SHIFT			4
142 #define  CCM_INT_PLL_PRE_DIV_MASK			0x3f
143 #define  CCM_INT_PLL_POST_DIV_SHIFT			0
144 #define  CCM_INT_PLL_POST_DIV_MASK			0x7
145 
146 /* Frac PLL */
147 #define CCM_FRAC_IMX8M_ARM_PLL0			0x28
148 #define CCM_FRAC_IMX8M_ARM_PLL1			0x2c
149 #define  CCM_FRAC_PLL_LOCK				(1U << 31)
150 #define  CCM_FRAC_PLL_ENABLE				(1 << 21)
151 #define  CCM_FRAC_PLL_POWERDOWN				(1 << 19)
152 #define  CCM_FRAC_PLL_REFCLK_SEL_SHIFT			16
153 #define  CCM_FRAC_PLL_REFCLK_SEL_MASK			0x3
154 #define  CCM_FRAC_PLL_LOCK_SEL				(1 << 15)
155 #define  CCM_FRAC_PLL_BYPASS				(1 << 14)
156 #define  CCM_FRAC_PLL_COUNTCLK_SEL			(1 << 13)
157 #define  CCM_FRAC_PLL_NEWDIV_VAL			(1 << 12)
158 #define  CCM_FRAC_PLL_NEWDIV_ACK			(1 << 11)
159 #define  CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT		5
160 #define  CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK		0x3f
161 #define  CCM_FRAC_PLL_OUTPUT_DIV_VAL_SHIFT		0
162 #define  CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK		0x1f
163 #define  CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT		7
164 #define  CCM_FRAC_PLL_FRAC_DIV_CTL_MASK			0x1ffffff
165 #define  CCM_FRAC_PLL_INT_DIV_CTL_SHIFT			0
166 #define  CCM_FRAC_PLL_INT_DIV_CTL_MASK			0x7f
167 #define  CCM_FRAC_PLL_DENOM				(1 << 24)
168 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG		0x78
169 #define  CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT	20
170 #define  CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK		0x7
171 
172 #define HCLK_FREQ				24000000
173 #define PLL3_60M				60000000
174 #define PLL3_80M				80000000
175 
176 #define HREAD4(sc, reg)							\
177 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
178 #define HWRITE4(sc, reg, val)						\
179 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
180 #define HSET4(sc, reg, bits)						\
181 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
182 #define HCLR4(sc, reg, bits)						\
183 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
184 
185 struct imxccm_gate {
186 	uint16_t reg;
187 	uint8_t pos;
188 	uint16_t parent;
189 };
190 
191 struct imxccm_divider {
192 	uint16_t reg;
193 	uint16_t shift;
194 	uint16_t mask;
195 	uint16_t parent;
196 	uint16_t fixed;
197 };
198 
199 struct imxccm_mux {
200 	uint16_t reg;
201 	uint16_t shift;
202 	uint16_t mask;
203 };
204 
205 #include "imxccm_clocks.h"
206 
207 struct imxccm_softc {
208 	struct device		sc_dev;
209 	bus_space_tag_t		sc_iot;
210 	bus_space_handle_t	sc_ioh;
211 	int			sc_node;
212 	uint32_t		sc_phandle;
213 
214 	struct regmap		*sc_anatop;
215 
216 	struct imxccm_gate	*sc_gates;
217 	int			sc_ngates;
218 	struct imxccm_divider	*sc_divs;
219 	int			sc_ndivs;
220 	struct imxccm_mux	*sc_muxs;
221 	int			sc_nmuxs;
222 	struct imxccm_divider	*sc_predivs;
223 	int			sc_npredivs;
224 	struct clock_device	sc_cd;
225 };
226 
227 int	imxccm_match(struct device *, void *, void *);
228 void	imxccm_attach(struct device *parent, struct device *self, void *args);
229 
230 struct cfattach	imxccm_ca = {
231 	sizeof (struct imxccm_softc), imxccm_match, imxccm_attach
232 };
233 
234 struct cfdriver imxccm_cd = {
235 	NULL, "imxccm", DV_DULL
236 };
237 
238 uint32_t imxccm_get_armclk(struct imxccm_softc *);
239 void imxccm_armclk_set_parent(struct imxccm_softc *, enum imxanatop_clocks);
240 uint32_t imxccm_get_usdhx(struct imxccm_softc *, int x);
241 uint32_t imxccm_get_periphclk(struct imxccm_softc *);
242 uint32_t imxccm_get_ahbclk(struct imxccm_softc *);
243 uint32_t imxccm_get_ipgclk(struct imxccm_softc *);
244 uint32_t imxccm_get_ipg_perclk(struct imxccm_softc *);
245 uint32_t imxccm_get_uartclk(struct imxccm_softc *);
246 uint32_t imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t);
247 uint32_t imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t);
248 uint32_t imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t);
249 uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t);
250 uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t);
251 uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t);
252 uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t);
253 uint32_t imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t);
254 uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t);
255 uint32_t imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t);
256 uint32_t imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t);
257 uint32_t imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t);
258 uint32_t imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t);
259 int imxccm_imx8m_set_div(struct imxccm_softc *, uint32_t, uint64_t, uint64_t);
260 void imxccm_enable(void *, uint32_t *, int);
261 uint32_t imxccm_get_frequency(void *, uint32_t *);
262 int imxccm_set_frequency(void *, uint32_t *, uint32_t);
263 int imxccm_set_parent(void *, uint32_t *, uint32_t *);
264 
265 int
266 imxccm_match(struct device *parent, void *match, void *aux)
267 {
268 	struct fdt_attach_args *faa = aux;
269 
270 	return (OF_is_compatible(faa->fa_node, "fsl,imx6q-ccm") ||
271 	    OF_is_compatible(faa->fa_node, "fsl,imx6sl-ccm") ||
272 	    OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") ||
273 	    OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") ||
274 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") ||
275 	    OF_is_compatible(faa->fa_node, "fsl,imx8mm-ccm") ||
276 	    OF_is_compatible(faa->fa_node, "fsl,imx8mp-ccm") ||
277 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm"));
278 }
279 
280 void
281 imxccm_attach(struct device *parent, struct device *self, void *aux)
282 {
283 	struct imxccm_softc *sc = (struct imxccm_softc *)self;
284 	struct fdt_attach_args *faa = aux;
285 
286 	KASSERT(faa->fa_nreg >= 1);
287 
288 	sc->sc_node = faa->fa_node;
289 	sc->sc_iot = faa->fa_iot;
290 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
291 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
292 		panic("%s: bus_space_map failed!", __func__);
293 
294 	sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0);
295 
296 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-ccm")) {
297 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mm-anatop");
298 		KASSERT(sc->sc_anatop != NULL);
299 		sc->sc_gates = imx8mm_gates;
300 		sc->sc_ngates = nitems(imx8mm_gates);
301 		sc->sc_divs = imx8mm_divs;
302 		sc->sc_ndivs = nitems(imx8mm_divs);
303 		sc->sc_muxs = imx8mm_muxs;
304 		sc->sc_nmuxs = nitems(imx8mm_muxs);
305 		sc->sc_predivs = imx8mm_predivs;
306 		sc->sc_npredivs = nitems(imx8mm_predivs);
307 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx8mp-ccm")) {
308 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mp-anatop");
309 		KASSERT(sc->sc_anatop != NULL);
310 		sc->sc_gates = imx8mp_gates;
311 		sc->sc_ngates = nitems(imx8mp_gates);
312 		sc->sc_divs = imx8mp_divs;
313 		sc->sc_ndivs = nitems(imx8mp_divs);
314 		sc->sc_muxs = imx8mp_muxs;
315 		sc->sc_nmuxs = nitems(imx8mp_muxs);
316 		sc->sc_predivs = imx8mp_predivs;
317 		sc->sc_npredivs = nitems(imx8mp_predivs);
318 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) {
319 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop");
320 		KASSERT(sc->sc_anatop != NULL);
321 		sc->sc_gates = imx8mq_gates;
322 		sc->sc_ngates = nitems(imx8mq_gates);
323 		sc->sc_divs = imx8mq_divs;
324 		sc->sc_ndivs = nitems(imx8mq_divs);
325 		sc->sc_muxs = imx8mq_muxs;
326 		sc->sc_nmuxs = nitems(imx8mq_muxs);
327 		sc->sc_predivs = imx8mq_predivs;
328 		sc->sc_npredivs = nitems(imx8mq_predivs);
329 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx7d-ccm")) {
330 		sc->sc_gates = imx7d_gates;
331 		sc->sc_ngates = nitems(imx7d_gates);
332 		sc->sc_divs = imx7d_divs;
333 		sc->sc_ndivs = nitems(imx7d_divs);
334 		sc->sc_muxs = imx7d_muxs;
335 		sc->sc_nmuxs = nitems(imx7d_muxs);
336 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx6ul-ccm")) {
337 		sc->sc_gates = imx6ul_gates;
338 		sc->sc_ngates = nitems(imx6ul_gates);
339 	} else {
340 		sc->sc_gates = imx6_gates;
341 		sc->sc_ngates = nitems(imx6_gates);
342 	}
343 
344 	printf("\n");
345 
346 	sc->sc_cd.cd_node = faa->fa_node;
347 	sc->sc_cd.cd_cookie = sc;
348 	sc->sc_cd.cd_enable = imxccm_enable;
349 	sc->sc_cd.cd_get_frequency = imxccm_get_frequency;
350 	sc->sc_cd.cd_set_frequency = imxccm_set_frequency;
351 	sc->sc_cd.cd_set_parent = imxccm_set_parent;
352 	clock_register(&sc->sc_cd);
353 }
354 
355 uint32_t
356 imxccm_get_armclk(struct imxccm_softc *sc)
357 {
358 	uint32_t ccsr = HREAD4(sc, CCM_CCSR);
359 
360 	if (!(ccsr & CCM_CCSR_PLL1_SW_CLK_SEL))
361 		return imxanatop_decode_pll(ARM_PLL1, HCLK_FREQ);
362 	else if (ccsr & CCM_CCSR_STEP_SEL)
363 		return imxanatop_get_pll2_pfd(2);
364 	else
365 		return HCLK_FREQ;
366 }
367 
368 void
369 imxccm_armclk_set_parent(struct imxccm_softc *sc, enum imxanatop_clocks clock)
370 {
371 	switch (clock)
372 	{
373 	case ARM_PLL1:
374 		/* jump onto pll1 */
375 		HCLR4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
376 		/* put step clk on OSC, power saving */
377 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
378 		break;
379 	case OSC:
380 		/* put step clk on OSC */
381 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
382 		/* jump onto step clk */
383 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
384 		break;
385 	case SYS_PLL2_PFD2:
386 		/* put step clk on pll2-pfd2 400 MHz */
387 		HSET4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
388 		/* jump onto step clk */
389 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
390 		break;
391 	default:
392 		panic("%s: parent not possible for arm clk", __func__);
393 	}
394 }
395 
396 uint32_t
397 imxccm_get_ecspiclk(struct imxccm_softc *sc)
398 {
399 	uint32_t clkroot = PLL3_60M;
400 	uint32_t podf = HREAD4(sc, CCM_CSCDR2);
401 
402 	podf >>= CCM_CSCDR2_ECSPI_PODF_SHIFT;
403 	podf &= CCM_CSCDR2_ECSPI_PODF_MASK;
404 
405 	return clkroot / (podf + 1);
406 }
407 
408 unsigned int
409 imxccm_get_usdhx(struct imxccm_softc *sc, int x)
410 {
411 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
412 	uint32_t cscdr1 = HREAD4(sc, CCM_CSCDR1);
413 	uint32_t podf, clkroot;
414 
415 	// Odd bitsetting. Damn you.
416 	if (x == 1)
417 		podf = ((cscdr1 >> 11) & CCM_CSCDR1_USDHCx_PODF_MASK);
418 	else
419 		podf = ((cscdr1 >> (10 + 3*x)) & CCM_CSCDR1_USDHCx_PODF_MASK);
420 
421 	if (cscmr1 & (1 << CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)))
422 		clkroot = imxanatop_get_pll2_pfd(0); // 352 MHz
423 	else
424 		clkroot = imxanatop_get_pll2_pfd(2); // 396 MHz
425 
426 	return clkroot / (podf + 1);
427 }
428 
429 uint32_t
430 imxccm_get_uartclk(struct imxccm_softc *sc)
431 {
432 	uint32_t clkroot = PLL3_80M;
433 	uint32_t podf = HREAD4(sc, CCM_CSCDR1) & CCM_CSCDR1_UART_PODF_MASK;
434 
435 	return clkroot / (podf + 1);
436 }
437 
438 uint32_t
439 imxccm_get_periphclk(struct imxccm_softc *sc)
440 {
441 	if ((HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_PERIPH_CLK_SEL_SHIFT)
442 		    & CCM_CBCDR_PERIPH_CLK_SEL_MASK) {
443 		switch((HREAD4(sc, CCM_CBCMR)
444 		    >> CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT) & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) {
445 		case 0:
446 			return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ);
447 		case 1:
448 		case 2:
449 			return HCLK_FREQ;
450 		default:
451 			return 0;
452 		}
453 
454 	} else {
455 		switch((HREAD4(sc, CCM_CBCMR)
456 		    >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) {
457 		default:
458 		case 0:
459 			return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ);
460 		case 1:
461 			return imxanatop_get_pll2_pfd(2); // 396 MHz
462 		case 2:
463 			return imxanatop_get_pll2_pfd(0); // 352 MHz
464 		case 3:
465 			return imxanatop_get_pll2_pfd(2) / 2; // 198 MHz
466 		}
467 	}
468 }
469 
470 uint32_t
471 imxccm_get_ahbclk(struct imxccm_softc *sc)
472 {
473 	uint32_t ahb_podf;
474 
475 	ahb_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_AHB_PODF_SHIFT)
476 	    & CCM_CBCDR_AHB_PODF_MASK;
477 	return imxccm_get_periphclk(sc) / (ahb_podf + 1);
478 }
479 
480 uint32_t
481 imxccm_get_ipgclk(struct imxccm_softc *sc)
482 {
483 	uint32_t ipg_podf;
484 
485 	ipg_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_IPG_PODF_SHIFT)
486 	    & CCM_CBCDR_IPG_PODF_MASK;
487 	return imxccm_get_ahbclk(sc) / (ipg_podf + 1);
488 }
489 
490 uint32_t
491 imxccm_get_ipg_perclk(struct imxccm_softc *sc)
492 {
493 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
494 	uint32_t freq, ipg_podf;
495 
496 	if (sc->sc_gates == imx6ul_gates &&
497 	    cscmr1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK)
498 		freq = HCLK_FREQ;
499 	else
500 		freq = imxccm_get_ipgclk(sc);
501 
502 	ipg_podf = cscmr1 & CCM_CSCMR1_PERCLK_CLK_PODF_MASK;
503 
504 	return freq / (ipg_podf + 1);
505 }
506 
507 void
508 imxccm_imx6_enable_pll_enet(struct imxccm_softc *sc, int on)
509 {
510 	KASSERT(on);
511 
512 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
513 	    CCM_ANALOG_PLL_ENET_POWERDOWN);
514 
515 	/* Wait for the PLL to lock. */
516 	while ((regmap_read_4(sc->sc_anatop,
517 	    CCM_ANALOG_PLL_ENET) & CCM_ANALOG_PLL_ENET_LOCK) == 0)
518 		;
519 
520 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
521 	    CCM_ANALOG_PLL_ENET_BYPASS);
522 }
523 
524 void
525 imxccm_imx6_enable_pll_usb1(struct imxccm_softc *sc, int on)
526 {
527 	KASSERT(on);
528 
529 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
530 	    CCM_ANALOG_PLL_USB1_POWER);
531 
532 	/* Wait for the PLL to lock. */
533 	while ((regmap_read_4(sc->sc_anatop,
534 	    CCM_ANALOG_PLL_USB1) & CCM_ANALOG_PLL_USB1_LOCK) == 0)
535 		;
536 
537 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_CLR,
538 	    CCM_ANALOG_PLL_USB1_BYPASS);
539 }
540 
541 void
542 imxccm_imx6_enable_pll_usb2(struct imxccm_softc *sc, int on)
543 {
544 	KASSERT(on);
545 
546 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
547 	    CCM_ANALOG_PLL_USB2_POWER);
548 
549 	/* Wait for the PLL to lock. */
550 	while ((regmap_read_4(sc->sc_anatop,
551 	    CCM_ANALOG_PLL_USB2) & CCM_ANALOG_PLL_USB2_LOCK) == 0)
552 		;
553 
554 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_CLR,
555 	    CCM_ANALOG_PLL_USB2_BYPASS);
556 }
557 
558 uint32_t
559 imxccm_imx7d_enet(struct imxccm_softc *sc, uint32_t idx)
560 {
561 	uint32_t mux;
562 
563 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
564 		return 0;
565 
566 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
567 	mux >>= sc->sc_muxs[idx].shift;
568 	mux &= sc->sc_muxs[idx].mask;
569 
570 	switch (mux) {
571 	case 0:
572 		return clock_get_frequency(sc->sc_node, "osc");
573 	case 7:
574 		return 392000000; /* pll_sys_pfd4_clk XXX not fixed */
575 	default:
576 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
577 		return 0;
578 	}
579 }
580 
581 uint32_t
582 imxccm_imx7d_i2c(struct imxccm_softc *sc, uint32_t idx)
583 {
584 	uint32_t mux;
585 
586 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
587 		return 0;
588 
589 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
590 	mux >>= sc->sc_muxs[idx].shift;
591 	mux &= sc->sc_muxs[idx].mask;
592 
593 	switch (mux) {
594 	case 0:
595 		return clock_get_frequency(sc->sc_node, "osc");
596 	case 1:
597 		return 120000000; /* pll_sys_main_120m_clk */
598 	default:
599 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
600 		return 0;
601 	}
602 }
603 
604 uint32_t
605 imxccm_imx7d_uart(struct imxccm_softc *sc, uint32_t idx)
606 {
607 	uint32_t mux;
608 
609 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
610 		return 0;
611 
612 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
613 	mux >>= sc->sc_muxs[idx].shift;
614 	mux &= sc->sc_muxs[idx].mask;
615 
616 	switch (mux) {
617 	case 0:
618 		return clock_get_frequency(sc->sc_node, "osc");
619 	default:
620 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
621 		return 0;
622 	}
623 }
624 
625 uint32_t
626 imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx)
627 {
628 	uint32_t mux;
629 
630 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
631 		return 0;
632 
633 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
634 	mux >>= sc->sc_muxs[idx].shift;
635 	mux &= sc->sc_muxs[idx].mask;
636 
637 	switch (mux) {
638 	case 0:
639 		return clock_get_frequency(sc->sc_node, "osc");
640 	case 1:
641 		return 392000000; /* pll_sys_pfd0_392m_clk */
642 	default:
643 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
644 		return 0;
645 	}
646 }
647 
648 uint32_t
649 imxccm_imx8mm_get_pll(struct imxccm_softc *sc, uint32_t idx)
650 {
651 	uint64_t main_div, pre_div, post_div, div;
652 	uint32_t pll0, pll1;
653 	uint64_t freq;
654 
655 	switch (idx) {
656 	case IMX8MM_ARM_PLL:
657 		pll0 = regmap_read_4(sc->sc_anatop,
658 		    CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL);
659 		pll1 = regmap_read_4(sc->sc_anatop,
660 		    CCM_14XX_IMX8M_ARM_PLL_DIV_CTL);
661 		div = 1;
662 		break;
663 	default:
664 		printf("%s: 0x%08x\n", __func__, idx);
665 		return 0;
666 	}
667 
668 	freq = clock_get_frequency(sc->sc_node, "osc_24m");
669 	if (pll0 & CCM_INT_PLL_BYPASS)
670 		return freq;
671 
672 	main_div = (pll1 >> CCM_INT_PLL_MAIN_DIV_SHIFT) &
673 	    CCM_INT_PLL_MAIN_DIV_MASK;
674 	pre_div = (pll1 >> CCM_INT_PLL_PRE_DIV_SHIFT) &
675 	    CCM_INT_PLL_PRE_DIV_MASK;
676 	post_div = (pll1 >> CCM_INT_PLL_POST_DIV_SHIFT) &
677 	    CCM_INT_PLL_POST_DIV_MASK;
678 
679 	freq = freq * main_div;
680 	freq = freq / (pre_div * (1 << post_div) * div);
681 	return freq;
682 }
683 
684 int
685 imxccm_imx8mm_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
686 {
687 	uint64_t main_div, pre_div, post_div;
688 	uint32_t pll0, pll1, reg;
689 	int i;
690 
691 	switch (idx) {
692 	case IMX8MM_ARM_PLL:
693 		pre_div = 3;
694 		switch (freq) {
695 		case 1800000000U:
696 			main_div = 225;
697 			post_div = 0;
698 			break;
699 		case 1600000000U:
700 			main_div = 200;
701 			post_div = 0;
702 			break;
703 		case 1200000000U:
704 			main_div = 300;
705 			post_div = 1;
706 			break;
707 		case 1000000000U:
708 			main_div = 250;
709 			post_div = 1;
710 			break;
711 		case 800000000U:
712 			main_div = 200;
713 			post_div = 1;
714 			break;
715 		case 750000000U:
716 			main_div = 250;
717 			post_div = 2;
718 			break;
719 		case 700000000U:
720 			main_div = 350;
721 			post_div = 2;
722 			break;
723 		case 600000000U:
724 			main_div = 300;
725 			post_div = 2;
726 			break;
727 		default:
728 			printf("%s: 0x%08x\n", __func__, idx);
729 			return -1;
730 		}
731 		pll0 = CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL;
732 		pll1 = CCM_14XX_IMX8M_ARM_PLL_DIV_CTL;
733 		break;
734 	default:
735 		printf("%s: 0x%08x\n", __func__, idx);
736 		return -1;
737 	}
738 
739 	regmap_write_4(sc->sc_anatop, pll0,
740 	    regmap_read_4(sc->sc_anatop, pll0) |
741 	    CCM_INT_PLL_LOCK_SEL);
742 	regmap_write_4(sc->sc_anatop, pll0,
743 	    regmap_read_4(sc->sc_anatop, pll0) &
744 	    ~CCM_INT_PLL_RST);
745 	regmap_write_4(sc->sc_anatop, pll1,
746 	    main_div << CCM_INT_PLL_MAIN_DIV_SHIFT |
747 	    pre_div << CCM_INT_PLL_PRE_DIV_SHIFT |
748 	    post_div << CCM_INT_PLL_POST_DIV_SHIFT);
749 	delay(3);
750 	regmap_write_4(sc->sc_anatop, pll0,
751 	    regmap_read_4(sc->sc_anatop, pll0) |
752 	    CCM_INT_PLL_RST);
753 	for (i = 0; i < 5000; i++) {
754 		reg = regmap_read_4(sc->sc_anatop, pll0);
755 		if (reg & CCM_INT_PLL_LOCK)
756 			break;
757 		delay(10);
758 	}
759 	if (i == 5000)
760 		printf("%s: timeout\n", __func__);
761 	regmap_write_4(sc->sc_anatop, pll0,
762 	    regmap_read_4(sc->sc_anatop, pll0) &
763 	    ~CCM_INT_PLL_BYPASS);
764 
765 	return 0;
766 }
767 
768 uint32_t
769 imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t idx)
770 {
771 	uint32_t mux;
772 
773 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
774 		return 0;
775 
776 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
777 	mux >>= sc->sc_muxs[idx].shift;
778 	mux &= sc->sc_muxs[idx].mask;
779 
780 	switch (mux) {
781 	case 0:
782 		return clock_get_frequency(sc->sc_node, "osc_24m");
783 	case 1:
784 		return 266 * 1000 * 1000; /* sys1_pll_266m */
785 	default:
786 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
787 		return 0;
788 	}
789 }
790 
791 uint32_t
792 imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t idx)
793 {
794 	uint32_t mux;
795 
796 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
797 		return 0;
798 
799 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
800 	mux >>= sc->sc_muxs[idx].shift;
801 	mux &= sc->sc_muxs[idx].mask;
802 
803 	switch (mux) {
804 	case 0:
805 		return clock_get_frequency(sc->sc_node, "osc_24m");
806 	case 1:
807 		return 133 * 1000 * 1000; /* sys_pll1_133m */
808 	case 2:
809 		return 800 * 1000 * 1000; /* sys_pll1_800m */
810 	case 3:
811 		return 400 * 1000 * 1000; /* sys_pll1_400m */
812 	case 4:
813 		return 125 * 1000 * 1000; /* sys_pll2_125m */
814 	default:
815 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
816 		return 0;
817 	}
818 }
819 
820 uint32_t
821 imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t idx)
822 {
823 	uint32_t mux;
824 
825 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
826 		return 0;
827 
828 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
829 	mux >>= sc->sc_muxs[idx].shift;
830 	mux &= sc->sc_muxs[idx].mask;
831 
832 	switch (mux) {
833 	case 0:
834 		return clock_get_frequency(sc->sc_node, "osc_24m");
835 	default:
836 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
837 		return 0;
838 	}
839 }
840 
841 uint32_t
842 imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t idx)
843 {
844 	uint32_t mux;
845 
846 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
847 		return 0;
848 
849 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
850 	mux >>= sc->sc_muxs[idx].shift;
851 	mux &= sc->sc_muxs[idx].mask;
852 
853 	switch (mux) {
854 	case 0:
855 		return clock_get_frequency(sc->sc_node, "osc_24m");
856 	default:
857 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
858 		return 0;
859 	}
860 }
861 
862 uint32_t
863 imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx)
864 {
865 	uint32_t mux;
866 
867 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
868 		return 0;
869 
870 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
871 	mux >>= sc->sc_muxs[idx].shift;
872 	mux &= sc->sc_muxs[idx].mask;
873 
874 	switch (mux) {
875 	case 0:
876 		return clock_get_frequency(sc->sc_node, "osc_24m");
877 	case 1:
878 		return 400 * 1000 * 1000; /* sys1_pll_400m */
879 	default:
880 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
881 		return 0;
882 	}
883 }
884 
885 uint32_t
886 imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx)
887 {
888 	uint32_t mux;
889 
890 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
891 		return 0;
892 
893 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
894 	mux >>= sc->sc_muxs[idx].shift;
895 	mux &= sc->sc_muxs[idx].mask;
896 
897 	switch (mux) {
898 	case 0:
899 		return clock_get_frequency(sc->sc_node, "osc_25m");
900 	case 1:
901 		return 200 * 1000 * 1000; /* sys2_pll_200m */
902 	default:
903 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
904 		return 0;
905 	}
906 }
907 
908 uint32_t
909 imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t idx)
910 {
911 	uint32_t mux;
912 
913 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
914 		return 0;
915 
916 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
917 	mux >>= sc->sc_muxs[idx].shift;
918 	mux &= sc->sc_muxs[idx].mask;
919 
920 	switch (mux) {
921 	case 0:
922 		return clock_get_frequency(sc->sc_node, "osc_25m");
923 	case 1:
924 		return 266 * 1000 * 1000; /* sys1_pll_266m */
925 	default:
926 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
927 		return 0;
928 	}
929 }
930 
931 uint32_t
932 imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t idx)
933 {
934 	uint32_t mux;
935 
936 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
937 		return 0;
938 
939 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
940 	mux >>= sc->sc_muxs[idx].shift;
941 	mux &= sc->sc_muxs[idx].mask;
942 
943 	switch (mux) {
944 	case 0:
945 		return clock_get_frequency(sc->sc_node, "osc_25m");
946 	case 1:
947 		return 133 * 1000 * 1000; /* sys1_pll_133m */
948 	case 2:
949 		return 800 * 1000 * 1000; /* sys1_pll_800m */
950 	case 3:
951 		return 400 * 1000 * 1000; /* sys1_pll_400m */
952 	case 4:
953 		return 125 * 1000 * 1000; /* sys2_pll_125m */
954 	default:
955 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
956 		return 0;
957 	}
958 }
959 
960 uint32_t
961 imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t idx)
962 {
963 	uint32_t mux;
964 
965 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
966 		return 0;
967 
968 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
969 	mux >>= sc->sc_muxs[idx].shift;
970 	mux &= sc->sc_muxs[idx].mask;
971 
972 	switch (mux) {
973 	case 0:
974 		return clock_get_frequency(sc->sc_node, "osc_25m");
975 	default:
976 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
977 		return 0;
978 	}
979 }
980 
981 uint32_t
982 imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t idx)
983 {
984 	uint32_t mux;
985 
986 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
987 		return 0;
988 
989 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
990 	mux >>= sc->sc_muxs[idx].shift;
991 	mux &= sc->sc_muxs[idx].mask;
992 
993 	switch (mux) {
994 	case 0:
995 		return clock_get_frequency(sc->sc_node, "osc_25m");
996 	case 1:
997 		return 100 * 1000 * 1000; /* sys1_pll_100m */
998 	case 2:
999 		return 160 * 1000 * 1000; /* sys1_pll_160m */
1000 	case 3:
1001 		return 40 * 1000 * 1000; /* sys1_pll_40m */
1002 	default:
1003 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1004 		return 0;
1005 	}
1006 }
1007 
1008 uint32_t
1009 imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t idx)
1010 {
1011 	uint32_t mux;
1012 
1013 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1014 		return 0;
1015 
1016 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1017 	mux >>= sc->sc_muxs[idx].shift;
1018 	mux &= sc->sc_muxs[idx].mask;
1019 
1020 	switch (mux) {
1021 	case 0:
1022 		return clock_get_frequency(sc->sc_node, "osc_25m");
1023 	default:
1024 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1025 		return 0;
1026 	}
1027 }
1028 
1029 uint32_t
1030 imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t idx)
1031 {
1032 	uint32_t mux;
1033 
1034 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1035 		return 0;
1036 
1037 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1038 	mux >>= sc->sc_muxs[idx].shift;
1039 	mux &= sc->sc_muxs[idx].mask;
1040 
1041 	switch (mux) {
1042 	case 0:
1043 		return clock_get_frequency(sc->sc_node, "osc_25m");
1044 	case 1:
1045 		return 400 * 1000 * 1000; /* sys1_pll_400m */
1046 	default:
1047 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1048 		return 0;
1049 	}
1050 }
1051 
1052 uint32_t
1053 imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t idx)
1054 {
1055 	uint32_t mux;
1056 
1057 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1058 		return 0;
1059 
1060 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1061 	mux >>= sc->sc_muxs[idx].shift;
1062 	mux &= sc->sc_muxs[idx].mask;
1063 
1064 	switch (mux) {
1065 	case 0:
1066 		return clock_get_frequency(sc->sc_node, "osc_25m");
1067 	case 1:
1068 		if (idx == IMX8MQ_CLK_USB_CORE_REF ||
1069 		    idx == IMX8MQ_CLK_USB_PHY_REF)
1070 			return 100 * 1000 * 1000; /* sys1_pll_100m */
1071 		if (idx == IMX8MQ_CLK_USB_BUS)
1072 			return 500 * 1000 * 1000; /* sys2_pll_500m */
1073 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1074 		return 0;
1075 	default:
1076 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1077 		return 0;
1078 	}
1079 }
1080 
1081 uint32_t
1082 imxccm_imx8mq_get_pll(struct imxccm_softc *sc, uint32_t idx)
1083 {
1084 	uint32_t divr_val, divq_val, divf_val;
1085 	uint32_t divff, divfi;
1086 	uint32_t pllout_div;
1087 	uint32_t pll0, pll1;
1088 	uint32_t freq;
1089 	uint32_t mux;
1090 
1091 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1092 
1093 	switch (idx) {
1094 	case IMX8MQ_ARM_PLL:
1095 		pll0 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL0);
1096 		pll1 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL1);
1097 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1098 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1099 		break;
1100 	default:
1101 		printf("%s: 0x%08x\n", __func__, idx);
1102 		return 0;
1103 	}
1104 
1105 	if (pll0 & CCM_FRAC_PLL_POWERDOWN)
1106 		return 0;
1107 
1108 	if ((pll0 & CCM_FRAC_PLL_ENABLE) == 0)
1109 		return 0;
1110 
1111 	mux = (pll0 >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1112 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1113 	switch (mux) {
1114 	case 0:
1115 		freq = clock_get_frequency(sc->sc_node, "osc_25m");
1116 		break;
1117 	case 1:
1118 	case 2:
1119 		freq = clock_get_frequency(sc->sc_node, "osc_27m");
1120 		break;
1121 	default:
1122 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1123 		return 0;
1124 	}
1125 
1126 	if (pll0 & CCM_FRAC_PLL_BYPASS)
1127 		return freq;
1128 
1129 	divr_val = (pll0 >> CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT) &
1130 	    CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK;
1131 	divq_val = pll0 & CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1132 	divff = (pll1 >> CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT) &
1133 	    CCM_FRAC_PLL_FRAC_DIV_CTL_MASK;
1134 	divfi = pll1 & CCM_FRAC_PLL_INT_DIV_CTL_MASK;
1135 	divf_val = 1 + divfi + divff / CCM_FRAC_PLL_DENOM;
1136 
1137 	freq = freq / (divr_val + 1) * 8 * divf_val / ((divq_val + 1) * 2);
1138 	return freq / (pllout_div + 1);
1139 }
1140 
1141 int
1142 imxccm_imx8mq_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
1143 {
1144 	uint64_t divff, divfi, divr;
1145 	uint32_t pllout_div;
1146 	uint32_t pll0, pll1;
1147 	uint32_t mux, reg;
1148 	uint64_t pfreq;
1149 	int i;
1150 
1151 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1152 
1153 	switch (idx) {
1154 	case IMX8MQ_ARM_PLL:
1155 		pll0 = CCM_FRAC_IMX8M_ARM_PLL0;
1156 		pll1 = CCM_FRAC_IMX8M_ARM_PLL1;
1157 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1158 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1159 		/* XXX: Assume fixed divider to ease math. */
1160 		KASSERT(pllout_div == 0);
1161 		divr = 5;
1162 		break;
1163 	default:
1164 		printf("%s: 0x%08x\n", __func__, idx);
1165 		return -1;
1166 	}
1167 
1168 	reg = regmap_read_4(sc->sc_anatop, pll0);
1169 	mux = (reg >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1170 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1171 	switch (mux) {
1172 	case 0:
1173 		pfreq = clock_get_frequency(sc->sc_node, "osc_25m");
1174 		break;
1175 	case 1:
1176 	case 2:
1177 		pfreq = clock_get_frequency(sc->sc_node, "osc_27m");
1178 		break;
1179 	default:
1180 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1181 		return -1;
1182 	}
1183 
1184 	/* Frac divider follows the PLL */
1185 	freq *= divr;
1186 
1187 	/* PLL calculation */
1188 	freq *= 2;
1189 	pfreq *= 8;
1190 	divfi = freq / pfreq;
1191 	divff = (uint64_t)(freq - divfi * pfreq);
1192 	divff = (divff * CCM_FRAC_PLL_DENOM) / pfreq;
1193 
1194 	reg = regmap_read_4(sc->sc_anatop, pll1);
1195 	reg &= ~(CCM_FRAC_PLL_FRAC_DIV_CTL_MASK << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT);
1196 	reg |= divff << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT;
1197 	reg &= ~(CCM_FRAC_PLL_INT_DIV_CTL_MASK << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT);
1198 	reg |= (divfi - 1) << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT;
1199 	regmap_write_4(sc->sc_anatop, pll1, reg);
1200 
1201 	reg = regmap_read_4(sc->sc_anatop, pll0);
1202 	reg &= ~CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1203 	reg &= ~(CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT);
1204 	reg |= (divr - 1) << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT;
1205 	regmap_write_4(sc->sc_anatop, pll0, reg);
1206 
1207 	reg = regmap_read_4(sc->sc_anatop, pll0);
1208 	reg |= CCM_FRAC_PLL_NEWDIV_VAL;
1209 	regmap_write_4(sc->sc_anatop, pll0, reg);
1210 
1211 	for (i = 0; i < 5000; i++) {
1212 		reg = regmap_read_4(sc->sc_anatop, pll0);
1213 		if (reg & CCM_FRAC_PLL_BYPASS)
1214 			break;
1215 		if (reg & CCM_FRAC_PLL_POWERDOWN)
1216 			break;
1217 		if (reg & CCM_FRAC_PLL_NEWDIV_ACK)
1218 			break;
1219 		delay(10);
1220 	}
1221 	if (i == 5000)
1222 		printf("%s: timeout\n", __func__);
1223 
1224 	reg = regmap_read_4(sc->sc_anatop, pll0);
1225 	reg &= ~CCM_FRAC_PLL_NEWDIV_VAL;
1226 	regmap_write_4(sc->sc_anatop, pll0, reg);
1227 
1228 	return 0;
1229 }
1230 
1231 int
1232 imxccm_imx8m_set_div(struct imxccm_softc *sc, uint32_t idx, uint64_t freq,
1233     uint64_t parent_freq)
1234 {
1235 	uint64_t div;
1236 	uint32_t reg;
1237 
1238 	if (parent_freq < freq) {
1239 		printf("%s: parent frequency too low (0x%08x)\n",
1240 		    __func__, idx);
1241 		return -1;
1242 	}
1243 
1244 	/* divisor can only be changed if enabled */
1245 	imxccm_enable(sc, &idx, 1);
1246 
1247 	div = 0;
1248 	while (parent_freq / (div + 1) > freq)
1249 		div++;
1250 	reg = HREAD4(sc, sc->sc_divs[idx].reg);
1251 	reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
1252 	reg |= (div << sc->sc_divs[idx].shift);
1253 	HWRITE4(sc, sc->sc_divs[idx].reg, reg);
1254 	HCLR4(sc, sc->sc_predivs[idx].reg,
1255 	    sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift);
1256 	return 0;
1257 }
1258 
1259 void
1260 imxccm_enable_parent(struct imxccm_softc *sc, uint32_t parent, int on)
1261 {
1262 	if (on)
1263 		imxccm_enable(sc, &parent, on);
1264 }
1265 
1266 void
1267 imxccm_enable(void *cookie, uint32_t *cells, int on)
1268 {
1269 	struct imxccm_softc *sc = cookie;
1270 	uint32_t idx = cells[0], parent;
1271 	uint32_t pcells[2];
1272 	uint16_t reg;
1273 	uint8_t pos;
1274 
1275 	/* Dummy clock. */
1276 	if (idx == 0)
1277 		return;
1278 
1279 	if (sc->sc_gates == imx8mm_gates) {
1280 		switch (idx) {
1281 		case IMX8MM_CLK_PCIE1_CTRL:
1282 		case IMX8MM_CLK_PCIE2_CTRL:
1283 			pcells[0] = sc->sc_phandle;
1284 			pcells[1] = IMX8MM_SYS_PLL2_250M;
1285 			imxccm_set_parent(cookie, &idx, pcells);
1286 			break;
1287 		case IMX8MM_CLK_PCIE1_PHY:
1288 		case IMX8MM_CLK_PCIE2_PHY:
1289 			pcells[0] = sc->sc_phandle;
1290 			pcells[1] = IMX8MM_SYS_PLL2_100M;
1291 			imxccm_set_parent(cookie, &idx, pcells);
1292 			break;
1293 		}
1294 	} else if (sc->sc_gates == imx8mq_gates) {
1295 		switch (idx) {
1296 		case IMX8MQ_CLK_32K:
1297 			/* always on */
1298 			return;
1299 		case IMX8MQ_CLK_PCIE1_CTRL:
1300 		case IMX8MQ_CLK_PCIE2_CTRL:
1301 			pcells[0] = sc->sc_phandle;
1302 			pcells[1] = IMX8MQ_SYS2_PLL_250M;
1303 			imxccm_set_parent(cookie, &idx, pcells);
1304 			break;
1305 		case IMX8MQ_CLK_PCIE1_PHY:
1306 		case IMX8MQ_CLK_PCIE2_PHY:
1307 			pcells[0] = sc->sc_phandle;
1308 			pcells[1] = IMX8MQ_SYS2_PLL_100M;
1309 			imxccm_set_parent(cookie, &idx, pcells);
1310 			break;
1311 		}
1312 	} else if (sc->sc_gates == imx7d_gates) {
1313 		if (sc->sc_anatop == NULL) {
1314 			sc->sc_anatop = regmap_bycompatible("fsl,imx7d-anatop");
1315 			KASSERT(sc->sc_anatop);
1316 		}
1317 
1318 		switch (idx) {
1319 		case IMX7D_PLL_ENET_MAIN_125M_CLK:
1320 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_SET,
1321 			    CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ);
1322 			return;
1323 		default:
1324 			break;
1325 		}
1326 	} else if (sc->sc_gates == imx6_gates) {
1327 		if (sc->sc_anatop == NULL) {
1328 			sc->sc_anatop = regmap_bycompatible("fsl,imx6q-anatop");
1329 			KASSERT(sc->sc_anatop);
1330 		}
1331 
1332 		switch (idx) {
1333 		case IMX6_CLK_PLL3:
1334 			imxccm_imx6_enable_pll_usb1(sc, on);
1335 			return;
1336 		case IMX6_CLK_PLL6:
1337 			imxccm_imx6_enable_pll_enet(sc, on);
1338 			return;
1339 		case IMX6_CLK_PLL7:
1340 			imxccm_imx6_enable_pll_usb2(sc, on);
1341 			return;
1342 		case IMX6_CLK_PLL3_USB_OTG:
1343 			imxccm_enable_parent(sc, IMX6_CLK_PLL3, on);
1344 			regmap_write_4(sc->sc_anatop,
1345 			    on ? CCM_ANALOG_PLL_USB1_SET : CCM_ANALOG_PLL_USB1_CLR,
1346 			    CCM_ANALOG_PLL_USB1_ENABLE);
1347 			return;
1348 		case IMX6_CLK_PLL6_ENET:
1349 			imxccm_enable_parent(sc, IMX6_CLK_PLL6, on);
1350 			regmap_write_4(sc->sc_anatop,
1351 			    on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
1352 			    CCM_ANALOG_PLL_ENET_ENABLE);
1353 			return;
1354 		case IMX6_CLK_PLL7_USB_HOST:
1355 			imxccm_enable_parent(sc, IMX6_CLK_PLL7, on);
1356 			regmap_write_4(sc->sc_anatop,
1357 			    on ? CCM_ANALOG_PLL_USB2_SET : CCM_ANALOG_PLL_USB2_CLR,
1358 			    CCM_ANALOG_PLL_USB2_ENABLE);
1359 			return;
1360 		case IMX6_CLK_USBPHY1:
1361 			/* PLL outputs should alwas be on. */
1362 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
1363 			    CCM_ANALOG_PLL_USB1_EN_USB_CLKS);
1364 			imxccm_enable_parent(sc, IMX6_CLK_PLL3_USB_OTG, on);
1365 			return;
1366 		case IMX6_CLK_USBPHY2:
1367 			/* PLL outputs should alwas be on. */
1368 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
1369 			    CCM_ANALOG_PLL_USB2_EN_USB_CLKS);
1370 			imxccm_enable_parent(sc, IMX6_CLK_PLL7_USB_HOST, on);
1371 			return;
1372 		case IMX6_CLK_SATA_REF_100:
1373 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
1374 			regmap_write_4(sc->sc_anatop,
1375 			   on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
1376 			   CCM_ANALOG_PLL_ENET_ENABLE_100M);
1377 			return;
1378 		case IMX6_CLK_ENET_REF:
1379 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
1380 			return;
1381 		case IMX6_CLK_IPG:
1382 		case IMX6_CLK_IPG_PER:
1383 		case IMX6_CLK_ECSPI_ROOT:
1384 			/* always on */
1385 			return;
1386 		default:
1387 			break;
1388 		}
1389 	}
1390 
1391 	if (on) {
1392 		if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
1393 			parent = sc->sc_gates[idx].parent;
1394 			imxccm_enable(sc, &parent, on);
1395 		}
1396 
1397 		if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1398 			parent = sc->sc_divs[idx].parent;
1399 			imxccm_enable(sc, &parent, on);
1400 		}
1401 	}
1402 
1403 	if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
1404 		if ((idx < sc->sc_ndivs && sc->sc_divs[idx].reg != 0) ||
1405 		    (idx < sc->sc_nmuxs && sc->sc_muxs[idx].reg != 0))
1406 			return;
1407 		printf("%s: 0x%08x\n", __func__, idx);
1408 		return;
1409 	}
1410 
1411 	reg = sc->sc_gates[idx].reg;
1412 	pos = sc->sc_gates[idx].pos;
1413 
1414 	if (on)
1415 		HSET4(sc, reg, 0x3 << (2 * pos));
1416 	else
1417 		HCLR4(sc, reg, 0x3 << (2 * pos));
1418 }
1419 
1420 uint32_t
1421 imxccm_get_frequency(void *cookie, uint32_t *cells)
1422 {
1423 	struct imxccm_softc *sc = cookie;
1424 	uint32_t idx = cells[0];
1425 	uint32_t div, pre, reg, parent;
1426 	uint32_t freq;
1427 
1428 	/* Dummy clock. */
1429 	if (idx == 0)
1430 		return 0;
1431 
1432 	if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
1433 		parent = sc->sc_gates[idx].parent;
1434 		return imxccm_get_frequency(sc, &parent);
1435 	}
1436 
1437 	if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1438 		div = HREAD4(sc, sc->sc_divs[idx].reg);
1439 		div = div >> sc->sc_divs[idx].shift;
1440 		div = div & sc->sc_divs[idx].mask;
1441 		parent = sc->sc_divs[idx].parent;
1442 		return imxccm_get_frequency(sc, &parent) / (div + 1);
1443 	}
1444 
1445 	if (sc->sc_gates == imx8mm_gates) {
1446 		switch (idx) {
1447 		case IMX8MM_CLK_ARM:
1448 			parent = IMX8MM_ARM_PLL;
1449 			return imxccm_get_frequency(sc, &parent);
1450 		case IMX8MM_ARM_PLL:
1451 			return imxccm_imx8mm_get_pll(sc, idx);
1452 		}
1453 
1454 		/* These are composite clocks. */
1455 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1456 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1457 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1458 			switch (idx) {
1459 			case IMX8MM_CLK_ENET_AXI:
1460 				freq = imxccm_imx8mm_enet(sc, idx);
1461 				break;
1462 			case IMX8MM_CLK_AHB:
1463 				freq = imxccm_imx8mm_ahb(sc, idx);
1464 				break;
1465 			case IMX8MM_CLK_I2C1:
1466 			case IMX8MM_CLK_I2C2:
1467 			case IMX8MM_CLK_I2C3:
1468 			case IMX8MM_CLK_I2C4:
1469 				freq = imxccm_imx8mm_i2c(sc, idx);
1470 				break;
1471 			case IMX8MM_CLK_UART1:
1472 			case IMX8MM_CLK_UART2:
1473 			case IMX8MM_CLK_UART3:
1474 			case IMX8MM_CLK_UART4:
1475 				freq = imxccm_imx8mm_uart(sc, idx);
1476 				break;
1477 			case IMX8MM_CLK_USDHC1:
1478 			case IMX8MM_CLK_USDHC2:
1479 			case IMX8MM_CLK_USDHC3:
1480 				freq = imxccm_imx8mm_usdhc(sc, idx);
1481 				break;
1482 			default:
1483 				printf("%s: 0x%08x\n", __func__, idx);
1484 				return 0;
1485 			}
1486 
1487 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1488 			div = reg >> sc->sc_divs[idx].shift;
1489 			div = div & sc->sc_divs[idx].mask;
1490 			pre = reg >> sc->sc_predivs[idx].shift;
1491 			pre = pre & sc->sc_predivs[idx].mask;
1492 			return ((freq / (pre + 1)) / (div + 1));
1493 		}
1494 	} else if (sc->sc_gates == imx8mp_gates) {
1495 		/* These are composite clocks. */
1496 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1497 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1498 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1499 			switch (idx) {
1500 			case IMX8MP_CLK_ENET_AXI:
1501 				freq = imxccm_imx8mm_enet(sc, idx);
1502 				break;
1503 			case IMX8MP_CLK_I2C1:
1504 			case IMX8MP_CLK_I2C2:
1505 			case IMX8MP_CLK_I2C3:
1506 			case IMX8MP_CLK_I2C4:
1507 			case IMX8MP_CLK_I2C5:
1508 			case IMX8MP_CLK_I2C6:
1509 				freq = imxccm_imx8mm_i2c(sc, idx);
1510 				break;
1511 			case IMX8MP_CLK_UART1:
1512 			case IMX8MP_CLK_UART2:
1513 			case IMX8MP_CLK_UART3:
1514 			case IMX8MP_CLK_UART4:
1515 				freq = imxccm_imx8mm_uart(sc, idx);
1516 				break;
1517 			case IMX8MP_CLK_USDHC1:
1518 			case IMX8MP_CLK_USDHC2:
1519 			case IMX8MP_CLK_USDHC3:
1520 				freq = imxccm_imx8mm_usdhc(sc, idx);
1521 				break;
1522 			default:
1523 				printf("%s: 0x%08x\n", __func__, idx);
1524 				return 0;
1525 			}
1526 
1527 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1528 			div = reg >> sc->sc_divs[idx].shift;
1529 			div = div & sc->sc_divs[idx].mask;
1530 			pre = reg >> sc->sc_predivs[idx].shift;
1531 			pre = pre & sc->sc_predivs[idx].mask;
1532 			return ((freq / (pre + 1)) / (div + 1));
1533 		}
1534 	} else if (sc->sc_gates == imx8mq_gates) {
1535 		switch (idx) {
1536 		case IMX8MQ_CLK_ARM:
1537 			parent = IMX8MQ_ARM_PLL;
1538 			return imxccm_get_frequency(sc, &parent);
1539 		case IMX8MQ_ARM_PLL:
1540 			return imxccm_imx8mq_get_pll(sc, idx);
1541 		}
1542 
1543 		/* These are composite clocks. */
1544 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1545 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1546 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1547 			switch (idx) {
1548 			case IMX8MQ_CLK_ENET_AXI:
1549 				freq = imxccm_imx8mq_enet(sc, idx);
1550 				break;
1551 			case IMX8MQ_CLK_AHB:
1552 				freq = imxccm_imx8mq_ahb(sc, idx);
1553 				break;
1554 			case IMX8MQ_CLK_I2C1:
1555 			case IMX8MQ_CLK_I2C2:
1556 			case IMX8MQ_CLK_I2C3:
1557 			case IMX8MQ_CLK_I2C4:
1558 				freq = imxccm_imx8mq_i2c(sc, idx);
1559 				break;
1560 			case IMX8MQ_CLK_UART1:
1561 			case IMX8MQ_CLK_UART2:
1562 			case IMX8MQ_CLK_UART3:
1563 			case IMX8MQ_CLK_UART4:
1564 				freq = imxccm_imx8mq_uart(sc, idx);
1565 				break;
1566 			case IMX8MQ_CLK_USDHC1:
1567 			case IMX8MQ_CLK_USDHC2:
1568 				freq = imxccm_imx8mq_usdhc(sc, idx);
1569 				break;
1570 			case IMX8MQ_CLK_USB_BUS:
1571 			case IMX8MQ_CLK_USB_CORE_REF:
1572 			case IMX8MQ_CLK_USB_PHY_REF:
1573 				freq = imxccm_imx8mq_usb(sc, idx);
1574 				break;
1575 			case IMX8MQ_CLK_ECSPI1:
1576 			case IMX8MQ_CLK_ECSPI2:
1577 			case IMX8MQ_CLK_ECSPI3:
1578 				freq = imxccm_imx8mq_ecspi(sc, idx);
1579 				break;
1580 			case IMX8MQ_CLK_PWM1:
1581 			case IMX8MQ_CLK_PWM2:
1582 			case IMX8MQ_CLK_PWM3:
1583 			case IMX8MQ_CLK_PWM4:
1584 				freq = imxccm_imx8mq_pwm(sc, idx);
1585 				break;
1586 			default:
1587 				printf("%s: 0x%08x\n", __func__, idx);
1588 				return 0;
1589 			}
1590 
1591 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1592 			div = reg >> sc->sc_divs[idx].shift;
1593 			div = div & sc->sc_divs[idx].mask;
1594 			pre = reg >> sc->sc_predivs[idx].shift;
1595 			pre = pre & sc->sc_predivs[idx].mask;
1596 			return ((freq / (pre + 1)) / (div + 1));
1597 		}
1598 
1599 	} else if (sc->sc_gates == imx7d_gates) {
1600 		switch (idx) {
1601 		case IMX7D_ENET_AXI_ROOT_SRC:
1602 			return imxccm_imx7d_enet(sc, idx);
1603 		case IMX7D_I2C1_ROOT_SRC:
1604 		case IMX7D_I2C2_ROOT_SRC:
1605 		case IMX7D_I2C3_ROOT_SRC:
1606 		case IMX7D_I2C4_ROOT_SRC:
1607 			return imxccm_imx7d_i2c(sc, idx);
1608 		case IMX7D_UART1_ROOT_SRC:
1609 		case IMX7D_UART2_ROOT_SRC:
1610 		case IMX7D_UART3_ROOT_SRC:
1611 		case IMX7D_UART4_ROOT_SRC:
1612 		case IMX7D_UART5_ROOT_SRC:
1613 		case IMX7D_UART6_ROOT_SRC:
1614 		case IMX7D_UART7_ROOT_SRC:
1615 			return imxccm_imx7d_uart(sc, idx);
1616 		case IMX7D_USDHC1_ROOT_SRC:
1617 		case IMX7D_USDHC2_ROOT_SRC:
1618 		case IMX7D_USDHC3_ROOT_SRC:
1619 			return imxccm_imx7d_usdhc(sc, idx);
1620 		}
1621 	} else if (sc->sc_gates == imx6ul_gates) {
1622 		switch (idx) {
1623 		case IMX6UL_CLK_ARM:
1624 			return imxccm_get_armclk(sc);
1625 		case IMX6UL_CLK_IPG:
1626 			return imxccm_get_ipgclk(sc);
1627 		case IMX6UL_CLK_PERCLK:
1628 			return imxccm_get_ipg_perclk(sc);
1629 		case IMX6UL_CLK_UART1_SERIAL:
1630 			return imxccm_get_uartclk(sc);
1631 		case IMX6UL_CLK_USDHC1:
1632 		case IMX6UL_CLK_USDHC2:
1633 			return imxccm_get_usdhx(sc, idx - IMX6UL_CLK_USDHC1 + 1);
1634 		}
1635 	} else if (sc->sc_gates == imx6_gates) {
1636 		switch (idx) {
1637 		case IMX6_CLK_AHB:
1638 			return imxccm_get_ahbclk(sc);
1639 		case IMX6_CLK_ARM:
1640 			return imxccm_get_armclk(sc);
1641 		case IMX6_CLK_IPG:
1642 			return imxccm_get_ipgclk(sc);
1643 		case IMX6_CLK_IPG_PER:
1644 			return imxccm_get_ipg_perclk(sc);
1645 		case IMX6_CLK_ECSPI_ROOT:
1646 			return imxccm_get_ecspiclk(sc);
1647 		case IMX6_CLK_UART_SERIAL:
1648 			return imxccm_get_uartclk(sc);
1649 		case IMX6_CLK_USDHC1:
1650 		case IMX6_CLK_USDHC2:
1651 		case IMX6_CLK_USDHC3:
1652 		case IMX6_CLK_USDHC4:
1653 			return imxccm_get_usdhx(sc, idx - IMX6_CLK_USDHC1 + 1);
1654 		}
1655 	}
1656 
1657 	printf("%s: 0x%08x\n", __func__, idx);
1658 	return 0;
1659 }
1660 
1661 int
1662 imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1663 {
1664 	struct imxccm_softc *sc = cookie;
1665 	uint32_t idx = cells[0];
1666 	uint32_t reg, div, parent, parent_freq;
1667 	uint32_t pcells[2];
1668 	int ret;
1669 
1670 	if (sc->sc_divs == imx8mm_divs) {
1671 		switch (idx) {
1672 		case IMX8MM_CLK_ARM:
1673 			parent = IMX8MM_CLK_A53_SRC;
1674 			return imxccm_set_frequency(cookie, &parent, freq);
1675 		case IMX8MM_CLK_A53_SRC:
1676 			pcells[0] = sc->sc_phandle;
1677 			pcells[1] = IMX8MM_SYS_PLL1_800M;
1678 			ret = imxccm_set_parent(cookie, &idx, pcells);
1679 			if (ret)
1680 				return ret;
1681 			ret = imxccm_imx8mm_set_pll(sc, IMX8MM_ARM_PLL, freq);
1682 			pcells[0] = sc->sc_phandle;
1683 			pcells[1] = IMX8MM_ARM_PLL_OUT;
1684 			imxccm_set_parent(cookie, &idx, pcells);
1685 			return ret;
1686 		case IMX8MM_CLK_USDHC1_ROOT:
1687 		case IMX8MM_CLK_USDHC2_ROOT:
1688 		case IMX8MM_CLK_USDHC3_ROOT:
1689 			parent = sc->sc_gates[idx].parent;
1690 			return imxccm_set_frequency(sc, &parent, freq);
1691 		case IMX8MM_CLK_USDHC1:
1692 		case IMX8MM_CLK_USDHC2:
1693 		case IMX8MM_CLK_USDHC3:
1694 			parent_freq = imxccm_imx8mm_usdhc(sc, idx);
1695 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1696 		}
1697 	} else if (sc->sc_divs == imx8mq_divs) {
1698 		switch (idx) {
1699 		case IMX8MQ_CLK_ARM:
1700 			parent = IMX8MQ_CLK_A53_SRC;
1701 			return imxccm_set_frequency(cookie, &parent, freq);
1702 		case IMX8MQ_CLK_A53_SRC:
1703 			pcells[0] = sc->sc_phandle;
1704 			pcells[1] = IMX8MQ_SYS1_PLL_800M;
1705 			ret = imxccm_set_parent(cookie, &idx, pcells);
1706 			if (ret)
1707 				return ret;
1708 			ret = imxccm_imx8mq_set_pll(sc, IMX8MQ_ARM_PLL, freq);
1709 			pcells[0] = sc->sc_phandle;
1710 			pcells[1] = IMX8MQ_ARM_PLL_OUT;
1711 			imxccm_set_parent(cookie, &idx, pcells);
1712 			return ret;
1713 		case IMX8MQ_CLK_USB_BUS:
1714 		case IMX8MQ_CLK_USB_CORE_REF:
1715 		case IMX8MQ_CLK_USB_PHY_REF:
1716 			if (imxccm_get_frequency(sc, cells) != freq)
1717 				break;
1718 			return 0;
1719 		case IMX8MQ_CLK_USDHC1:
1720 		case IMX8MQ_CLK_USDHC2:
1721 			parent_freq = imxccm_imx8mq_usdhc(sc, idx);
1722 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1723 		}
1724 	} else if (sc->sc_divs == imx7d_divs) {
1725 		switch (idx) {
1726 		case IMX7D_USDHC1_ROOT_CLK:
1727 		case IMX7D_USDHC2_ROOT_CLK:
1728 		case IMX7D_USDHC3_ROOT_CLK:
1729 			parent = sc->sc_gates[idx].parent;
1730 			return imxccm_set_frequency(sc, &parent, freq);
1731 		case IMX7D_USDHC1_ROOT_DIV:
1732 		case IMX7D_USDHC2_ROOT_DIV:
1733 		case IMX7D_USDHC3_ROOT_DIV:
1734 			parent = sc->sc_divs[idx].parent;
1735 			parent_freq = imxccm_get_frequency(sc, &parent);
1736 			div = 0;
1737 			while (parent_freq / (div + 1) > freq)
1738 				div++;
1739 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1740 			reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
1741 			reg |= (div << sc->sc_divs[idx].shift);
1742 			HWRITE4(sc, sc->sc_divs[idx].reg, reg);
1743 			return 0;
1744 		}
1745 	}
1746 
1747 	printf("%s: 0x%08x %x\n", __func__, idx, freq);
1748 	return -1;
1749 }
1750 
1751 int
1752 imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1753 {
1754 	struct imxccm_softc *sc = cookie;
1755 	uint32_t idx = cells[0];
1756 	uint32_t pidx;
1757 	uint32_t mux;
1758 
1759 	if (pcells[0] != sc->sc_phandle) {
1760 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, pcells[0]);
1761 		return -1;
1762 	}
1763 
1764 	pidx = pcells[1];
1765 
1766 	if (sc->sc_muxs == imx8mm_muxs) {
1767 		switch (idx) {
1768 		case IMX8MM_CLK_A53_SRC:
1769 			if (pidx != IMX8MM_ARM_PLL_OUT &&
1770 			    pidx != IMX8MM_SYS_PLL1_800M)
1771 				break;
1772 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1773 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1774 			if (pidx == IMX8MM_ARM_PLL_OUT)
1775 				mux |= (0x1 << sc->sc_muxs[idx].shift);
1776 			if (pidx == IMX8MM_SYS_PLL1_800M)
1777 				mux |= (0x4 << sc->sc_muxs[idx].shift);
1778 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1779 			return 0;
1780 		case IMX8MM_CLK_USB_BUS:
1781 			if (pidx != IMX8MM_SYS_PLL2_500M)
1782 				break;
1783 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1784 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1785 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1786 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1787 			return 0;
1788 		case IMX8MM_CLK_USB_CORE_REF:
1789 		case IMX8MM_CLK_USB_PHY_REF:
1790 			if (pidx != IMX8MM_SYS_PLL1_100M)
1791 				break;
1792 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1793 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1794 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1795 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1796 			return 0;
1797 		case IMX8MM_CLK_PCIE1_CTRL:
1798 		case IMX8MM_CLK_PCIE2_CTRL:
1799 			if (pidx != IMX8MM_SYS_PLL2_250M)
1800 				break;
1801 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1802 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1803 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1804 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1805 			return 0;
1806 		case IMX8MM_CLK_PCIE1_PHY:
1807 		case IMX8MM_CLK_PCIE2_PHY:
1808 			if (pidx != IMX8MM_SYS_PLL2_100M)
1809 				break;
1810 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1811 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1812 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1813 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1814 			return 0;
1815 		}
1816 	} else if (sc->sc_muxs == imx8mq_muxs) {
1817 		switch (idx) {
1818 		case IMX8MQ_CLK_A53_SRC:
1819 			if (pidx != IMX8MQ_ARM_PLL_OUT &&
1820 			    pidx != IMX8MQ_SYS1_PLL_800M)
1821 				break;
1822 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1823 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1824 			if (pidx == IMX8MQ_ARM_PLL_OUT)
1825 				mux |= (0x1 << sc->sc_muxs[idx].shift);
1826 			if (pidx == IMX8MQ_SYS1_PLL_800M)
1827 				mux |= (0x4 << sc->sc_muxs[idx].shift);
1828 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1829 			return 0;
1830 		case IMX8MQ_CLK_USB_BUS:
1831 			if (pidx != IMX8MQ_SYS2_PLL_500M)
1832 				break;
1833 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1834 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1835 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1836 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1837 			return 0;
1838 		case IMX8MQ_CLK_USB_CORE_REF:
1839 		case IMX8MQ_CLK_USB_PHY_REF:
1840 			if (pidx != IMX8MQ_SYS1_PLL_100M)
1841 				break;
1842 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1843 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1844 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1845 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1846 			return 0;
1847 		case IMX8MQ_CLK_PCIE1_CTRL:
1848 		case IMX8MQ_CLK_PCIE2_CTRL:
1849 			if (pidx != IMX8MQ_SYS2_PLL_250M)
1850 				break;
1851 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1852 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1853 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1854 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1855 			return 0;
1856 		case IMX8MQ_CLK_PCIE1_PHY:
1857 		case IMX8MQ_CLK_PCIE2_PHY:
1858 			if (pidx != IMX8MQ_SYS2_PLL_100M)
1859 				break;
1860 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1861 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1862 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1863 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1864 			return 0;
1865 		}
1866 	}
1867 
1868 	printf("%s: 0x%08x 0x%08x\n", __func__, idx, pidx);
1869 	return -1;
1870 }
1871