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