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