1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021, Adrian Chadd <adrian@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* Driver for Qualcomm IPQ4018 clock and reset device */
29
30 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/module.h>
35 #include <sys/sglist.h>
36 #include <sys/random.h>
37 #include <sys/stdatomic.h>
38 #include <sys/mutex.h>
39
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/bus.h>
43
44 #include <dev/fdt/fdt_common.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47
48 #include <dev/extres/clk/clk_div.h>
49 #include <dev/extres/clk/clk_fixed.h>
50 #include <dev/extres/clk/clk_mux.h>
51 #include <dev/extres/clk/clk_link.h>
52
53 #include <dt-bindings/clock/qcom,gcc-ipq4019.h>
54
55 #include <dev/qcom_clk/qcom_clk_freqtbl.h>
56 #include <dev/qcom_clk/qcom_clk_fepll.h>
57 #include <dev/qcom_clk/qcom_clk_fdiv.h>
58 #include <dev/qcom_clk/qcom_clk_apssdiv.h>
59 #include <dev/qcom_clk/qcom_clk_rcg2.h>
60 #include <dev/qcom_clk/qcom_clk_branch2.h>
61 #include <dev/qcom_clk/qcom_clk_ro_div.h>
62
63 #include "qcom_gcc_ipq4018_var.h"
64
65
66 /* Fixed rate clock. */
67 #define F_RATE(_id, cname, _freq) \
68 { \
69 .clkdef.id = _id, \
70 .clkdef.name = cname, \
71 .clkdef.parent_names = NULL, \
72 .clkdef.parent_cnt = 0, \
73 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
74 .freq = _freq, \
75 }
76
77 /* Linked clock. */
78 #define F_LINK(_id, _cname) \
79 { \
80 .clkdef.id = _id, \
81 .clkdef.name = _cname, \
82 .clkdef.parent_names = NULL, \
83 .clkdef.parent_cnt = 0, \
84 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
85 }
86
87
88 /* FEPLL clock */
89 #define F_FEPLL(_id, _cname, _parent, _reg, _fs, _fw, _rs, _rw) \
90 { \
91 .clkdef.id = _id, \
92 .clkdef.name = _cname, \
93 .clkdef.parent_names = (const char *[]){_parent}, \
94 .clkdef.parent_cnt = 1, \
95 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
96 .offset = _reg, \
97 .fdbkdiv_shift = _fs, \
98 .fdbkdiv_width = _fw, \
99 .refclkdiv_shift = _rs, \
100 .refclkdiv_width = _rw, \
101 }
102
103 /* Fixed divisor clock */
104 #define F_FDIV(_id, _cname, _parent, _divisor) \
105 { \
106 .clkdef.id = _id, \
107 .clkdef.name = _cname, \
108 .clkdef.parent_names = (const char *[]){_parent}, \
109 .clkdef.parent_cnt = 1, \
110 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
111 .divisor = _divisor, \
112 }
113
114 /* APSS DIV clock */
115 #define F_APSSDIV(_id, _cname, _parent, _doffset, _dshift, _dwidth, \
116 _eoffset, _eshift, _freqtbl) \
117 { \
118 .clkdef.id = _id, \
119 .clkdef.name = _cname, \
120 .clkdef.parent_names = (const char *[]){_parent}, \
121 .clkdef.parent_cnt = 1, \
122 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
123 .div_offset = _doffset, \
124 .div_width = _dwidth, \
125 .div_shift = _dshift, \
126 .enable_offset = _eoffset, \
127 .enable_shift = _eshift, \
128 .freq_tbl = _freqtbl, \
129 }
130
131 /* read-only div table */
132 #define F_RO_DIV(_id, _cname, _parent, _offset, _shift, _width, _tbl) \
133 { \
134 .clkdef.id = _id, \
135 .clkdef.name = _cname, \
136 .clkdef.parent_names = (const char *[]){_parent}, \
137 .clkdef.parent_cnt = 1, \
138 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
139 .offset = _offset, \
140 .width = _width, \
141 .shift = _shift, \
142 .div_tbl = _tbl, \
143 }
144
145 /* RCG2 clock */
146 #define F_RCG2(_id, _cname, _parents, _rcgr, _hid_width, _mnd_width, \
147 _safe_src_idx, _safe_pre_parent_idx, _cfg_offset, _flags, \
148 _freq_tbl) \
149 { \
150 .clkdef.id = _id, \
151 .clkdef.name = _cname, \
152 .clkdef.parent_names = _parents, \
153 .clkdef.parent_cnt = nitems(_parents), \
154 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
155 .cmd_rcgr = _rcgr, \
156 .hid_width = _hid_width, \
157 .mnd_width = _mnd_width, \
158 .safe_src_idx = _safe_src_idx, \
159 .flags= _flags, \
160 .safe_pre_parent_idx = _safe_pre_parent_idx, \
161 .freq_tbl = _freq_tbl, \
162 }
163
164 /* branch2 gate nodes */
165 #define F_BRANCH2(_id, _cname, _parent, _eo, _es, _hr, _hs, _haltreg, \
166 _type, _voted, _flags) \
167 { \
168 .clkdef.id = _id, \
169 .clkdef.name = _cname, \
170 .clkdef.parent_names = (const char *[]){_parent}, \
171 .clkdef.parent_cnt = 1, \
172 .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
173 .enable_offset = _eo, \
174 .enable_shift = _es, \
175 .hwcg_reg = _hr, \
176 .hwcg_bit = _hs, \
177 .halt_reg = _haltreg, \
178 .halt_check_type = _type, \
179 .halt_check_voted = _voted, \
180 .flags = _flags, \
181 }
182
183 /*
184 * Fixed "gcc_fepll_vco" PLL derived sources:
185 *
186 * P_FEPLL125 - 125MHz
187 * P_FEPLL125DLY - 125MHz
188 * P_FEPLL200 - 200MHz
189 * "fepll500" - 500MHz
190 *
191 * Fixed "gcc_apps_ddrpll_vco" PLL derived sources:
192 *
193 * P_DDRPLL - 192MHz
194 */
195 static struct qcom_clk_fdiv_def fdiv_tbl[] = {
196 F_FDIV(GCC_FEPLL125_CLK, "fepll125", "gcc_fepll_vco", 32),
197 F_FDIV(GCC_FEPLL125DLY_CLK, "fepll125dly", "gcc_fepll_vco", 32),
198 F_FDIV(GCC_FEPLL200_CLK, "fepll200", "gcc_fepll_vco", 20),
199 F_FDIV(GCC_FEPLL500_CLK, "fepll500", "gcc_fepll_vco", 8),
200 F_FDIV(GCC_SDCC_PLLDIV_CLK, "ddrpllsdcc", "gcc_apps_ddrpll_vco", 28),
201 };
202
203 /*
204 * FEPLL - 48MHz (xo) input, 4GHz output
205 * DDRPLL - 48MHz (xo) input, 5.376GHz output
206 */
207 static struct qcom_clk_fepll_def fepll_tbl[] = {
208 F_FEPLL(GCC_FEPLL_VCO, "gcc_fepll_vco", "xo", 0x2f020, 16, 8, 24, 5),
209 F_FEPLL(GCC_APSS_DDRPLL_VCO, "gcc_apps_ddrpll_vco", "xo", 0x2e020,
210 16, 8, 24, 5),
211 };
212
213 /*
214 * Frequency table for the APSS PLL/DIV path for the CPU frequency.
215 *
216 * Note - the APSS DIV code only needs the frequency and pre-divisor,
217 * not the other fields.
218 */
219 static struct qcom_clk_freq_tbl apss_freq_tbl[] = {
220 { 384000000, "gcc_apps_ddrpll_vco", 0xd, 0, 0 },
221 { 413000000, "gcc_apps_ddrpll_vco", 0xc, 0, 0 },
222 { 448000000, "gcc_apps_ddrpll_vco", 0xb, 0, 0 },
223 { 488000000, "gcc_apps_ddrpll_vco", 0xa, 0, 0 },
224 { 512000000, "gcc_apps_ddrpll_vco", 0x9, 0, 0 },
225 { 537000000, "gcc_apps_ddrpll_vco", 0x8, 0, 0 },
226 { 565000000, "gcc_apps_ddrpll_vco", 0x7, 0, 0 },
227 { 597000000, "gcc_apps_ddrpll_vco", 0x6, 0, 0 },
228 { 632000000, "gcc_apps_ddrpll_vco", 0x5, 0, 0 },
229 { 672000000, "gcc_apps_ddrpll_vco", 0x4, 0, 0 },
230 { 716000000, "gcc_apps_ddrpll_vco", 0x3, 0, 0 },
231 { 768000000, "gcc_apps_ddrpll_vco", 0x2, 0, 0 },
232 { 823000000, "gcc_apps_ddrpll_vco", 0x1, 0, 0 },
233 { 896000000, "gcc_apps_ddrpll_vco", 0x0, 0, 0 },
234 { 0, }
235 };
236
237 /*
238 * APSS div/gate
239 */
240 static struct qcom_clk_apssdiv_def apssdiv_tbl[] = {
241 F_APSSDIV(GCC_APSS_CPU_PLLDIV_CLK, "ddrpllapss",
242 "gcc_apps_ddrpll_vco", 0x2e020,
243 4, 4, 0x2e000, 0, &apss_freq_tbl[0]),
244 };
245
246 /*
247 * Parent clocks for the apps_clk_src clock.
248 */
249 static const char * apps_clk_src_parents[] = {
250 "xo", "ddrpllapss", "fepll500", "fepll200"
251 };
252
253 /*
254 * Parents lists for a variety of blocks.
255 */
256 static const char * gcc_xo_200_parents[] = {
257 "xo", "fepll200"
258 };
259 static const char * gcc_xo_200_500_parents[] = {
260 "xo", "fepll200", "fepll500"
261 };
262 static const char * gcc_xo_200_spi_parents[] = {
263 "xo", NULL, "fepll200"
264 };
265 static const char * gcc_xo_sdcc1_500_parents[] = {
266 "xo", "ddrpllsdcc", "fepll500"
267 };
268
269 static const char * gcc_xo_125_dly_parents[] = {
270 "xo", "fepll125dly"
271 };
272
273 static const char * gcc_xo_wcss2g_parents[] = {
274 "xo", "fepllwcss2g"
275 };
276
277 static const char * gcc_xo_wcss5g_parents[] = {
278 "xo", "fepllwcss5g"
279 };
280
281 static struct qcom_clk_freq_tbl apps_clk_src_freq_tbl[] = {
282 { 48000000, "xo", 1, 0, 0 },
283 { 200000000, "fepll200", 1, 0, 0 },
284 { 384000000, "ddrpllapss", 1, 0, 0 },
285 { 413000000, "ddrpllapss", 1, 0, 0 },
286 { 448000000, "ddrpllapss", 1, 0, 0 },
287 { 488000000, "ddrpllapss", 1, 0, 0 },
288 { 500000000, "fepll500", 1, 0, 0 },
289 { 512000000, "ddrpllapss", 1, 0, 0 },
290 { 537000000, "ddrpllapss", 1, 0, 0 },
291 { 565000000, "ddrpllapss", 1, 0, 0 },
292 { 597000000, "ddrpllapss", 1, 0, 0 },
293 { 632000000, "ddrpllapss", 1, 0, 0 },
294 { 672000000, "ddrpllapss", 1, 0, 0 },
295 { 716000000, "ddrpllapss", 1, 0, 0 },
296 { 0,}
297
298 };
299
300 static struct qcom_clk_freq_tbl audio_clk_src_freq_tbl[] = {
301 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
302 { 200000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
303 { 0,}
304 };
305
306 static struct qcom_clk_freq_tbl blsp1_qup1_i2c_apps_clk_src_freq_tbl[] = {
307 { 19050000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10.5), 1, 1 },
308 { 0,}
309 };
310
311 static struct qcom_clk_freq_tbl blsp1_qup1_spi_apps_clk_src_freq_tbl[] = {
312 { 960000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(12), 1, 4 },
313 { 4800000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 },
314 { 9600000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 },
315 { 15000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 3 },
316 { 19200000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 5 },
317 { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 },
318 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
319 { 0,}
320 };
321
322 static struct qcom_clk_freq_tbl gcc_pcnoc_ahb_clk_src_freq_tbl[] = {
323 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
324 { 100000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 },
325 { 0, }
326 };
327
328 static struct qcom_clk_freq_tbl blsp1_uart1_apps_clk_src_freq_tbl[] = {
329 { 1843200, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 144, 15625 },
330 { 3686400, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 288, 15625 },
331 { 7372800, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 576, 15625 },
332 { 14745600, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1152, 15625 },
333 { 16000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 2, 25 },
334 { 24000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 2 },
335 { 32000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 25 },
336 { 40000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 },
337 { 46400000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 29, 125 },
338 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
339 { 0, }
340 };
341
342 static struct qcom_clk_freq_tbl gp1_clk_src_freq_tbl[] = {
343 { 1250000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 16, 0 },
344 { 2500000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 8, 0 },
345 { 5000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 4, 0 },
346 { 0, }
347 };
348
349 static struct qcom_clk_freq_tbl sdcc1_apps_clk_src_freq_tbl[] = {
350 { 144000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 3, 240 },
351 { 400000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 0 },
352 { 20000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 25 },
353 { 25000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 20 },
354 { 50000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 10 },
355 { 100000000, "fepll500", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 1, 5 },
356 { 192000000, "ddrpllsdcc", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
357 { 0, }
358 };
359
360 static struct qcom_clk_freq_tbl apps_ahb_clk_src_freq_tbl[] = {
361 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
362 { 100000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(2), 0, 0 },
363 { 0, }
364 };
365
366 static struct qcom_clk_freq_tbl usb30_mock_utmi_clk_src_freq_tbl[] = {
367 { 2000000, "fepll200", QCOM_CLK_FREQTBL_PREDIV_RCG2(10), 0, 0 },
368 { 0, }
369 };
370
371 static struct qcom_clk_freq_tbl fephy_125m_dly_clk_src_freq_tbl[] = {
372 { 125000000, "fepll125dly", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
373 { 0, }
374 };
375
376 static struct qcom_clk_freq_tbl wcss2g_clk_src_freq_tbl[] = {
377 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
378 { 250000000, "fepllwcss2g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
379 { 0, }
380 };
381
382 static struct qcom_clk_freq_tbl wcss5g_clk_src_freq_tbl[] = {
383 { 48000000, "xo", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
384 { 250000000, "fepllwcss5g", QCOM_CLK_FREQTBL_PREDIV_RCG2(1), 0, 0 },
385 { 0, }
386 };
387
388 /*
389 * Divisor table for the 2g/5g wifi clock divisors.
390 */
391 static struct qcom_clk_ro_div_tbl fepllwcss_clk_div_tbl[] = {
392 { 0, 15 },
393 { 1, 16 },
394 { 2, 18 },
395 { 3, 20 },
396 { 0, 0 }
397 };
398
399 /*
400 * Read-only divisor table clocks.
401 */
402 static struct qcom_clk_ro_div_def ro_div_tbl[] = {
403 F_RO_DIV(GCC_FEPLL_WCSS2G_CLK, "fepllwcss2g", "gcc_fepll_vco",
404 0x2f020, 8, 2, &fepllwcss_clk_div_tbl[0]),
405 F_RO_DIV(GCC_FEPLL_WCSS5G_CLK, "fepllwcss5g", "gcc_fepll_vco",
406 0x2f020, 12, 2, &fepllwcss_clk_div_tbl[0]),
407 };
408
409 /*
410 * RCG2 clocks
411 */
412 static struct qcom_clk_rcg2_def rcg2_tbl[] = {
413 F_RCG2(AUDIO_CLK_SRC, "audio_clk_src", gcc_xo_200_parents,
414 0x1b000, 5, 0, -1, -1, 0, 0, &audio_clk_src_freq_tbl[0]),
415 F_RCG2(BLSP1_QUP1_I2C_APPS_CLK_SRC, "blsp1_qup1_i2c_apps_clk_src",
416 gcc_xo_200_parents, 0x200c, 5, 0, -1, -1, 0, 0,
417 &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]),
418 F_RCG2(BLSP1_QUP2_I2C_APPS_CLK_SRC, "blsp1_qup2_i2c_apps_clk_src",
419 gcc_xo_200_parents, 0x3000, 5, 0, -1, -1, 0, 0,
420 &blsp1_qup1_i2c_apps_clk_src_freq_tbl[0]),
421 F_RCG2(BLSP1_QUP1_SPI_APPS_CLK_SRC, "blsp1_qup1_spi_apps_clk_src",
422 gcc_xo_200_spi_parents, 0x2024, 5, 8, -1, -1, 0, 0,
423 &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]),
424 F_RCG2(BLSP1_QUP2_SPI_APPS_CLK_SRC, "blsp1_qup2_spi_apps_clk_src",
425 gcc_xo_200_spi_parents, 0x3014, 5, 8, -1, -1, 0, 0,
426 &blsp1_qup1_spi_apps_clk_src_freq_tbl[0]),
427 F_RCG2(BLSP1_UART1_APPS_CLK_SRC, "blsp1_uart1_apps_clk_src",
428 gcc_xo_200_spi_parents, 0x2044, 5, 16, -1, -1, 0, 0,
429 &blsp1_uart1_apps_clk_src_freq_tbl[0]),
430 F_RCG2(BLSP1_UART2_APPS_CLK_SRC, "blsp1_uart2_apps_clk_src",
431 gcc_xo_200_spi_parents, 0x3034, 5, 16, -1, -1, 0, 0,
432 &blsp1_uart1_apps_clk_src_freq_tbl[0]),
433 F_RCG2(GP1_CLK_SRC, "gp1_clk_src", gcc_xo_200_parents, 0x8004,
434 5, 8, -1, -1, 0, 0,
435 &gp1_clk_src_freq_tbl[0]),
436 F_RCG2(GP2_CLK_SRC, "gp2_clk_src", gcc_xo_200_parents, 0x9004,
437 5, 8, -1, -1, 0, 0,
438 &gp1_clk_src_freq_tbl[0]),
439 F_RCG2(GP3_CLK_SRC, "gp3_clk_src", gcc_xo_200_parents, 0xa004,
440 5, 8, -1, -1, 0, 0,
441 &gp1_clk_src_freq_tbl[0]),
442 F_RCG2(SDCC1_APPS_CLK_SRC, "sdcc1_apps_clk_src",
443 gcc_xo_sdcc1_500_parents, 0x18004, 5, 0, -1, -1, 0, 0,
444 &sdcc1_apps_clk_src_freq_tbl[0]),
445 F_RCG2(GCC_APPS_CLK_SRC, "apps_clk_src", apps_clk_src_parents,
446 0x1900c, 5, 0, -1, 2, 0,
447 QCOM_CLK_RCG2_FLAGS_SET_RATE_PARENT,
448 &apps_clk_src_freq_tbl[0]),
449 F_RCG2(GCC_APPS_AHB_CLK_SRC, "apps_ahb_clk_src",
450 gcc_xo_200_500_parents, 0x19014, 5, 0, -1, -1, 0,
451 0, &apps_ahb_clk_src_freq_tbl[0]),
452 F_RCG2(GCC_USB3_MOCK_UTMI_CLK_SRC, "usb30_mock_utmi_clk_src",
453 gcc_xo_200_parents, 0x1e000, 5, 0, -1, -1, 0, 0,
454 &usb30_mock_utmi_clk_src_freq_tbl[0]),
455 F_RCG2(FEPHY_125M_DLY_CLK_SRC, "fephy_125m_dly_clk_src",
456 gcc_xo_125_dly_parents, 0x12000, 5, 0, -1, -1, 0, 0,
457 &fephy_125m_dly_clk_src_freq_tbl[0]),
458 F_RCG2(WCSS2G_CLK_SRC, "wcss2g_clk_src", gcc_xo_wcss2g_parents,
459 0x1f000, 5, 0, -1, -1, 0, 0,
460 &wcss2g_clk_src_freq_tbl[0]),
461 F_RCG2(WCSS5G_CLK_SRC, "wcss5g_clk_src", gcc_xo_wcss5g_parents,
462 0x20000, 5, 0, -1, -1, 0, 0,
463 &wcss5g_clk_src_freq_tbl[0]),
464 F_RCG2(GCC_PCNOC_AHB_CLK_SRC, "gcc_pcnoc_ahb_clk_src",
465 gcc_xo_200_500_parents, 0x21024, 5, 0, -1, -1, 0, 0,
466 &gcc_pcnoc_ahb_clk_src_freq_tbl[0]),
467 };
468
469 /*
470 * branch2 clocks
471 */
472 static struct qcom_clk_branch2_def branch2_tbl[] = {
473 F_BRANCH2(GCC_AUDIO_AHB_CLK, "gcc_audio_ahb_clk", "pcnoc_clk_src",
474 0x1b010, 0, 0, 0, 0x1b010, QCOM_CLK_BRANCH2_BRANCH_HALT,
475 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
476 F_BRANCH2(GCC_AUDIO_PWM_CLK, "gcc_audio_pwm_clk", "audio_clk_src",
477 0x1b00c, 0, 0, 0, 0x1b00c, QCOM_CLK_BRANCH2_BRANCH_HALT,
478 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
479 F_BRANCH2(GCC_BLSP1_QUP1_I2C_APPS_CLK, "gcc_blsp1_qup1_i2c_apps_clk",
480 "blsp1_qup1_i2c_apps_clk_src",
481 0x2008, 0, 0, 0, 0x2008, QCOM_CLK_BRANCH2_BRANCH_HALT,
482 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
483 F_BRANCH2(GCC_BLSP1_QUP2_I2C_APPS_CLK, "gcc_blsp1_qup2_i2c_apps_clk",
484 "blsp1_qup2_i2c_apps_clk_src",
485 0x3010, 0, 0, 0, 0x3010, QCOM_CLK_BRANCH2_BRANCH_HALT,
486 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
487 F_BRANCH2(GCC_BLSP1_QUP1_SPI_APPS_CLK, "gcc_blsp1_qup1_spi_apps_clk",
488 "blsp1_qup1_spi_apps_clk_src",
489 0x2004, 0, 0, 0, 0x2004, QCOM_CLK_BRANCH2_BRANCH_HALT,
490 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
491 F_BRANCH2(GCC_BLSP1_QUP2_SPI_APPS_CLK, "gcc_blsp1_qup2_spi_apps_clk",
492 "blsp1_qup2_spi_apps_clk_src",
493 0x300c, 0, 0, 0, 0x300c, QCOM_CLK_BRANCH2_BRANCH_HALT,
494 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
495 F_BRANCH2(GCC_BLSP1_UART1_APPS_CLK, "gcc_blsp1_uart1_apps_clk",
496 "blsp1_uart1_apps_clk_src",
497 0x203c, 0, 0, 0, 0x203c, QCOM_CLK_BRANCH2_BRANCH_HALT,
498 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
499 F_BRANCH2(GCC_BLSP1_UART2_APPS_CLK, "gcc_blsp1_uart2_apps_clk",
500 "blsp1_uart2_apps_clk_src",
501 0x302c, 0, 0, 0, 0x302c, QCOM_CLK_BRANCH2_BRANCH_HALT,
502 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
503 F_BRANCH2(GCC_GP1_CLK, "gcc_gp1_clk", "gp1_clk_src",
504 0x8000, 0, 0, 0, 0x8000, QCOM_CLK_BRANCH2_BRANCH_HALT,
505 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
506 F_BRANCH2(GCC_GP2_CLK, "gcc_gp2_clk", "gp2_clk_src",
507 0x9000, 0, 0, 0, 0x9000, QCOM_CLK_BRANCH2_BRANCH_HALT,
508 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
509 F_BRANCH2(GCC_GP3_CLK, "gcc_gp3_clk", "gp3_clk_src",
510 0xa000, 0, 0, 0, 0xa000, QCOM_CLK_BRANCH2_BRANCH_HALT,
511 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
512 /* BRANCH_HALT_VOTED; note the different enable/halt */
513 F_BRANCH2(GCC_APPS_AHB_CLK_SRC, "gcc_apss_ahb_clk",
514 "apps_ahb_clk_src",
515 0x6000, 14, 0, 0, 0x19004, QCOM_CLK_BRANCH2_BRANCH_HALT,
516 true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
517 F_BRANCH2(GCC_BLSP1_AHB_CLK, "gcc_blsp1_ahb_clk",
518 "pcnoc_clk_src",
519 0x6000, 10, 0, 0, 0x1008, QCOM_CLK_BRANCH2_BRANCH_HALT,
520 true, 0), /* BRANCH_HALT_VOTED */
521 F_BRANCH2(GCC_DCD_XO_CLK, "gcc_dcd_xo_clk", "xo",
522 0x2103c, 0, 0, 0, 0x2103c, QCOM_CLK_BRANCH2_BRANCH_HALT,
523 false, 0),
524 F_BRANCH2(GCC_BOOT_ROM_AHB_CLK, "gcc_boot_rom_ahb_clk",
525 "pcnoc_clk_src", 0x1300c, 0, 0, 0, 0x1300c,
526 QCOM_CLK_BRANCH2_BRANCH_HALT,
527 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
528 F_BRANCH2(GCC_CRYPTO_AHB_CLK, "gcc_crypto_ahb_clk",
529 "pcnoc_clk_src", 0x6000, 0, 0, 0, 0x16024,
530 QCOM_CLK_BRANCH2_BRANCH_HALT,
531 true, 0), /* BRANCH_HALT_VOTED */
532 F_BRANCH2(GCC_CRYPTO_AXI_CLK, "gcc_crypto_axi_clk",
533 "fepll125", 0x6000, 1, 0, 0, 0x16020,
534 QCOM_CLK_BRANCH2_BRANCH_HALT,
535 true, 0), /* BRANCH_HALT_VOTED */
536 F_BRANCH2(GCC_CRYPTO_CLK, "gcc_crypto_clk", "fepll125",
537 0x6000, 2, 0, 0, 0x1601c, QCOM_CLK_BRANCH2_BRANCH_HALT,
538 true, 0), /* BRANCH_HALT_VOTED */
539 F_BRANCH2(GCC_ESS_CLK, "gcc_ess_clk", "fephy_125m_dly_clk_src",
540 0x12010, 0, 0, 0, 0x12010, QCOM_CLK_BRANCH2_BRANCH_HALT,
541 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
542 /* BRANCH_HALT_VOTED */
543 F_BRANCH2(GCC_IMEM_AXI_CLK, "gcc_imem_axi_clk", "fepll200",
544 0x6000, 17, 0, 0, 0xe004, QCOM_CLK_BRANCH2_BRANCH_HALT,
545 true, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
546 F_BRANCH2(GCC_IMEM_CFG_AHB_CLK, "gcc_imem_cfg_ahb_clk",
547 "pcnoc_clk_src",
548 0xe008, 0, 0, 0, 0xe008, QCOM_CLK_BRANCH2_BRANCH_HALT,
549 false, 0),
550 F_BRANCH2(GCC_PCIE_AHB_CLK, "gcc_pcie_ahb_clk", "pcnoc_clk_src",
551 0x1d00c, 0, 0, 0, 0x1d00c, QCOM_CLK_BRANCH2_BRANCH_HALT,
552 false, 0),
553 F_BRANCH2(GCC_PCIE_AXI_M_CLK, "gcc_pcie_axi_m_clk", "fepll200",
554 0x1d004, 0, 0, 0, 0x1d004, QCOM_CLK_BRANCH2_BRANCH_HALT,
555 false, 0),
556 F_BRANCH2(GCC_PCIE_AXI_S_CLK, "gcc_pcie_axi_s_clk", "fepll200",
557 0x1d008, 0, 0, 0, 0x1d008, QCOM_CLK_BRANCH2_BRANCH_HALT,
558 false, 0),
559 F_BRANCH2(GCC_PRNG_AHB_CLK, "gcc_prng_ahb_clk", "pcnoc_clk_src",
560 0x6000, 8, 0, 0, 0x13004, QCOM_CLK_BRANCH2_BRANCH_HALT,
561 true, 0), /* BRANCH_HALT_VOTED */
562 F_BRANCH2(GCC_QPIC_AHB_CLK, "gcc_qpic_ahb_clk", "pcnoc_clk_src",
563 0x1c008, 0, 0, 0, 0x1c008, QCOM_CLK_BRANCH2_BRANCH_HALT,
564 false, 0),
565 F_BRANCH2(GCC_QPIC_CLK, "gcc_qpic_clk", "pcnoc_clk_src",
566 0x1c004, 0, 0, 0, 0x1c004, QCOM_CLK_BRANCH2_BRANCH_HALT,
567 false, 0),
568 F_BRANCH2(GCC_SDCC1_AHB_CLK, "gcc_sdcc1_ahb_clk", "pcnoc_clk_src",
569 0x18010, 0, 0, 0, 0x18010, QCOM_CLK_BRANCH2_BRANCH_HALT,
570 false, 0),
571 F_BRANCH2(GCC_SDCC1_APPS_CLK, "gcc_sdcc1_apps_clk",
572 "sdcc1_apps_clk_src", 0x1800c, 0, 0, 0, 0x1800c,
573 QCOM_CLK_BRANCH2_BRANCH_HALT,
574 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
575 F_BRANCH2(GCC_TLMM_AHB_CLK, "gcc_tlmm_ahb_clk", "pcnoc_clk_src",
576 0x6000, 5, 0, 0, 0x5004, QCOM_CLK_BRANCH2_BRANCH_HALT,
577 true, 0), /* BRANCH_HALT_VOTED */
578 F_BRANCH2(GCC_USB2_MASTER_CLK, "gcc_usb2_master_clk", "pcnoc_clk_src",
579 0x1e00c, 0, 0, 0, 0x1e00c, QCOM_CLK_BRANCH2_BRANCH_HALT,
580 false, 0),
581 F_BRANCH2(GCC_USB2_SLEEP_CLK, "gcc_usb2_sleep_clk",
582 "gcc_sleep_clk_src", 0x1e010, 0, 0, 0, 0x1e010,
583 QCOM_CLK_BRANCH2_BRANCH_HALT,
584 false, 0),
585 F_BRANCH2(GCC_USB2_MOCK_UTMI_CLK, "gcc_usb2_mock_utmi_clk",
586 "usb30_mock_utmi_clk_src", 0x1e014, 0, 0, 0, 0x1e014,
587 QCOM_CLK_BRANCH2_BRANCH_HALT,
588 false, 0),
589 F_BRANCH2(GCC_USB3_MASTER_CLK, "gcc_usb3_master_clk", "fepll125",
590 0x1e028, 0, 0, 0, 0x1e028, QCOM_CLK_BRANCH2_BRANCH_HALT,
591 false, 0),
592 F_BRANCH2(GCC_USB3_SLEEP_CLK, "gcc_usb3_sleep_clk", "gcc_sleep_clk_src",
593 0x1e02c, 0, 0, 0, 0x1e02c, QCOM_CLK_BRANCH2_BRANCH_HALT,
594 false, 0),
595 F_BRANCH2(GCC_USB3_MOCK_UTMI_CLK, "gcc_usb3_mock_utmi_clk",
596 "usb30_mock_utmi_clk_src",
597 0x1e030, 0, 0, 0, 0x1e030, QCOM_CLK_BRANCH2_BRANCH_HALT,
598 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
599 /* Note - yes, these two have the same registers in linux */
600 F_BRANCH2(GCC_WCSS2G_CLK, "gcc_wcss2g_clk", "wcss2g_clk_src",
601 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT,
602 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
603 F_BRANCH2(GCC_WCSS2G_REF_CLK, "gcc_wcss2g_ref_clk", "xo",
604 0x1f00c, 0, 0, 0, 0x1f00c, QCOM_CLK_BRANCH2_BRANCH_HALT,
605 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
606 F_BRANCH2(GCC_WCSS2G_RTC_CLK, "gcc_wcss2g_rtc_clk", "gcc_sleep_clk_src",
607 0x1f010, 0, 0, 0, 0x1f010, QCOM_CLK_BRANCH2_BRANCH_HALT,
608 false, 0),
609
610 /* Note - yes, these two have the same registers in linux */
611 F_BRANCH2(GCC_WCSS5G_CLK, "gcc_wcss5g_clk", "wcss5g_clk_src",
612 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT,
613 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
614 F_BRANCH2(GCC_WCSS5G_REF_CLK, "gcc_wcss5g_ref_clk", "xo",
615 0x1f00c, 0, 0, 0, 0x2000c, QCOM_CLK_BRANCH2_BRANCH_HALT,
616 false, QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
617 F_BRANCH2(GCC_WCSS5G_RTC_CLK, "gcc_wcss5g_rtc_clk", "gcc_sleep_clk_src",
618 0x1f010, 0, 0, 0, 0x20010, QCOM_CLK_BRANCH2_BRANCH_HALT,
619 false, 0),
620
621 F_BRANCH2(GCC_PCNOC_AHB_CLK, "pcnoc_clk_src", "gcc_pcnoc_ahb_clk_src",
622 0x21030, 0, 0, 0, 0x21030, QCOM_CLK_BRANCH2_BRANCH_HALT, false,
623 QCOM_CLK_BRANCH2_FLAGS_CRITICAL |
624 QCOM_CLK_BRANCH2_FLAGS_SET_RATE_PARENT),
625 };
626
627 static void
qcom_gcc_ipq4018_clock_init_fepll(struct qcom_gcc_ipq4018_softc * sc)628 qcom_gcc_ipq4018_clock_init_fepll(struct qcom_gcc_ipq4018_softc *sc)
629 {
630 int i, rv;
631
632 for (i = 0; i < nitems(fepll_tbl); i++) {
633 rv = qcom_clk_fepll_register(sc->clkdom, fepll_tbl + i);
634 if (rv != 0)
635 panic("qcom_clk_fepll_register failed");
636 }
637 }
638
639 static void
qcom_gcc_ipq4018_clock_init_fdiv(struct qcom_gcc_ipq4018_softc * sc)640 qcom_gcc_ipq4018_clock_init_fdiv(struct qcom_gcc_ipq4018_softc *sc)
641 {
642 int i, rv;
643
644 for (i = 0; i < nitems(fdiv_tbl); i++) {
645 rv = qcom_clk_fdiv_register(sc->clkdom, fdiv_tbl + i);
646 if (rv != 0)
647 panic("qcom_clk_fdiv_register failed");
648 }
649 }
650
651 static void
qcom_gcc_ipq4018_clock_init_apssdiv(struct qcom_gcc_ipq4018_softc * sc)652 qcom_gcc_ipq4018_clock_init_apssdiv(struct qcom_gcc_ipq4018_softc *sc)
653 {
654 int i, rv;
655
656 for (i = 0; i < nitems(apssdiv_tbl); i++) {
657 rv = qcom_clk_apssdiv_register(sc->clkdom, apssdiv_tbl + i);
658 if (rv != 0)
659 panic("qcom_clk_apssdiv_register failed");
660 }
661 }
662
663 static void
qcom_gcc_ipq4018_clock_init_rcg2(struct qcom_gcc_ipq4018_softc * sc)664 qcom_gcc_ipq4018_clock_init_rcg2(struct qcom_gcc_ipq4018_softc *sc)
665 {
666 int i, rv;
667
668 for (i = 0; i < nitems(rcg2_tbl); i++) {
669 rv = qcom_clk_rcg2_register(sc->clkdom, rcg2_tbl + i);
670 if (rv != 0)
671 panic("qcom_clk_rcg2_register failed");
672 }
673 }
674
675 static void
qcom_gcc_ipq4018_clock_init_branch2(struct qcom_gcc_ipq4018_softc * sc)676 qcom_gcc_ipq4018_clock_init_branch2(struct qcom_gcc_ipq4018_softc *sc)
677 {
678 int i, rv;
679
680 for (i = 0; i < nitems(branch2_tbl); i++) {
681 rv = qcom_clk_branch2_register(sc->clkdom, branch2_tbl + i);
682 if (rv != 0)
683 panic("qcom_clk_branch2_register failed");
684 }
685 }
686
687 static void
qcom_gcc_ipq4018_clock_init_ro_div(struct qcom_gcc_ipq4018_softc * sc)688 qcom_gcc_ipq4018_clock_init_ro_div(struct qcom_gcc_ipq4018_softc *sc)
689 {
690 int i, rv;
691
692 for (i = 0; i < nitems(ro_div_tbl); i++) {
693 rv = qcom_clk_ro_div_register(sc->clkdom, ro_div_tbl + i);
694 if (rv != 0)
695 panic("qcom_clk_ro_div_register failed");
696 }
697 }
698
699 int
qcom_gcc_ipq4018_clock_read(device_t dev,bus_addr_t addr,uint32_t * val)700 qcom_gcc_ipq4018_clock_read(device_t dev, bus_addr_t addr, uint32_t *val)
701 {
702 struct qcom_gcc_ipq4018_softc *sc;
703
704 sc = device_get_softc(dev);
705 *val = bus_read_4(sc->reg, addr);
706 return (0);
707 }
708
709 int
qcom_gcc_ipq4018_clock_write(device_t dev,bus_addr_t addr,uint32_t val)710 qcom_gcc_ipq4018_clock_write(device_t dev, bus_addr_t addr, uint32_t val)
711 {
712 struct qcom_gcc_ipq4018_softc *sc;
713
714 sc = device_get_softc(dev);
715 bus_write_4(sc->reg, addr, val);
716 return (0);
717 }
718
719 int
qcom_gcc_ipq4018_clock_modify(device_t dev,bus_addr_t addr,uint32_t clear_mask,uint32_t set_mask)720 qcom_gcc_ipq4018_clock_modify(device_t dev, bus_addr_t addr,
721 uint32_t clear_mask, uint32_t set_mask)
722 {
723 struct qcom_gcc_ipq4018_softc *sc;
724 uint32_t reg;
725
726 sc = device_get_softc(dev);
727 reg = bus_read_4(sc->reg, addr);
728 reg &= clear_mask;
729 reg |= set_mask;
730 bus_write_4(sc->reg, addr, reg);
731 return (0);
732 }
733
734 void
qcom_gcc_ipq4018_clock_setup(struct qcom_gcc_ipq4018_softc * sc)735 qcom_gcc_ipq4018_clock_setup(struct qcom_gcc_ipq4018_softc *sc)
736 {
737
738 sc->clkdom = clkdom_create(sc->dev);
739
740 /* Setup stuff */
741 qcom_gcc_ipq4018_clock_init_fepll(sc);
742 qcom_gcc_ipq4018_clock_init_fdiv(sc);
743 qcom_gcc_ipq4018_clock_init_apssdiv(sc);
744 qcom_gcc_ipq4018_clock_init_rcg2(sc);
745 qcom_gcc_ipq4018_clock_init_branch2(sc);
746 qcom_gcc_ipq4018_clock_init_ro_div(sc);
747
748 /* Finalise clock tree */
749 clkdom_finit(sc->clkdom);
750 }
751
752 void
qcom_gcc_ipq4018_clock_lock(device_t dev)753 qcom_gcc_ipq4018_clock_lock(device_t dev)
754 {
755 struct qcom_gcc_ipq4018_softc *sc;
756
757 sc = device_get_softc(dev);
758 mtx_lock(&sc->mtx);
759 }
760
761 void
qcom_gcc_ipq4018_clock_unlock(device_t dev)762 qcom_gcc_ipq4018_clock_unlock(device_t dev)
763 {
764 struct qcom_gcc_ipq4018_softc *sc;
765
766 sc = device_get_softc(dev);
767 mtx_unlock(&sc->mtx);
768 }
769