2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/param.h>
29 #include <sys/systm.h>
32 #include <sys/mutex.h>
35 #include <machine/bus.h>
37 #include <dev/clk/clk.h>
39 #include <dt-bindings/clock/tegra210-car.h>
40 #include <dt-bindings/reset/tegra210-car.h>
42 #include "tegra210_car.h"
44 /* Bits in base register. */
45 #define PERLCK_AMUX_MASK 0x0F
46 #define PERLCK_AMUX_SHIFT 16
47 #define PERLCK_AMUX_DIS (1 << 20)
48 #define PERLCK_UDIV_DIS (1 << 24)
49 #define PERLCK_ENA_MASK (1 << 28)
50 #define PERLCK_MUX_SHIFT 29
51 #define PERLCK_MUX_MASK 0x07
55 struct clknode_init_def clkdef
;
65 struct clknode_init_def clkdef
;
69 #define PLIST(x) static const char *x[]
71 #define GATE(_id, cname, plist, _idx) \
73 .clkdef.id = TEGRA210_CLK_##_id, \
74 .clkdef.name = cname, \
75 .clkdef.parent_names = (const char *[]){plist}, \
76 .clkdef.parent_cnt = 1, \
77 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
81 /* Sources for multiplexors. */
82 PLIST(mux_N_N_c_N_p_N_a
) =
83 {"bogus", NULL
, "pllC_out0", NULL
,
84 "pllP_out0", NULL
, "pllA_out0", NULL
};
85 PLIST(mux_N_N_p_N_N_N_clkm
) =
86 {NULL
, NULL
, "pllP_out0", NULL
,
87 NULL
, NULL
, "clk_m", NULL
};
88 PLIST(mux_N_c_p_a1_c2_c3_clkm
) =
89 {NULL
, "pllC_out0", "pllP_out0", "pllA1_out0",
90 "pllC2_out0", "pllC3_out0", "clk_m", NULL
};
91 PLIST(mux_N_c_p_a1_c2_c3_clkm_c4
) =
92 {NULL
, "pllC_out0", "pllP_out0", "pllA1_out0",
93 "pllC2_out0", "pllC3_out0", "clk_m", "pllC4_out0"};
94 PLIST(mux_N_c_p_clkm_N_c4_c4o1_c4o1
) =
95 {NULL
, "pllC_out0", "pllP_out0", "clk_m",
96 NULL
, "pllC4_out0", "pllC4_out1", "pllC4_out1"};
97 PLIST(mux_N_c_p_clkm_N_c4_c4o1_c4o2
) =
98 {NULL
, "pllC_out0", "pllP_out0", "clk_m",
99 NULL
, "pllC4_out0", "pllC4_out1", "pllC4_out2"};
101 PLIST(mux_N_c2_c_c3_p_N_a
) =
102 {NULL
, "pllC2_out0", "pllC_out0", "pllC3_out0",
103 "pllP_out0", NULL
, "pllA_out0", NULL
};
104 PLIST(mux_N_c2_c_c3_p_clkm_a1_c4
) =
105 {NULL
, "pllC2_out0", "pllC_out0", "pllC3_out0",
106 "pllP_out0", "clk_m", "pllA1_out0", "pllC4_out0"};
107 PLIST(mux_N_c2_c_c3_p_N_a1_clkm
) =
108 {NULL
, "pllC2_out0", "pllC_out0", "pllC3_out0",
109 "pllP_out0", NULL
, "pllA1_out0", "clk_m"};
111 PLIST(mux_a_N_audio_N_p_N_clkm
) =
112 {"pllA_out0", NULL
, "audio", NULL
,
113 "pllP_out0", NULL
, "clk_m"};
114 PLIST(mux_a_N_audio0_N_p_N_clkm
) =
115 {"pllA_out0", NULL
, "audio0", NULL
,
116 "pllP_out0", NULL
, "clk_m"};
117 PLIST(mux_a_N_audio1_N_p_N_clkm
) =
118 {"pllA_out0", NULL
, "audio1", NULL
,
119 "pllP_out0", NULL
, "clk_m"};
120 PLIST(mux_a_N_audio2_N_p_N_clkm
) =
121 {"pllA_out0", NULL
, "audio2", NULL
,
122 "pllP_out0", NULL
, "clk_m"};
123 PLIST(mux_a_N_audio3_N_p_N_clkm
) =
124 {"pllA_out0", NULL
, "audio3", NULL
,
125 "pllP_out0", NULL
, "clk_m"};
126 PLIST(mux_a_N_audio4_N_p_N_clkm
) =
127 {"pllA_out0", NULL
, "audio4", NULL
,
128 "pllP_out0", NULL
, "clk_m"};
129 PLIST(mux_a_audiod1_p_clkm
) =
130 {"pllA_out0", "audiod1", "pllP_out0", "clk_m",
131 NULL
, NULL
, NULL
, NULL
};
132 PLIST(mux_a_audiod2_p_clkm
) =
133 {"pllA_out0", "audiod2", "pllP_out0", "clk_m",
134 NULL
, NULL
, NULL
, NULL
};
135 PLIST(mux_a_audiod3_p_clkm
) =
136 {"pllA_out0", "audiod3", "pllP_out0", "clk_m",
137 NULL
, NULL
, NULL
, NULL
};
138 PLIST(mux_a_c4_c_c4o1_p_N_clkm_c4o2
) =
139 {"pllA_out0", "pllC4_out0", "pllC_out0", "pllC4_out1",
140 "pllP_out0", NULL
, "clk_m", "pllC4_out2"};
142 PLIST(mux_a_clks_p_clkm_e
) =
143 {"pllA_out0", "clk_s", "pllP_out0", "clk_m",
145 PLIST(mux_c4o1_c2_c_c4_p_clkm_a_c4
) =
146 {"pllC4_out1", "pllC2_out0", "pllC_out0", "pllC4_out0",
147 "pllP_out0", "clk_m","pllA_out0", "pllC4_out0", };
149 PLIST(mux_m_c_p_clkm_mud_mbud_mb_pud
) =
150 {"pllM_out0", "pllC_out0", "pllP_out0", "clk_m",
151 "pllM_UD", "pllMB_UD", "pllMB_out0", "pllP_UD"};
152 PLIST(mux_p_N_N_c4o2_c4o1_N_clkm_c4
) =
153 {"pllP_out0", NULL
, NULL
, "pllC4_out2",
154 "pllC4_out1", NULL
, "clk_m", "pllC4_out0"};
155 PLIST(mux_p_N_c_c4_c4o1_c4o2_clkm
) =
156 {"pllP_out0", NULL
, "pllC_out0", "pllC4_out0",
157 "pllC4_out1", "pllC4_out2", "clk_m"};
158 PLIST(mux_p_N_c_c4_N_c4o1_clkm_c4o2
) =
159 {"pllP_out0", NULL
, "pllC_out0", "pllC4_out0",
160 NULL
, "pllC4_out1", "clk_m", "pllC4_out2"};
161 PLIST(mux_p_N_d_N_N_d2_clkm
) =
162 {"pllP_out0", NULL
, "pllD_out0", NULL
,
163 NULL
, "pllD2_out0", "clk_m"};
164 PLIST(mux_p_N_clkm_N_clks_N_E
) =
165 {"pllP_out0", NULL
, "clk_m", NULL
,
166 NULL
, "clk_s", NULL
, "pllE_out0"};
167 PLIST(mux_p_c_c2_N_c2_N_clkm
) =
168 {"pllP_out0", "pllC_out0", "pllC2_out0", NULL
,
169 "pllC2_out0", NULL
, "clk_m", NULL
};
170 PLIST(mux_p_co1_c_N_c4o2_c4o1_clkm_c4
) =
171 {"pllP_out0", "pllC_out1", "pllC_out0", NULL
,
172 "pllC4_out2", "pllC4_out1" ,"clk_m", "pllC4_out0"};
173 PLIST(mux_p_c2_c_c3_N_a1_clkm_c4
) =
174 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
175 NULL
, "pllA1_out0", "clk_m", "pllC4_out0"};
176 PLIST(mux_p_c2_c_c3_N_N_clkm
) =
177 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
178 NULL
, NULL
, "clk_m", NULL
};
179 PLIST(mux_p_c2_c_c3_m_e_clkm
) =
180 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
181 "pllM_out0", "pllE_out0", "clk_m"};
182 PLIST(mux_p_c2_c_c4_N_c4o1_clkm_c4o2
) =
183 {"pllP_out0", "pllC2_out0", "pllC4_out0",
184 NULL
, "pllC4_out1", "clk_m", "pllC4_out2"};
185 PLIST(mux_p_c2_c_c4_a_c4o1_clkm_c4o2
) =
186 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC4_out0",
187 "pllA_out0", "pllC4_out1", "clk_m", "pllC4_out2"};
188 PLIST(mux_p_c2_c_c4o2_c4o1_clks_clkm_c4
) =
189 {"pllP_out0", "pllC2_out0", "pllC4_out2",
190 "pllC4_out1", "clk_s", "clk_m", "pllC4_out0"};
192 PLIST(mux_p_c2_c_c4_c4o1_clkm_c4o2
) =
193 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC4_out0",
194 "pllC4_out1", "clk_m", "pllC4_out2"};
195 PLIST(mux_p_c2_c_c4_clkm_c4o1_c4o2
) =
196 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC4_out0",
197 "clk_m", "pllC4_out1", "pllC4_out2"};
198 PLIST(mux_p_c2_c_c4_clks_c4o1_clkm_c4o2
) =
199 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC4_out0",
200 "clk_s", "pllC4_out1", "clk_m", "pllC4_out2"};
201 PLIST(mux_p_c2_c_c4_clkm_c4o1_clks_c4o2
) =
202 {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC4_out0",
203 "clk_m", "pllC4_out1", "clk_s", "pllC4_out2"};
204 PLIST(mux_p_c2_refe1_c3_m_a1_clkm_C4
) =
205 {"pllP_out0", "pllC2_out0", "pllREFE_out1", "pllC3_out0",
206 "pllM_out0", "pllA1_out0", "clk_m", "pllC4_out0"};
207 PLIST(mux_p_c4_c_c4o1_N_c4o2_clkm
) =
208 {"pllP_out0", "pllC4_out0", "pllC_out0", "pllC4_out1",
209 NULL
, "pllC4_out2", "clk_m", NULL
};
210 PLIST(mux_p_m_d_a_c_d2_clkm
) =
211 {"pllP_out0", "pllM_out0", "pllD_out0", "pllA_out0",
212 "pllC_out0", "pllD2_out0", "clk_m"};
213 PLIST(mux_p_po3_clkm_clks_a
) =
214 {"pllP_out0", "pllP_out3", "clk_m", "clk_s",
215 "pllA_out0", NULL
, NULL
, NULL
};
217 PLIST(mux_po3_c_c2_clkm_p_c4_c4o1_c4o2
) =
218 {"pllP_out3", "pllC_out0", "pllC2_out0", "clk_m",
219 "pllP_out0", "pllC4_out0", "pllC4_out1", "pllC4_out2"};
221 PLIST(mux_clkm_p_N_N_N_refre
) =
222 {"clk_m", "pllP_xusb", NULL
, NULL
,
223 NULL
, "pllREFE_out0", NULL
, NULL
};
224 PLIST(mux_clkm_N_u48_N_p_N_u480
) =
225 {"clk_m", NULL
, "pllU_48", NULL
,
226 "pllP_out0", NULL
, "pllU_480"};
227 PLIST(mux_clkm_refe_clks_u480
) =
228 {"clk_m", "pllREFE_out0", "clk_s", "pllU_480",
229 NULL
, NULL
, NULL
, NULL
};
231 PLIST(mux_sep_audio
) =
232 {"pllA_out0", "pllC4_out0", "pllC_out0", "pllC4_out0",
233 "pllP_out0", "pllC4_out0", "clk_m", NULL
,
234 "spdif_in", "i2s1", "i2s2", "i2s3",
235 "i2s4", "i2s5", "pllA_out0", "ext_vimclk"};
237 static uint32_t clk_enable_reg
[] = {
247 static uint32_t clk_reset_reg
[] = {
257 #define L(n) ((0 * 32) + (n))
258 #define H(n) ((1 * 32) + (n))
259 #define U(n) ((2 * 32) + (n))
260 #define V(n) ((3 * 32) + (n))
261 #define W(n) ((4 * 32) + (n))
262 #define X(n) ((5 * 32) + (n))
263 #define Y(n) ((6 * 32) + (n))
265 /* Clock IDs not yet defined in binding header file. */
266 #define TEGRA210_CLK_STAT_MON H(5)
267 #define TEGRA210_CLK_IRAMA U(20)
268 #define TEGRA210_CLK_IRAMB U(21)
269 #define TEGRA210_CLK_IRAMC U(22)
270 #define TEGRA210_CLK_IRAMD U(23)
271 #define TEGRA210_CLK_CRAM2 U(24)
272 #define TEGRA210_CLK_M_DOUBLER U(26)
273 #define TEGRA210_CLK_DEVD2_OUT U(29)
274 #define TEGRA210_CLK_DEVD1_OUT U(30)
275 #define TEGRA210_CLK_CPUG V(0)
276 #define TEGRA210_CLK_ATOMICS V(16)
277 #define TEGRA210_CLK_PCIERX0 W(2)
278 #define TEGRA210_CLK_PCIERX1 W(3)
279 #define TEGRA210_CLK_PCIERX2 W(4)
280 #define TEGRA210_CLK_PCIERX3 W(5)
281 #define TEGRA210_CLK_PCIERX4 W(6)
282 #define TEGRA210_CLK_PCIERX5 W(7)
283 #define TEGRA210_CLK_PCIE2_IOBIST W(9)
284 #define TEGRA210_CLK_EMC_IOBIST W(10)
285 #define TEGRA210_CLK_SATA_IOBIST W(12)
286 #define TEGRA210_CLK_MIPI_IOBIST W(13)
287 #define TEGRA210_CLK_EMC_LATENCY W(29)
288 #define TEGRA210_CLK_MC1 W(30)
289 #define TEGRA210_CLK_ETR X(3)
290 #define TEGRA210_CLK_CAM_MCLK X(4)
291 #define TEGRA210_CLK_CAM_MCLK2 X(5)
292 #define TEGRA210_CLK_MC_CAPA X(7)
293 #define TEGRA210_CLK_MC_CBPA X(8)
294 #define TEGRA210_CLK_MC_CPU X(9)
295 #define TEGRA210_CLK_MC_BBC X(10)
296 #define TEGRA210_CLK_EMC_DLL X(14)
297 #define TEGRA210_CLK_UART_FST_MIPI_CAL X(17)
298 #define TEGRA210_CLK_HPLL_ADSP X(26)
299 #define TEGRA210_CLK_PLLP_ADSP X(27)
300 #define TEGRA210_CLK_PLLA_ADSP X(28)
301 #define TEGRA210_CLK_PLLG_REF X(29)
302 #define TEGRA210_CLK_AXIAP Y(4)
303 #define TEGRA210_CLK_MC_CDPA Y(8)
304 #define TEGRA210_CLK_MC_CCPA Y(9)
307 static struct pgate_def pgate_def
[] = {
309 GATE(ISPB
, "ispb", "clk_m", L(3)),
310 GATE(RTC
, "rtc", "clk_s", L(4)),
311 GATE(TIMER
, "timer", "clk_m", L(5)),
312 GATE(UARTA
, "uarta", "pc_uarta" , L(6)),
313 GATE(UARTB
, "uartb", "pc_uartb", L(7)),
314 GATE(GPIO
, "gpio", "clk_m", L(8)),
315 GATE(SDMMC2
, "sdmmc2", "pc_sdmmc2", L(9)),
316 GATE(SPDIF_OUT
, "spdif_out", "pc_spdif_out", L(10)),
317 GATE(SPDIF_IN
, "spdif_in", "pc_spdif_in", L(10)),
318 GATE(I2S1
, "i2s2", "pc_i2s2", L(11)),
319 GATE(I2C1
, "i2c1", "pc_i2c1", L(12)),
320 GATE(SDMMC1
, "sdmmc1", "pc_sdmmc1", L(14)),
321 GATE(SDMMC4
, "sdmmc4", "pc_sdmmc4", L(15)),
322 GATE(PWM
, "pwm", "pc_pwm", L(17)),
323 GATE(I2S2
, "i2s3", "pc_i2s3", L(18)),
324 GATE(VI
, "vi", "pc_vi", L(20)),
325 GATE(USBD
, "usbd", "clk_m", L(22)),
326 GATE(ISP
, "isp", "pc_isp", L(23)),
327 GATE(DISP2
, "disp2", "pc_disp2", L(26)),
328 GATE(DISP1
, "disp1", "pc_disp1", L(27)),
329 GATE(HOST1X
, "host1x", "pc_host1x", L(28)),
330 GATE(I2S0
, "i2s1", "pc_i2s1", L(30)),
332 /* bank H -> 32-63 */
333 GATE(MC
, "mem", "clk_m", H(0)),
334 GATE(AHBDMA
, "ahbdma", "clk_m", H(1)),
335 GATE(APBDMA
, "apbdma", "clk_m", H(2)),
336 GATE(STAT_MON
, "stat_mon", "clk_s", H(5)),
337 GATE(PMC
, "pmc", "clk_s", H(6)),
338 GATE(FUSE
, "fuse", "clk_m", H(7)),
339 GATE(KFUSE
, "kfuse", "clk_m", H(8)),
340 GATE(SBC1
, "spi1", "pc_spi1", H(9)),
341 GATE(SBC2
, "spi2", "pc_spi2", H(12)),
342 GATE(SBC3
, "spi3", "pc_spi3", H(14)),
343 GATE(I2C5
, "i2c5", "pc_i2c5", H(15)),
344 GATE(DSIA
, "dsia", "pllD_dsi_csi", H(16)),
345 GATE(CSI
, "csi", "pllP_out3", H(20)),
346 GATE(I2C2
, "i2c2", "pc_i2c2", H(22)),
347 GATE(UARTC
, "uartc", "pc_uartc", H(23)),
348 GATE(MIPI_CAL
, "mipi_cal", "clk_m", H(24)),
349 GATE(EMC
, "emc", "pc_emc", H(25)),
350 GATE(USB2
, "usb2", "clk_m", H(26)),
351 GATE(BSEV
, "bsev", "clk_m", H(31)),
353 /* bank U -> 64-95 */
354 GATE(UARTD
, "uartd", "pc_uartd", U(1)),
355 GATE(I2C3
, "i2c3", "pc_i2c3", U(3)),
356 GATE(SBC4
, "spi4", "pc_spi4", U(4)),
357 GATE(SDMMC3
, "sdmmc3", "pc_sdmmc3", U(5)),
358 GATE(PCIE
, "pcie", "clk_m", U(6)),
359 GATE(AFI
, "afi", "clk_m", U(8)),
360 GATE(CSITE
, "csite", "pc_csite", U(9)),
361 GATE(SOC_THERM
, "soc_therm", "pc_soc_therm", U(14)),
362 GATE(DTV
, "dtv", "clk_m", U(15)),
363 GATE(I2CSLOW
, "i2c_slow", "pc_i2c_slow", U(17)),
364 GATE(DSIB
, "dsib", "pllD_dsi_csi", U(18)),
365 GATE(TSEC
, "tsec", "pc_tsec", U(19)),
366 GATE(IRAMA
, "irama", "clk_m", U(20)),
367 GATE(IRAMB
, "iramb", "clk_m", U(21)),
368 GATE(IRAMC
, "iramc", "clk_m", U(22)),
369 GATE(IRAMD
, "iramd", "clk_m", U(23)),
370 GATE(CRAM2
, "cram2", "clk_m", U(24)),
371 GATE(XUSB_HOST
, "xusb_host", "pc_xusb_core_host", U(25)),
372 GATE(M_DOUBLER
, "m_doubler", "clk_m", U(26)),
373 GATE(CSUS
, "sus_out", "clk_m", U(28)),
374 GATE(DEVD2_OUT
, "devd2_out", "clk_m", U(29)),
375 GATE(DEVD1_OUT
, "devd1_out", "clk_m", U(30)),
376 GATE(XUSB_DEV
, "xusb_core_dev", "pc_xusb_core_dev", U(31)),
378 /* bank V -> 96-127 */
379 GATE(CPUG
, "cpug", "clk_m", V(0)),
380 GATE(MSELECT
, "mselect", "pc_mselect", V(3)),
381 GATE(TSENSOR
, "tsensor", "pc_tsensor", V(4)),
382 GATE(I2S4
, "i2s5", "pc_i2s5", V(5)),
383 GATE(I2S3
, "i2s4", "pc_i2s4", V(6)),
384 GATE(I2C4
, "i2c4", "pc_i2c4", V(7)),
385 GATE(D_AUDIO
, "ahub", "pc_ahub", V(10)),
386 GATE(APB2APE
, "apb2ape", "clk_m", V(11)),
387 GATE(HDA2CODEC_2X
, "hda2codec_2x", "pc_hda2codec_2x", V(15)),
388 GATE(ATOMICS
, "atomics", "clk_m", V(16)),
389 GATE(SPDIF_2X
, "spdif_doubler", "clk_m", V(22)),
390 GATE(ACTMON
, "actmon", "pc_actmon", V(23)),
391 GATE(EXTERN1
, "extperiph1", "pc_extperiph1", V(24)),
392 GATE(EXTERN2
, "extperiph2", "pc_extperiph2", V(25)),
393 GATE(EXTERN3
, "extperiph3", "pc_extperiph3", V(26)),
394 GATE(SATA_OOB
, "sata_oob", "pc_sata_oob", V(27)),
395 GATE(SATA
, "sata", "pc_sata", V(28)),
396 GATE(HDA
, "hda", "pc_hda", V(29)),
398 /* bank W -> 128-159*/
399 GATE(HDA2HDMI
, "hda2hdmi", "clk_m", W(0)),
400 /* GATE(SATA_COLD, "sata_cold", "clk_m", W(1)),*/ /* Reset only */
401 GATE(PCIERX0
, "pcierx0", "clk_m", W(2)),
402 GATE(PCIERX1
, "pcierx1", "clk_m", W(3)),
403 GATE(PCIERX2
, "pcierx2", "clk_m", W(4)),
404 GATE(PCIERX3
, "pcierx3", "clk_m", W(5)),
405 GATE(PCIERX4
, "pcierx4", "clk_m", W(6)),
406 GATE(PCIERX5
, "pcierx5", "clk_m", W(7)),
407 GATE(CEC
, "cec", "clk_m", W(8)),
408 GATE(PCIE2_IOBIST
, "pcie2_iobist", "clk_m", W(9)),
409 GATE(EMC_IOBIST
, "emc_iobist", "clk_m", W(10)),
410 GATE(SATA_IOBIST
, "sata_iobist", "clk_m", W(12)),
411 GATE(MIPI_IOBIST
, "mipi_iobist", "clk_m", W(13)),
412 GATE(XUSB_GATE
, "xusb_gate", "clk_m", W(15)),
413 GATE(CILAB
, "cilab", "pc_cilab", W(16)),
414 GATE(CILCD
, "cilcd", "pc_cilcd", W(17)),
415 GATE(CILE
, "cilef", "pc_cilef", W(18)),
416 GATE(DSIALP
, "dsia_lp", "pc_dsia_lp", W(19)),
417 GATE(DSIBLP
, "dsib_lp", "pc_dsib_lp", W(20)),
418 GATE(ENTROPY
, "entropy", "pc_entropy", W(21)),
419 GATE(DFLL_REF
, "dvfs_ref", "pc_dvfs_ref", W(27)),
420 GATE(DFLL_SOC
, "dvfs_soc", "pc_dvfs_soc", W(27)),
421 GATE(XUSB_SS
, "xusb_ss", "pc_xusb_ss", W(28)),
422 GATE(EMC_LATENCY
, "emc_latency", "pc_emc_latency", W(29)),
423 GATE(MC1
, "mc1", "clk_m", W(30)),
425 /* bank X -> 160-191*/
426 /*GATE(SPARE, "spare", "clk_m", X(0)), */
427 GATE(DMIC1
, "dmic1", "clk_m", X(1)),
428 GATE(DMIC2
, "dmic2", "clk_m", X(2)),
429 GATE(ETR
, "etr", "clk_m", X(3)),
430 GATE(CAM_MCLK
, "CAM_MCLK", "clk_m", X(4)),
431 GATE(CAM_MCLK2
, "CAM_MCLK2", "clk_m", X(5)),
432 GATE(I2C6
, "i2c6", "pc_i2c6", X(6)),
433 GATE(MC_CAPA
, "mc_capa", "clk_m", X(7)),
434 GATE(MC_CBPA
, "mc_cbpa", "clk_m", X(8)),
435 GATE(MC_CPU
, "mc_cpu", "clk_m", X(9)),
436 GATE(MC_BBC
, "mc_bbc", "clk_m", X(10)),
437 GATE(VIM2_CLK
, "vim2_clk", "clk_m", X(11)),
438 GATE(MIPIBIF
, "mipibif", "clk_m", X(13)),
439 GATE(EMC_DLL
, "emc_dll", "pc_emc_dll", X(14)),
440 GATE(UART_FST_MIPI_CAL
, "uart_fst_mipi_cal", "clk_m", X(17)),
441 GATE(VIC03
, "vic", "pc_vic", X(18)),
442 GATE(DPAUX
, "dpaux", "dpaux_div", X(21)),
443 GATE(SOR0
, "sor0", "pc_sor0", X(22)),
444 GATE(SOR1
, "sor1", "pc_sor1", X(23)),
445 GATE(GPU
, "gpu", "osc_div_clk", X(24)),
446 GATE(DBGAPB
, "dbgapb", "clk_m", X(25)),
447 GATE(HPLL_ADSP
, "hpll_adsp", "clk_m", X(26)),
448 GATE(PLLP_ADSP
, "pllp_adsp", "clk_m", X(27)),
449 GATE(PLLA_ADSP
, "plla_adsp", "clk_m", X(28)),
450 GATE(PLLG_REF
, "pllg_ref", "clk_m", X(29)),
452 /* bank Y -> 192-224*/
453 /* GATE(SPARE1, "spare1", "clk_m", Y(0)), */
454 GATE(SDMMC_LEGACY
, "sdmmc_legacy_tm", "pc_sdmmc_legacy_tm", Y(1)),
455 GATE(NVDEC
, "nvdec", "pc_nvdec", Y(2)),
456 GATE(NVJPG
, "nvjpg", "clk_m", Y(3)),
457 GATE(AXIAP
, "axiap", "clk_m", Y(4)),
458 GATE(DMIC3
, "dmic3", "clk_m", Y(5)),
459 GATE(APE
, "ape", "clk_m", Y(6)),
460 GATE(ADSP
, "adsp", "clk_m", Y(7)),
461 GATE(MC_CDPA
, "mc_cdpa", "clk_m", Y(8)),
462 GATE(MC_CCPA
, "mc_ccpa", "clk_m", Y(9)),
463 GATE(MAUD
, "mc_maud", "clk_m", Y(10)),
464 GATE(TSECB
, "tsecb", "clk_m", Y(14)),
465 GATE(DPAUX1
, "dpaux1", "dpaux1_div", Y(15)),
466 GATE(VI_I2C
, "vi_i2c", "clk_m", Y(16)),
467 GATE(HSIC_TRK
, "hsic_trk", "clk_m", Y(17)),
468 GATE(USB2_TRK
, "usb2_trk", "clk_m", Y(18)),
469 GATE(QSPI
, "qspi", "clk_m", Y(19)),
470 GATE(UARTAPE
, "uarape", "clk_m", Y(20)),
471 GATE(ADSP_NEON
, "adspneon", "clk_m", Y(26)),
472 GATE(NVENC
, "nvenc", "clk_m", Y(27)),
473 GATE(IQC2
, "iqc2", "clk_m", Y(28)),
474 GATE(IQC1
, "iqc1", "clk_m", Y(29)),
475 GATE(SOR_SAFE
, "sor_safe", "sor_safe_div", Y(30)),
476 GATE(PLL_P_OUT_CPU
, "pllp_out_cpu", "clk_m", Y(31)),
479 /* Peripheral clock clock */
480 #define DCF_HAVE_MUX 0x0100 /* Block with multipexor */
481 #define DCF_HAVE_ENA 0x0200 /* Block with enable bit */
482 #define DCF_HAVE_DIV 0x0400 /* Block with divider */
484 /* Mark block with additional bits / functionality. */
485 #define DCF_IS_MASK 0x00FF
486 #define DCF_IS_UART 0x0001
487 #define DCF_IS_VI 0x0002
488 #define DCF_IS_HOST1X 0x0003
489 #define DCF_IS_XUSB_SS 0x0004
490 #define DCF_IS_EMC_DLL 0x0005
491 #define DCF_IS_SATA 0x0006
492 #define DCF_IS_VIC 0x0007
493 #define DCF_IS_AHUB 0x0008
494 #define DCF_IS_SOR0 0x0009
495 #define DCF_IS_EMC 0x000A
496 #define DCF_IS_QSPI 0x000B
497 #define DCF_IS_EMC_SAFE 0x000C
498 /* Basic pheripheral clock */
499 #define PER_CLK(_id, cn, pl, r, diw, fiw, f) \
503 .clkdef.parent_names = pl, \
504 .clkdef.parent_cnt = nitems(pl), \
505 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
508 .div_f_width = fiw, \
512 /* Mux with fractional 8.1 divider. */
513 #define CLK_8_1(id, cn, pl, r, f) \
514 PER_CLK(id, cn, pl, r, 8, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
515 /* Mux with integer 8bits divider. */
516 #define CLK_8_0(id, cn, pl, r, f) \
517 PER_CLK(id, cn, pl, r, 8, 0, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
519 /* Mux with fractional 16.1 divider. */
520 #define CLK16_1(id, cn, pl, r, f) \
521 PER_CLK(id, cn, pl, r, 16, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
522 /* Mux with integer 16bits divider. */
523 #define CLK16_0(id, cn, pl, r, f) \
524 PER_CLK(id, cn, pl, r, 16, 0, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
525 /* Mux wihout divider. */
526 #define CLK_0_0(id, cn, pl, r, f) \
527 PER_CLK(id, cn, pl, r, 0, 0, (f) | DCF_HAVE_MUX)
529 static struct periph_def periph_def
[] = {
530 CLK_8_1(0, "pc_i2s2", mux_a_N_audio1_N_p_N_clkm
, CLK_SOURCE_I2S2
, DCF_HAVE_ENA
),
531 CLK_8_1(0, "pc_i2s3", mux_a_N_audio2_N_p_N_clkm
, CLK_SOURCE_I2S3
, DCF_HAVE_ENA
),
532 CLK_8_1(0, "pc_spdif_out", mux_a_N_audio_N_p_N_clkm
, CLK_SOURCE_SPDIF_OUT
, 0),
533 CLK_8_1(0, "pc_spdif_in", mux_p_c2_c_c4_clkm_c4o1_c4o2
, CLK_SOURCE_SPDIF_IN
, 0),
534 CLK_8_1(0, "pc_pwm", mux_p_c2_c_c4_clks_c4o1_clkm_c4o2
, CLK_SOURCE_PWM
, 0),
535 CLK_8_1(0, "pc_spi2", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_SPI2
, 0),
536 CLK_8_1(0, "pc_spi3", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_SPI3
, 0),
537 CLK16_0(0, "pc_i2c1", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C1
, 0),
538 CLK16_0(0, "pc_i2c5", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C5
, 0),
539 CLK_8_1(0, "pc_spi1", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_SPI1
, 0),
540 CLK_0_0(0, "pc_disp1", mux_p_N_d_N_N_d2_clkm
, CLK_SOURCE_DISP1
, 0),
541 CLK_0_0(0, "pc_disp2", mux_p_N_d_N_N_d2_clkm
, CLK_SOURCE_DISP2
, 0),
542 CLK_8_1(0, "pc_isp", mux_N_c_p_a1_c2_c3_clkm_c4
, CLK_SOURCE_ISP
, 0),
543 CLK_8_1(0, "pc_vi", mux_N_c2_c_c3_p_clkm_a1_c4
, CLK_SOURCE_VI
, DCF_IS_VI
),
544 CLK_8_1(0, "pc_sdmmc1", mux_p_N_N_c4o2_c4o1_N_clkm_c4
, CLK_SOURCE_SDMMC1
, 0),
545 CLK_8_1(0, "pc_sdmmc2", mux_p_N_N_c4o2_c4o1_N_clkm_c4
, CLK_SOURCE_SDMMC2
, 0),
546 CLK_8_1(0, "pc_sdmmc4", mux_p_N_N_c4o2_c4o1_N_clkm_c4
, CLK_SOURCE_SDMMC4
, 0),
547 CLK16_1(0, "pc_uarta", mux_p_c2_c_c4_c4o1_clkm_c4o2
, CLK_SOURCE_UARTA
, DCF_IS_UART
),
548 CLK16_1(0, "pc_uartb", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_UARTB
, DCF_IS_UART
),
549 CLK_8_1(0, "pc_host1x", mux_c4o1_c2_c_c4_p_clkm_a_c4
, CLK_SOURCE_HOST1X
, DCF_IS_HOST1X
),
550 CLK16_0(0, "pc_i2c2", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C2
, 0),
551 CLK_8_1(0, "pc_emc", mux_m_c_p_clkm_mud_mbud_mb_pud
, CLK_SOURCE_EMC
, DCF_IS_EMC
),
552 CLK16_1(0, "pc_uartc", mux_p_c2_c_c4_c4o1_clkm_c4o2
, CLK_SOURCE_UARTC
, DCF_IS_UART
),
553 CLK_8_1(0, "pc_vi_sensor", mux_N_c2_c_c3_p_N_a
, CLK_SOURCE_VI_SENSOR
, 0),
554 CLK_8_1(0, "pc_spi4", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_SPI4
, 0),
555 CLK16_0(0, "pc_i2c3", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C3
, 0),
556 CLK_8_1(0, "pc_sdmmc3", mux_p_c2_c_c3_m_e_clkm
, CLK_SOURCE_SDMMC3
, 0),
557 CLK16_1(0, "pc_uartd", mux_p_c2_c_c4_c4o1_clkm_c4o2
, CLK_SOURCE_UARTD
, DCF_IS_UART
),
558 CLK_8_1(0, "pc_csite", mux_p_c2_refe1_c3_m_a1_clkm_C4
, CLK_SOURCE_CSITE
, 0),
559 CLK_8_1(0, "pc_i2s1", mux_a_N_audio0_N_p_N_clkm
, CLK_SOURCE_I2S1
, 0),
561 CLK_8_1(0, "pc_tsec", mux_p_c2_c_c3_N_a1_clkm_c4
, CLK_SOURCE_TSEC
, 0),
563 CLK_8_1(0, "pc_mselect", mux_p_c2_c_c4o2_c4o1_clks_clkm_c4
, CLK_SOURCE_MSELECT
, 0),
564 CLK_8_1(0, "pc_tsensor", mux_p_c2_c_c4_clkm_c4o1_clks_c4o2
, CLK_SOURCE_TSENSOR
, 0),
565 CLK_8_1(0, "pc_i2s4", mux_a_N_audio3_N_p_N_clkm
, CLK_SOURCE_I2S3
, DCF_HAVE_ENA
),
566 CLK_8_1(0, "pc_i2s5", mux_a_N_audio4_N_p_N_clkm
, CLK_SOURCE_I2S4
, DCF_HAVE_ENA
),
567 CLK16_0(0, "pc_i2c4", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C4
, 0),
568 CLK_8_1(0, "pc_ahub", mux_sep_audio
, CLK_SOURCE_AHUB
, DCF_IS_AHUB
),
569 CLK_8_1(0, "pc_hda2codec_2x", mux_p_c2_c_c4_a_c4o1_clkm_c4o2
, CLK_SOURCE_HDA2CODEC_2X
, 0),
570 CLK_8_1(0, "pc_actmon", mux_p_c2_c_c4_clks_c4o1_clkm_c4o2
, CLK_SOURCE_ACTMON
, 0),
571 CLK_8_1(0, "pc_extperiph1", mux_a_clks_p_clkm_e
, CLK_SOURCE_EXTPERIPH1
, 0),
572 CLK_8_1(0, "pc_extperiph2", mux_a_clks_p_clkm_e
, CLK_SOURCE_EXTPERIPH2
, 0),
573 CLK_8_1(0, "pc_extperiph3", mux_a_clks_p_clkm_e
, CLK_SOURCE_EXTPERIPH3
, 0),
574 CLK_8_1(0, "pc_i2c_slow", mux_p_c2_c_c4_clks_c4o1_clkm_c4o2
, CLK_SOURCE_I2C_SLOW
, 0),
576 CLK_8_1(0, "pc_ispb", mux_N_N_c_N_p_N_a
, CLK_SOURCE_ISPB
, 0),
577 CLK_8_1(0, "pc_sor1", mux_p_N_d_N_N_d2_clkm
, CLK_SOURCE_SOR1
, DCF_IS_SOR0
),
578 CLK_8_1(0, "pc_sor0", mux_p_m_d_a_c_d2_clkm
, CLK_SOURCE_SOR0
, DCF_IS_SOR0
),
579 CLK_8_1(0, "pc_sata_oob", mux_p_c4_c_c4o1_N_c4o2_clkm
, CLK_SOURCE_SATA_OOB
, 0),
580 CLK_8_1(0, "pc_sata", mux_p_N_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_SATA
, DCF_IS_SATA
),
581 CLK_8_1(0, "pc_hda", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_HDA
, 0),
582 CLK_8_1(TEGRA210_CLK_XUSB_HOST_SRC
,
583 "pc_xusb_core_host", mux_clkm_p_N_N_N_refre
, CLK_SOURCE_XUSB_CORE_HOST
, 0),
584 CLK_8_1(TEGRA210_CLK_XUSB_FALCON_SRC
,
585 "pc_xusb_falcon", mux_clkm_p_N_N_N_refre
, CLK_SOURCE_XUSB_FALCON
, 0),
586 CLK_8_1(TEGRA210_CLK_XUSB_FS_SRC
,
587 "pc_xusb_fs", mux_clkm_N_u48_N_p_N_u480
, CLK_SOURCE_XUSB_FS
, 0),
588 CLK_8_1(TEGRA210_CLK_XUSB_DEV_SRC
,
589 "pc_xusb_core_dev", mux_clkm_p_N_N_N_refre
, CLK_SOURCE_XUSB_CORE_DEV
, 0),
590 CLK_8_1(TEGRA210_CLK_XUSB_SS_SRC
,
591 "pc_xusb_ss", mux_clkm_refe_clks_u480
, CLK_SOURCE_XUSB_SS
, DCF_IS_XUSB_SS
),
592 CLK_8_1(0, "pc_cilab", mux_p_N_c_c4_c4o1_c4o2_clkm
, CLK_SOURCE_CILAB
, 0),
593 CLK_8_1(0, "pc_cilcd", mux_p_N_c_c4_c4o1_c4o2_clkm
, CLK_SOURCE_CILCD
, 0),
594 CLK_8_1(0, "pc_cilef", mux_p_N_c_c4_c4o1_c4o2_clkm
, CLK_SOURCE_CILEF
, 0),
595 CLK_8_1(0, "pc_dsia_lp", mux_p_N_c_c4_c4o1_c4o2_clkm
, CLK_SOURCE_DSIA_LP
, 0),
596 CLK_8_1(0, "pc_dsib_lp", mux_p_N_c_c4_c4o1_c4o2_clkm
, CLK_SOURCE_DSIB_LP
, 0),
597 CLK_8_1(0, "pc_entropy", mux_p_N_clkm_N_clks_N_E
, CLK_SOURCE_ENTROPY
, 0),
598 CLK_8_1(0, "pc_dvfs_ref", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_DVFS_REF
, DCF_HAVE_ENA
),
599 CLK_8_1(0, "pc_dvfs_soc", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_DVFS_SOC
, DCF_HAVE_ENA
),
600 CLK_8_1(0, "pc_emc_latency", mux_N_c_p_clkm_N_c4_c4o1_c4o2
, CLK_SOURCE_EMC_LATENCY
, 0),
601 CLK_8_1(0, "pc_soc_therm", mux_N_c_p_clkm_N_c4_c4o1_c4o1
, CLK_SOURCE_SOC_THERM
, 0),
602 CLK_8_1(0, "pc_dmic1", mux_a_audiod1_p_clkm
, CLK_SOURCE_DMIC1
, 0),
603 CLK_8_1(0, "pc_dmic2", mux_a_audiod2_p_clkm
, CLK_SOURCE_DMIC2
, 0),
604 CLK_8_1(0, "pc_vi_sensor2", mux_N_c2_c_c3_p_N_a
, CLK_SOURCE_VI_SENSOR2
, 0),
605 CLK16_0(0, "pc_i2c6", mux_p_c2_c_c4_N_c4o1_clkm_c4o2
, CLK_SOURCE_I2C6
, 0),
607 CLK_8_1(0, "pc_emc_dll", mux_m_c_p_clkm_mud_mbud_mb_pud
, CLK_SOURCE_EMC_DLL
, DCF_IS_EMC_DLL
),
608 CLK_8_1(0, "pc_uart_fst_mipi_cal", mux_p_c_c2_N_c2_N_clkm
, CLK_SOURCE_UART_FST_MIPI_CAL
, 0),
609 CLK_8_1(0, "pc_vic", mux_N_c_p_a1_c2_c3_clkm
, CLK_SOURCE_VIC
, DCF_IS_VIC
),
611 CLK_8_1(0, "pc_sdmmc_legacy_tm", mux_po3_c_c2_clkm_p_c4_c4o1_c4o2
, CLK_SOURCE_SDMMC_LEGACY_TM
, 0),
612 CLK_8_1(0, "pc_nvdec", mux_N_c2_c_c3_p_N_a1_clkm
, CLK_SOURCE_NVDEC
, 0),
613 CLK_8_1(0, "pc_nvjpg", mux_N_c2_c_c3_p_N_a1_clkm
, CLK_SOURCE_NVJPG
, 0),
614 CLK_8_1(0, "pc_nvenc", mux_N_c2_c_c3_p_N_a1_clkm
, CLK_SOURCE_NVENC
, 0),
615 CLK_8_1(0, "pc_dmic3", mux_a_audiod3_p_clkm
, CLK_SOURCE_DMIC3
, 0),
616 CLK_8_1(0, "pc_ape", mux_a_c4_c_c4o1_p_N_clkm_c4o2
, CLK_SOURCE_APE
, 0),
617 CLK_8_1(0, "pc_qspi", mux_p_co1_c_N_c4o2_c4o1_clkm_c4
, CLK_SOURCE_QSPI
, DCF_IS_QSPI
),
618 CLK_8_1(0, "pc_vi_i2c", mux_p_c2_c_c3_N_N_clkm
, CLK_SOURCE_VI_I2C
, 0),
620 CLK_8_0(0, "pc_maud", mux_p_po3_clkm_clks_a
, CLK_SOURCE_MAUD
, 0),
621 CLK_8_1(0, "pc_tsecb", mux_p_c2_c_c3_N_a1_clkm_c4
, CLK_SOURCE_TSECB
, 0),
622 CLK_8_1(0, "pc_uartape", mux_p_c2_c_c3_N_N_clkm
, CLK_SOURCE_UARTAPE
, 0),
623 CLK_8_1(0, "pc_dbgapb", mux_N_N_p_N_N_N_clkm
, CLK_SOURCE_DBGAPB
, 0),
624 CLK_8_1(0, "pc_emc_safe", mux_m_c_p_clkm_mud_mbud_mb_pud
, CLK_SOURCE_EMC_SAFE
, DCF_IS_EMC_SAFE
),
627 static int periph_init(struct clknode
*clk
, device_t dev
);
628 static int periph_recalc(struct clknode
*clk
, uint64_t *freq
);
629 static int periph_set_freq(struct clknode
*clk
, uint64_t fin
,
630 uint64_t *fout
, int flags
, int *stop
);
631 static int periph_set_mux(struct clknode
*clk
, int idx
);
639 uint32_t div_f_width
;
647 static clknode_method_t periph_methods
[] = {
648 /* Device interface */
649 CLKNODEMETHOD(clknode_init
, periph_init
),
650 CLKNODEMETHOD(clknode_recalc_freq
, periph_recalc
),
651 CLKNODEMETHOD(clknode_set_freq
, periph_set_freq
),
652 CLKNODEMETHOD(clknode_set_mux
, periph_set_mux
),
655 DEFINE_CLASS_1(tegra210_periph
, tegra210_periph_class
, periph_methods
,
656 sizeof(struct periph_sc
), clknode_class
);
659 periph_init(struct clknode
*clk
, device_t dev
)
661 struct periph_sc
*sc
;
663 sc
= clknode_get_softc(clk
);
666 if (sc
->flags
& DCF_HAVE_ENA
)
667 MD4(sc
, sc
->base_reg
, PERLCK_ENA_MASK
, PERLCK_ENA_MASK
);
669 RD4(sc
, sc
->base_reg
, ®
);
673 if (sc
->flags
& DCF_HAVE_MUX
)
674 sc
->mux
= (reg
>> PERLCK_MUX_SHIFT
) & PERLCK_MUX_MASK
;
677 if (sc
->flags
& DCF_HAVE_DIV
)
678 sc
->divider
= (reg
& sc
->div_mask
) + 2;
681 if ((sc
->flags
& DCF_IS_MASK
) == DCF_IS_UART
) {
682 if (!(reg
& PERLCK_UDIV_DIS
))
687 if ((sc
->flags
& DCF_IS_MASK
) == DCF_IS_AHUB
) {
688 if (!(reg
& PERLCK_AMUX_DIS
) && (sc
->mux
== 7)) {
690 ((reg
>> PERLCK_AMUX_SHIFT
) & PERLCK_MUX_MASK
);
693 clknode_init_parent_idx(clk
, sc
->mux
);
698 periph_set_mux(struct clknode
*clk
, int idx
)
700 struct periph_sc
*sc
;
704 sc
= clknode_get_softc(clk
);
705 if (!(sc
->flags
& DCF_HAVE_MUX
))
710 RD4(sc
, sc
->base_reg
, ®
);
711 reg
&= ~(PERLCK_MUX_MASK
<< PERLCK_MUX_SHIFT
);
712 if ((sc
->flags
& DCF_IS_MASK
) == DCF_IS_AHUB
) {
713 reg
&= ~PERLCK_AMUX_DIS
;
714 reg
&= ~(PERLCK_MUX_MASK
<< PERLCK_AMUX_SHIFT
);
717 reg
|= idx
<< PERLCK_MUX_SHIFT
;
719 reg
|= 7 << PERLCK_MUX_SHIFT
;
720 reg
|= (idx
- 8) << PERLCK_AMUX_SHIFT
;
723 reg
|= idx
<< PERLCK_MUX_SHIFT
;
725 WR4(sc
, sc
->base_reg
, reg
);
732 periph_recalc(struct clknode
*clk
, uint64_t *freq
)
734 struct periph_sc
*sc
;
737 sc
= clknode_get_softc(clk
);
739 if (sc
->flags
& DCF_HAVE_DIV
) {
741 RD4(sc
, sc
->base_reg
, ®
);
743 *freq
= (*freq
<< sc
->div_f_width
) / sc
->divider
;
749 periph_set_freq(struct clknode
*clk
, uint64_t fin
, uint64_t *fout
,
750 int flags
, int *stop
)
752 struct periph_sc
*sc
;
753 uint64_t tmp
, divider
;
755 sc
= clknode_get_softc(clk
);
756 if (!(sc
->flags
& DCF_HAVE_DIV
)) {
761 tmp
= fin
<< sc
->div_f_width
;
762 divider
= tmp
/ *fout
;
763 if ((tmp
% *fout
) != 0)
766 if (divider
< (1 << sc
->div_f_width
))
767 divider
= 1 << (sc
->div_f_width
- 1);
769 if (flags
& CLK_SET_DRYRUN
) {
770 if (((flags
& (CLK_SET_ROUND_UP
| CLK_SET_ROUND_DOWN
)) == 0) &&
771 (*fout
!= (tmp
/ divider
)))
775 MD4(sc
, sc
->base_reg
, sc
->div_mask
,
776 (divider
- (1 << sc
->div_f_width
)));
778 sc
->divider
= divider
;
780 *fout
= tmp
/ divider
;
786 periph_register(struct clkdom
*clkdom
, struct periph_def
*clkdef
)
789 struct periph_sc
*sc
;
791 clk
= clknode_create(clkdom
, &tegra210_periph_class
, &clkdef
->clkdef
);
795 sc
= clknode_get_softc(clk
);
796 sc
->clkdev
= clknode_get_device(clk
);
797 sc
->base_reg
= clkdef
->base_reg
;
798 sc
->div_width
= clkdef
->div_width
;
799 sc
->div_mask
= (1 <<clkdef
->div_width
) - 1;
800 sc
->div_f_width
= clkdef
->div_f_width
;
801 sc
->div_f_mask
= (1 <<clkdef
->div_f_width
) - 1;
802 sc
->flags
= clkdef
->flags
;
804 clknode_register(clkdom
, clk
);
808 /* -------------------------------------------------------------------------- */
809 static int pgate_init(struct clknode
*clk
, device_t dev
);
810 static int pgate_set_gate(struct clknode
*clk
, bool enable
);
811 static int pgate_get_gate(struct clknode
*clk
, bool *enabled
);
821 static clknode_method_t pgate_methods
[] = {
822 /* Device interface */
823 CLKNODEMETHOD(clknode_init
, pgate_init
),
824 CLKNODEMETHOD(clknode_set_gate
, pgate_set_gate
),
825 CLKNODEMETHOD(clknode_get_gate
, pgate_get_gate
),
828 DEFINE_CLASS_1(tegra210_pgate
, tegra210_pgate_class
, pgate_methods
,
829 sizeof(struct pgate_sc
), clknode_class
);
832 get_enable_reg(int idx
)
834 KASSERT(idx
/ 32 < nitems(clk_enable_reg
),
835 ("Invalid clock index for enable: %d", idx
));
836 return (clk_enable_reg
[idx
/ 32]);
840 get_reset_reg(int idx
)
842 KASSERT(idx
/ 32 < nitems(clk_reset_reg
),
843 ("Invalid clock index for reset: %d", idx
));
844 return (clk_reset_reg
[idx
/ 32]);
848 pgate_init(struct clknode
*clk
, device_t dev
)
851 uint32_t ena_reg
, rst_reg
, mask
;
853 sc
= clknode_get_softc(clk
);
854 mask
= 1 << (sc
->idx
% 32);
857 RD4(sc
, get_enable_reg(sc
->idx
), &ena_reg
);
858 RD4(sc
, get_reset_reg(sc
->idx
), &rst_reg
);
861 sc
->enabled
= ena_reg
& mask
? 1 : 0;
862 clknode_init_parent_idx(clk
, 0);
868 pgate_set_gate(struct clknode
*clk
, bool enable
)
871 uint32_t reg
, mask
, base_reg
;
873 sc
= clknode_get_softc(clk
);
874 mask
= 1 << (sc
->idx
% 32);
875 sc
->enabled
= enable
;
876 base_reg
= get_enable_reg(sc
->idx
);
879 MD4(sc
, base_reg
, mask
, enable
? mask
: 0);
880 RD4(sc
, base_reg
, ®
);
888 pgate_get_gate(struct clknode
*clk
, bool *enabled
)
891 uint32_t reg
, mask
, base_reg
;
893 sc
= clknode_get_softc(clk
);
894 mask
= 1 << (sc
->idx
% 32);
895 base_reg
= get_enable_reg(sc
->idx
);
898 RD4(sc
, base_reg
, ®
);
900 *enabled
= reg
& mask
? true: false;
906 tegra210_hwreset_by_idx(struct tegra210_car_softc
*sc
, intptr_t idx
, bool reset
)
908 uint32_t reg
, mask
, reset_reg
;
910 CLKDEV_DEVICE_LOCK(sc
->dev
);
911 if (idx
== TEGRA210_RST_DFLL_DVCO
) {
912 CLKDEV_MODIFY_4(sc
->dev
, DFLL_BASE
, DFLL_BASE_DVFS_DFLL_RESET
,
913 reset
? DFLL_BASE_DVFS_DFLL_RESET
: 0);
914 CLKDEV_READ_4(sc
->dev
, DFLL_BASE
, ®
);
916 if (idx
== TEGRA210_RST_ADSP
) {
917 reset_reg
= (reset
) ? RST_DEV_Y_SET
: RST_DEV_Y_CLR
;
918 mask
= (0x1F << 22) |(1 << 7);
919 CLKDEV_WRITE_4(sc
->dev
, reset_reg
, mask
);
920 CLKDEV_READ_4(sc
->dev
, reset_reg
, ®
);
922 mask
= 1 << (idx
% 32);
923 reset_reg
= get_reset_reg(idx
);
925 CLKDEV_MODIFY_4(sc
->dev
, reset_reg
, mask
, reset
? mask
: 0);
926 CLKDEV_READ_4(sc
->dev
, reset_reg
, ®
);
928 CLKDEV_DEVICE_UNLOCK(sc
->dev
);
934 pgate_register(struct clkdom
*clkdom
, struct pgate_def
*clkdef
)
939 clk
= clknode_create(clkdom
, &tegra210_pgate_class
, &clkdef
->clkdef
);
943 sc
= clknode_get_softc(clk
);
944 sc
->clkdev
= clknode_get_device(clk
);
945 sc
->idx
= clkdef
->idx
;
946 sc
->flags
= clkdef
->flags
;
948 clknode_register(clkdom
, clk
);
953 tegra210_periph_clock(struct tegra210_car_softc
*sc
)
957 for (i
= 0; i
< nitems(periph_def
); i
++) {
958 rv
= periph_register(sc
->clkdom
, &periph_def
[i
]);
960 panic("tegra210_periph_register failed");
962 for (i
= 0; i
< nitems(pgate_def
); i
++) {
963 rv
= pgate_register(sc
->clkdom
, &pgate_def
[i
]);
965 panic("tegra210_pgate_register failed");