xref: /openbsd-src/sys/dev/fdt/imxccm.c (revision c020cf82e0cc147236f01a8dca7052034cf9d30d)
1 /* $OpenBSD: imxccm.c,v 1.21 2020/04/28 19:26:45 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_i2c(struct imxccm_softc *sc, uint32_t);
248 uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t);
249 uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t);
250 uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t);
251 uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t);
252 uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t);
253 uint32_t imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t);
254 uint32_t imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t);
255 uint32_t imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t);
256 uint32_t imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t);
257 int imxccm_imx8m_set_div(struct imxccm_softc *, uint32_t, uint64_t, uint64_t);
258 void imxccm_enable(void *, uint32_t *, int);
259 uint32_t imxccm_get_frequency(void *, uint32_t *);
260 int imxccm_set_frequency(void *, uint32_t *, uint32_t);
261 int imxccm_set_parent(void *, uint32_t *, uint32_t *);
262 
263 int
264 imxccm_match(struct device *parent, void *match, void *aux)
265 {
266 	struct fdt_attach_args *faa = aux;
267 
268 	return (OF_is_compatible(faa->fa_node, "fsl,imx6q-ccm") ||
269 	    OF_is_compatible(faa->fa_node, "fsl,imx6sl-ccm") ||
270 	    OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") ||
271 	    OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") ||
272 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") ||
273 	    OF_is_compatible(faa->fa_node, "fsl,imx8mm-ccm") ||
274 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm"));
275 }
276 
277 void
278 imxccm_attach(struct device *parent, struct device *self, void *aux)
279 {
280 	struct imxccm_softc *sc = (struct imxccm_softc *)self;
281 	struct fdt_attach_args *faa = aux;
282 
283 	KASSERT(faa->fa_nreg >= 1);
284 
285 	sc->sc_node = faa->fa_node;
286 	sc->sc_iot = faa->fa_iot;
287 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
288 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
289 		panic("%s: bus_space_map failed!", __func__);
290 
291 	sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0);
292 
293 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-ccm")) {
294 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mm-anatop");
295 		KASSERT(sc->sc_anatop != NULL);
296 		sc->sc_gates = imx8mm_gates;
297 		sc->sc_ngates = nitems(imx8mm_gates);
298 		sc->sc_divs = imx8mm_divs;
299 		sc->sc_ndivs = nitems(imx8mm_divs);
300 		sc->sc_muxs = imx8mm_muxs;
301 		sc->sc_nmuxs = nitems(imx8mm_muxs);
302 		sc->sc_predivs = imx8mm_predivs;
303 		sc->sc_npredivs = nitems(imx8mm_predivs);
304 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) {
305 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop");
306 		KASSERT(sc->sc_anatop != NULL);
307 		sc->sc_gates = imx8mq_gates;
308 		sc->sc_ngates = nitems(imx8mq_gates);
309 		sc->sc_divs = imx8mq_divs;
310 		sc->sc_ndivs = nitems(imx8mq_divs);
311 		sc->sc_muxs = imx8mq_muxs;
312 		sc->sc_nmuxs = nitems(imx8mq_muxs);
313 		sc->sc_predivs = imx8mq_predivs;
314 		sc->sc_npredivs = nitems(imx8mq_predivs);
315 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx7d-ccm")) {
316 		sc->sc_gates = imx7d_gates;
317 		sc->sc_ngates = nitems(imx7d_gates);
318 		sc->sc_divs = imx7d_divs;
319 		sc->sc_ndivs = nitems(imx7d_divs);
320 		sc->sc_muxs = imx7d_muxs;
321 		sc->sc_nmuxs = nitems(imx7d_muxs);
322 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx6ul-ccm")) {
323 		sc->sc_gates = imx6ul_gates;
324 		sc->sc_ngates = nitems(imx6ul_gates);
325 	} else {
326 		sc->sc_gates = imx6_gates;
327 		sc->sc_ngates = nitems(imx6_gates);
328 	}
329 
330 	printf("\n");
331 
332 	sc->sc_cd.cd_node = faa->fa_node;
333 	sc->sc_cd.cd_cookie = sc;
334 	sc->sc_cd.cd_enable = imxccm_enable;
335 	sc->sc_cd.cd_get_frequency = imxccm_get_frequency;
336 	sc->sc_cd.cd_set_frequency = imxccm_set_frequency;
337 	sc->sc_cd.cd_set_parent = imxccm_set_parent;
338 	clock_register(&sc->sc_cd);
339 }
340 
341 uint32_t
342 imxccm_get_armclk(struct imxccm_softc *sc)
343 {
344 	uint32_t ccsr = HREAD4(sc, CCM_CCSR);
345 
346 	if (!(ccsr & CCM_CCSR_PLL1_SW_CLK_SEL))
347 		return imxanatop_decode_pll(ARM_PLL1, HCLK_FREQ);
348 	else if (ccsr & CCM_CCSR_STEP_SEL)
349 		return imxanatop_get_pll2_pfd(2);
350 	else
351 		return HCLK_FREQ;
352 }
353 
354 void
355 imxccm_armclk_set_parent(struct imxccm_softc *sc, enum imxanatop_clocks clock)
356 {
357 	switch (clock)
358 	{
359 	case ARM_PLL1:
360 		/* jump onto pll1 */
361 		HCLR4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
362 		/* put step clk on OSC, power saving */
363 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
364 		break;
365 	case OSC:
366 		/* put step clk on OSC */
367 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
368 		/* jump onto step clk */
369 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
370 		break;
371 	case SYS_PLL2_PFD2:
372 		/* put step clk on pll2-pfd2 400 MHz */
373 		HSET4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
374 		/* jump onto step clk */
375 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
376 		break;
377 	default:
378 		panic("%s: parent not possible for arm clk", __func__);
379 	}
380 }
381 
382 uint32_t
383 imxccm_get_ecspiclk(struct imxccm_softc *sc)
384 {
385 	uint32_t clkroot = PLL3_60M;
386 	uint32_t podf = HREAD4(sc, CCM_CSCDR2);
387 
388 	podf >>= CCM_CSCDR2_ECSPI_PODF_SHIFT;
389 	podf &= CCM_CSCDR2_ECSPI_PODF_MASK;
390 
391 	return clkroot / (podf + 1);
392 }
393 
394 unsigned int
395 imxccm_get_usdhx(struct imxccm_softc *sc, int x)
396 {
397 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
398 	uint32_t cscdr1 = HREAD4(sc, CCM_CSCDR1);
399 	uint32_t podf, clkroot;
400 
401 	// Odd bitsetting. Damn you.
402 	if (x == 1)
403 		podf = ((cscdr1 >> 11) & CCM_CSCDR1_USDHCx_PODF_MASK);
404 	else
405 		podf = ((cscdr1 >> (10 + 3*x)) & CCM_CSCDR1_USDHCx_PODF_MASK);
406 
407 	if (cscmr1 & (1 << CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)))
408 		clkroot = imxanatop_get_pll2_pfd(0); // 352 MHz
409 	else
410 		clkroot = imxanatop_get_pll2_pfd(2); // 396 MHz
411 
412 	return clkroot / (podf + 1);
413 }
414 
415 uint32_t
416 imxccm_get_uartclk(struct imxccm_softc *sc)
417 {
418 	uint32_t clkroot = PLL3_80M;
419 	uint32_t podf = HREAD4(sc, CCM_CSCDR1) & CCM_CSCDR1_UART_PODF_MASK;
420 
421 	return clkroot / (podf + 1);
422 }
423 
424 uint32_t
425 imxccm_get_periphclk(struct imxccm_softc *sc)
426 {
427 	if ((HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_PERIPH_CLK_SEL_SHIFT)
428 		    & CCM_CBCDR_PERIPH_CLK_SEL_MASK) {
429 		switch((HREAD4(sc, CCM_CBCMR)
430 		    >> CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT) & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) {
431 		case 0:
432 			return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ);
433 		case 1:
434 		case 2:
435 			return HCLK_FREQ;
436 		default:
437 			return 0;
438 		}
439 
440 	} else {
441 		switch((HREAD4(sc, CCM_CBCMR)
442 		    >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) {
443 		default:
444 		case 0:
445 			return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ);
446 		case 1:
447 			return imxanatop_get_pll2_pfd(2); // 396 MHz
448 		case 2:
449 			return imxanatop_get_pll2_pfd(0); // 352 MHz
450 		case 3:
451 			return imxanatop_get_pll2_pfd(2) / 2; // 198 MHz
452 		}
453 	}
454 }
455 
456 uint32_t
457 imxccm_get_ahbclk(struct imxccm_softc *sc)
458 {
459 	uint32_t ahb_podf;
460 
461 	ahb_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_AHB_PODF_SHIFT)
462 	    & CCM_CBCDR_AHB_PODF_MASK;
463 	return imxccm_get_periphclk(sc) / (ahb_podf + 1);
464 }
465 
466 uint32_t
467 imxccm_get_ipgclk(struct imxccm_softc *sc)
468 {
469 	uint32_t ipg_podf;
470 
471 	ipg_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_IPG_PODF_SHIFT)
472 	    & CCM_CBCDR_IPG_PODF_MASK;
473 	return imxccm_get_ahbclk(sc) / (ipg_podf + 1);
474 }
475 
476 uint32_t
477 imxccm_get_ipg_perclk(struct imxccm_softc *sc)
478 {
479 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
480 	uint32_t freq, ipg_podf;
481 
482 	if (sc->sc_gates == imx6ul_gates &&
483 	    cscmr1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK)
484 		freq = HCLK_FREQ;
485 	else
486 		freq = imxccm_get_ipgclk(sc);
487 
488 	ipg_podf = cscmr1 & CCM_CSCMR1_PERCLK_CLK_PODF_MASK;
489 
490 	return freq / (ipg_podf + 1);
491 }
492 
493 void
494 imxccm_imx6_enable_pll_enet(struct imxccm_softc *sc, int on)
495 {
496 	KASSERT(on);
497 
498 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
499 	    CCM_ANALOG_PLL_ENET_POWERDOWN);
500 
501 	/* Wait for the PLL to lock. */
502 	while ((regmap_read_4(sc->sc_anatop,
503 	    CCM_ANALOG_PLL_ENET) & CCM_ANALOG_PLL_ENET_LOCK) == 0)
504 		;
505 
506 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
507 	    CCM_ANALOG_PLL_ENET_BYPASS);
508 }
509 
510 void
511 imxccm_imx6_enable_pll_usb1(struct imxccm_softc *sc, int on)
512 {
513 	KASSERT(on);
514 
515 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
516 	    CCM_ANALOG_PLL_USB1_POWER);
517 
518 	/* Wait for the PLL to lock. */
519 	while ((regmap_read_4(sc->sc_anatop,
520 	    CCM_ANALOG_PLL_USB1) & CCM_ANALOG_PLL_USB1_LOCK) == 0)
521 		;
522 
523 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_CLR,
524 	    CCM_ANALOG_PLL_USB1_BYPASS);
525 }
526 
527 void
528 imxccm_imx6_enable_pll_usb2(struct imxccm_softc *sc, int on)
529 {
530 	KASSERT(on);
531 
532 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
533 	    CCM_ANALOG_PLL_USB2_POWER);
534 
535 	/* Wait for the PLL to lock. */
536 	while ((regmap_read_4(sc->sc_anatop,
537 	    CCM_ANALOG_PLL_USB2) & CCM_ANALOG_PLL_USB2_LOCK) == 0)
538 		;
539 
540 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_CLR,
541 	    CCM_ANALOG_PLL_USB2_BYPASS);
542 }
543 
544 uint32_t
545 imxccm_imx7d_enet(struct imxccm_softc *sc, uint32_t idx)
546 {
547 	uint32_t mux;
548 
549 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
550 		return 0;
551 
552 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
553 	mux >>= sc->sc_muxs[idx].shift;
554 	mux &= sc->sc_muxs[idx].mask;
555 
556 	switch (mux) {
557 	case 0:
558 		return clock_get_frequency(sc->sc_node, "osc");
559 	case 7:
560 		return 392000000; /* pll_sys_pfd4_clk XXX not fixed */
561 	default:
562 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
563 		return 0;
564 	}
565 }
566 
567 uint32_t
568 imxccm_imx7d_i2c(struct imxccm_softc *sc, uint32_t idx)
569 {
570 	uint32_t mux;
571 
572 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
573 		return 0;
574 
575 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
576 	mux >>= sc->sc_muxs[idx].shift;
577 	mux &= sc->sc_muxs[idx].mask;
578 
579 	switch (mux) {
580 	case 0:
581 		return clock_get_frequency(sc->sc_node, "osc");
582 	case 1:
583 		return 120000000; /* pll_sys_main_120m_clk */
584 	default:
585 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
586 		return 0;
587 	}
588 }
589 
590 uint32_t
591 imxccm_imx7d_uart(struct imxccm_softc *sc, uint32_t idx)
592 {
593 	uint32_t mux;
594 
595 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
596 		return 0;
597 
598 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
599 	mux >>= sc->sc_muxs[idx].shift;
600 	mux &= sc->sc_muxs[idx].mask;
601 
602 	switch (mux) {
603 	case 0:
604 		return clock_get_frequency(sc->sc_node, "osc");
605 	default:
606 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
607 		return 0;
608 	}
609 }
610 
611 uint32_t
612 imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx)
613 {
614 	uint32_t mux;
615 
616 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
617 		return 0;
618 
619 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
620 	mux >>= sc->sc_muxs[idx].shift;
621 	mux &= sc->sc_muxs[idx].mask;
622 
623 	switch (mux) {
624 	case 0:
625 		return clock_get_frequency(sc->sc_node, "osc");
626 	case 1:
627 		return 392000000; /* pll_sys_pfd0_392m_clk */
628 	default:
629 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
630 		return 0;
631 	}
632 }
633 
634 uint32_t
635 imxccm_imx8mm_get_pll(struct imxccm_softc *sc, uint32_t idx)
636 {
637 	uint64_t main_div, pre_div, post_div, div;
638 	uint32_t pll0, pll1;
639 	uint64_t freq;
640 
641 	switch (idx) {
642 	case IMX8MM_ARM_PLL:
643 		pll0 = regmap_read_4(sc->sc_anatop,
644 		    CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL);
645 		pll1 = regmap_read_4(sc->sc_anatop,
646 		    CCM_14XX_IMX8M_ARM_PLL_DIV_CTL);
647 		div = 1;
648 		break;
649 	default:
650 		printf("%s: 0x%08x\n", __func__, idx);
651 		return 0;
652 	}
653 
654 	freq = clock_get_frequency(sc->sc_node, "osc_24m");
655 	if (pll0 & CCM_INT_PLL_BYPASS)
656 		return freq;
657 
658 	main_div = (pll1 >> CCM_INT_PLL_MAIN_DIV_SHIFT) &
659 	    CCM_INT_PLL_MAIN_DIV_MASK;
660 	pre_div = (pll1 >> CCM_INT_PLL_PRE_DIV_SHIFT) &
661 	    CCM_INT_PLL_PRE_DIV_MASK;
662 	post_div = (pll1 >> CCM_INT_PLL_POST_DIV_SHIFT) &
663 	    CCM_INT_PLL_POST_DIV_MASK;
664 
665 	freq = freq * main_div;
666 	freq = freq / (pre_div * (1 << post_div) * div);
667 	return freq;
668 }
669 
670 int
671 imxccm_imx8mm_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
672 {
673 	uint64_t main_div, pre_div, post_div;
674 	uint32_t pll0, pll1, reg;
675 	int i;
676 
677 	switch (idx) {
678 	case IMX8MM_ARM_PLL:
679 		pre_div = 3;
680 		switch (freq) {
681 		case 1800000000U:
682 			main_div = 225;
683 			post_div = 0;
684 			break;
685 		case 1600000000U:
686 			main_div = 200;
687 			post_div = 0;
688 			break;
689 		case 1200000000U:
690 			main_div = 300;
691 			post_div = 1;
692 			break;
693 		case 1000000000U:
694 			main_div = 250;
695 			post_div = 1;
696 			break;
697 		case 800000000U:
698 			main_div = 200;
699 			post_div = 1;
700 			break;
701 		case 750000000U:
702 			main_div = 250;
703 			post_div = 2;
704 			break;
705 		case 700000000U:
706 			main_div = 350;
707 			post_div = 2;
708 			break;
709 		case 600000000U:
710 			main_div = 300;
711 			post_div = 2;
712 			break;
713 		default:
714 			printf("%s: 0x%08x\n", __func__, idx);
715 			return -1;
716 		}
717 		pll0 = CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL;
718 		pll1 = CCM_14XX_IMX8M_ARM_PLL_DIV_CTL;
719 		break;
720 	default:
721 		printf("%s: 0x%08x\n", __func__, idx);
722 		return -1;
723 	}
724 
725 	regmap_write_4(sc->sc_anatop, pll0,
726 	    regmap_read_4(sc->sc_anatop, pll0) |
727 	    CCM_INT_PLL_LOCK_SEL);
728 	regmap_write_4(sc->sc_anatop, pll0,
729 	    regmap_read_4(sc->sc_anatop, pll0) &
730 	    ~CCM_INT_PLL_RST);
731 	regmap_write_4(sc->sc_anatop, pll1,
732 	    main_div << CCM_INT_PLL_MAIN_DIV_SHIFT |
733 	    pre_div << CCM_INT_PLL_PRE_DIV_SHIFT |
734 	    post_div << CCM_INT_PLL_POST_DIV_SHIFT);
735 	delay(3);
736 	regmap_write_4(sc->sc_anatop, pll0,
737 	    regmap_read_4(sc->sc_anatop, pll0) |
738 	    CCM_INT_PLL_RST);
739 	for (i = 0; i < 5000; i++) {
740 		reg = regmap_read_4(sc->sc_anatop, pll0);
741 		if (reg & CCM_INT_PLL_LOCK)
742 			break;
743 		delay(10);
744 	}
745 	if (i == 5000)
746 		printf("%s: timeout\n", __func__);
747 	regmap_write_4(sc->sc_anatop, pll0,
748 	    regmap_read_4(sc->sc_anatop, pll0) &
749 	    ~CCM_INT_PLL_BYPASS);
750 
751 	return 0;
752 }
753 
754 uint32_t
755 imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t idx)
756 {
757 	uint32_t mux;
758 
759 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
760 		return 0;
761 
762 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
763 	mux >>= sc->sc_muxs[idx].shift;
764 	mux &= sc->sc_muxs[idx].mask;
765 
766 	switch (mux) {
767 	case 0:
768 		return clock_get_frequency(sc->sc_node, "osc_24m");
769 	case 1:
770 		return 266 * 1000 * 1000; /* sys1_pll_266m */
771 	default:
772 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
773 		return 0;
774 	}
775 }
776 
777 uint32_t
778 imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t idx)
779 {
780 	uint32_t mux;
781 
782 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
783 		return 0;
784 
785 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
786 	mux >>= sc->sc_muxs[idx].shift;
787 	mux &= sc->sc_muxs[idx].mask;
788 
789 	switch (mux) {
790 	case 0:
791 		return clock_get_frequency(sc->sc_node, "osc_24m");
792 	default:
793 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
794 		return 0;
795 	}
796 }
797 
798 uint32_t
799 imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t idx)
800 {
801 	uint32_t mux;
802 
803 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
804 		return 0;
805 
806 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
807 	mux >>= sc->sc_muxs[idx].shift;
808 	mux &= sc->sc_muxs[idx].mask;
809 
810 	switch (mux) {
811 	case 0:
812 		return clock_get_frequency(sc->sc_node, "osc_24m");
813 	default:
814 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
815 		return 0;
816 	}
817 }
818 
819 uint32_t
820 imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx)
821 {
822 	uint32_t mux;
823 
824 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
825 		return 0;
826 
827 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
828 	mux >>= sc->sc_muxs[idx].shift;
829 	mux &= sc->sc_muxs[idx].mask;
830 
831 	switch (mux) {
832 	case 0:
833 		return clock_get_frequency(sc->sc_node, "osc_24m");
834 	case 1:
835 		return 400 * 1000 * 1000; /* sys1_pll_400m */
836 	default:
837 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
838 		return 0;
839 	}
840 }
841 
842 uint32_t
843 imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx)
844 {
845 	uint32_t mux;
846 
847 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
848 		return 0;
849 
850 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
851 	mux >>= sc->sc_muxs[idx].shift;
852 	mux &= sc->sc_muxs[idx].mask;
853 
854 	switch (mux) {
855 	case 0:
856 		return clock_get_frequency(sc->sc_node, "osc_25m");
857 	case 1:
858 		return 200 * 1000 * 1000; /* sys2_pll_200m */
859 	default:
860 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
861 		return 0;
862 	}
863 }
864 
865 uint32_t
866 imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t idx)
867 {
868 	uint32_t mux;
869 
870 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
871 		return 0;
872 
873 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
874 	mux >>= sc->sc_muxs[idx].shift;
875 	mux &= sc->sc_muxs[idx].mask;
876 
877 	switch (mux) {
878 	case 0:
879 		return clock_get_frequency(sc->sc_node, "osc_25m");
880 	case 1:
881 		return 266 * 1000 * 1000; /* sys1_pll_266m */
882 	default:
883 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
884 		return 0;
885 	}
886 }
887 
888 uint32_t
889 imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t idx)
890 {
891 	uint32_t mux;
892 
893 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
894 		return 0;
895 
896 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
897 	mux >>= sc->sc_muxs[idx].shift;
898 	mux &= sc->sc_muxs[idx].mask;
899 
900 	switch (mux) {
901 	case 0:
902 		return clock_get_frequency(sc->sc_node, "osc_25m");
903 	default:
904 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
905 		return 0;
906 	}
907 }
908 
909 uint32_t
910 imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t idx)
911 {
912 	uint32_t mux;
913 
914 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
915 		return 0;
916 
917 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
918 	mux >>= sc->sc_muxs[idx].shift;
919 	mux &= sc->sc_muxs[idx].mask;
920 
921 	switch (mux) {
922 	case 0:
923 		return clock_get_frequency(sc->sc_node, "osc_25m");
924 	case 1:
925 		return 100 * 1000 * 1000; /* sys1_pll_100m */
926 	case 2:
927 		return 160 * 1000 * 1000; /* sys1_pll_160m */
928 	case 3:
929 		return 40 * 1000 * 1000; /* sys1_pll_40m */
930 	default:
931 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
932 		return 0;
933 	}
934 }
935 
936 uint32_t
937 imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t idx)
938 {
939 	uint32_t mux;
940 
941 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
942 		return 0;
943 
944 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
945 	mux >>= sc->sc_muxs[idx].shift;
946 	mux &= sc->sc_muxs[idx].mask;
947 
948 	switch (mux) {
949 	case 0:
950 		return clock_get_frequency(sc->sc_node, "osc_25m");
951 	default:
952 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
953 		return 0;
954 	}
955 }
956 
957 uint32_t
958 imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t idx)
959 {
960 	uint32_t mux;
961 
962 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
963 		return 0;
964 
965 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
966 	mux >>= sc->sc_muxs[idx].shift;
967 	mux &= sc->sc_muxs[idx].mask;
968 
969 	switch (mux) {
970 	case 0:
971 		return clock_get_frequency(sc->sc_node, "osc_25m");
972 	case 1:
973 		return 400 * 1000 * 1000; /* sys1_pll_400m */
974 	default:
975 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
976 		return 0;
977 	}
978 }
979 
980 uint32_t
981 imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t idx)
982 {
983 	uint32_t mux;
984 
985 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
986 		return 0;
987 
988 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
989 	mux >>= sc->sc_muxs[idx].shift;
990 	mux &= sc->sc_muxs[idx].mask;
991 
992 	switch (mux) {
993 	case 0:
994 		return clock_get_frequency(sc->sc_node, "osc_25m");
995 	case 1:
996 		if (idx == IMX8MQ_CLK_USB_CORE_REF ||
997 		    idx == IMX8MQ_CLK_USB_PHY_REF)
998 			return 100 * 1000 * 1000; /* sys1_pll_100m */
999 		if (idx == IMX8MQ_CLK_USB_BUS)
1000 			return 500 * 1000 * 1000; /* sys2_pll_500m */
1001 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1002 		return 0;
1003 	default:
1004 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1005 		return 0;
1006 	}
1007 }
1008 
1009 uint32_t
1010 imxccm_imx8mq_get_pll(struct imxccm_softc *sc, uint32_t idx)
1011 {
1012 	uint32_t divr_val, divq_val, divf_val;
1013 	uint32_t divff, divfi;
1014 	uint32_t pllout_div;
1015 	uint32_t pll0, pll1;
1016 	uint32_t freq;
1017 	uint32_t mux;
1018 
1019 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1020 
1021 	switch (idx) {
1022 	case IMX8MQ_ARM_PLL:
1023 		pll0 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL0);
1024 		pll1 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL1);
1025 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1026 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1027 		break;
1028 	default:
1029 		printf("%s: 0x%08x\n", __func__, idx);
1030 		return 0;
1031 	}
1032 
1033 	if (pll0 & CCM_FRAC_PLL_POWERDOWN)
1034 		return 0;
1035 
1036 	if ((pll0 & CCM_FRAC_PLL_ENABLE) == 0)
1037 		return 0;
1038 
1039 	mux = (pll0 >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1040 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1041 	switch (mux) {
1042 	case 0:
1043 		freq = clock_get_frequency(sc->sc_node, "osc_25m");
1044 		break;
1045 	case 1:
1046 	case 2:
1047 		freq = clock_get_frequency(sc->sc_node, "osc_27m");
1048 		break;
1049 	default:
1050 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1051 		return 0;
1052 	}
1053 
1054 	if (pll0 & CCM_FRAC_PLL_BYPASS)
1055 		return freq;
1056 
1057 	divr_val = (pll0 >> CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT) &
1058 	    CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK;
1059 	divq_val = pll0 & CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1060 	divff = (pll1 >> CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT) &
1061 	    CCM_FRAC_PLL_FRAC_DIV_CTL_MASK;
1062 	divfi = pll1 & CCM_FRAC_PLL_INT_DIV_CTL_MASK;
1063 	divf_val = 1 + divfi + divff / CCM_FRAC_PLL_DENOM;
1064 
1065 	freq = freq / (divr_val + 1) * 8 * divf_val / ((divq_val + 1) * 2);
1066 	return freq / (pllout_div + 1);
1067 }
1068 
1069 int
1070 imxccm_imx8mq_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
1071 {
1072 	uint64_t divff, divfi, divr;
1073 	uint32_t pllout_div;
1074 	uint32_t pll0, pll1;
1075 	uint32_t mux, reg;
1076 	uint64_t pfreq;
1077 	int i;
1078 
1079 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1080 
1081 	switch (idx) {
1082 	case IMX8MQ_ARM_PLL:
1083 		pll0 = CCM_FRAC_IMX8M_ARM_PLL0;
1084 		pll1 = CCM_FRAC_IMX8M_ARM_PLL1;
1085 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1086 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1087 		/* XXX: Assume fixed divider to ease math. */
1088 		KASSERT(pllout_div == 0);
1089 		divr = 5;
1090 		break;
1091 	default:
1092 		printf("%s: 0x%08x\n", __func__, idx);
1093 		return -1;
1094 	}
1095 
1096 	reg = regmap_read_4(sc->sc_anatop, pll0);
1097 	mux = (reg >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1098 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1099 	switch (mux) {
1100 	case 0:
1101 		pfreq = clock_get_frequency(sc->sc_node, "osc_25m");
1102 		break;
1103 	case 1:
1104 	case 2:
1105 		pfreq = clock_get_frequency(sc->sc_node, "osc_27m");
1106 		break;
1107 	default:
1108 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1109 		return -1;
1110 	}
1111 
1112 	/* Frac divider follows the PLL */
1113 	freq *= divr;
1114 
1115 	/* PLL calculation */
1116 	freq *= 2;
1117 	pfreq *= 8;
1118 	divfi = freq / pfreq;
1119 	divff = (uint64_t)(freq - divfi * pfreq);
1120 	divff = (divff * CCM_FRAC_PLL_DENOM) / pfreq;
1121 
1122 	reg = regmap_read_4(sc->sc_anatop, pll1);
1123 	reg &= ~(CCM_FRAC_PLL_FRAC_DIV_CTL_MASK << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT);
1124 	reg |= divff << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT;
1125 	reg &= ~(CCM_FRAC_PLL_INT_DIV_CTL_MASK << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT);
1126 	reg |= (divfi - 1) << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT;
1127 	regmap_write_4(sc->sc_anatop, pll1, reg);
1128 
1129 	reg = regmap_read_4(sc->sc_anatop, pll0);
1130 	reg &= ~CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1131 	reg &= ~(CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT);
1132 	reg |= (divr - 1) << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT;
1133 	regmap_write_4(sc->sc_anatop, pll0, reg);
1134 
1135 	reg = regmap_read_4(sc->sc_anatop, pll0);
1136 	reg |= CCM_FRAC_PLL_NEWDIV_VAL;
1137 	regmap_write_4(sc->sc_anatop, pll0, reg);
1138 
1139 	for (i = 0; i < 5000; i++) {
1140 		reg = regmap_read_4(sc->sc_anatop, pll0);
1141 		if (reg & CCM_FRAC_PLL_BYPASS)
1142 			break;
1143 		if (reg & CCM_FRAC_PLL_POWERDOWN)
1144 			break;
1145 		if (reg & CCM_FRAC_PLL_NEWDIV_ACK)
1146 			break;
1147 		delay(10);
1148 	}
1149 	if (i == 5000)
1150 		printf("%s: timeout\n", __func__);
1151 
1152 	reg = regmap_read_4(sc->sc_anatop, pll0);
1153 	reg &= ~CCM_FRAC_PLL_NEWDIV_VAL;
1154 	regmap_write_4(sc->sc_anatop, pll0, reg);
1155 
1156 	return 0;
1157 }
1158 
1159 int
1160 imxccm_imx8m_set_div(struct imxccm_softc *sc, uint32_t idx, uint64_t freq,
1161     uint64_t parent_freq)
1162 {
1163 	uint64_t div;
1164 	uint32_t reg;
1165 
1166 	if (parent_freq < freq) {
1167 		printf("%s: parent frequency too low (0x%08x)\n",
1168 		    __func__, idx);
1169 		return -1;
1170 	}
1171 
1172 	/* divisor can only be changed if enabled */
1173 	imxccm_enable(sc, &idx, 1);
1174 
1175 	div = 0;
1176 	while (parent_freq / (div + 1) > freq)
1177 		div++;
1178 	reg = HREAD4(sc, sc->sc_divs[idx].reg);
1179 	reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
1180 	reg |= (div << sc->sc_divs[idx].shift);
1181 	HWRITE4(sc, sc->sc_divs[idx].reg, reg);
1182 	HCLR4(sc, sc->sc_predivs[idx].reg,
1183 	    sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift);
1184 	return 0;
1185 }
1186 
1187 void
1188 imxccm_enable_parent(struct imxccm_softc *sc, uint32_t parent, int on)
1189 {
1190 	if (on)
1191 		imxccm_enable(sc, &parent, on);
1192 }
1193 
1194 void
1195 imxccm_enable(void *cookie, uint32_t *cells, int on)
1196 {
1197 	struct imxccm_softc *sc = cookie;
1198 	uint32_t idx = cells[0], parent;
1199 	uint32_t pcells[2];
1200 	uint16_t reg;
1201 	uint8_t pos;
1202 
1203 	/* Dummy clock. */
1204 	if (idx == 0)
1205 		return;
1206 
1207 	if (sc->sc_gates == imx8mm_gates) {
1208 		switch (idx) {
1209 		case IMX8MM_CLK_PCIE1_CTRL:
1210 		case IMX8MM_CLK_PCIE2_CTRL:
1211 			pcells[0] = sc->sc_phandle;
1212 			pcells[1] = IMX8MM_SYS_PLL2_250M;
1213 			imxccm_set_parent(cookie, &idx, pcells);
1214 			break;
1215 		case IMX8MM_CLK_PCIE1_PHY:
1216 		case IMX8MM_CLK_PCIE2_PHY:
1217 			pcells[0] = sc->sc_phandle;
1218 			pcells[1] = IMX8MM_SYS_PLL2_100M;
1219 			imxccm_set_parent(cookie, &idx, pcells);
1220 			break;
1221 		}
1222 	} else if (sc->sc_gates == imx8mq_gates) {
1223 		switch (idx) {
1224 		case IMX8MQ_CLK_32K:
1225 			/* always on */
1226 			return;
1227 		case IMX8MQ_CLK_PCIE1_CTRL:
1228 		case IMX8MQ_CLK_PCIE2_CTRL:
1229 			pcells[0] = sc->sc_phandle;
1230 			pcells[1] = IMX8MQ_SYS2_PLL_250M;
1231 			imxccm_set_parent(cookie, &idx, pcells);
1232 			break;
1233 		case IMX8MQ_CLK_PCIE1_PHY:
1234 		case IMX8MQ_CLK_PCIE2_PHY:
1235 			pcells[0] = sc->sc_phandle;
1236 			pcells[1] = IMX8MQ_SYS2_PLL_100M;
1237 			imxccm_set_parent(cookie, &idx, pcells);
1238 			break;
1239 		}
1240 	} else if (sc->sc_gates == imx7d_gates) {
1241 		if (sc->sc_anatop == NULL) {
1242 			sc->sc_anatop = regmap_bycompatible("fsl,imx7d-anatop");
1243 			KASSERT(sc->sc_anatop);
1244 		}
1245 
1246 		switch (idx) {
1247 		case IMX7D_PLL_ENET_MAIN_125M_CLK:
1248 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_SET,
1249 			    CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ);
1250 			return;
1251 		default:
1252 			break;
1253 		}
1254 	} else if (sc->sc_gates == imx6_gates) {
1255 		if (sc->sc_anatop == NULL) {
1256 			sc->sc_anatop = regmap_bycompatible("fsl,imx6q-anatop");
1257 			KASSERT(sc->sc_anatop);
1258 		}
1259 
1260 		switch (idx) {
1261 		case IMX6_CLK_PLL3:
1262 			imxccm_imx6_enable_pll_usb1(sc, on);
1263 			return;
1264 		case IMX6_CLK_PLL6:
1265 			imxccm_imx6_enable_pll_enet(sc, on);
1266 			return;
1267 		case IMX6_CLK_PLL7:
1268 			imxccm_imx6_enable_pll_usb2(sc, on);
1269 			return;
1270 		case IMX6_CLK_PLL3_USB_OTG:
1271 			imxccm_enable_parent(sc, IMX6_CLK_PLL3, on);
1272 			regmap_write_4(sc->sc_anatop,
1273 			    on ? CCM_ANALOG_PLL_USB1_SET : CCM_ANALOG_PLL_USB1_CLR,
1274 			    CCM_ANALOG_PLL_USB1_ENABLE);
1275 			return;
1276 		case IMX6_CLK_PLL6_ENET:
1277 			imxccm_enable_parent(sc, IMX6_CLK_PLL6, on);
1278 			regmap_write_4(sc->sc_anatop,
1279 			    on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
1280 			    CCM_ANALOG_PLL_ENET_ENABLE);
1281 			return;
1282 		case IMX6_CLK_PLL7_USB_HOST:
1283 			imxccm_enable_parent(sc, IMX6_CLK_PLL7, on);
1284 			regmap_write_4(sc->sc_anatop,
1285 			    on ? CCM_ANALOG_PLL_USB2_SET : CCM_ANALOG_PLL_USB2_CLR,
1286 			    CCM_ANALOG_PLL_USB2_ENABLE);
1287 			return;
1288 		case IMX6_CLK_USBPHY1:
1289 			/* PLL outputs should alwas be on. */
1290 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
1291 			    CCM_ANALOG_PLL_USB1_EN_USB_CLKS);
1292 			imxccm_enable_parent(sc, IMX6_CLK_PLL3_USB_OTG, on);
1293 			return;
1294 		case IMX6_CLK_USBPHY2:
1295 			/* PLL outputs should alwas be on. */
1296 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
1297 			    CCM_ANALOG_PLL_USB2_EN_USB_CLKS);
1298 			imxccm_enable_parent(sc, IMX6_CLK_PLL7_USB_HOST, on);
1299 			return;
1300 		case IMX6_CLK_SATA_REF_100:
1301 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
1302 			regmap_write_4(sc->sc_anatop,
1303 			   on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
1304 			   CCM_ANALOG_PLL_ENET_ENABLE_100M);
1305 			return;
1306 		case IMX6_CLK_ENET_REF:
1307 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
1308 			return;
1309 		case IMX6_CLK_IPG:
1310 		case IMX6_CLK_IPG_PER:
1311 		case IMX6_CLK_ECSPI_ROOT:
1312 			/* always on */
1313 			return;
1314 		default:
1315 			break;
1316 		}
1317 	}
1318 
1319 	if (on) {
1320 		if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
1321 			parent = sc->sc_gates[idx].parent;
1322 			imxccm_enable(sc, &parent, on);
1323 		}
1324 
1325 		if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1326 			parent = sc->sc_divs[idx].parent;
1327 			imxccm_enable(sc, &parent, on);
1328 		}
1329 	}
1330 
1331 	if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
1332 		if ((idx < sc->sc_ndivs && sc->sc_divs[idx].reg != 0) ||
1333 		    (idx < sc->sc_nmuxs && sc->sc_muxs[idx].reg != 0))
1334 			return;
1335 		printf("%s: 0x%08x\n", __func__, idx);
1336 		return;
1337 	}
1338 
1339 	reg = sc->sc_gates[idx].reg;
1340 	pos = sc->sc_gates[idx].pos;
1341 
1342 	if (on)
1343 		HSET4(sc, reg, 0x3 << (2 * pos));
1344 	else
1345 		HCLR4(sc, reg, 0x3 << (2 * pos));
1346 }
1347 
1348 uint32_t
1349 imxccm_get_frequency(void *cookie, uint32_t *cells)
1350 {
1351 	struct imxccm_softc *sc = cookie;
1352 	uint32_t idx = cells[0];
1353 	uint32_t div, pre, reg, parent;
1354 	uint32_t freq;
1355 
1356 	/* Dummy clock. */
1357 	if (idx == 0)
1358 		return 0;
1359 
1360 	if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
1361 		parent = sc->sc_gates[idx].parent;
1362 		return imxccm_get_frequency(sc, &parent);
1363 	}
1364 
1365 	if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1366 		div = HREAD4(sc, sc->sc_divs[idx].reg);
1367 		div = div >> sc->sc_divs[idx].shift;
1368 		div = div & sc->sc_divs[idx].mask;
1369 		parent = sc->sc_divs[idx].parent;
1370 		return imxccm_get_frequency(sc, &parent) / (div + 1);
1371 	}
1372 
1373 	if (sc->sc_gates == imx8mm_gates) {
1374 		switch (idx) {
1375 		case IMX8MM_CLK_ARM:
1376 			parent = IMX8MM_ARM_PLL;
1377 			return imxccm_get_frequency(sc, &parent);
1378 		case IMX8MM_ARM_PLL:
1379 			return imxccm_imx8mm_get_pll(sc, idx);
1380 		}
1381 
1382 		/* These are composite clocks. */
1383 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1384 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1385 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1386 			switch (idx) {
1387 			case IMX8MM_CLK_ENET_AXI:
1388 				freq = imxccm_imx8mm_enet(sc, idx);
1389 				break;
1390 			case IMX8MM_CLK_I2C1:
1391 			case IMX8MM_CLK_I2C2:
1392 			case IMX8MM_CLK_I2C3:
1393 			case IMX8MM_CLK_I2C4:
1394 				freq = imxccm_imx8mm_i2c(sc, idx);
1395 				break;
1396 			case IMX8MM_CLK_UART1:
1397 			case IMX8MM_CLK_UART2:
1398 			case IMX8MM_CLK_UART3:
1399 			case IMX8MM_CLK_UART4:
1400 				freq = imxccm_imx8mm_uart(sc, idx);
1401 				break;
1402 			case IMX8MM_CLK_USDHC1:
1403 			case IMX8MM_CLK_USDHC2:
1404 			case IMX8MM_CLK_USDHC3:
1405 				freq = imxccm_imx8mm_usdhc(sc, idx);
1406 				break;
1407 			default:
1408 				printf("%s: 0x%08x\n", __func__, idx);
1409 				return 0;
1410 			}
1411 
1412 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1413 			div = reg >> sc->sc_divs[idx].shift;
1414 			div = div & sc->sc_divs[idx].mask;
1415 			pre = reg >> sc->sc_predivs[idx].shift;
1416 			pre = pre & sc->sc_predivs[idx].mask;
1417 			return ((freq / (pre + 1)) / (div + 1));
1418 		}
1419 	} else if (sc->sc_gates == imx8mq_gates) {
1420 		switch (idx) {
1421 		case IMX8MQ_CLK_ARM:
1422 			parent = IMX8MQ_ARM_PLL;
1423 			return imxccm_get_frequency(sc, &parent);
1424 		case IMX8MQ_ARM_PLL:
1425 			return imxccm_imx8mq_get_pll(sc, idx);
1426 		}
1427 
1428 		/* These are composite clocks. */
1429 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1430 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1431 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1432 			switch (idx) {
1433 			case IMX8MQ_CLK_ENET_AXI:
1434 				freq = imxccm_imx8mq_enet(sc, idx);
1435 				break;
1436 			case IMX8MQ_CLK_I2C1:
1437 			case IMX8MQ_CLK_I2C2:
1438 			case IMX8MQ_CLK_I2C3:
1439 			case IMX8MQ_CLK_I2C4:
1440 				freq = imxccm_imx8mq_i2c(sc, idx);
1441 				break;
1442 			case IMX8MQ_CLK_UART1:
1443 			case IMX8MQ_CLK_UART2:
1444 			case IMX8MQ_CLK_UART3:
1445 			case IMX8MQ_CLK_UART4:
1446 				freq = imxccm_imx8mq_uart(sc, idx);
1447 				break;
1448 			case IMX8MQ_CLK_USDHC1:
1449 			case IMX8MQ_CLK_USDHC2:
1450 				freq = imxccm_imx8mq_usdhc(sc, idx);
1451 				break;
1452 			case IMX8MQ_CLK_USB_BUS:
1453 			case IMX8MQ_CLK_USB_CORE_REF:
1454 			case IMX8MQ_CLK_USB_PHY_REF:
1455 				freq = imxccm_imx8mq_usb(sc, idx);
1456 				break;
1457 			case IMX8MQ_CLK_ECSPI1:
1458 			case IMX8MQ_CLK_ECSPI2:
1459 			case IMX8MQ_CLK_ECSPI3:
1460 				freq = imxccm_imx8mq_ecspi(sc, idx);
1461 				break;
1462 			case IMX8MQ_CLK_PWM1:
1463 			case IMX8MQ_CLK_PWM2:
1464 			case IMX8MQ_CLK_PWM3:
1465 			case IMX8MQ_CLK_PWM4:
1466 				freq = imxccm_imx8mq_pwm(sc, idx);
1467 				break;
1468 			default:
1469 				printf("%s: 0x%08x\n", __func__, idx);
1470 				return 0;
1471 			}
1472 
1473 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1474 			div = reg >> sc->sc_divs[idx].shift;
1475 			div = div & sc->sc_divs[idx].mask;
1476 			pre = reg >> sc->sc_predivs[idx].shift;
1477 			pre = pre & sc->sc_predivs[idx].mask;
1478 			return ((freq / (pre + 1)) / (div + 1));
1479 		}
1480 
1481 	} else if (sc->sc_gates == imx7d_gates) {
1482 		switch (idx) {
1483 		case IMX7D_ENET_AXI_ROOT_SRC:
1484 			return imxccm_imx7d_enet(sc, idx);
1485 		case IMX7D_I2C1_ROOT_SRC:
1486 		case IMX7D_I2C2_ROOT_SRC:
1487 		case IMX7D_I2C3_ROOT_SRC:
1488 		case IMX7D_I2C4_ROOT_SRC:
1489 			return imxccm_imx7d_i2c(sc, idx);
1490 		case IMX7D_UART1_ROOT_SRC:
1491 		case IMX7D_UART2_ROOT_SRC:
1492 		case IMX7D_UART3_ROOT_SRC:
1493 		case IMX7D_UART4_ROOT_SRC:
1494 		case IMX7D_UART5_ROOT_SRC:
1495 		case IMX7D_UART6_ROOT_SRC:
1496 		case IMX7D_UART7_ROOT_SRC:
1497 			return imxccm_imx7d_uart(sc, idx);
1498 		case IMX7D_USDHC1_ROOT_SRC:
1499 		case IMX7D_USDHC2_ROOT_SRC:
1500 		case IMX7D_USDHC3_ROOT_SRC:
1501 			return imxccm_imx7d_usdhc(sc, idx);
1502 		}
1503 	} else if (sc->sc_gates == imx6ul_gates) {
1504 		switch (idx) {
1505 		case IMX6UL_CLK_ARM:
1506 			return imxccm_get_armclk(sc);
1507 		case IMX6UL_CLK_IPG:
1508 			return imxccm_get_ipgclk(sc);
1509 		case IMX6UL_CLK_PERCLK:
1510 			return imxccm_get_ipg_perclk(sc);
1511 		case IMX6UL_CLK_UART1_SERIAL:
1512 			return imxccm_get_uartclk(sc);
1513 		case IMX6UL_CLK_USDHC1:
1514 		case IMX6UL_CLK_USDHC2:
1515 			return imxccm_get_usdhx(sc, idx - IMX6UL_CLK_USDHC1 + 1);
1516 		}
1517 	} else if (sc->sc_gates == imx6_gates) {
1518 		switch (idx) {
1519 		case IMX6_CLK_AHB:
1520 			return imxccm_get_ahbclk(sc);
1521 		case IMX6_CLK_ARM:
1522 			return imxccm_get_armclk(sc);
1523 		case IMX6_CLK_IPG:
1524 			return imxccm_get_ipgclk(sc);
1525 		case IMX6_CLK_IPG_PER:
1526 			return imxccm_get_ipg_perclk(sc);
1527 		case IMX6_CLK_ECSPI_ROOT:
1528 			return imxccm_get_ecspiclk(sc);
1529 		case IMX6_CLK_UART_SERIAL:
1530 			return imxccm_get_uartclk(sc);
1531 		case IMX6_CLK_USDHC1:
1532 		case IMX6_CLK_USDHC2:
1533 		case IMX6_CLK_USDHC3:
1534 		case IMX6_CLK_USDHC4:
1535 			return imxccm_get_usdhx(sc, idx - IMX6_CLK_USDHC1 + 1);
1536 		}
1537 	}
1538 
1539 	printf("%s: 0x%08x\n", __func__, idx);
1540 	return 0;
1541 }
1542 
1543 int
1544 imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1545 {
1546 	struct imxccm_softc *sc = cookie;
1547 	uint32_t idx = cells[0];
1548 	uint32_t reg, div, parent, parent_freq;
1549 	uint32_t pcells[2];
1550 	int ret;
1551 
1552 	if (sc->sc_divs == imx8mm_divs) {
1553 		switch (idx) {
1554 		case IMX8MM_CLK_ARM:
1555 			parent = IMX8MM_CLK_A53_SRC;
1556 			return imxccm_set_frequency(cookie, &parent, freq);
1557 		case IMX8MM_CLK_A53_SRC:
1558 			pcells[0] = sc->sc_phandle;
1559 			pcells[1] = IMX8MM_SYS_PLL1_800M;
1560 			ret = imxccm_set_parent(cookie, &idx, pcells);
1561 			if (ret)
1562 				return ret;
1563 			ret = imxccm_imx8mm_set_pll(sc, IMX8MM_ARM_PLL, freq);
1564 			pcells[0] = sc->sc_phandle;
1565 			pcells[1] = IMX8MM_ARM_PLL_OUT;
1566 			imxccm_set_parent(cookie, &idx, pcells);
1567 			return ret;
1568 		case IMX8MM_CLK_USDHC1_ROOT:
1569 		case IMX8MM_CLK_USDHC2_ROOT:
1570 		case IMX8MM_CLK_USDHC3_ROOT:
1571 			parent = sc->sc_gates[idx].parent;
1572 			return imxccm_set_frequency(sc, &parent, freq);
1573 		case IMX8MM_CLK_USDHC1:
1574 		case IMX8MM_CLK_USDHC2:
1575 		case IMX8MM_CLK_USDHC3:
1576 			parent_freq = imxccm_imx8mm_usdhc(sc, idx);
1577 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1578 		}
1579 	} else if (sc->sc_divs == imx8mq_divs) {
1580 		switch (idx) {
1581 		case IMX8MQ_CLK_ARM:
1582 			parent = IMX8MQ_CLK_A53_SRC;
1583 			return imxccm_set_frequency(cookie, &parent, freq);
1584 		case IMX8MQ_CLK_A53_SRC:
1585 			pcells[0] = sc->sc_phandle;
1586 			pcells[1] = IMX8MQ_SYS1_PLL_800M;
1587 			ret = imxccm_set_parent(cookie, &idx, pcells);
1588 			if (ret)
1589 				return ret;
1590 			ret = imxccm_imx8mq_set_pll(sc, IMX8MQ_ARM_PLL, freq);
1591 			pcells[0] = sc->sc_phandle;
1592 			pcells[1] = IMX8MQ_ARM_PLL_OUT;
1593 			imxccm_set_parent(cookie, &idx, pcells);
1594 			return ret;
1595 		case IMX8MQ_CLK_USB_BUS:
1596 		case IMX8MQ_CLK_USB_CORE_REF:
1597 		case IMX8MQ_CLK_USB_PHY_REF:
1598 			if (imxccm_get_frequency(sc, cells) != freq)
1599 				break;
1600 			return 0;
1601 		case IMX8MQ_CLK_USDHC1:
1602 		case IMX8MQ_CLK_USDHC2:
1603 			parent_freq = imxccm_imx8mq_usdhc(sc, idx);
1604 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1605 		}
1606 	} else if (sc->sc_divs == imx7d_divs) {
1607 		switch (idx) {
1608 		case IMX7D_USDHC1_ROOT_CLK:
1609 		case IMX7D_USDHC2_ROOT_CLK:
1610 		case IMX7D_USDHC3_ROOT_CLK:
1611 			parent = sc->sc_gates[idx].parent;
1612 			return imxccm_set_frequency(sc, &parent, freq);
1613 		case IMX7D_USDHC1_ROOT_DIV:
1614 		case IMX7D_USDHC2_ROOT_DIV:
1615 		case IMX7D_USDHC3_ROOT_DIV:
1616 			parent = sc->sc_divs[idx].parent;
1617 			parent_freq = imxccm_get_frequency(sc, &parent);
1618 			div = 0;
1619 			while (parent_freq / (div + 1) > freq)
1620 				div++;
1621 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1622 			reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
1623 			reg |= (div << sc->sc_divs[idx].shift);
1624 			HWRITE4(sc, sc->sc_divs[idx].reg, reg);
1625 			return 0;
1626 		}
1627 	}
1628 
1629 	printf("%s: 0x%08x %x\n", __func__, idx, freq);
1630 	return -1;
1631 }
1632 
1633 int
1634 imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1635 {
1636 	struct imxccm_softc *sc = cookie;
1637 	uint32_t idx = cells[0];
1638 	uint32_t pidx;
1639 	uint32_t mux;
1640 
1641 	if (pcells[0] != sc->sc_phandle) {
1642 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, pcells[0]);
1643 		return -1;
1644 	}
1645 
1646 	pidx = pcells[1];
1647 
1648 	if (sc->sc_muxs == imx8mm_muxs) {
1649 		switch (idx) {
1650 		case IMX8MM_CLK_A53_SRC:
1651 			if (pidx != IMX8MM_ARM_PLL_OUT &&
1652 			    pidx != IMX8MM_SYS_PLL1_800M)
1653 				break;
1654 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1655 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1656 			if (pidx == IMX8MM_ARM_PLL_OUT)
1657 				mux |= (0x1 << sc->sc_muxs[idx].shift);
1658 			if (pidx == IMX8MM_SYS_PLL1_800M)
1659 				mux |= (0x4 << sc->sc_muxs[idx].shift);
1660 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1661 			return 0;
1662 		case IMX8MM_CLK_USB_BUS:
1663 			if (pidx != IMX8MM_SYS_PLL2_500M)
1664 				break;
1665 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1666 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1667 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1668 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1669 			return 0;
1670 		case IMX8MM_CLK_USB_CORE_REF:
1671 		case IMX8MM_CLK_USB_PHY_REF:
1672 			if (pidx != IMX8MM_SYS_PLL1_100M)
1673 				break;
1674 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1675 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1676 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1677 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1678 			return 0;
1679 		case IMX8MM_CLK_PCIE1_CTRL:
1680 		case IMX8MM_CLK_PCIE2_CTRL:
1681 			if (pidx != IMX8MM_SYS_PLL2_250M)
1682 				break;
1683 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1684 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1685 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1686 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1687 			return 0;
1688 		case IMX8MM_CLK_PCIE1_PHY:
1689 		case IMX8MM_CLK_PCIE2_PHY:
1690 			if (pidx != IMX8MM_SYS_PLL2_100M)
1691 				break;
1692 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1693 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1694 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1695 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1696 			return 0;
1697 		}
1698 	} else if (sc->sc_muxs == imx8mq_muxs) {
1699 		switch (idx) {
1700 		case IMX8MQ_CLK_A53_SRC:
1701 			if (pidx != IMX8MQ_ARM_PLL_OUT &&
1702 			    pidx != IMX8MQ_SYS1_PLL_800M)
1703 				break;
1704 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1705 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1706 			if (pidx == IMX8MQ_ARM_PLL_OUT)
1707 				mux |= (0x1 << sc->sc_muxs[idx].shift);
1708 			if (pidx == IMX8MQ_SYS1_PLL_800M)
1709 				mux |= (0x4 << sc->sc_muxs[idx].shift);
1710 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1711 			return 0;
1712 		case IMX8MQ_CLK_USB_BUS:
1713 			if (pidx != IMX8MQ_SYS2_PLL_500M)
1714 				break;
1715 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1716 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1717 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1718 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1719 			return 0;
1720 		case IMX8MQ_CLK_USB_CORE_REF:
1721 		case IMX8MQ_CLK_USB_PHY_REF:
1722 			if (pidx != IMX8MQ_SYS1_PLL_100M)
1723 				break;
1724 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1725 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1726 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1727 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1728 			return 0;
1729 		case IMX8MQ_CLK_PCIE1_CTRL:
1730 		case IMX8MQ_CLK_PCIE2_CTRL:
1731 			if (pidx != IMX8MQ_SYS2_PLL_250M)
1732 				break;
1733 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1734 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1735 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1736 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1737 			return 0;
1738 		case IMX8MQ_CLK_PCIE1_PHY:
1739 		case IMX8MQ_CLK_PCIE2_PHY:
1740 			if (pidx != IMX8MQ_SYS2_PLL_100M)
1741 				break;
1742 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1743 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1744 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1745 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1746 			return 0;
1747 		}
1748 	}
1749 
1750 	printf("%s: 0x%08x 0x%08x\n", __func__, idx, pidx);
1751 	return -1;
1752 }
1753