xref: /openbsd-src/sys/dev/fdt/imxccm.c (revision 37c734d33dee3fea3589b7f939107ac40734e75e)
1*37c734d3Snaddy /* $OpenBSD: imxccm.c,v 1.29 2022/06/28 23:43:12 naddy Exp $ */
24bed6a7dSpatrick /*
34bed6a7dSpatrick  * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se>
44bed6a7dSpatrick  *
54bed6a7dSpatrick  * Permission to use, copy, modify, and distribute this software for any
64bed6a7dSpatrick  * purpose with or without fee is hereby granted, provided that the above
74bed6a7dSpatrick  * copyright notice and this permission notice appear in all copies.
84bed6a7dSpatrick  *
94bed6a7dSpatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104bed6a7dSpatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114bed6a7dSpatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124bed6a7dSpatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134bed6a7dSpatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144bed6a7dSpatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154bed6a7dSpatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164bed6a7dSpatrick  */
174bed6a7dSpatrick 
184bed6a7dSpatrick #include <sys/param.h>
194bed6a7dSpatrick #include <sys/systm.h>
204bed6a7dSpatrick #include <sys/queue.h>
214bed6a7dSpatrick #include <sys/malloc.h>
224bed6a7dSpatrick #include <sys/sysctl.h>
234bed6a7dSpatrick #include <sys/device.h>
244bed6a7dSpatrick #include <sys/evcount.h>
254bed6a7dSpatrick #include <sys/socket.h>
264bed6a7dSpatrick #include <sys/timeout.h>
274bed6a7dSpatrick 
284bed6a7dSpatrick #include <machine/intr.h>
294bed6a7dSpatrick #include <machine/bus.h>
304bed6a7dSpatrick #include <machine/fdt.h>
314bed6a7dSpatrick 
324bed6a7dSpatrick #include <dev/ofw/openfirm.h>
334bed6a7dSpatrick #include <dev/ofw/ofw_clock.h>
3486101169Skettenis #include <dev/ofw/ofw_misc.h>
35b31392d8Spatrick #include <dev/ofw/ofw_regulator.h>
364bed6a7dSpatrick #include <dev/ofw/fdt.h>
374bed6a7dSpatrick 
3829009701Spatrick #include <dev/fdt/imxanatopvar.h>
3929009701Spatrick 
404bed6a7dSpatrick /* registers */
414bed6a7dSpatrick #define CCM_CCR		0x00
424bed6a7dSpatrick #define CCM_CCDR	0x04
434bed6a7dSpatrick #define CCM_CSR		0x08
444bed6a7dSpatrick #define CCM_CCSR	0x0c
454bed6a7dSpatrick #define CCM_CACRR	0x10
464bed6a7dSpatrick #define CCM_CBCDR	0x14
474bed6a7dSpatrick #define CCM_CBCMR	0x18
484bed6a7dSpatrick #define CCM_CSCMR1	0x1c
494bed6a7dSpatrick #define CCM_CSCMR2	0x20
504bed6a7dSpatrick #define CCM_CSCDR1	0x24
514bed6a7dSpatrick #define CCM_CS1CDR	0x28
524bed6a7dSpatrick #define CCM_CS2CDR	0x2c
534bed6a7dSpatrick #define CCM_CDCDR	0x30
544bed6a7dSpatrick #define CCM_CHSCCDR	0x34
554bed6a7dSpatrick #define CCM_CSCDR2	0x38
564bed6a7dSpatrick #define CCM_CSCDR3	0x3c
574bed6a7dSpatrick #define CCM_CSCDR4	0x40
584bed6a7dSpatrick #define CCM_CDHIPR	0x48
594bed6a7dSpatrick #define CCM_CDCR	0x4c
604bed6a7dSpatrick #define CCM_CTOR	0x50
614bed6a7dSpatrick #define CCM_CLPCR	0x54
624bed6a7dSpatrick #define CCM_CISR	0x58
634bed6a7dSpatrick #define CCM_CIMR	0x5c
644bed6a7dSpatrick #define CCM_CCOSR	0x60
654bed6a7dSpatrick #define CCM_CGPR	0x64
664bed6a7dSpatrick #define CCM_CCGR0	0x68
674bed6a7dSpatrick #define CCM_CCGR1	0x6c
684bed6a7dSpatrick #define CCM_CCGR2	0x70
694bed6a7dSpatrick #define CCM_CCGR3	0x74
704bed6a7dSpatrick #define CCM_CCGR4	0x78
714bed6a7dSpatrick #define CCM_CCGR5	0x7c
724bed6a7dSpatrick #define CCM_CCGR6	0x80
734bed6a7dSpatrick #define CCM_CCGR7	0x84
744bed6a7dSpatrick #define CCM_CMEOR	0x88
754bed6a7dSpatrick 
764bed6a7dSpatrick /* bits and bytes */
774bed6a7dSpatrick #define CCM_CCSR_PLL3_SW_CLK_SEL		(1 << 0)
784bed6a7dSpatrick #define CCM_CCSR_PLL2_SW_CLK_SEL		(1 << 1)
794bed6a7dSpatrick #define CCM_CCSR_PLL1_SW_CLK_SEL		(1 << 2)
804bed6a7dSpatrick #define CCM_CCSR_STEP_SEL			(1 << 8)
814bed6a7dSpatrick #define CCM_CBCDR_IPG_PODF_SHIFT		8
824bed6a7dSpatrick #define CCM_CBCDR_IPG_PODF_MASK			0x3
834bed6a7dSpatrick #define CCM_CBCDR_AHB_PODF_SHIFT		10
844bed6a7dSpatrick #define CCM_CBCDR_AHB_PODF_MASK			0x7
854bed6a7dSpatrick #define CCM_CBCDR_PERIPH_CLK_SEL_SHIFT		25
864bed6a7dSpatrick #define CCM_CBCDR_PERIPH_CLK_SEL_MASK		0x1
874bed6a7dSpatrick #define CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT		12
884bed6a7dSpatrick #define CCM_CBCMR_PERIPH_CLK2_SEL_MASK		0x3
894bed6a7dSpatrick #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT	18
904bed6a7dSpatrick #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK	0x3
914bed6a7dSpatrick #define CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)	((x) + 15)
924bed6a7dSpatrick #define CCM_CSCDR1_USDHCx_CLK_SEL_MASK		0x1
934bed6a7dSpatrick #define CCM_CSCDR1_USDHCx_PODF_MASK		0x7
944bed6a7dSpatrick #define CCM_CSCDR1_UART_PODF_MASK		0x7
95e45f7b26Spatrick #define CCM_CSCDR2_ECSPI_PODF_SHIFT		19
96e45f7b26Spatrick #define CCM_CSCDR2_ECSPI_PODF_MASK		0x7
974bed6a7dSpatrick #define CCM_CCGR1_ENET				(3 << 10)
984bed6a7dSpatrick #define CCM_CCGR4_125M_PCIE			(3 << 0)
994bed6a7dSpatrick #define CCM_CCGR5_100M_SATA			(3 << 4)
1004bed6a7dSpatrick #define CCM_CSCMR1_PERCLK_CLK_PODF_MASK		0x1f
1014bed6a7dSpatrick #define CCM_CSCMR1_PERCLK_CLK_SEL_MASK		(1 << 6)
1024bed6a7dSpatrick 
10386101169Skettenis /* Analog registers */
1046c60662eSkettenis #define CCM_ANALOG_PLL_USB1			0x0010
1056c60662eSkettenis #define CCM_ANALOG_PLL_USB1_SET			0x0014
1066c60662eSkettenis #define CCM_ANALOG_PLL_USB1_CLR			0x0018
1076c60662eSkettenis #define  CCM_ANALOG_PLL_USB1_LOCK		(1U << 31)
1086c60662eSkettenis #define  CCM_ANALOG_PLL_USB1_BYPASS		(1 << 16)
1096c60662eSkettenis #define  CCM_ANALOG_PLL_USB1_ENABLE		(1 << 13)
1106c60662eSkettenis #define  CCM_ANALOG_PLL_USB1_POWER		(1 << 12)
1116c60662eSkettenis #define  CCM_ANALOG_PLL_USB1_EN_USB_CLKS	(1 << 6)
1126c60662eSkettenis #define CCM_ANALOG_PLL_USB2			0x0020
1136c60662eSkettenis #define CCM_ANALOG_PLL_USB2_SET			0x0024
1146c60662eSkettenis #define CCM_ANALOG_PLL_USB2_CLR			0x0028
1156c60662eSkettenis #define  CCM_ANALOG_PLL_USB2_LOCK		(1U << 31)
1166c60662eSkettenis #define  CCM_ANALOG_PLL_USB2_BYPASS		(1 << 16)
1176c60662eSkettenis #define  CCM_ANALOG_PLL_USB2_ENABLE		(1 << 13)
1186c60662eSkettenis #define  CCM_ANALOG_PLL_USB2_POWER		(1 << 12)
1196c60662eSkettenis #define  CCM_ANALOG_PLL_USB2_EN_USB_CLKS	(1 << 6)
1206c60662eSkettenis #define CCM_ANALOG_PLL_ENET			0x00e0
12186101169Skettenis #define CCM_ANALOG_PLL_ENET_SET			0x00e4
1226c60662eSkettenis #define CCM_ANALOG_PLL_ENET_CLR			0x00e8
1236c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_LOCK		(1U << 31)
1246c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_ENABLE_100M	(1 << 20) /* i.MX6 */
1256c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_BYPASS		(1 << 16)
1266c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_ENABLE		(1 << 13) /* i.MX6 */
1276c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_POWERDOWN		(1 << 12) /* i.MX6 */
1286c60662eSkettenis #define  CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ	(1 << 10) /* i.MX7 */
12986101169Skettenis 
1306e71e8feSpatrick /* Int PLL */
1316e71e8feSpatrick #define CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL		0x84
1326e71e8feSpatrick #define CCM_14XX_IMX8M_ARM_PLL_DIV_CTL		0x88
1336e71e8feSpatrick #define CCM_14XX_IMX8M_SYS_PLL1_GNRL_CTL	0x94
1346e71e8feSpatrick #define CCM_14XX_IMX8M_SYS_PLL1_DIV_CTL		0x98
1356e71e8feSpatrick #define  CCM_INT_PLL_LOCK				(1U << 31)
1366e71e8feSpatrick #define  CCM_INT_PLL_LOCK_SEL				(1 << 29)
1376e71e8feSpatrick #define  CCM_INT_PLL_RST				(1 << 9)
1386e71e8feSpatrick #define  CCM_INT_PLL_BYPASS				(1 << 4)
1396e71e8feSpatrick #define  CCM_INT_PLL_MAIN_DIV_SHIFT			12
1406e71e8feSpatrick #define  CCM_INT_PLL_MAIN_DIV_MASK			0x3ff
1416e71e8feSpatrick #define  CCM_INT_PLL_PRE_DIV_SHIFT			4
1426e71e8feSpatrick #define  CCM_INT_PLL_PRE_DIV_MASK			0x3f
1436e71e8feSpatrick #define  CCM_INT_PLL_POST_DIV_SHIFT			0
1446e71e8feSpatrick #define  CCM_INT_PLL_POST_DIV_MASK			0x7
1456e71e8feSpatrick 
146b31392d8Spatrick /* Frac PLL */
147b31392d8Spatrick #define CCM_FRAC_IMX8M_ARM_PLL0			0x28
148b31392d8Spatrick #define CCM_FRAC_IMX8M_ARM_PLL1			0x2c
1496e71e8feSpatrick #define  CCM_FRAC_PLL_LOCK				(1U << 31)
150b31392d8Spatrick #define  CCM_FRAC_PLL_ENABLE				(1 << 21)
151b31392d8Spatrick #define  CCM_FRAC_PLL_POWERDOWN				(1 << 19)
152b31392d8Spatrick #define  CCM_FRAC_PLL_REFCLK_SEL_SHIFT			16
153b31392d8Spatrick #define  CCM_FRAC_PLL_REFCLK_SEL_MASK			0x3
154b31392d8Spatrick #define  CCM_FRAC_PLL_LOCK_SEL				(1 << 15)
155b31392d8Spatrick #define  CCM_FRAC_PLL_BYPASS				(1 << 14)
156b31392d8Spatrick #define  CCM_FRAC_PLL_COUNTCLK_SEL			(1 << 13)
157b31392d8Spatrick #define  CCM_FRAC_PLL_NEWDIV_VAL			(1 << 12)
158b31392d8Spatrick #define  CCM_FRAC_PLL_NEWDIV_ACK			(1 << 11)
159b31392d8Spatrick #define  CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT		5
160b31392d8Spatrick #define  CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK		0x3f
161b31392d8Spatrick #define  CCM_FRAC_PLL_OUTPUT_DIV_VAL_SHIFT		0
162b31392d8Spatrick #define  CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK		0x1f
163b31392d8Spatrick #define  CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT		7
164b31392d8Spatrick #define  CCM_FRAC_PLL_FRAC_DIV_CTL_MASK			0x1ffffff
165b31392d8Spatrick #define  CCM_FRAC_PLL_INT_DIV_CTL_SHIFT			0
166b31392d8Spatrick #define  CCM_FRAC_PLL_INT_DIV_CTL_MASK			0x7f
167b31392d8Spatrick #define  CCM_FRAC_PLL_DENOM				(1 << 24)
168b31392d8Spatrick #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG		0x78
169b31392d8Spatrick #define  CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT	20
170b31392d8Spatrick #define  CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK		0x7
171b31392d8Spatrick 
1724bed6a7dSpatrick #define HCLK_FREQ				24000000
173e45f7b26Spatrick #define PLL3_60M				60000000
1744bed6a7dSpatrick #define PLL3_80M				80000000
1754bed6a7dSpatrick 
1764bed6a7dSpatrick #define HREAD4(sc, reg)							\
1774bed6a7dSpatrick 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
1784bed6a7dSpatrick #define HWRITE4(sc, reg, val)						\
1794bed6a7dSpatrick 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
1804bed6a7dSpatrick #define HSET4(sc, reg, bits)						\
1814bed6a7dSpatrick 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
1824bed6a7dSpatrick #define HCLR4(sc, reg, bits)						\
1834bed6a7dSpatrick 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
1844bed6a7dSpatrick 
1854bed6a7dSpatrick struct imxccm_gate {
186a8196585Spatrick 	uint16_t reg;
1874bed6a7dSpatrick 	uint8_t pos;
188a8196585Spatrick 	uint16_t parent;
189a8196585Spatrick };
190a8196585Spatrick 
191a8196585Spatrick struct imxccm_divider {
192a8196585Spatrick 	uint16_t reg;
193a8196585Spatrick 	uint16_t shift;
194a8196585Spatrick 	uint16_t mask;
195a8196585Spatrick 	uint16_t parent;
196a8196585Spatrick 	uint16_t fixed;
197a8196585Spatrick };
198a8196585Spatrick 
199a8196585Spatrick struct imxccm_mux {
200a8196585Spatrick 	uint16_t reg;
201a8196585Spatrick 	uint16_t shift;
202a8196585Spatrick 	uint16_t mask;
2034bed6a7dSpatrick };
2044bed6a7dSpatrick 
2054bed6a7dSpatrick #include "imxccm_clocks.h"
2064bed6a7dSpatrick 
2074bed6a7dSpatrick struct imxccm_softc {
2084bed6a7dSpatrick 	struct device		sc_dev;
2094bed6a7dSpatrick 	bus_space_tag_t		sc_iot;
2104bed6a7dSpatrick 	bus_space_handle_t	sc_ioh;
2114bed6a7dSpatrick 	int			sc_node;
212f70b9bfaSkettenis 	uint32_t		sc_phandle;
2134bed6a7dSpatrick 
21486101169Skettenis 	struct regmap		*sc_anatop;
21586101169Skettenis 
216*37c734d3Snaddy 	const struct imxccm_gate *sc_gates;
2174bed6a7dSpatrick 	int			sc_ngates;
218*37c734d3Snaddy 	const struct imxccm_divider *sc_divs;
219a8196585Spatrick 	int			sc_ndivs;
220*37c734d3Snaddy 	const struct imxccm_mux	*sc_muxs;
221a8196585Spatrick 	int			sc_nmuxs;
222*37c734d3Snaddy 	const struct imxccm_divider *sc_predivs;
223071150a2Spatrick 	int			sc_npredivs;
2244bed6a7dSpatrick 	struct clock_device	sc_cd;
2254bed6a7dSpatrick };
2264bed6a7dSpatrick 
2274bed6a7dSpatrick int	imxccm_match(struct device *, void *, void *);
2284bed6a7dSpatrick void	imxccm_attach(struct device *parent, struct device *self, void *args);
2294bed6a7dSpatrick 
2309fdf0c62Smpi const struct cfattach	imxccm_ca = {
2314bed6a7dSpatrick 	sizeof (struct imxccm_softc), imxccm_match, imxccm_attach
2324bed6a7dSpatrick };
2334bed6a7dSpatrick 
2344bed6a7dSpatrick struct cfdriver imxccm_cd = {
2354bed6a7dSpatrick 	NULL, "imxccm", DV_DULL
2364bed6a7dSpatrick };
2374bed6a7dSpatrick 
2384bed6a7dSpatrick uint32_t imxccm_get_armclk(struct imxccm_softc *);
23929009701Spatrick void imxccm_armclk_set_parent(struct imxccm_softc *, enum imxanatop_clocks);
2404bed6a7dSpatrick uint32_t imxccm_get_usdhx(struct imxccm_softc *, int x);
2414bed6a7dSpatrick uint32_t imxccm_get_periphclk(struct imxccm_softc *);
2424bed6a7dSpatrick uint32_t imxccm_get_ahbclk(struct imxccm_softc *);
2434bed6a7dSpatrick uint32_t imxccm_get_ipgclk(struct imxccm_softc *);
2444bed6a7dSpatrick uint32_t imxccm_get_ipg_perclk(struct imxccm_softc *);
2454bed6a7dSpatrick uint32_t imxccm_get_uartclk(struct imxccm_softc *);
2466e71e8feSpatrick uint32_t imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t);
2476d21c932Spatrick uint32_t imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t);
2486e71e8feSpatrick uint32_t imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t);
2496e71e8feSpatrick uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t);
2506e71e8feSpatrick uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t);
251a74ead0bSpatrick uint32_t imxccm_imx8mp_enet_qos_timer(struct imxccm_softc *sc, uint32_t);
252a74ead0bSpatrick uint32_t imxccm_imx8mp_enet_qos(struct imxccm_softc *sc, uint32_t);
25359cc782fSpatrick uint32_t imxccm_imx8mp_hsio_axi(struct imxccm_softc *sc, uint32_t);
2548ea71dd1Spatrick uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t);
2558ea71dd1Spatrick uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t);
2566d21c932Spatrick uint32_t imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t);
257a8196585Spatrick uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t);
258392fcdd1Spatrick uint32_t imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t);
259a8196585Spatrick uint32_t imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t);
260a8196585Spatrick uint32_t imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t);
261a8196585Spatrick uint32_t imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t);
26258c0d41eSpatrick int imxccm_imx8m_set_div(struct imxccm_softc *, uint32_t, uint64_t, uint64_t);
2634bed6a7dSpatrick void imxccm_enable(void *, uint32_t *, int);
2644bed6a7dSpatrick uint32_t imxccm_get_frequency(void *, uint32_t *);
265a8196585Spatrick int imxccm_set_frequency(void *, uint32_t *, uint32_t);
266a8196585Spatrick int imxccm_set_parent(void *, uint32_t *, uint32_t *);
2674bed6a7dSpatrick 
2684bed6a7dSpatrick int
imxccm_match(struct device * parent,void * match,void * aux)2694bed6a7dSpatrick imxccm_match(struct device *parent, void *match, void *aux)
2704bed6a7dSpatrick {
2714bed6a7dSpatrick 	struct fdt_attach_args *faa = aux;
2724bed6a7dSpatrick 
2734bed6a7dSpatrick 	return (OF_is_compatible(faa->fa_node, "fsl,imx6q-ccm") ||
2744bed6a7dSpatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx6sl-ccm") ||
2754bed6a7dSpatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") ||
276a8196585Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") ||
277b7ac005eSkettenis 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") ||
2786e71e8feSpatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mm-ccm") ||
27922a4f870Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mp-ccm") ||
280a8196585Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm"));
2814bed6a7dSpatrick }
2824bed6a7dSpatrick 
2834bed6a7dSpatrick void
imxccm_attach(struct device * parent,struct device * self,void * aux)2844bed6a7dSpatrick imxccm_attach(struct device *parent, struct device *self, void *aux)
2854bed6a7dSpatrick {
2864bed6a7dSpatrick 	struct imxccm_softc *sc = (struct imxccm_softc *)self;
2874bed6a7dSpatrick 	struct fdt_attach_args *faa = aux;
2884bed6a7dSpatrick 
2894bed6a7dSpatrick 	KASSERT(faa->fa_nreg >= 1);
2904bed6a7dSpatrick 
2914bed6a7dSpatrick 	sc->sc_node = faa->fa_node;
2924bed6a7dSpatrick 	sc->sc_iot = faa->fa_iot;
2934bed6a7dSpatrick 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
29429009701Spatrick 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
2954bed6a7dSpatrick 		panic("%s: bus_space_map failed!", __func__);
2964bed6a7dSpatrick 
297f70b9bfaSkettenis 	sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0);
298f70b9bfaSkettenis 
2996e71e8feSpatrick 	if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-ccm")) {
3006e71e8feSpatrick 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mm-anatop");
3016e71e8feSpatrick 		KASSERT(sc->sc_anatop != NULL);
3026e71e8feSpatrick 		sc->sc_gates = imx8mm_gates;
3036e71e8feSpatrick 		sc->sc_ngates = nitems(imx8mm_gates);
3046e71e8feSpatrick 		sc->sc_divs = imx8mm_divs;
3056e71e8feSpatrick 		sc->sc_ndivs = nitems(imx8mm_divs);
3066e71e8feSpatrick 		sc->sc_muxs = imx8mm_muxs;
3076e71e8feSpatrick 		sc->sc_nmuxs = nitems(imx8mm_muxs);
3086e71e8feSpatrick 		sc->sc_predivs = imx8mm_predivs;
3096e71e8feSpatrick 		sc->sc_npredivs = nitems(imx8mm_predivs);
31022a4f870Spatrick 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx8mp-ccm")) {
31122a4f870Spatrick 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mp-anatop");
31222a4f870Spatrick 		KASSERT(sc->sc_anatop != NULL);
31322a4f870Spatrick 		sc->sc_gates = imx8mp_gates;
31422a4f870Spatrick 		sc->sc_ngates = nitems(imx8mp_gates);
31522a4f870Spatrick 		sc->sc_divs = imx8mp_divs;
31622a4f870Spatrick 		sc->sc_ndivs = nitems(imx8mp_divs);
31722a4f870Spatrick 		sc->sc_muxs = imx8mp_muxs;
31822a4f870Spatrick 		sc->sc_nmuxs = nitems(imx8mp_muxs);
31922a4f870Spatrick 		sc->sc_predivs = imx8mp_predivs;
32022a4f870Spatrick 		sc->sc_npredivs = nitems(imx8mp_predivs);
3216e71e8feSpatrick 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) {
322b31392d8Spatrick 		sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop");
323b31392d8Spatrick 		KASSERT(sc->sc_anatop != NULL);
324a8196585Spatrick 		sc->sc_gates = imx8mq_gates;
325a8196585Spatrick 		sc->sc_ngates = nitems(imx8mq_gates);
326a8196585Spatrick 		sc->sc_divs = imx8mq_divs;
327a8196585Spatrick 		sc->sc_ndivs = nitems(imx8mq_divs);
328a8196585Spatrick 		sc->sc_muxs = imx8mq_muxs;
329a8196585Spatrick 		sc->sc_nmuxs = nitems(imx8mq_muxs);
330071150a2Spatrick 		sc->sc_predivs = imx8mq_predivs;
331071150a2Spatrick 		sc->sc_npredivs = nitems(imx8mq_predivs);
332b7ac005eSkettenis 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx7d-ccm")) {
333b7ac005eSkettenis 		sc->sc_gates = imx7d_gates;
334b7ac005eSkettenis 		sc->sc_ngates = nitems(imx7d_gates);
335b7ac005eSkettenis 		sc->sc_divs = imx7d_divs;
336b7ac005eSkettenis 		sc->sc_ndivs = nitems(imx7d_divs);
337b7ac005eSkettenis 		sc->sc_muxs = imx7d_muxs;
338b7ac005eSkettenis 		sc->sc_nmuxs = nitems(imx7d_muxs);
339a8196585Spatrick 	} else if (OF_is_compatible(sc->sc_node, "fsl,imx6ul-ccm")) {
3404bed6a7dSpatrick 		sc->sc_gates = imx6ul_gates;
3414bed6a7dSpatrick 		sc->sc_ngates = nitems(imx6ul_gates);
3424bed6a7dSpatrick 	} else {
3434bed6a7dSpatrick 		sc->sc_gates = imx6_gates;
3444bed6a7dSpatrick 		sc->sc_ngates = nitems(imx6_gates);
3454bed6a7dSpatrick 	}
3464bed6a7dSpatrick 
3474bed6a7dSpatrick 	printf("\n");
3484bed6a7dSpatrick 
3494bed6a7dSpatrick 	sc->sc_cd.cd_node = faa->fa_node;
3504bed6a7dSpatrick 	sc->sc_cd.cd_cookie = sc;
3514bed6a7dSpatrick 	sc->sc_cd.cd_enable = imxccm_enable;
3524bed6a7dSpatrick 	sc->sc_cd.cd_get_frequency = imxccm_get_frequency;
353a8196585Spatrick 	sc->sc_cd.cd_set_frequency = imxccm_set_frequency;
354a8196585Spatrick 	sc->sc_cd.cd_set_parent = imxccm_set_parent;
3554bed6a7dSpatrick 	clock_register(&sc->sc_cd);
3564bed6a7dSpatrick }
3574bed6a7dSpatrick 
3584bed6a7dSpatrick uint32_t
imxccm_get_armclk(struct imxccm_softc * sc)3594bed6a7dSpatrick imxccm_get_armclk(struct imxccm_softc *sc)
3604bed6a7dSpatrick {
3614bed6a7dSpatrick 	uint32_t ccsr = HREAD4(sc, CCM_CCSR);
3624bed6a7dSpatrick 
3634bed6a7dSpatrick 	if (!(ccsr & CCM_CCSR_PLL1_SW_CLK_SEL))
36429009701Spatrick 		return imxanatop_decode_pll(ARM_PLL1, HCLK_FREQ);
3654bed6a7dSpatrick 	else if (ccsr & CCM_CCSR_STEP_SEL)
36629009701Spatrick 		return imxanatop_get_pll2_pfd(2);
3674bed6a7dSpatrick 	else
3684bed6a7dSpatrick 		return HCLK_FREQ;
3694bed6a7dSpatrick }
3704bed6a7dSpatrick 
3714bed6a7dSpatrick void
imxccm_armclk_set_parent(struct imxccm_softc * sc,enum imxanatop_clocks clock)37229009701Spatrick imxccm_armclk_set_parent(struct imxccm_softc *sc, enum imxanatop_clocks clock)
3734bed6a7dSpatrick {
3744bed6a7dSpatrick 	switch (clock)
3754bed6a7dSpatrick 	{
3764bed6a7dSpatrick 	case ARM_PLL1:
3774bed6a7dSpatrick 		/* jump onto pll1 */
3784bed6a7dSpatrick 		HCLR4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
3794bed6a7dSpatrick 		/* put step clk on OSC, power saving */
3804bed6a7dSpatrick 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
3814bed6a7dSpatrick 		break;
3824bed6a7dSpatrick 	case OSC:
3834bed6a7dSpatrick 		/* put step clk on OSC */
3844bed6a7dSpatrick 		HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
3854bed6a7dSpatrick 		/* jump onto step clk */
3864bed6a7dSpatrick 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
3874bed6a7dSpatrick 		break;
3884bed6a7dSpatrick 	case SYS_PLL2_PFD2:
3894bed6a7dSpatrick 		/* put step clk on pll2-pfd2 400 MHz */
3904bed6a7dSpatrick 		HSET4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL);
3914bed6a7dSpatrick 		/* jump onto step clk */
3924bed6a7dSpatrick 		HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL);
3934bed6a7dSpatrick 		break;
3944bed6a7dSpatrick 	default:
3954bed6a7dSpatrick 		panic("%s: parent not possible for arm clk", __func__);
3964bed6a7dSpatrick 	}
3974bed6a7dSpatrick }
3984bed6a7dSpatrick 
399e45f7b26Spatrick uint32_t
imxccm_get_ecspiclk(struct imxccm_softc * sc)400e45f7b26Spatrick imxccm_get_ecspiclk(struct imxccm_softc *sc)
401e45f7b26Spatrick {
402e45f7b26Spatrick 	uint32_t clkroot = PLL3_60M;
403e45f7b26Spatrick 	uint32_t podf = HREAD4(sc, CCM_CSCDR2);
404e45f7b26Spatrick 
405e45f7b26Spatrick 	podf >>= CCM_CSCDR2_ECSPI_PODF_SHIFT;
406e45f7b26Spatrick 	podf &= CCM_CSCDR2_ECSPI_PODF_MASK;
407e45f7b26Spatrick 
408e45f7b26Spatrick 	return clkroot / (podf + 1);
409e45f7b26Spatrick }
410e45f7b26Spatrick 
4114bed6a7dSpatrick unsigned int
imxccm_get_usdhx(struct imxccm_softc * sc,int x)4124bed6a7dSpatrick imxccm_get_usdhx(struct imxccm_softc *sc, int x)
4134bed6a7dSpatrick {
4144bed6a7dSpatrick 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
4154bed6a7dSpatrick 	uint32_t cscdr1 = HREAD4(sc, CCM_CSCDR1);
4164bed6a7dSpatrick 	uint32_t podf, clkroot;
4174bed6a7dSpatrick 
4184bed6a7dSpatrick 	// Odd bitsetting. Damn you.
4194bed6a7dSpatrick 	if (x == 1)
4204bed6a7dSpatrick 		podf = ((cscdr1 >> 11) & CCM_CSCDR1_USDHCx_PODF_MASK);
4214bed6a7dSpatrick 	else
4224bed6a7dSpatrick 		podf = ((cscdr1 >> (10 + 3*x)) & CCM_CSCDR1_USDHCx_PODF_MASK);
4234bed6a7dSpatrick 
4244bed6a7dSpatrick 	if (cscmr1 & (1 << CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x)))
42529009701Spatrick 		clkroot = imxanatop_get_pll2_pfd(0); // 352 MHz
4264bed6a7dSpatrick 	else
42729009701Spatrick 		clkroot = imxanatop_get_pll2_pfd(2); // 396 MHz
4284bed6a7dSpatrick 
4294bed6a7dSpatrick 	return clkroot / (podf + 1);
4304bed6a7dSpatrick }
4314bed6a7dSpatrick 
4324bed6a7dSpatrick uint32_t
imxccm_get_uartclk(struct imxccm_softc * sc)4334bed6a7dSpatrick imxccm_get_uartclk(struct imxccm_softc *sc)
4344bed6a7dSpatrick {
4354bed6a7dSpatrick 	uint32_t clkroot = PLL3_80M;
4364bed6a7dSpatrick 	uint32_t podf = HREAD4(sc, CCM_CSCDR1) & CCM_CSCDR1_UART_PODF_MASK;
4374bed6a7dSpatrick 
4384bed6a7dSpatrick 	return clkroot / (podf + 1);
4394bed6a7dSpatrick }
4404bed6a7dSpatrick 
4414bed6a7dSpatrick uint32_t
imxccm_get_periphclk(struct imxccm_softc * sc)4424bed6a7dSpatrick imxccm_get_periphclk(struct imxccm_softc *sc)
4434bed6a7dSpatrick {
4444bed6a7dSpatrick 	if ((HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_PERIPH_CLK_SEL_SHIFT)
4454bed6a7dSpatrick 		    & CCM_CBCDR_PERIPH_CLK_SEL_MASK) {
4464bed6a7dSpatrick 		switch((HREAD4(sc, CCM_CBCMR)
4474bed6a7dSpatrick 		    >> CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT) & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) {
4484bed6a7dSpatrick 		case 0:
44929009701Spatrick 			return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ);
4504bed6a7dSpatrick 		case 1:
4514bed6a7dSpatrick 		case 2:
4524bed6a7dSpatrick 			return HCLK_FREQ;
4534bed6a7dSpatrick 		default:
4544bed6a7dSpatrick 			return 0;
4554bed6a7dSpatrick 		}
4564bed6a7dSpatrick 
4574bed6a7dSpatrick 	} else {
4584bed6a7dSpatrick 		switch((HREAD4(sc, CCM_CBCMR)
4594bed6a7dSpatrick 		    >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) {
4604bed6a7dSpatrick 		default:
4614bed6a7dSpatrick 		case 0:
46229009701Spatrick 			return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ);
4634bed6a7dSpatrick 		case 1:
46429009701Spatrick 			return imxanatop_get_pll2_pfd(2); // 396 MHz
4654bed6a7dSpatrick 		case 2:
46629009701Spatrick 			return imxanatop_get_pll2_pfd(0); // 352 MHz
4674bed6a7dSpatrick 		case 3:
46829009701Spatrick 			return imxanatop_get_pll2_pfd(2) / 2; // 198 MHz
4694bed6a7dSpatrick 		}
4704bed6a7dSpatrick 	}
4714bed6a7dSpatrick }
4724bed6a7dSpatrick 
4734bed6a7dSpatrick uint32_t
imxccm_get_ahbclk(struct imxccm_softc * sc)4744bed6a7dSpatrick imxccm_get_ahbclk(struct imxccm_softc *sc)
4754bed6a7dSpatrick {
4764bed6a7dSpatrick 	uint32_t ahb_podf;
4774bed6a7dSpatrick 
4784bed6a7dSpatrick 	ahb_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_AHB_PODF_SHIFT)
4794bed6a7dSpatrick 	    & CCM_CBCDR_AHB_PODF_MASK;
4804bed6a7dSpatrick 	return imxccm_get_periphclk(sc) / (ahb_podf + 1);
4814bed6a7dSpatrick }
4824bed6a7dSpatrick 
4834bed6a7dSpatrick uint32_t
imxccm_get_ipgclk(struct imxccm_softc * sc)4844bed6a7dSpatrick imxccm_get_ipgclk(struct imxccm_softc *sc)
4854bed6a7dSpatrick {
4864bed6a7dSpatrick 	uint32_t ipg_podf;
4874bed6a7dSpatrick 
4884bed6a7dSpatrick 	ipg_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_IPG_PODF_SHIFT)
4894bed6a7dSpatrick 	    & CCM_CBCDR_IPG_PODF_MASK;
4904bed6a7dSpatrick 	return imxccm_get_ahbclk(sc) / (ipg_podf + 1);
4914bed6a7dSpatrick }
4924bed6a7dSpatrick 
4934bed6a7dSpatrick uint32_t
imxccm_get_ipg_perclk(struct imxccm_softc * sc)4944bed6a7dSpatrick imxccm_get_ipg_perclk(struct imxccm_softc *sc)
4954bed6a7dSpatrick {
4964bed6a7dSpatrick 	uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1);
4974bed6a7dSpatrick 	uint32_t freq, ipg_podf;
4984bed6a7dSpatrick 
4994bed6a7dSpatrick 	if (sc->sc_gates == imx6ul_gates &&
5004bed6a7dSpatrick 	    cscmr1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK)
5014bed6a7dSpatrick 		freq = HCLK_FREQ;
5024bed6a7dSpatrick 	else
5034bed6a7dSpatrick 		freq = imxccm_get_ipgclk(sc);
5044bed6a7dSpatrick 
5054bed6a7dSpatrick 	ipg_podf = cscmr1 & CCM_CSCMR1_PERCLK_CLK_PODF_MASK;
5064bed6a7dSpatrick 
5074bed6a7dSpatrick 	return freq / (ipg_podf + 1);
5084bed6a7dSpatrick }
5094bed6a7dSpatrick 
5106c60662eSkettenis void
imxccm_imx6_enable_pll_enet(struct imxccm_softc * sc,int on)5116c60662eSkettenis imxccm_imx6_enable_pll_enet(struct imxccm_softc *sc, int on)
5126c60662eSkettenis {
5136c60662eSkettenis 	KASSERT(on);
5146c60662eSkettenis 
5156c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
5166c60662eSkettenis 	    CCM_ANALOG_PLL_ENET_POWERDOWN);
5176c60662eSkettenis 
5186c60662eSkettenis 	/* Wait for the PLL to lock. */
5196c60662eSkettenis 	while ((regmap_read_4(sc->sc_anatop,
5206c60662eSkettenis 	    CCM_ANALOG_PLL_ENET) & CCM_ANALOG_PLL_ENET_LOCK) == 0)
5216c60662eSkettenis 		;
5226c60662eSkettenis 
5236c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR,
5246c60662eSkettenis 	    CCM_ANALOG_PLL_ENET_BYPASS);
5256c60662eSkettenis }
5266c60662eSkettenis 
5276c60662eSkettenis void
imxccm_imx6_enable_pll_usb1(struct imxccm_softc * sc,int on)5286c60662eSkettenis imxccm_imx6_enable_pll_usb1(struct imxccm_softc *sc, int on)
5296c60662eSkettenis {
5306c60662eSkettenis 	KASSERT(on);
5316c60662eSkettenis 
5326c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
5336c60662eSkettenis 	    CCM_ANALOG_PLL_USB1_POWER);
5346c60662eSkettenis 
5356c60662eSkettenis 	/* Wait for the PLL to lock. */
5366c60662eSkettenis 	while ((regmap_read_4(sc->sc_anatop,
5376c60662eSkettenis 	    CCM_ANALOG_PLL_USB1) & CCM_ANALOG_PLL_USB1_LOCK) == 0)
5386c60662eSkettenis 		;
5396c60662eSkettenis 
5406c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_CLR,
5416c60662eSkettenis 	    CCM_ANALOG_PLL_USB1_BYPASS);
5426c60662eSkettenis }
5436c60662eSkettenis 
5446c60662eSkettenis void
imxccm_imx6_enable_pll_usb2(struct imxccm_softc * sc,int on)5456c60662eSkettenis imxccm_imx6_enable_pll_usb2(struct imxccm_softc *sc, int on)
5466c60662eSkettenis {
5476c60662eSkettenis 	KASSERT(on);
5486c60662eSkettenis 
5496c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
5506c60662eSkettenis 	    CCM_ANALOG_PLL_USB2_POWER);
5516c60662eSkettenis 
5526c60662eSkettenis 	/* Wait for the PLL to lock. */
5536c60662eSkettenis 	while ((regmap_read_4(sc->sc_anatop,
5546c60662eSkettenis 	    CCM_ANALOG_PLL_USB2) & CCM_ANALOG_PLL_USB2_LOCK) == 0)
5556c60662eSkettenis 		;
5566c60662eSkettenis 
5576c60662eSkettenis 	regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_CLR,
5586c60662eSkettenis 	    CCM_ANALOG_PLL_USB2_BYPASS);
5596c60662eSkettenis }
5606c60662eSkettenis 
561a8196585Spatrick uint32_t
imxccm_imx7d_enet(struct imxccm_softc * sc,uint32_t idx)56258d1c2c8Skettenis imxccm_imx7d_enet(struct imxccm_softc *sc, uint32_t idx)
56358d1c2c8Skettenis {
56458d1c2c8Skettenis 	uint32_t mux;
56558d1c2c8Skettenis 
56658d1c2c8Skettenis 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
56758d1c2c8Skettenis 		return 0;
56858d1c2c8Skettenis 
56958d1c2c8Skettenis 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
57058d1c2c8Skettenis 	mux >>= sc->sc_muxs[idx].shift;
57158d1c2c8Skettenis 	mux &= sc->sc_muxs[idx].mask;
57258d1c2c8Skettenis 
57358d1c2c8Skettenis 	switch (mux) {
57458d1c2c8Skettenis 	case 0:
57558d1c2c8Skettenis 		return clock_get_frequency(sc->sc_node, "osc");
57658d1c2c8Skettenis 	case 7:
57758d1c2c8Skettenis 		return 392000000; /* pll_sys_pfd4_clk XXX not fixed */
57858d1c2c8Skettenis 	default:
57958d1c2c8Skettenis 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
58058d1c2c8Skettenis 		return 0;
58158d1c2c8Skettenis 	}
58258d1c2c8Skettenis }
58358d1c2c8Skettenis 
58458d1c2c8Skettenis uint32_t
imxccm_imx7d_i2c(struct imxccm_softc * sc,uint32_t idx)585b7ac005eSkettenis imxccm_imx7d_i2c(struct imxccm_softc *sc, uint32_t idx)
586b7ac005eSkettenis {
587b7ac005eSkettenis 	uint32_t mux;
588b7ac005eSkettenis 
589b7ac005eSkettenis 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
590b7ac005eSkettenis 		return 0;
591b7ac005eSkettenis 
592b7ac005eSkettenis 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
593b7ac005eSkettenis 	mux >>= sc->sc_muxs[idx].shift;
594b7ac005eSkettenis 	mux &= sc->sc_muxs[idx].mask;
595b7ac005eSkettenis 
596b7ac005eSkettenis 	switch (mux) {
597b7ac005eSkettenis 	case 0:
598b7ac005eSkettenis 		return clock_get_frequency(sc->sc_node, "osc");
599b7ac005eSkettenis 	case 1:
600b7ac005eSkettenis 		return 120000000; /* pll_sys_main_120m_clk */
601b7ac005eSkettenis 	default:
602b7ac005eSkettenis 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
603b7ac005eSkettenis 		return 0;
604b7ac005eSkettenis 	}
605b7ac005eSkettenis }
606b7ac005eSkettenis 
607b7ac005eSkettenis uint32_t
imxccm_imx7d_uart(struct imxccm_softc * sc,uint32_t idx)608b7ac005eSkettenis imxccm_imx7d_uart(struct imxccm_softc *sc, uint32_t idx)
609b7ac005eSkettenis {
610b7ac005eSkettenis 	uint32_t mux;
611b7ac005eSkettenis 
612b7ac005eSkettenis 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
613b7ac005eSkettenis 		return 0;
614b7ac005eSkettenis 
615b7ac005eSkettenis 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
616b7ac005eSkettenis 	mux >>= sc->sc_muxs[idx].shift;
617b7ac005eSkettenis 	mux &= sc->sc_muxs[idx].mask;
618b7ac005eSkettenis 
619b7ac005eSkettenis 	switch (mux) {
620b7ac005eSkettenis 	case 0:
621b7ac005eSkettenis 		return clock_get_frequency(sc->sc_node, "osc");
622b7ac005eSkettenis 	default:
623b7ac005eSkettenis 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
624b7ac005eSkettenis 		return 0;
625b7ac005eSkettenis 	}
626b7ac005eSkettenis }
627b7ac005eSkettenis 
628b7ac005eSkettenis uint32_t
imxccm_imx7d_usdhc(struct imxccm_softc * sc,uint32_t idx)629b7ac005eSkettenis imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx)
630b7ac005eSkettenis {
631b7ac005eSkettenis 	uint32_t mux;
632b7ac005eSkettenis 
633b7ac005eSkettenis 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
634b7ac005eSkettenis 		return 0;
635b7ac005eSkettenis 
636b7ac005eSkettenis 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
637b7ac005eSkettenis 	mux >>= sc->sc_muxs[idx].shift;
638b7ac005eSkettenis 	mux &= sc->sc_muxs[idx].mask;
639b7ac005eSkettenis 
640b7ac005eSkettenis 	switch (mux) {
641b7ac005eSkettenis 	case 0:
642b7ac005eSkettenis 		return clock_get_frequency(sc->sc_node, "osc");
643b7ac005eSkettenis 	case 1:
644b7ac005eSkettenis 		return 392000000; /* pll_sys_pfd0_392m_clk */
645b7ac005eSkettenis 	default:
646b7ac005eSkettenis 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
647b7ac005eSkettenis 		return 0;
648b7ac005eSkettenis 	}
649b7ac005eSkettenis }
650b7ac005eSkettenis 
651b7ac005eSkettenis uint32_t
imxccm_imx8mm_get_pll(struct imxccm_softc * sc,uint32_t idx)6526e71e8feSpatrick imxccm_imx8mm_get_pll(struct imxccm_softc *sc, uint32_t idx)
6536e71e8feSpatrick {
6546e71e8feSpatrick 	uint64_t main_div, pre_div, post_div, div;
6556e71e8feSpatrick 	uint32_t pll0, pll1;
6566e71e8feSpatrick 	uint64_t freq;
6576e71e8feSpatrick 
6586e71e8feSpatrick 	switch (idx) {
6596e71e8feSpatrick 	case IMX8MM_ARM_PLL:
6606e71e8feSpatrick 		pll0 = regmap_read_4(sc->sc_anatop,
6616e71e8feSpatrick 		    CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL);
6626e71e8feSpatrick 		pll1 = regmap_read_4(sc->sc_anatop,
6636e71e8feSpatrick 		    CCM_14XX_IMX8M_ARM_PLL_DIV_CTL);
6646e71e8feSpatrick 		div = 1;
6656e71e8feSpatrick 		break;
6666e71e8feSpatrick 	default:
6676e71e8feSpatrick 		printf("%s: 0x%08x\n", __func__, idx);
6686e71e8feSpatrick 		return 0;
6696e71e8feSpatrick 	}
6706e71e8feSpatrick 
6716e71e8feSpatrick 	freq = clock_get_frequency(sc->sc_node, "osc_24m");
6726e71e8feSpatrick 	if (pll0 & CCM_INT_PLL_BYPASS)
6736e71e8feSpatrick 		return freq;
6746e71e8feSpatrick 
6756e71e8feSpatrick 	main_div = (pll1 >> CCM_INT_PLL_MAIN_DIV_SHIFT) &
6766e71e8feSpatrick 	    CCM_INT_PLL_MAIN_DIV_MASK;
6776e71e8feSpatrick 	pre_div = (pll1 >> CCM_INT_PLL_PRE_DIV_SHIFT) &
6786e71e8feSpatrick 	    CCM_INT_PLL_PRE_DIV_MASK;
6796e71e8feSpatrick 	post_div = (pll1 >> CCM_INT_PLL_POST_DIV_SHIFT) &
6806e71e8feSpatrick 	    CCM_INT_PLL_POST_DIV_MASK;
6816e71e8feSpatrick 
6826e71e8feSpatrick 	freq = freq * main_div;
6836e71e8feSpatrick 	freq = freq / (pre_div * (1 << post_div) * div);
6846e71e8feSpatrick 	return freq;
6856e71e8feSpatrick }
6866e71e8feSpatrick 
6876e71e8feSpatrick int
imxccm_imx8mm_set_pll(struct imxccm_softc * sc,uint32_t idx,uint64_t freq)6886e71e8feSpatrick imxccm_imx8mm_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
6896e71e8feSpatrick {
6906e71e8feSpatrick 	uint64_t main_div, pre_div, post_div;
6916e71e8feSpatrick 	uint32_t pll0, pll1, reg;
6926e71e8feSpatrick 	int i;
6936e71e8feSpatrick 
6946e71e8feSpatrick 	switch (idx) {
6956e71e8feSpatrick 	case IMX8MM_ARM_PLL:
6966e71e8feSpatrick 		pre_div = 3;
6976e71e8feSpatrick 		switch (freq) {
6986e71e8feSpatrick 		case 1800000000U:
6996e71e8feSpatrick 			main_div = 225;
7006e71e8feSpatrick 			post_div = 0;
7016e71e8feSpatrick 			break;
7026e71e8feSpatrick 		case 1600000000U:
7036e71e8feSpatrick 			main_div = 200;
7046e71e8feSpatrick 			post_div = 0;
7056e71e8feSpatrick 			break;
7066e71e8feSpatrick 		case 1200000000U:
7076e71e8feSpatrick 			main_div = 300;
7086e71e8feSpatrick 			post_div = 1;
7096e71e8feSpatrick 			break;
7106e71e8feSpatrick 		case 1000000000U:
7116e71e8feSpatrick 			main_div = 250;
7126e71e8feSpatrick 			post_div = 1;
7136e71e8feSpatrick 			break;
7146e71e8feSpatrick 		case 800000000U:
7156e71e8feSpatrick 			main_div = 200;
7166e71e8feSpatrick 			post_div = 1;
7176e71e8feSpatrick 			break;
7186e71e8feSpatrick 		case 750000000U:
7196e71e8feSpatrick 			main_div = 250;
7206e71e8feSpatrick 			post_div = 2;
7216e71e8feSpatrick 			break;
7226e71e8feSpatrick 		case 700000000U:
7236e71e8feSpatrick 			main_div = 350;
7246e71e8feSpatrick 			post_div = 2;
7256e71e8feSpatrick 			break;
7266e71e8feSpatrick 		case 600000000U:
7276e71e8feSpatrick 			main_div = 300;
7286e71e8feSpatrick 			post_div = 2;
7296e71e8feSpatrick 			break;
7306e71e8feSpatrick 		default:
7316e71e8feSpatrick 			printf("%s: 0x%08x\n", __func__, idx);
7326e71e8feSpatrick 			return -1;
7336e71e8feSpatrick 		}
7346e71e8feSpatrick 		pll0 = CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL;
7356e71e8feSpatrick 		pll1 = CCM_14XX_IMX8M_ARM_PLL_DIV_CTL;
7366e71e8feSpatrick 		break;
7376e71e8feSpatrick 	default:
7386e71e8feSpatrick 		printf("%s: 0x%08x\n", __func__, idx);
7396e71e8feSpatrick 		return -1;
7406e71e8feSpatrick 	}
7416e71e8feSpatrick 
7426e71e8feSpatrick 	regmap_write_4(sc->sc_anatop, pll0,
7436e71e8feSpatrick 	    regmap_read_4(sc->sc_anatop, pll0) |
7446e71e8feSpatrick 	    CCM_INT_PLL_LOCK_SEL);
7456e71e8feSpatrick 	regmap_write_4(sc->sc_anatop, pll0,
7466e71e8feSpatrick 	    regmap_read_4(sc->sc_anatop, pll0) &
7476e71e8feSpatrick 	    ~CCM_INT_PLL_RST);
7486e71e8feSpatrick 	regmap_write_4(sc->sc_anatop, pll1,
7496e71e8feSpatrick 	    main_div << CCM_INT_PLL_MAIN_DIV_SHIFT |
7506e71e8feSpatrick 	    pre_div << CCM_INT_PLL_PRE_DIV_SHIFT |
7516e71e8feSpatrick 	    post_div << CCM_INT_PLL_POST_DIV_SHIFT);
7526e71e8feSpatrick 	delay(3);
7536e71e8feSpatrick 	regmap_write_4(sc->sc_anatop, pll0,
7546e71e8feSpatrick 	    regmap_read_4(sc->sc_anatop, pll0) |
7556e71e8feSpatrick 	    CCM_INT_PLL_RST);
7566e71e8feSpatrick 	for (i = 0; i < 5000; i++) {
7576e71e8feSpatrick 		reg = regmap_read_4(sc->sc_anatop, pll0);
7586e71e8feSpatrick 		if (reg & CCM_INT_PLL_LOCK)
7596e71e8feSpatrick 			break;
7606e71e8feSpatrick 		delay(10);
7616e71e8feSpatrick 	}
7626e71e8feSpatrick 	if (i == 5000)
7636e71e8feSpatrick 		printf("%s: timeout\n", __func__);
7646e71e8feSpatrick 	regmap_write_4(sc->sc_anatop, pll0,
7656e71e8feSpatrick 	    regmap_read_4(sc->sc_anatop, pll0) &
7666e71e8feSpatrick 	    ~CCM_INT_PLL_BYPASS);
7676e71e8feSpatrick 
7686e71e8feSpatrick 	return 0;
7696e71e8feSpatrick }
7706e71e8feSpatrick 
7716e71e8feSpatrick uint32_t
imxccm_imx8mm_enet(struct imxccm_softc * sc,uint32_t idx)7726e71e8feSpatrick imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t idx)
7736e71e8feSpatrick {
7746e71e8feSpatrick 	uint32_t mux;
7756e71e8feSpatrick 
7766e71e8feSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
7776e71e8feSpatrick 		return 0;
7786e71e8feSpatrick 
7796e71e8feSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
7806e71e8feSpatrick 	mux >>= sc->sc_muxs[idx].shift;
7816e71e8feSpatrick 	mux &= sc->sc_muxs[idx].mask;
7826e71e8feSpatrick 
7836e71e8feSpatrick 	switch (mux) {
7846e71e8feSpatrick 	case 0:
7856e71e8feSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
7866e71e8feSpatrick 	case 1:
7876e71e8feSpatrick 		return 266 * 1000 * 1000; /* sys1_pll_266m */
7886e71e8feSpatrick 	default:
7896e71e8feSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
7906e71e8feSpatrick 		return 0;
7916e71e8feSpatrick 	}
7926e71e8feSpatrick }
7936e71e8feSpatrick 
7946e71e8feSpatrick uint32_t
imxccm_imx8mm_ahb(struct imxccm_softc * sc,uint32_t idx)7956d21c932Spatrick imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t idx)
7966d21c932Spatrick {
7976d21c932Spatrick 	uint32_t mux;
7986d21c932Spatrick 
7996d21c932Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
8006d21c932Spatrick 		return 0;
8016d21c932Spatrick 
8026d21c932Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
8036d21c932Spatrick 	mux >>= sc->sc_muxs[idx].shift;
8046d21c932Spatrick 	mux &= sc->sc_muxs[idx].mask;
8056d21c932Spatrick 
8066d21c932Spatrick 	switch (mux) {
8076d21c932Spatrick 	case 0:
8086d21c932Spatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
8096d21c932Spatrick 	case 1:
8106d21c932Spatrick 		return 133 * 1000 * 1000; /* sys_pll1_133m */
8116d21c932Spatrick 	case 2:
8126d21c932Spatrick 		return 800 * 1000 * 1000; /* sys_pll1_800m */
8136d21c932Spatrick 	case 3:
8146d21c932Spatrick 		return 400 * 1000 * 1000; /* sys_pll1_400m */
8156d21c932Spatrick 	case 4:
8166d21c932Spatrick 		return 125 * 1000 * 1000; /* sys_pll2_125m */
8176d21c932Spatrick 	default:
8186d21c932Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
8196d21c932Spatrick 		return 0;
8206d21c932Spatrick 	}
8216d21c932Spatrick }
8226d21c932Spatrick 
8236d21c932Spatrick uint32_t
imxccm_imx8mm_i2c(struct imxccm_softc * sc,uint32_t idx)8246e71e8feSpatrick imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t idx)
8256e71e8feSpatrick {
8266e71e8feSpatrick 	uint32_t mux;
8276e71e8feSpatrick 
8286e71e8feSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
8296e71e8feSpatrick 		return 0;
8306e71e8feSpatrick 
8316e71e8feSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
8326e71e8feSpatrick 	mux >>= sc->sc_muxs[idx].shift;
8336e71e8feSpatrick 	mux &= sc->sc_muxs[idx].mask;
8346e71e8feSpatrick 
8356e71e8feSpatrick 	switch (mux) {
8366e71e8feSpatrick 	case 0:
8376e71e8feSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
8386e71e8feSpatrick 	default:
8396e71e8feSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
8406e71e8feSpatrick 		return 0;
8416e71e8feSpatrick 	}
8426e71e8feSpatrick }
8436e71e8feSpatrick 
8446e71e8feSpatrick uint32_t
imxccm_imx8mm_uart(struct imxccm_softc * sc,uint32_t idx)8456e71e8feSpatrick imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t idx)
8466e71e8feSpatrick {
8476e71e8feSpatrick 	uint32_t mux;
8486e71e8feSpatrick 
8496e71e8feSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
8506e71e8feSpatrick 		return 0;
8516e71e8feSpatrick 
8526e71e8feSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
8536e71e8feSpatrick 	mux >>= sc->sc_muxs[idx].shift;
8546e71e8feSpatrick 	mux &= sc->sc_muxs[idx].mask;
8556e71e8feSpatrick 
8566e71e8feSpatrick 	switch (mux) {
8576e71e8feSpatrick 	case 0:
8586e71e8feSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
8596e71e8feSpatrick 	default:
8606e71e8feSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
8616e71e8feSpatrick 		return 0;
8626e71e8feSpatrick 	}
8636e71e8feSpatrick }
8646e71e8feSpatrick 
8656e71e8feSpatrick uint32_t
imxccm_imx8mm_usdhc(struct imxccm_softc * sc,uint32_t idx)8666e71e8feSpatrick imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx)
8676e71e8feSpatrick {
8686e71e8feSpatrick 	uint32_t mux;
8696e71e8feSpatrick 
8706e71e8feSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
8716e71e8feSpatrick 		return 0;
8726e71e8feSpatrick 
8736e71e8feSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
8746e71e8feSpatrick 	mux >>= sc->sc_muxs[idx].shift;
8756e71e8feSpatrick 	mux &= sc->sc_muxs[idx].mask;
8766e71e8feSpatrick 
8776e71e8feSpatrick 	switch (mux) {
8786e71e8feSpatrick 	case 0:
8796e71e8feSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
8806e71e8feSpatrick 	case 1:
8816e71e8feSpatrick 		return 400 * 1000 * 1000; /* sys1_pll_400m */
8826e71e8feSpatrick 	default:
8836e71e8feSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
8846e71e8feSpatrick 		return 0;
8856e71e8feSpatrick 	}
8866e71e8feSpatrick }
8876e71e8feSpatrick 
8886e71e8feSpatrick uint32_t
imxccm_imx8mp_enet_qos(struct imxccm_softc * sc,uint32_t idx)889a74ead0bSpatrick imxccm_imx8mp_enet_qos(struct imxccm_softc *sc, uint32_t idx)
890a74ead0bSpatrick {
891a74ead0bSpatrick 	uint32_t mux;
892a74ead0bSpatrick 
893a74ead0bSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
894a74ead0bSpatrick 		return 0;
895a74ead0bSpatrick 
896a74ead0bSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
897a74ead0bSpatrick 	mux >>= sc->sc_muxs[idx].shift;
898a74ead0bSpatrick 	mux &= sc->sc_muxs[idx].mask;
899a74ead0bSpatrick 
900a74ead0bSpatrick 	switch (mux) {
901a74ead0bSpatrick 	case 0:
902a74ead0bSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
903a74ead0bSpatrick 	case 1:
904a74ead0bSpatrick 		return 125 * 1000 * 1000; /* sys2_pll_125m */
905a74ead0bSpatrick 	default:
906a74ead0bSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
907a74ead0bSpatrick 		return 0;
908a74ead0bSpatrick 	}
909a74ead0bSpatrick }
910a74ead0bSpatrick 
911a74ead0bSpatrick uint32_t
imxccm_imx8mp_enet_qos_timer(struct imxccm_softc * sc,uint32_t idx)912a74ead0bSpatrick imxccm_imx8mp_enet_qos_timer(struct imxccm_softc *sc, uint32_t idx)
913a74ead0bSpatrick {
914a74ead0bSpatrick 	uint32_t mux;
915a74ead0bSpatrick 
916a74ead0bSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
917a74ead0bSpatrick 		return 0;
918a74ead0bSpatrick 
919a74ead0bSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
920a74ead0bSpatrick 	mux >>= sc->sc_muxs[idx].shift;
921a74ead0bSpatrick 	mux &= sc->sc_muxs[idx].mask;
922a74ead0bSpatrick 
923a74ead0bSpatrick 	switch (mux) {
924a74ead0bSpatrick 	case 0:
925a74ead0bSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
926a74ead0bSpatrick 	case 1:
927a74ead0bSpatrick 		return 100 * 1000 * 1000; /* sys2_pll_100m */
928a74ead0bSpatrick 	default:
929a74ead0bSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
930a74ead0bSpatrick 		return 0;
931a74ead0bSpatrick 	}
932a74ead0bSpatrick }
933a74ead0bSpatrick 
934a74ead0bSpatrick uint32_t
imxccm_imx8mp_hsio_axi(struct imxccm_softc * sc,uint32_t idx)93559cc782fSpatrick imxccm_imx8mp_hsio_axi(struct imxccm_softc *sc, uint32_t idx)
93659cc782fSpatrick {
93759cc782fSpatrick 	uint32_t mux;
93859cc782fSpatrick 
93959cc782fSpatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
94059cc782fSpatrick 		return 0;
94159cc782fSpatrick 
94259cc782fSpatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
94359cc782fSpatrick 	mux >>= sc->sc_muxs[idx].shift;
94459cc782fSpatrick 	mux &= sc->sc_muxs[idx].mask;
94559cc782fSpatrick 
94659cc782fSpatrick 	switch (mux) {
94759cc782fSpatrick 	case 0:
94859cc782fSpatrick 		return clock_get_frequency(sc->sc_node, "osc_24m");
94959cc782fSpatrick 	case 1:
95059cc782fSpatrick 		return 500 * 1000 * 1000; /* sys2_pll_500m */
95159cc782fSpatrick 	default:
95259cc782fSpatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
95359cc782fSpatrick 		return 0;
95459cc782fSpatrick 	}
95559cc782fSpatrick }
95659cc782fSpatrick 
95759cc782fSpatrick uint32_t
imxccm_imx8mq_ecspi(struct imxccm_softc * sc,uint32_t idx)9588ea71dd1Spatrick imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx)
9598ea71dd1Spatrick {
9608ea71dd1Spatrick 	uint32_t mux;
9618ea71dd1Spatrick 
9628ea71dd1Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
9638ea71dd1Spatrick 		return 0;
9648ea71dd1Spatrick 
9658ea71dd1Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
9668ea71dd1Spatrick 	mux >>= sc->sc_muxs[idx].shift;
9678ea71dd1Spatrick 	mux &= sc->sc_muxs[idx].mask;
9688ea71dd1Spatrick 
9698ea71dd1Spatrick 	switch (mux) {
9708ea71dd1Spatrick 	case 0:
9718ea71dd1Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
9728ea71dd1Spatrick 	case 1:
9738ea71dd1Spatrick 		return 200 * 1000 * 1000; /* sys2_pll_200m */
9748ea71dd1Spatrick 	default:
9758ea71dd1Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
9768ea71dd1Spatrick 		return 0;
9778ea71dd1Spatrick 	}
9788ea71dd1Spatrick }
9798ea71dd1Spatrick 
9808ea71dd1Spatrick uint32_t
imxccm_imx8mq_enet(struct imxccm_softc * sc,uint32_t idx)981a8196585Spatrick imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t idx)
982a8196585Spatrick {
983a8196585Spatrick 	uint32_t mux;
984a8196585Spatrick 
985a8196585Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
986a8196585Spatrick 		return 0;
987a8196585Spatrick 
988a8196585Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
989a8196585Spatrick 	mux >>= sc->sc_muxs[idx].shift;
990a8196585Spatrick 	mux &= sc->sc_muxs[idx].mask;
991a8196585Spatrick 
992a8196585Spatrick 	switch (mux) {
993a8196585Spatrick 	case 0:
994a8196585Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
995a8196585Spatrick 	case 1:
996a8196585Spatrick 		return 266 * 1000 * 1000; /* sys1_pll_266m */
997a8196585Spatrick 	default:
998a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
999a8196585Spatrick 		return 0;
1000a8196585Spatrick 	}
1001a8196585Spatrick }
1002a8196585Spatrick 
1003a8196585Spatrick uint32_t
imxccm_imx8mq_ahb(struct imxccm_softc * sc,uint32_t idx)10046d21c932Spatrick imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t idx)
10056d21c932Spatrick {
10066d21c932Spatrick 	uint32_t mux;
10076d21c932Spatrick 
10086d21c932Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
10096d21c932Spatrick 		return 0;
10106d21c932Spatrick 
10116d21c932Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
10126d21c932Spatrick 	mux >>= sc->sc_muxs[idx].shift;
10136d21c932Spatrick 	mux &= sc->sc_muxs[idx].mask;
10146d21c932Spatrick 
10156d21c932Spatrick 	switch (mux) {
10166d21c932Spatrick 	case 0:
10176d21c932Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
10186d21c932Spatrick 	case 1:
10196d21c932Spatrick 		return 133 * 1000 * 1000; /* sys1_pll_133m */
10206d21c932Spatrick 	case 2:
10216d21c932Spatrick 		return 800 * 1000 * 1000; /* sys1_pll_800m */
10226d21c932Spatrick 	case 3:
10236d21c932Spatrick 		return 400 * 1000 * 1000; /* sys1_pll_400m */
10246d21c932Spatrick 	case 4:
10256d21c932Spatrick 		return 125 * 1000 * 1000; /* sys2_pll_125m */
10266d21c932Spatrick 	default:
10276d21c932Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
10286d21c932Spatrick 		return 0;
10296d21c932Spatrick 	}
10306d21c932Spatrick }
10316d21c932Spatrick 
10326d21c932Spatrick uint32_t
imxccm_imx8mq_i2c(struct imxccm_softc * sc,uint32_t idx)1033a8196585Spatrick imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t idx)
1034a8196585Spatrick {
1035a8196585Spatrick 	uint32_t mux;
1036a8196585Spatrick 
1037a8196585Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1038a8196585Spatrick 		return 0;
1039a8196585Spatrick 
1040a8196585Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1041a8196585Spatrick 	mux >>= sc->sc_muxs[idx].shift;
1042a8196585Spatrick 	mux &= sc->sc_muxs[idx].mask;
1043a8196585Spatrick 
1044a8196585Spatrick 	switch (mux) {
1045a8196585Spatrick 	case 0:
1046a8196585Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
1047a8196585Spatrick 	default:
1048a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1049a8196585Spatrick 		return 0;
1050a8196585Spatrick 	}
1051a8196585Spatrick }
1052a8196585Spatrick 
1053a8196585Spatrick uint32_t
imxccm_imx8mq_pwm(struct imxccm_softc * sc,uint32_t idx)1054392fcdd1Spatrick imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t idx)
1055392fcdd1Spatrick {
1056392fcdd1Spatrick 	uint32_t mux;
1057392fcdd1Spatrick 
1058392fcdd1Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1059392fcdd1Spatrick 		return 0;
1060392fcdd1Spatrick 
1061392fcdd1Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1062392fcdd1Spatrick 	mux >>= sc->sc_muxs[idx].shift;
1063392fcdd1Spatrick 	mux &= sc->sc_muxs[idx].mask;
1064392fcdd1Spatrick 
1065392fcdd1Spatrick 	switch (mux) {
1066392fcdd1Spatrick 	case 0:
1067392fcdd1Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
1068392fcdd1Spatrick 	case 1:
1069392fcdd1Spatrick 		return 100 * 1000 * 1000; /* sys1_pll_100m */
1070392fcdd1Spatrick 	case 2:
1071392fcdd1Spatrick 		return 160 * 1000 * 1000; /* sys1_pll_160m */
1072392fcdd1Spatrick 	case 3:
1073392fcdd1Spatrick 		return 40 * 1000 * 1000; /* sys1_pll_40m */
1074392fcdd1Spatrick 	default:
1075392fcdd1Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1076392fcdd1Spatrick 		return 0;
1077392fcdd1Spatrick 	}
1078392fcdd1Spatrick }
1079392fcdd1Spatrick 
1080392fcdd1Spatrick uint32_t
imxccm_imx8mq_uart(struct imxccm_softc * sc,uint32_t idx)1081a8196585Spatrick imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t idx)
1082a8196585Spatrick {
1083a8196585Spatrick 	uint32_t mux;
1084a8196585Spatrick 
1085a8196585Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1086a8196585Spatrick 		return 0;
1087a8196585Spatrick 
1088a8196585Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1089a8196585Spatrick 	mux >>= sc->sc_muxs[idx].shift;
1090a8196585Spatrick 	mux &= sc->sc_muxs[idx].mask;
1091a8196585Spatrick 
1092a8196585Spatrick 	switch (mux) {
1093a8196585Spatrick 	case 0:
1094a8196585Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
1095a8196585Spatrick 	default:
1096a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1097a8196585Spatrick 		return 0;
1098a8196585Spatrick 	}
1099a8196585Spatrick }
1100a8196585Spatrick 
1101a8196585Spatrick uint32_t
imxccm_imx8mq_usdhc(struct imxccm_softc * sc,uint32_t idx)1102a8196585Spatrick imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t idx)
1103a8196585Spatrick {
1104a8196585Spatrick 	uint32_t mux;
1105a8196585Spatrick 
1106a8196585Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1107a8196585Spatrick 		return 0;
1108a8196585Spatrick 
1109a8196585Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1110a8196585Spatrick 	mux >>= sc->sc_muxs[idx].shift;
1111a8196585Spatrick 	mux &= sc->sc_muxs[idx].mask;
1112a8196585Spatrick 
1113a8196585Spatrick 	switch (mux) {
1114a8196585Spatrick 	case 0:
1115a8196585Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
1116a8196585Spatrick 	case 1:
1117a8196585Spatrick 		return 400 * 1000 * 1000; /* sys1_pll_400m */
1118a8196585Spatrick 	default:
1119a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1120a8196585Spatrick 		return 0;
1121a8196585Spatrick 	}
1122a8196585Spatrick }
1123a8196585Spatrick 
1124a8196585Spatrick uint32_t
imxccm_imx8mq_usb(struct imxccm_softc * sc,uint32_t idx)1125a8196585Spatrick imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t idx)
1126a8196585Spatrick {
1127a8196585Spatrick 	uint32_t mux;
1128a8196585Spatrick 
1129a8196585Spatrick 	if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0)
1130a8196585Spatrick 		return 0;
1131a8196585Spatrick 
1132a8196585Spatrick 	mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1133a8196585Spatrick 	mux >>= sc->sc_muxs[idx].shift;
1134a8196585Spatrick 	mux &= sc->sc_muxs[idx].mask;
1135a8196585Spatrick 
1136a8196585Spatrick 	switch (mux) {
1137a8196585Spatrick 	case 0:
1138a8196585Spatrick 		return clock_get_frequency(sc->sc_node, "osc_25m");
1139a8196585Spatrick 	case 1:
1140071150a2Spatrick 		if (idx == IMX8MQ_CLK_USB_CORE_REF ||
1141071150a2Spatrick 		    idx == IMX8MQ_CLK_USB_PHY_REF)
1142a8196585Spatrick 			return 100 * 1000 * 1000; /* sys1_pll_100m */
1143071150a2Spatrick 		if (idx == IMX8MQ_CLK_USB_BUS)
1144a8196585Spatrick 			return 500 * 1000 * 1000; /* sys2_pll_500m */
1145a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1146a8196585Spatrick 		return 0;
1147a8196585Spatrick 	default:
1148a8196585Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1149a8196585Spatrick 		return 0;
1150a8196585Spatrick 	}
1151a8196585Spatrick }
1152a8196585Spatrick 
1153b31392d8Spatrick uint32_t
imxccm_imx8mq_get_pll(struct imxccm_softc * sc,uint32_t idx)1154b31392d8Spatrick imxccm_imx8mq_get_pll(struct imxccm_softc *sc, uint32_t idx)
1155b31392d8Spatrick {
1156b31392d8Spatrick 	uint32_t divr_val, divq_val, divf_val;
1157b31392d8Spatrick 	uint32_t divff, divfi;
1158b31392d8Spatrick 	uint32_t pllout_div;
1159b31392d8Spatrick 	uint32_t pll0, pll1;
1160b31392d8Spatrick 	uint32_t freq;
1161b31392d8Spatrick 	uint32_t mux;
1162b31392d8Spatrick 
1163b31392d8Spatrick 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1164b31392d8Spatrick 
1165b31392d8Spatrick 	switch (idx) {
1166b31392d8Spatrick 	case IMX8MQ_ARM_PLL:
1167b31392d8Spatrick 		pll0 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL0);
1168b31392d8Spatrick 		pll1 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL1);
1169b31392d8Spatrick 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1170b31392d8Spatrick 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1171b31392d8Spatrick 		break;
1172b31392d8Spatrick 	default:
1173b31392d8Spatrick 		printf("%s: 0x%08x\n", __func__, idx);
1174b31392d8Spatrick 		return 0;
1175b31392d8Spatrick 	}
1176b31392d8Spatrick 
1177b31392d8Spatrick 	if (pll0 & CCM_FRAC_PLL_POWERDOWN)
1178b31392d8Spatrick 		return 0;
1179b31392d8Spatrick 
1180b31392d8Spatrick 	if ((pll0 & CCM_FRAC_PLL_ENABLE) == 0)
1181b31392d8Spatrick 		return 0;
1182b31392d8Spatrick 
1183b31392d8Spatrick 	mux = (pll0 >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1184b31392d8Spatrick 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1185b31392d8Spatrick 	switch (mux) {
1186b31392d8Spatrick 	case 0:
1187b31392d8Spatrick 		freq = clock_get_frequency(sc->sc_node, "osc_25m");
1188b31392d8Spatrick 		break;
1189b31392d8Spatrick 	case 1:
1190b31392d8Spatrick 	case 2:
1191b31392d8Spatrick 		freq = clock_get_frequency(sc->sc_node, "osc_27m");
1192b31392d8Spatrick 		break;
1193b31392d8Spatrick 	default:
1194b31392d8Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1195b31392d8Spatrick 		return 0;
1196b31392d8Spatrick 	}
1197b31392d8Spatrick 
1198b31392d8Spatrick 	if (pll0 & CCM_FRAC_PLL_BYPASS)
1199b31392d8Spatrick 		return freq;
1200b31392d8Spatrick 
1201b31392d8Spatrick 	divr_val = (pll0 >> CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT) &
1202b31392d8Spatrick 	    CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK;
1203b31392d8Spatrick 	divq_val = pll0 & CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1204b31392d8Spatrick 	divff = (pll1 >> CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT) &
1205b31392d8Spatrick 	    CCM_FRAC_PLL_FRAC_DIV_CTL_MASK;
1206b31392d8Spatrick 	divfi = pll1 & CCM_FRAC_PLL_INT_DIV_CTL_MASK;
1207b31392d8Spatrick 	divf_val = 1 + divfi + divff / CCM_FRAC_PLL_DENOM;
1208b31392d8Spatrick 
1209b31392d8Spatrick 	freq = freq / (divr_val + 1) * 8 * divf_val / ((divq_val + 1) * 2);
1210b31392d8Spatrick 	return freq / (pllout_div + 1);
1211b31392d8Spatrick }
1212b31392d8Spatrick 
1213b31392d8Spatrick int
imxccm_imx8mq_set_pll(struct imxccm_softc * sc,uint32_t idx,uint64_t freq)1214b31392d8Spatrick imxccm_imx8mq_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq)
1215b31392d8Spatrick {
1216b31392d8Spatrick 	uint64_t divff, divfi, divr;
1217b31392d8Spatrick 	uint32_t pllout_div;
1218b31392d8Spatrick 	uint32_t pll0, pll1;
1219b31392d8Spatrick 	uint32_t mux, reg;
1220b31392d8Spatrick 	uint64_t pfreq;
1221b31392d8Spatrick 	int i;
1222b31392d8Spatrick 
1223b31392d8Spatrick 	pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG);
1224b31392d8Spatrick 
1225b31392d8Spatrick 	switch (idx) {
1226b31392d8Spatrick 	case IMX8MQ_ARM_PLL:
1227b31392d8Spatrick 		pll0 = CCM_FRAC_IMX8M_ARM_PLL0;
1228b31392d8Spatrick 		pll1 = CCM_FRAC_IMX8M_ARM_PLL1;
1229b31392d8Spatrick 		pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT;
1230b31392d8Spatrick 		pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK;
1231b31392d8Spatrick 		/* XXX: Assume fixed divider to ease math. */
1232b31392d8Spatrick 		KASSERT(pllout_div == 0);
1233b31392d8Spatrick 		divr = 5;
1234b31392d8Spatrick 		break;
1235b31392d8Spatrick 	default:
1236b31392d8Spatrick 		printf("%s: 0x%08x\n", __func__, idx);
1237b31392d8Spatrick 		return -1;
1238b31392d8Spatrick 	}
1239b31392d8Spatrick 
1240b31392d8Spatrick 	reg = regmap_read_4(sc->sc_anatop, pll0);
1241b31392d8Spatrick 	mux = (reg >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) &
1242b31392d8Spatrick 	    CCM_FRAC_PLL_REFCLK_SEL_MASK;
1243b31392d8Spatrick 	switch (mux) {
1244b31392d8Spatrick 	case 0:
1245b31392d8Spatrick 		pfreq = clock_get_frequency(sc->sc_node, "osc_25m");
1246b31392d8Spatrick 		break;
1247b31392d8Spatrick 	case 1:
1248b31392d8Spatrick 	case 2:
1249b31392d8Spatrick 		pfreq = clock_get_frequency(sc->sc_node, "osc_27m");
1250b31392d8Spatrick 		break;
1251b31392d8Spatrick 	default:
1252b31392d8Spatrick 		printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux);
1253b31392d8Spatrick 		return -1;
1254b31392d8Spatrick 	}
1255b31392d8Spatrick 
1256b31392d8Spatrick 	/* Frac divider follows the PLL */
1257b31392d8Spatrick 	freq *= divr;
1258b31392d8Spatrick 
1259b31392d8Spatrick 	/* PLL calculation */
1260b31392d8Spatrick 	freq *= 2;
1261b31392d8Spatrick 	pfreq *= 8;
1262b31392d8Spatrick 	divfi = freq / pfreq;
1263b31392d8Spatrick 	divff = (uint64_t)(freq - divfi * pfreq);
1264b31392d8Spatrick 	divff = (divff * CCM_FRAC_PLL_DENOM) / pfreq;
1265b31392d8Spatrick 
1266b31392d8Spatrick 	reg = regmap_read_4(sc->sc_anatop, pll1);
1267b31392d8Spatrick 	reg &= ~(CCM_FRAC_PLL_FRAC_DIV_CTL_MASK << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT);
1268b31392d8Spatrick 	reg |= divff << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT;
1269b31392d8Spatrick 	reg &= ~(CCM_FRAC_PLL_INT_DIV_CTL_MASK << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT);
1270b31392d8Spatrick 	reg |= (divfi - 1) << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT;
1271b31392d8Spatrick 	regmap_write_4(sc->sc_anatop, pll1, reg);
1272b31392d8Spatrick 
1273b31392d8Spatrick 	reg = regmap_read_4(sc->sc_anatop, pll0);
1274b31392d8Spatrick 	reg &= ~CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK;
1275b31392d8Spatrick 	reg &= ~(CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT);
1276b31392d8Spatrick 	reg |= (divr - 1) << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT;
1277b31392d8Spatrick 	regmap_write_4(sc->sc_anatop, pll0, reg);
1278b31392d8Spatrick 
1279b31392d8Spatrick 	reg = regmap_read_4(sc->sc_anatop, pll0);
1280b31392d8Spatrick 	reg |= CCM_FRAC_PLL_NEWDIV_VAL;
1281b31392d8Spatrick 	regmap_write_4(sc->sc_anatop, pll0, reg);
1282b31392d8Spatrick 
1283b31392d8Spatrick 	for (i = 0; i < 5000; i++) {
1284b31392d8Spatrick 		reg = regmap_read_4(sc->sc_anatop, pll0);
1285b31392d8Spatrick 		if (reg & CCM_FRAC_PLL_BYPASS)
1286b31392d8Spatrick 			break;
1287b31392d8Spatrick 		if (reg & CCM_FRAC_PLL_POWERDOWN)
1288b31392d8Spatrick 			break;
1289b31392d8Spatrick 		if (reg & CCM_FRAC_PLL_NEWDIV_ACK)
1290b31392d8Spatrick 			break;
1291b31392d8Spatrick 		delay(10);
1292b31392d8Spatrick 	}
1293b31392d8Spatrick 	if (i == 5000)
1294b31392d8Spatrick 		printf("%s: timeout\n", __func__);
1295b31392d8Spatrick 
1296b31392d8Spatrick 	reg = regmap_read_4(sc->sc_anatop, pll0);
1297b31392d8Spatrick 	reg &= ~CCM_FRAC_PLL_NEWDIV_VAL;
1298b31392d8Spatrick 	regmap_write_4(sc->sc_anatop, pll0, reg);
1299b31392d8Spatrick 
1300b31392d8Spatrick 	return 0;
1301b31392d8Spatrick }
1302b31392d8Spatrick 
130358c0d41eSpatrick int
imxccm_imx8m_set_div(struct imxccm_softc * sc,uint32_t idx,uint64_t freq,uint64_t parent_freq)130458c0d41eSpatrick imxccm_imx8m_set_div(struct imxccm_softc *sc, uint32_t idx, uint64_t freq,
130558c0d41eSpatrick     uint64_t parent_freq)
130658c0d41eSpatrick {
130758c0d41eSpatrick 	uint64_t div;
130858c0d41eSpatrick 	uint32_t reg;
130958c0d41eSpatrick 
131058c0d41eSpatrick 	if (parent_freq < freq) {
131158c0d41eSpatrick 		printf("%s: parent frequency too low (0x%08x)\n",
131258c0d41eSpatrick 		    __func__, idx);
131358c0d41eSpatrick 		return -1;
131458c0d41eSpatrick 	}
131558c0d41eSpatrick 
131658c0d41eSpatrick 	/* divisor can only be changed if enabled */
131758c0d41eSpatrick 	imxccm_enable(sc, &idx, 1);
131858c0d41eSpatrick 
131958c0d41eSpatrick 	div = 0;
132058c0d41eSpatrick 	while (parent_freq / (div + 1) > freq)
132158c0d41eSpatrick 		div++;
132258c0d41eSpatrick 	reg = HREAD4(sc, sc->sc_divs[idx].reg);
132358c0d41eSpatrick 	reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
132458c0d41eSpatrick 	reg |= (div << sc->sc_divs[idx].shift);
132558c0d41eSpatrick 	HWRITE4(sc, sc->sc_divs[idx].reg, reg);
132658c0d41eSpatrick 	HCLR4(sc, sc->sc_predivs[idx].reg,
132758c0d41eSpatrick 	    sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift);
132858c0d41eSpatrick 	return 0;
132958c0d41eSpatrick }
133058c0d41eSpatrick 
13314bed6a7dSpatrick void
imxccm_enable_parent(struct imxccm_softc * sc,uint32_t parent,int on)13326c60662eSkettenis imxccm_enable_parent(struct imxccm_softc *sc, uint32_t parent, int on)
13336c60662eSkettenis {
13346c60662eSkettenis 	if (on)
13356c60662eSkettenis 		imxccm_enable(sc, &parent, on);
13366c60662eSkettenis }
13376c60662eSkettenis 
13386c60662eSkettenis void
imxccm_enable(void * cookie,uint32_t * cells,int on)13394bed6a7dSpatrick imxccm_enable(void *cookie, uint32_t *cells, int on)
13404bed6a7dSpatrick {
13414bed6a7dSpatrick 	struct imxccm_softc *sc = cookie;
1342a8196585Spatrick 	uint32_t idx = cells[0], parent;
1343d7894d79Spatrick 	uint32_t pcells[2];
1344a8196585Spatrick 	uint16_t reg;
1345a8196585Spatrick 	uint8_t pos;
13464bed6a7dSpatrick 
13474bed6a7dSpatrick 	/* Dummy clock. */
13484bed6a7dSpatrick 	if (idx == 0)
13494bed6a7dSpatrick 		return;
13504bed6a7dSpatrick 
135165c9ab81Spatrick 	if (sc->sc_gates == imx8mm_gates) {
135265c9ab81Spatrick 		switch (idx) {
135365c9ab81Spatrick 		case IMX8MM_CLK_PCIE1_CTRL:
135465c9ab81Spatrick 		case IMX8MM_CLK_PCIE2_CTRL:
135565c9ab81Spatrick 			pcells[0] = sc->sc_phandle;
135665c9ab81Spatrick 			pcells[1] = IMX8MM_SYS_PLL2_250M;
135765c9ab81Spatrick 			imxccm_set_parent(cookie, &idx, pcells);
135865c9ab81Spatrick 			break;
135965c9ab81Spatrick 		case IMX8MM_CLK_PCIE1_PHY:
136065c9ab81Spatrick 		case IMX8MM_CLK_PCIE2_PHY:
136165c9ab81Spatrick 			pcells[0] = sc->sc_phandle;
136265c9ab81Spatrick 			pcells[1] = IMX8MM_SYS_PLL2_100M;
136365c9ab81Spatrick 			imxccm_set_parent(cookie, &idx, pcells);
136465c9ab81Spatrick 			break;
136565c9ab81Spatrick 		}
136665c9ab81Spatrick 	} else if (sc->sc_gates == imx8mq_gates) {
1367d7894d79Spatrick 		switch (idx) {
1368a455bd9dSpatrick 		case IMX8MQ_CLK_32K:
1369a455bd9dSpatrick 			/* always on */
1370a455bd9dSpatrick 			return;
1371d7894d79Spatrick 		case IMX8MQ_CLK_PCIE1_CTRL:
1372d7894d79Spatrick 		case IMX8MQ_CLK_PCIE2_CTRL:
1373d7894d79Spatrick 			pcells[0] = sc->sc_phandle;
1374d7894d79Spatrick 			pcells[1] = IMX8MQ_SYS2_PLL_250M;
1375d7894d79Spatrick 			imxccm_set_parent(cookie, &idx, pcells);
1376d7894d79Spatrick 			break;
1377d7894d79Spatrick 		case IMX8MQ_CLK_PCIE1_PHY:
1378d7894d79Spatrick 		case IMX8MQ_CLK_PCIE2_PHY:
1379d7894d79Spatrick 			pcells[0] = sc->sc_phandle;
1380d7894d79Spatrick 			pcells[1] = IMX8MQ_SYS2_PLL_100M;
1381d7894d79Spatrick 			imxccm_set_parent(cookie, &idx, pcells);
1382d7894d79Spatrick 			break;
1383d7894d79Spatrick 		}
1384d7894d79Spatrick 	} else if (sc->sc_gates == imx7d_gates) {
13856c60662eSkettenis 		if (sc->sc_anatop == NULL) {
13866c60662eSkettenis 			sc->sc_anatop = regmap_bycompatible("fsl,imx7d-anatop");
13876c60662eSkettenis 			KASSERT(sc->sc_anatop);
13886c60662eSkettenis 		}
13896c60662eSkettenis 
139086101169Skettenis 		switch (idx) {
139186101169Skettenis 		case IMX7D_PLL_ENET_MAIN_125M_CLK:
139286101169Skettenis 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_SET,
139386101169Skettenis 			    CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ);
139486101169Skettenis 			return;
139586101169Skettenis 		default:
139686101169Skettenis 			break;
139786101169Skettenis 		}
139886101169Skettenis 	} else if (sc->sc_gates == imx6_gates) {
13996c60662eSkettenis 		if (sc->sc_anatop == NULL) {
14006c60662eSkettenis 			sc->sc_anatop = regmap_bycompatible("fsl,imx6q-anatop");
14016c60662eSkettenis 			KASSERT(sc->sc_anatop);
14026c60662eSkettenis 		}
14036c60662eSkettenis 
14044bed6a7dSpatrick 		switch (idx) {
14056c60662eSkettenis 		case IMX6_CLK_PLL3:
14066c60662eSkettenis 			imxccm_imx6_enable_pll_usb1(sc, on);
14076c60662eSkettenis 			return;
14086c60662eSkettenis 		case IMX6_CLK_PLL6:
14096c60662eSkettenis 			imxccm_imx6_enable_pll_enet(sc, on);
14106c60662eSkettenis 			return;
14116c60662eSkettenis 		case IMX6_CLK_PLL7:
14126c60662eSkettenis 			imxccm_imx6_enable_pll_usb2(sc, on);
14136c60662eSkettenis 			return;
14146c60662eSkettenis 		case IMX6_CLK_PLL3_USB_OTG:
14156c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL3, on);
14166c60662eSkettenis 			regmap_write_4(sc->sc_anatop,
14176c60662eSkettenis 			    on ? CCM_ANALOG_PLL_USB1_SET : CCM_ANALOG_PLL_USB1_CLR,
14186c60662eSkettenis 			    CCM_ANALOG_PLL_USB1_ENABLE);
14196c60662eSkettenis 			return;
14206c60662eSkettenis 		case IMX6_CLK_PLL6_ENET:
14216c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL6, on);
14226c60662eSkettenis 			regmap_write_4(sc->sc_anatop,
14236c60662eSkettenis 			    on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
14246c60662eSkettenis 			    CCM_ANALOG_PLL_ENET_ENABLE);
14256c60662eSkettenis 			return;
14266c60662eSkettenis 		case IMX6_CLK_PLL7_USB_HOST:
14276c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL7, on);
14286c60662eSkettenis 			regmap_write_4(sc->sc_anatop,
14296c60662eSkettenis 			    on ? CCM_ANALOG_PLL_USB2_SET : CCM_ANALOG_PLL_USB2_CLR,
14306c60662eSkettenis 			    CCM_ANALOG_PLL_USB2_ENABLE);
14316c60662eSkettenis 			return;
14324bed6a7dSpatrick 		case IMX6_CLK_USBPHY1:
14334b1a56afSjsg 			/* PLL outputs should always be on. */
14346c60662eSkettenis 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET,
14356c60662eSkettenis 			    CCM_ANALOG_PLL_USB1_EN_USB_CLKS);
14366c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL3_USB_OTG, on);
14374bed6a7dSpatrick 			return;
14384bed6a7dSpatrick 		case IMX6_CLK_USBPHY2:
14394b1a56afSjsg 			/* PLL outputs should always be on. */
14406c60662eSkettenis 			regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET,
14416c60662eSkettenis 			    CCM_ANALOG_PLL_USB2_EN_USB_CLKS);
14426c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL7_USB_HOST, on);
14434bed6a7dSpatrick 			return;
14444bed6a7dSpatrick 		case IMX6_CLK_SATA_REF_100:
14456c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
14466c60662eSkettenis 			regmap_write_4(sc->sc_anatop,
14476c60662eSkettenis 			   on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR,
14486c60662eSkettenis 			   CCM_ANALOG_PLL_ENET_ENABLE_100M);
14494bed6a7dSpatrick 			return;
14504bed6a7dSpatrick 		case IMX6_CLK_ENET_REF:
14516c60662eSkettenis 			imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on);
14524bed6a7dSpatrick 			return;
1453a8196585Spatrick 		case IMX6_CLK_IPG:
1454a8196585Spatrick 		case IMX6_CLK_IPG_PER:
1455e45f7b26Spatrick 		case IMX6_CLK_ECSPI_ROOT:
1456a8196585Spatrick 			/* always on */
1457a8196585Spatrick 			return;
14584bed6a7dSpatrick 		default:
14594bed6a7dSpatrick 			break;
14604bed6a7dSpatrick 		}
14614bed6a7dSpatrick 	}
14624bed6a7dSpatrick 
1463a8196585Spatrick 	if (on) {
1464a8196585Spatrick 		if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
1465a8196585Spatrick 			parent = sc->sc_gates[idx].parent;
1466a8196585Spatrick 			imxccm_enable(sc, &parent, on);
1467a8196585Spatrick 		}
1468a8196585Spatrick 
1469a8196585Spatrick 		if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1470a8196585Spatrick 			parent = sc->sc_divs[idx].parent;
1471a8196585Spatrick 			imxccm_enable(sc, &parent, on);
1472a8196585Spatrick 		}
1473a8196585Spatrick 	}
1474a8196585Spatrick 
1475c26129e1Spatrick 	if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
1476a8196585Spatrick 		if ((idx < sc->sc_ndivs && sc->sc_divs[idx].reg != 0) ||
1477a8196585Spatrick 		    (idx < sc->sc_nmuxs && sc->sc_muxs[idx].reg != 0))
1478a8196585Spatrick 			return;
14794bed6a7dSpatrick 		printf("%s: 0x%08x\n", __func__, idx);
14804bed6a7dSpatrick 		return;
14814bed6a7dSpatrick 	}
14824bed6a7dSpatrick 
14834bed6a7dSpatrick 	reg = sc->sc_gates[idx].reg;
14844bed6a7dSpatrick 	pos = sc->sc_gates[idx].pos;
14854bed6a7dSpatrick 
14864bed6a7dSpatrick 	if (on)
14874bed6a7dSpatrick 		HSET4(sc, reg, 0x3 << (2 * pos));
14884bed6a7dSpatrick 	else
14894bed6a7dSpatrick 		HCLR4(sc, reg, 0x3 << (2 * pos));
14904bed6a7dSpatrick }
14914bed6a7dSpatrick 
14924bed6a7dSpatrick uint32_t
imxccm_get_frequency(void * cookie,uint32_t * cells)14934bed6a7dSpatrick imxccm_get_frequency(void *cookie, uint32_t *cells)
14944bed6a7dSpatrick {
14954bed6a7dSpatrick 	struct imxccm_softc *sc = cookie;
14964bed6a7dSpatrick 	uint32_t idx = cells[0];
1497071150a2Spatrick 	uint32_t div, pre, reg, parent;
1498071150a2Spatrick 	uint32_t freq;
14994bed6a7dSpatrick 
15004bed6a7dSpatrick 	/* Dummy clock. */
15014bed6a7dSpatrick 	if (idx == 0)
15024bed6a7dSpatrick 		return 0;
15034bed6a7dSpatrick 
15044bed6a7dSpatrick 	if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
15054bed6a7dSpatrick 		parent = sc->sc_gates[idx].parent;
15064bed6a7dSpatrick 		return imxccm_get_frequency(sc, &parent);
15074bed6a7dSpatrick 	}
15084bed6a7dSpatrick 
1509a8196585Spatrick 	if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) {
1510a8196585Spatrick 		div = HREAD4(sc, sc->sc_divs[idx].reg);
1511a8196585Spatrick 		div = div >> sc->sc_divs[idx].shift;
1512a8196585Spatrick 		div = div & sc->sc_divs[idx].mask;
1513a8196585Spatrick 		parent = sc->sc_divs[idx].parent;
1514a8196585Spatrick 		return imxccm_get_frequency(sc, &parent) / (div + 1);
1515a8196585Spatrick 	}
1516a8196585Spatrick 
15176e71e8feSpatrick 	if (sc->sc_gates == imx8mm_gates) {
15186e71e8feSpatrick 		switch (idx) {
15196e71e8feSpatrick 		case IMX8MM_CLK_ARM:
15206e71e8feSpatrick 			parent = IMX8MM_ARM_PLL;
15216e71e8feSpatrick 			return imxccm_get_frequency(sc, &parent);
15226e71e8feSpatrick 		case IMX8MM_ARM_PLL:
15236e71e8feSpatrick 			return imxccm_imx8mm_get_pll(sc, idx);
15246e71e8feSpatrick 		}
15256e71e8feSpatrick 
15266e71e8feSpatrick 		/* These are composite clocks. */
15276e71e8feSpatrick 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
15286e71e8feSpatrick 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
15296e71e8feSpatrick 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
15306e71e8feSpatrick 			switch (idx) {
15316e71e8feSpatrick 			case IMX8MM_CLK_ENET_AXI:
15326e71e8feSpatrick 				freq = imxccm_imx8mm_enet(sc, idx);
15336e71e8feSpatrick 				break;
15346d21c932Spatrick 			case IMX8MM_CLK_AHB:
15356d21c932Spatrick 				freq = imxccm_imx8mm_ahb(sc, idx);
15366d21c932Spatrick 				break;
15376e71e8feSpatrick 			case IMX8MM_CLK_I2C1:
15386e71e8feSpatrick 			case IMX8MM_CLK_I2C2:
15396e71e8feSpatrick 			case IMX8MM_CLK_I2C3:
15406e71e8feSpatrick 			case IMX8MM_CLK_I2C4:
15416e71e8feSpatrick 				freq = imxccm_imx8mm_i2c(sc, idx);
15426e71e8feSpatrick 				break;
15436e71e8feSpatrick 			case IMX8MM_CLK_UART1:
15446e71e8feSpatrick 			case IMX8MM_CLK_UART2:
15456e71e8feSpatrick 			case IMX8MM_CLK_UART3:
15466e71e8feSpatrick 			case IMX8MM_CLK_UART4:
15476e71e8feSpatrick 				freq = imxccm_imx8mm_uart(sc, idx);
15486e71e8feSpatrick 				break;
15496e71e8feSpatrick 			case IMX8MM_CLK_USDHC1:
15506e71e8feSpatrick 			case IMX8MM_CLK_USDHC2:
15516e71e8feSpatrick 			case IMX8MM_CLK_USDHC3:
15526e71e8feSpatrick 				freq = imxccm_imx8mm_usdhc(sc, idx);
15536e71e8feSpatrick 				break;
15546e71e8feSpatrick 			default:
15556e71e8feSpatrick 				printf("%s: 0x%08x\n", __func__, idx);
15566e71e8feSpatrick 				return 0;
15576e71e8feSpatrick 			}
15586e71e8feSpatrick 
15596e71e8feSpatrick 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
15606e71e8feSpatrick 			div = reg >> sc->sc_divs[idx].shift;
15616e71e8feSpatrick 			div = div & sc->sc_divs[idx].mask;
15626e71e8feSpatrick 			pre = reg >> sc->sc_predivs[idx].shift;
15636e71e8feSpatrick 			pre = pre & sc->sc_predivs[idx].mask;
15646e71e8feSpatrick 			return ((freq / (pre + 1)) / (div + 1));
15656e71e8feSpatrick 		}
156622a4f870Spatrick 	} else if (sc->sc_gates == imx8mp_gates) {
156722a4f870Spatrick 		/* These are composite clocks. */
156822a4f870Spatrick 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
156922a4f870Spatrick 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
157022a4f870Spatrick 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
157122a4f870Spatrick 			switch (idx) {
157222a4f870Spatrick 			case IMX8MP_CLK_ENET_AXI:
157322a4f870Spatrick 				freq = imxccm_imx8mm_enet(sc, idx);
157422a4f870Spatrick 				break;
157559cc782fSpatrick 			case IMX8MP_CLK_AHB:
157659cc782fSpatrick 				freq = imxccm_imx8mm_ahb(sc, idx);
157759cc782fSpatrick 				break;
157822a4f870Spatrick 			case IMX8MP_CLK_I2C1:
157922a4f870Spatrick 			case IMX8MP_CLK_I2C2:
158022a4f870Spatrick 			case IMX8MP_CLK_I2C3:
158122a4f870Spatrick 			case IMX8MP_CLK_I2C4:
158222a4f870Spatrick 			case IMX8MP_CLK_I2C5:
158322a4f870Spatrick 			case IMX8MP_CLK_I2C6:
158422a4f870Spatrick 				freq = imxccm_imx8mm_i2c(sc, idx);
158522a4f870Spatrick 				break;
158622a4f870Spatrick 			case IMX8MP_CLK_UART1:
158722a4f870Spatrick 			case IMX8MP_CLK_UART2:
158822a4f870Spatrick 			case IMX8MP_CLK_UART3:
158922a4f870Spatrick 			case IMX8MP_CLK_UART4:
159022a4f870Spatrick 				freq = imxccm_imx8mm_uart(sc, idx);
159122a4f870Spatrick 				break;
159222a4f870Spatrick 			case IMX8MP_CLK_USDHC1:
159322a4f870Spatrick 			case IMX8MP_CLK_USDHC2:
159422a4f870Spatrick 			case IMX8MP_CLK_USDHC3:
159522a4f870Spatrick 				freq = imxccm_imx8mm_usdhc(sc, idx);
159622a4f870Spatrick 				break;
1597a74ead0bSpatrick 			case IMX8MP_CLK_ENET_QOS:
1598a74ead0bSpatrick 				freq = imxccm_imx8mp_enet_qos(sc, idx);
1599a74ead0bSpatrick 				break;
1600a74ead0bSpatrick 			case IMX8MP_CLK_ENET_QOS_TIMER:
1601a74ead0bSpatrick 				freq = imxccm_imx8mp_enet_qos_timer(sc, idx);
1602a74ead0bSpatrick 				break;
160359cc782fSpatrick 			case IMX8MP_CLK_HSIO_AXI:
160459cc782fSpatrick 				freq = imxccm_imx8mp_hsio_axi(sc, idx);
160559cc782fSpatrick 				break;
160622a4f870Spatrick 			default:
160722a4f870Spatrick 				printf("%s: 0x%08x\n", __func__, idx);
160822a4f870Spatrick 				return 0;
160922a4f870Spatrick 			}
161022a4f870Spatrick 
161122a4f870Spatrick 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
161222a4f870Spatrick 			div = reg >> sc->sc_divs[idx].shift;
161322a4f870Spatrick 			div = div & sc->sc_divs[idx].mask;
161422a4f870Spatrick 			pre = reg >> sc->sc_predivs[idx].shift;
161522a4f870Spatrick 			pre = pre & sc->sc_predivs[idx].mask;
161622a4f870Spatrick 			return ((freq / (pre + 1)) / (div + 1));
161722a4f870Spatrick 		}
16186e71e8feSpatrick 	} else if (sc->sc_gates == imx8mq_gates) {
1619a8196585Spatrick 		switch (idx) {
1620071150a2Spatrick 		case IMX8MQ_CLK_ARM:
1621b31392d8Spatrick 			parent = IMX8MQ_ARM_PLL;
1622b31392d8Spatrick 			return imxccm_get_frequency(sc, &parent);
1623071150a2Spatrick 		case IMX8MQ_ARM_PLL:
1624071150a2Spatrick 			return imxccm_imx8mq_get_pll(sc, idx);
1625a8196585Spatrick 		}
1626071150a2Spatrick 
1627071150a2Spatrick 		/* These are composite clocks. */
1628071150a2Spatrick 		if (idx < sc->sc_ngates && sc->sc_gates[idx].reg &&
1629071150a2Spatrick 		    idx < sc->sc_ndivs && sc->sc_divs[idx].reg &&
1630071150a2Spatrick 		    idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) {
1631071150a2Spatrick 			switch (idx) {
1632071150a2Spatrick 			case IMX8MQ_CLK_ENET_AXI:
1633071150a2Spatrick 				freq = imxccm_imx8mq_enet(sc, idx);
1634071150a2Spatrick 				break;
16356d21c932Spatrick 			case IMX8MQ_CLK_AHB:
16366d21c932Spatrick 				freq = imxccm_imx8mq_ahb(sc, idx);
16376d21c932Spatrick 				break;
1638071150a2Spatrick 			case IMX8MQ_CLK_I2C1:
1639071150a2Spatrick 			case IMX8MQ_CLK_I2C2:
1640071150a2Spatrick 			case IMX8MQ_CLK_I2C3:
1641071150a2Spatrick 			case IMX8MQ_CLK_I2C4:
1642071150a2Spatrick 				freq = imxccm_imx8mq_i2c(sc, idx);
1643071150a2Spatrick 				break;
1644071150a2Spatrick 			case IMX8MQ_CLK_UART1:
1645071150a2Spatrick 			case IMX8MQ_CLK_UART2:
1646071150a2Spatrick 			case IMX8MQ_CLK_UART3:
1647071150a2Spatrick 			case IMX8MQ_CLK_UART4:
1648071150a2Spatrick 				freq = imxccm_imx8mq_uart(sc, idx);
1649071150a2Spatrick 				break;
1650071150a2Spatrick 			case IMX8MQ_CLK_USDHC1:
1651071150a2Spatrick 			case IMX8MQ_CLK_USDHC2:
1652071150a2Spatrick 				freq = imxccm_imx8mq_usdhc(sc, idx);
1653071150a2Spatrick 				break;
1654071150a2Spatrick 			case IMX8MQ_CLK_USB_BUS:
1655071150a2Spatrick 			case IMX8MQ_CLK_USB_CORE_REF:
1656071150a2Spatrick 			case IMX8MQ_CLK_USB_PHY_REF:
1657071150a2Spatrick 				freq = imxccm_imx8mq_usb(sc, idx);
1658071150a2Spatrick 				break;
1659071150a2Spatrick 			case IMX8MQ_CLK_ECSPI1:
1660071150a2Spatrick 			case IMX8MQ_CLK_ECSPI2:
1661071150a2Spatrick 			case IMX8MQ_CLK_ECSPI3:
1662071150a2Spatrick 				freq = imxccm_imx8mq_ecspi(sc, idx);
1663071150a2Spatrick 				break;
1664071150a2Spatrick 			case IMX8MQ_CLK_PWM1:
1665071150a2Spatrick 			case IMX8MQ_CLK_PWM2:
1666071150a2Spatrick 			case IMX8MQ_CLK_PWM3:
1667071150a2Spatrick 			case IMX8MQ_CLK_PWM4:
1668071150a2Spatrick 				freq = imxccm_imx8mq_pwm(sc, idx);
1669071150a2Spatrick 				break;
1670071150a2Spatrick 			default:
1671071150a2Spatrick 				printf("%s: 0x%08x\n", __func__, idx);
1672071150a2Spatrick 				return 0;
1673071150a2Spatrick 			}
1674071150a2Spatrick 
1675071150a2Spatrick 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1676071150a2Spatrick 			div = reg >> sc->sc_divs[idx].shift;
1677071150a2Spatrick 			div = div & sc->sc_divs[idx].mask;
1678071150a2Spatrick 			pre = reg >> sc->sc_predivs[idx].shift;
1679071150a2Spatrick 			pre = pre & sc->sc_predivs[idx].mask;
1680071150a2Spatrick 			return ((freq / (pre + 1)) / (div + 1));
1681071150a2Spatrick 		}
1682071150a2Spatrick 
1683b7ac005eSkettenis 	} else if (sc->sc_gates == imx7d_gates) {
1684b7ac005eSkettenis 		switch (idx) {
168558d1c2c8Skettenis 		case IMX7D_ENET_AXI_ROOT_SRC:
168658d1c2c8Skettenis 			return imxccm_imx7d_enet(sc, idx);
1687b7ac005eSkettenis 		case IMX7D_I2C1_ROOT_SRC:
1688b7ac005eSkettenis 		case IMX7D_I2C2_ROOT_SRC:
1689b7ac005eSkettenis 		case IMX7D_I2C3_ROOT_SRC:
1690b7ac005eSkettenis 		case IMX7D_I2C4_ROOT_SRC:
1691b7ac005eSkettenis 			return imxccm_imx7d_i2c(sc, idx);
1692b7ac005eSkettenis 		case IMX7D_UART1_ROOT_SRC:
1693b7ac005eSkettenis 		case IMX7D_UART2_ROOT_SRC:
1694b7ac005eSkettenis 		case IMX7D_UART3_ROOT_SRC:
1695b7ac005eSkettenis 		case IMX7D_UART4_ROOT_SRC:
1696b7ac005eSkettenis 		case IMX7D_UART5_ROOT_SRC:
1697b7ac005eSkettenis 		case IMX7D_UART6_ROOT_SRC:
1698b7ac005eSkettenis 		case IMX7D_UART7_ROOT_SRC:
1699b7ac005eSkettenis 			return imxccm_imx7d_uart(sc, idx);
1700b7ac005eSkettenis 		case IMX7D_USDHC1_ROOT_SRC:
1701b7ac005eSkettenis 		case IMX7D_USDHC2_ROOT_SRC:
1702b7ac005eSkettenis 		case IMX7D_USDHC3_ROOT_SRC:
1703b7ac005eSkettenis 			return imxccm_imx7d_usdhc(sc, idx);
1704b7ac005eSkettenis 		}
1705a8196585Spatrick 	} else if (sc->sc_gates == imx6ul_gates) {
17064bed6a7dSpatrick 		switch (idx) {
17074bed6a7dSpatrick 		case IMX6UL_CLK_ARM:
17084bed6a7dSpatrick 			return imxccm_get_armclk(sc);
17094bed6a7dSpatrick 		case IMX6UL_CLK_IPG:
17104bed6a7dSpatrick 			return imxccm_get_ipgclk(sc);
17114bed6a7dSpatrick 		case IMX6UL_CLK_PERCLK:
17124bed6a7dSpatrick 			return imxccm_get_ipg_perclk(sc);
17134bed6a7dSpatrick 		case IMX6UL_CLK_UART1_SERIAL:
17144bed6a7dSpatrick 			return imxccm_get_uartclk(sc);
17154bed6a7dSpatrick 		case IMX6UL_CLK_USDHC1:
17164bed6a7dSpatrick 		case IMX6UL_CLK_USDHC2:
17174bed6a7dSpatrick 			return imxccm_get_usdhx(sc, idx - IMX6UL_CLK_USDHC1 + 1);
17184bed6a7dSpatrick 		}
1719b7ac005eSkettenis 	} else if (sc->sc_gates == imx6_gates) {
17204bed6a7dSpatrick 		switch (idx) {
17214bed6a7dSpatrick 		case IMX6_CLK_AHB:
17224bed6a7dSpatrick 			return imxccm_get_ahbclk(sc);
17234bed6a7dSpatrick 		case IMX6_CLK_ARM:
17244bed6a7dSpatrick 			return imxccm_get_armclk(sc);
17254bed6a7dSpatrick 		case IMX6_CLK_IPG:
17264bed6a7dSpatrick 			return imxccm_get_ipgclk(sc);
17274bed6a7dSpatrick 		case IMX6_CLK_IPG_PER:
17284bed6a7dSpatrick 			return imxccm_get_ipg_perclk(sc);
1729e45f7b26Spatrick 		case IMX6_CLK_ECSPI_ROOT:
1730e45f7b26Spatrick 			return imxccm_get_ecspiclk(sc);
17314bed6a7dSpatrick 		case IMX6_CLK_UART_SERIAL:
17324bed6a7dSpatrick 			return imxccm_get_uartclk(sc);
17334bed6a7dSpatrick 		case IMX6_CLK_USDHC1:
17344bed6a7dSpatrick 		case IMX6_CLK_USDHC2:
17354bed6a7dSpatrick 		case IMX6_CLK_USDHC3:
17364bed6a7dSpatrick 		case IMX6_CLK_USDHC4:
17374bed6a7dSpatrick 			return imxccm_get_usdhx(sc, idx - IMX6_CLK_USDHC1 + 1);
17384bed6a7dSpatrick 		}
17394bed6a7dSpatrick 	}
17404bed6a7dSpatrick 
17414bed6a7dSpatrick 	printf("%s: 0x%08x\n", __func__, idx);
17424bed6a7dSpatrick 	return 0;
17434bed6a7dSpatrick }
17444bed6a7dSpatrick 
1745a8196585Spatrick int
imxccm_set_frequency(void * cookie,uint32_t * cells,uint32_t freq)1746a8196585Spatrick imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1747a8196585Spatrick {
1748a8196585Spatrick 	struct imxccm_softc *sc = cookie;
1749a8196585Spatrick 	uint32_t idx = cells[0];
1750b7ac005eSkettenis 	uint32_t reg, div, parent, parent_freq;
1751b31392d8Spatrick 	uint32_t pcells[2];
1752b31392d8Spatrick 	int ret;
1753a8196585Spatrick 
17546e71e8feSpatrick 	if (sc->sc_divs == imx8mm_divs) {
17556e71e8feSpatrick 		switch (idx) {
17566e71e8feSpatrick 		case IMX8MM_CLK_ARM:
17576e71e8feSpatrick 			parent = IMX8MM_CLK_A53_SRC;
17586e71e8feSpatrick 			return imxccm_set_frequency(cookie, &parent, freq);
17596e71e8feSpatrick 		case IMX8MM_CLK_A53_SRC:
17606e71e8feSpatrick 			pcells[0] = sc->sc_phandle;
17616e71e8feSpatrick 			pcells[1] = IMX8MM_SYS_PLL1_800M;
17626e71e8feSpatrick 			ret = imxccm_set_parent(cookie, &idx, pcells);
17636e71e8feSpatrick 			if (ret)
17646e71e8feSpatrick 				return ret;
17656e71e8feSpatrick 			ret = imxccm_imx8mm_set_pll(sc, IMX8MM_ARM_PLL, freq);
17666e71e8feSpatrick 			pcells[0] = sc->sc_phandle;
17676e71e8feSpatrick 			pcells[1] = IMX8MM_ARM_PLL_OUT;
17686e71e8feSpatrick 			imxccm_set_parent(cookie, &idx, pcells);
17696e71e8feSpatrick 			return ret;
17706e71e8feSpatrick 		case IMX8MM_CLK_USDHC1_ROOT:
17716e71e8feSpatrick 		case IMX8MM_CLK_USDHC2_ROOT:
17726e71e8feSpatrick 		case IMX8MM_CLK_USDHC3_ROOT:
17736e71e8feSpatrick 			parent = sc->sc_gates[idx].parent;
17746e71e8feSpatrick 			return imxccm_set_frequency(sc, &parent, freq);
17756e71e8feSpatrick 		case IMX8MM_CLK_USDHC1:
17766e71e8feSpatrick 		case IMX8MM_CLK_USDHC2:
17776e71e8feSpatrick 		case IMX8MM_CLK_USDHC3:
177858c0d41eSpatrick 			parent_freq = imxccm_imx8mm_usdhc(sc, idx);
177958c0d41eSpatrick 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
17806e71e8feSpatrick 		}
178159cc782fSpatrick 	} else if (sc->sc_divs == imx8mp_divs) {
178259cc782fSpatrick 		switch (idx) {
1783a74ead0bSpatrick 		case IMX8MP_CLK_ENET_QOS:
1784a74ead0bSpatrick 			parent_freq = imxccm_imx8mp_enet_qos(sc, idx);
1785a74ead0bSpatrick 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1786a74ead0bSpatrick 		case IMX8MP_CLK_ENET_QOS_TIMER:
1787a74ead0bSpatrick 			parent_freq = imxccm_imx8mp_enet_qos_timer(sc, idx);
1788a74ead0bSpatrick 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
178959cc782fSpatrick 		case IMX8MP_CLK_HSIO_AXI:
1790a74ead0bSpatrick 			parent_freq = imxccm_imx8mp_hsio_axi(sc, idx);
1791a74ead0bSpatrick 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
179259cc782fSpatrick 		}
17936e71e8feSpatrick 	} else if (sc->sc_divs == imx8mq_divs) {
1794a8196585Spatrick 		switch (idx) {
1795071150a2Spatrick 		case IMX8MQ_CLK_ARM:
1796b31392d8Spatrick 			parent = IMX8MQ_CLK_A53_SRC;
1797b31392d8Spatrick 			return imxccm_set_frequency(cookie, &parent, freq);
1798b31392d8Spatrick 		case IMX8MQ_CLK_A53_SRC:
1799b31392d8Spatrick 			pcells[0] = sc->sc_phandle;
1800b31392d8Spatrick 			pcells[1] = IMX8MQ_SYS1_PLL_800M;
1801b31392d8Spatrick 			ret = imxccm_set_parent(cookie, &idx, pcells);
1802b31392d8Spatrick 			if (ret)
1803b31392d8Spatrick 				return ret;
1804b31392d8Spatrick 			ret = imxccm_imx8mq_set_pll(sc, IMX8MQ_ARM_PLL, freq);
1805b31392d8Spatrick 			pcells[0] = sc->sc_phandle;
1806b31392d8Spatrick 			pcells[1] = IMX8MQ_ARM_PLL_OUT;
1807b31392d8Spatrick 			imxccm_set_parent(cookie, &idx, pcells);
1808b31392d8Spatrick 			return ret;
1809071150a2Spatrick 		case IMX8MQ_CLK_USB_BUS:
1810071150a2Spatrick 		case IMX8MQ_CLK_USB_CORE_REF:
1811071150a2Spatrick 		case IMX8MQ_CLK_USB_PHY_REF:
1812a8196585Spatrick 			if (imxccm_get_frequency(sc, cells) != freq)
1813a8196585Spatrick 				break;
1814a8196585Spatrick 			return 0;
1815071150a2Spatrick 		case IMX8MQ_CLK_USDHC1:
181658c0d41eSpatrick 		case IMX8MQ_CLK_USDHC2:
181758c0d41eSpatrick 			parent_freq = imxccm_imx8mq_usdhc(sc, idx);
181858c0d41eSpatrick 			return imxccm_imx8m_set_div(sc, idx, freq, parent_freq);
1819b7ac005eSkettenis 		}
1820b7ac005eSkettenis 	} else if (sc->sc_divs == imx7d_divs) {
1821b7ac005eSkettenis 		switch (idx) {
1822b7ac005eSkettenis 		case IMX7D_USDHC1_ROOT_CLK:
1823b7ac005eSkettenis 		case IMX7D_USDHC2_ROOT_CLK:
1824b7ac005eSkettenis 		case IMX7D_USDHC3_ROOT_CLK:
1825b7ac005eSkettenis 			parent = sc->sc_gates[idx].parent;
1826b7ac005eSkettenis 			return imxccm_set_frequency(sc, &parent, freq);
1827b7ac005eSkettenis 		case IMX7D_USDHC1_ROOT_DIV:
1828b7ac005eSkettenis 		case IMX7D_USDHC2_ROOT_DIV:
1829b7ac005eSkettenis 		case IMX7D_USDHC3_ROOT_DIV:
1830b7ac005eSkettenis 			parent = sc->sc_divs[idx].parent;
1831b7ac005eSkettenis 			parent_freq = imxccm_get_frequency(sc, &parent);
1832b7ac005eSkettenis 			div = 0;
1833b7ac005eSkettenis 			while (parent_freq / (div + 1) > freq)
1834b7ac005eSkettenis 				div++;
1835b7ac005eSkettenis 			reg = HREAD4(sc, sc->sc_divs[idx].reg);
1836b7ac005eSkettenis 			reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift);
1837b7ac005eSkettenis 			reg |= (div << sc->sc_divs[idx].shift);
1838b7ac005eSkettenis 			HWRITE4(sc, sc->sc_divs[idx].reg, reg);
1839a8196585Spatrick 			return 0;
1840a8196585Spatrick 		}
1841a8196585Spatrick 	}
1842a8196585Spatrick 
1843a8196585Spatrick 	printf("%s: 0x%08x %x\n", __func__, idx, freq);
1844a8196585Spatrick 	return -1;
1845a8196585Spatrick }
1846a8196585Spatrick 
1847a8196585Spatrick int
imxccm_set_parent(void * cookie,uint32_t * cells,uint32_t * pcells)1848a8196585Spatrick imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1849a8196585Spatrick {
1850a8196585Spatrick 	struct imxccm_softc *sc = cookie;
1851a8196585Spatrick 	uint32_t idx = cells[0];
1852f70b9bfaSkettenis 	uint32_t pidx;
1853a8196585Spatrick 	uint32_t mux;
1854a8196585Spatrick 
1855f70b9bfaSkettenis 	if (pcells[0] != sc->sc_phandle) {
1856f70b9bfaSkettenis 		printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, pcells[0]);
1857f70b9bfaSkettenis 		return -1;
1858f70b9bfaSkettenis 	}
1859f70b9bfaSkettenis 
1860f70b9bfaSkettenis 	pidx = pcells[1];
1861f70b9bfaSkettenis 
18626e71e8feSpatrick 	if (sc->sc_muxs == imx8mm_muxs) {
18636e71e8feSpatrick 		switch (idx) {
18646e71e8feSpatrick 		case IMX8MM_CLK_A53_SRC:
18656e71e8feSpatrick 			if (pidx != IMX8MM_ARM_PLL_OUT &&
18666e71e8feSpatrick 			    pidx != IMX8MM_SYS_PLL1_800M)
18676e71e8feSpatrick 				break;
18686e71e8feSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
18696e71e8feSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
18706e71e8feSpatrick 			if (pidx == IMX8MM_ARM_PLL_OUT)
18716e71e8feSpatrick 				mux |= (0x1 << sc->sc_muxs[idx].shift);
18726e71e8feSpatrick 			if (pidx == IMX8MM_SYS_PLL1_800M)
18736e71e8feSpatrick 				mux |= (0x4 << sc->sc_muxs[idx].shift);
18746e71e8feSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
18756e71e8feSpatrick 			return 0;
18768186a0b7Spatrick 		case IMX8MM_CLK_USB_BUS:
18778186a0b7Spatrick 			if (pidx != IMX8MM_SYS_PLL2_500M)
18788186a0b7Spatrick 				break;
18798186a0b7Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
18808186a0b7Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
18818186a0b7Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
18828186a0b7Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
18838186a0b7Spatrick 			return 0;
18848186a0b7Spatrick 		case IMX8MM_CLK_USB_CORE_REF:
18858186a0b7Spatrick 		case IMX8MM_CLK_USB_PHY_REF:
18868186a0b7Spatrick 			if (pidx != IMX8MM_SYS_PLL1_100M)
18878186a0b7Spatrick 				break;
18888186a0b7Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
18898186a0b7Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
18908186a0b7Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
18918186a0b7Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
18928186a0b7Spatrick 			return 0;
189365c9ab81Spatrick 		case IMX8MM_CLK_PCIE1_CTRL:
189465c9ab81Spatrick 		case IMX8MM_CLK_PCIE2_CTRL:
189565c9ab81Spatrick 			if (pidx != IMX8MM_SYS_PLL2_250M)
189665c9ab81Spatrick 				break;
189765c9ab81Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
189865c9ab81Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
189965c9ab81Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
190065c9ab81Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
190165c9ab81Spatrick 			return 0;
190265c9ab81Spatrick 		case IMX8MM_CLK_PCIE1_PHY:
190365c9ab81Spatrick 		case IMX8MM_CLK_PCIE2_PHY:
190465c9ab81Spatrick 			if (pidx != IMX8MM_SYS_PLL2_100M)
190565c9ab81Spatrick 				break;
190665c9ab81Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
190765c9ab81Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
190865c9ab81Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
190965c9ab81Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
191065c9ab81Spatrick 			return 0;
19116e71e8feSpatrick 		}
191259cc782fSpatrick 	} else if (sc->sc_muxs == imx8mp_muxs) {
191359cc782fSpatrick 		switch (idx) {
1914a74ead0bSpatrick 		case IMX8MP_CLK_ENET_AXI:
1915a74ead0bSpatrick 			if (pidx != IMX8MP_SYS_PLL1_266M)
1916a74ead0bSpatrick 				break;
1917a74ead0bSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1918a74ead0bSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1919a74ead0bSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1920a74ead0bSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1921a74ead0bSpatrick 			return 0;
192267129edcSpatrick 		case IMX8MP_CLK_PCIE_PHY:
192367129edcSpatrick 			if (pidx != IMX8MP_CLK_24M)
192467129edcSpatrick 				break;
192567129edcSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
192667129edcSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
192767129edcSpatrick 			mux |= (0x0 << sc->sc_muxs[idx].shift);
192867129edcSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
192967129edcSpatrick 			return 0;
193067129edcSpatrick 		case IMX8MP_CLK_PCIE_AUX:
193167129edcSpatrick 			if (pidx != IMX8MP_SYS_PLL2_50M)
193267129edcSpatrick 				break;
193367129edcSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
193467129edcSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
193567129edcSpatrick 			mux |= (0x2 << sc->sc_muxs[idx].shift);
193667129edcSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
193767129edcSpatrick 			return 0;
1938a74ead0bSpatrick 		case IMX8MP_CLK_ENET_QOS:
1939a74ead0bSpatrick 			if (pidx != IMX8MP_SYS_PLL2_125M)
1940a74ead0bSpatrick 				break;
1941a74ead0bSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1942a74ead0bSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1943a74ead0bSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1944a74ead0bSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1945a74ead0bSpatrick 			return 0;
1946a74ead0bSpatrick 		case IMX8MP_CLK_ENET_QOS_TIMER:
1947a74ead0bSpatrick 			if (pidx != IMX8MP_SYS_PLL2_100M)
1948a74ead0bSpatrick 				break;
1949a74ead0bSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1950a74ead0bSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1951a74ead0bSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1952a74ead0bSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1953a74ead0bSpatrick 			return 0;
195459cc782fSpatrick 		case IMX8MP_CLK_USB_PHY_REF:
195559cc782fSpatrick 			if (pidx != IMX8MP_CLK_24M)
195659cc782fSpatrick 				break;
195759cc782fSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
195859cc782fSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
195959cc782fSpatrick 			mux |= (0x0 << sc->sc_muxs[idx].shift);
196059cc782fSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
196159cc782fSpatrick 			return 0;
196259cc782fSpatrick 		case IMX8MP_CLK_HSIO_AXI:
196359cc782fSpatrick 			if (pidx != IMX8MP_SYS_PLL2_500M)
196459cc782fSpatrick 				break;
196559cc782fSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
196659cc782fSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
196759cc782fSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
196859cc782fSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
196959cc782fSpatrick 			return 0;
197059cc782fSpatrick 		}
19716e71e8feSpatrick 	} else if (sc->sc_muxs == imx8mq_muxs) {
1972a8196585Spatrick 		switch (idx) {
1973b31392d8Spatrick 		case IMX8MQ_CLK_A53_SRC:
1974b31392d8Spatrick 			if (pidx != IMX8MQ_ARM_PLL_OUT &&
1975b31392d8Spatrick 			    pidx != IMX8MQ_SYS1_PLL_800M)
1976b31392d8Spatrick 				break;
1977b31392d8Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1978b31392d8Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1979b31392d8Spatrick 			if (pidx == IMX8MQ_ARM_PLL_OUT)
1980b31392d8Spatrick 				mux |= (0x1 << sc->sc_muxs[idx].shift);
1981b31392d8Spatrick 			if (pidx == IMX8MQ_SYS1_PLL_800M)
1982b31392d8Spatrick 				mux |= (0x4 << sc->sc_muxs[idx].shift);
1983b31392d8Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1984b31392d8Spatrick 			return 0;
1985071150a2Spatrick 		case IMX8MQ_CLK_USB_BUS:
1986a8196585Spatrick 			if (pidx != IMX8MQ_SYS2_PLL_500M)
1987a8196585Spatrick 				break;
1988a8196585Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1989a8196585Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1990a8196585Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
1991a8196585Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
1992a8196585Spatrick 			return 0;
1993071150a2Spatrick 		case IMX8MQ_CLK_USB_CORE_REF:
1994071150a2Spatrick 		case IMX8MQ_CLK_USB_PHY_REF:
1995a8196585Spatrick 			if (pidx != IMX8MQ_SYS1_PLL_100M)
1996a8196585Spatrick 				break;
1997a8196585Spatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
1998a8196585Spatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
1999a8196585Spatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
2000a8196585Spatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
2001a8196585Spatrick 			return 0;
2002071150a2Spatrick 		case IMX8MQ_CLK_PCIE1_CTRL:
2003071150a2Spatrick 		case IMX8MQ_CLK_PCIE2_CTRL:
2004845ecb9bSpatrick 			if (pidx != IMX8MQ_SYS2_PLL_250M)
2005845ecb9bSpatrick 				break;
2006845ecb9bSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
2007845ecb9bSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
2008845ecb9bSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
2009845ecb9bSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
2010845ecb9bSpatrick 			return 0;
2011071150a2Spatrick 		case IMX8MQ_CLK_PCIE1_PHY:
2012071150a2Spatrick 		case IMX8MQ_CLK_PCIE2_PHY:
2013845ecb9bSpatrick 			if (pidx != IMX8MQ_SYS2_PLL_100M)
2014845ecb9bSpatrick 				break;
2015845ecb9bSpatrick 			mux = HREAD4(sc, sc->sc_muxs[idx].reg);
2016845ecb9bSpatrick 			mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift);
2017845ecb9bSpatrick 			mux |= (0x1 << sc->sc_muxs[idx].shift);
2018845ecb9bSpatrick 			HWRITE4(sc, sc->sc_muxs[idx].reg, mux);
2019845ecb9bSpatrick 			return 0;
2020a8196585Spatrick 		}
2021a8196585Spatrick 	}
2022a8196585Spatrick 
2023a8196585Spatrick 	printf("%s: 0x%08x 0x%08x\n", __func__, idx, pidx);
2024a8196585Spatrick 	return -1;
2025a8196585Spatrick }
2026