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