xref: /openbmc/linux/drivers/clk/qcom/gcc-ipq4019.c (revision 85250a24)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015 The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/err.h>
8 #include <linux/platform_device.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/of_device.h>
12 #include <linux/clk-provider.h>
13 #include <linux/regmap.h>
14 #include <linux/reset-controller.h>
15 #include <linux/math64.h>
16 #include <linux/delay.h>
17 #include <linux/clk.h>
18 
19 #include <dt-bindings/clock/qcom,gcc-ipq4019.h>
20 
21 #include "common.h"
22 #include "clk-regmap.h"
23 #include "clk-rcg.h"
24 #include "clk-branch.h"
25 #include "reset.h"
26 #include "clk-regmap-divider.h"
27 
28 #define to_clk_regmap_div(_hw) container_of(to_clk_regmap(_hw),\
29 					struct clk_regmap_div, clkr)
30 
31 #define to_clk_fepll(_hw) container_of(to_clk_regmap_div(_hw),\
32 						struct clk_fepll, cdiv)
33 
34 enum {
35 	P_XO,
36 	P_FEPLL200,
37 	P_FEPLL500,
38 	P_DDRPLL,
39 	P_FEPLLWCSS2G,
40 	P_FEPLLWCSS5G,
41 	P_FEPLL125DLY,
42 	P_DDRPLLAPSS,
43 };
44 
45 /*
46  * struct clk_fepll_vco - vco feedback divider corresponds for FEPLL clocks
47  * @fdbkdiv_shift: lowest bit for FDBKDIV
48  * @fdbkdiv_width: number of bits in FDBKDIV
49  * @refclkdiv_shift: lowest bit for REFCLKDIV
50  * @refclkdiv_width: number of bits in REFCLKDIV
51  * @reg: PLL_DIV register address
52  */
53 struct clk_fepll_vco {
54 	u32 fdbkdiv_shift;
55 	u32 fdbkdiv_width;
56 	u32 refclkdiv_shift;
57 	u32 refclkdiv_width;
58 	u32 reg;
59 };
60 
61 /*
62  * struct clk_fepll - clk divider corresponds to FEPLL clocks
63  * @fixed_div: fixed divider value if divider is fixed
64  * @parent_map: map from software's parent index to hardware's src_sel field
65  * @cdiv: divider values for PLL_DIV
66  * @pll_vco: vco feedback divider
67  * @div_table: mapping for actual divider value to register divider value
68  *             in case of non fixed divider
69  * @freq_tbl: frequency table
70  */
71 struct clk_fepll {
72 	u32 fixed_div;
73 	const u8 *parent_map;
74 	struct clk_regmap_div cdiv;
75 	const struct clk_fepll_vco *pll_vco;
76 	const struct clk_div_table *div_table;
77 	const struct freq_tbl *freq_tbl;
78 };
79 
80 static struct parent_map gcc_xo_200_500_map[] = {
81 	{ P_XO, 0 },
82 	{ P_FEPLL200, 1 },
83 	{ P_FEPLL500, 2 },
84 };
85 
86 static const char * const gcc_xo_200_500[] = {
87 	"xo",
88 	"fepll200",
89 	"fepll500",
90 };
91 
92 static struct parent_map gcc_xo_200_map[] = {
93 	{  P_XO, 0 },
94 	{  P_FEPLL200, 1 },
95 };
96 
97 static const char * const gcc_xo_200[] = {
98 	"xo",
99 	"fepll200",
100 };
101 
102 static struct parent_map gcc_xo_200_spi_map[] = {
103 	{  P_XO, 0 },
104 	{  P_FEPLL200, 2 },
105 };
106 
107 static const char * const gcc_xo_200_spi[] = {
108 	"xo",
109 	"fepll200",
110 };
111 
112 static struct parent_map gcc_xo_sdcc1_500_map[] = {
113 	{  P_XO, 0 },
114 	{  P_DDRPLL, 1 },
115 	{  P_FEPLL500, 2 },
116 };
117 
118 static const char * const gcc_xo_sdcc1_500[] = {
119 	"xo",
120 	"ddrpllsdcc",
121 	"fepll500",
122 };
123 
124 static struct parent_map gcc_xo_wcss2g_map[] = {
125 	{  P_XO, 0 },
126 	{  P_FEPLLWCSS2G, 1 },
127 };
128 
129 static const char * const gcc_xo_wcss2g[] = {
130 	"xo",
131 	"fepllwcss2g",
132 };
133 
134 static struct parent_map gcc_xo_wcss5g_map[] = {
135 	{  P_XO, 0 },
136 	{  P_FEPLLWCSS5G, 1 },
137 };
138 
139 static const char * const gcc_xo_wcss5g[] = {
140 	"xo",
141 	"fepllwcss5g",
142 };
143 
144 static struct parent_map gcc_xo_125_dly_map[] = {
145 	{  P_XO, 0 },
146 	{  P_FEPLL125DLY, 1 },
147 };
148 
149 static const char * const gcc_xo_125_dly[] = {
150 	"xo",
151 	"fepll125dly",
152 };
153 
154 static struct parent_map gcc_xo_ddr_500_200_map[] = {
155 	{  P_XO, 0 },
156 	{  P_FEPLL200, 3 },
157 	{  P_FEPLL500, 2 },
158 	{  P_DDRPLLAPSS, 1 },
159 };
160 
161 /*
162  * Contains index for safe clock during APSS freq change.
163  * fepll500 is being used as safe clock so initialize it
164  * with its index in parents list gcc_xo_ddr_500_200.
165  */
166 static const int gcc_ipq4019_cpu_safe_parent = 2;
167 static const char * const gcc_xo_ddr_500_200[] = {
168 	"xo",
169 	"fepll200",
170 	"fepll500",
171 	"ddrpllapss",
172 };
173 
174 static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] = {
175 	F(48000000, P_XO, 1, 0, 0),
176 	F(200000000, P_FEPLL200, 1, 0, 0),
177 	{ }
178 };
179 
180 static struct clk_rcg2 audio_clk_src = {
181 	.cmd_rcgr = 0x1b000,
182 	.hid_width = 5,
183 	.parent_map = gcc_xo_200_map,
184 	.freq_tbl = ftbl_gcc_audio_pwm_clk,
185 	.clkr.hw.init = &(struct clk_init_data){
186 		.name = "audio_clk_src",
187 		.parent_names = gcc_xo_200,
188 		.num_parents = 2,
189 		.ops = &clk_rcg2_ops,
190 
191 	},
192 };
193 
194 static struct clk_branch gcc_audio_ahb_clk = {
195 	.halt_reg = 0x1b010,
196 	.clkr = {
197 		.enable_reg = 0x1b010,
198 		.enable_mask = BIT(0),
199 		.hw.init = &(struct clk_init_data){
200 			.name = "gcc_audio_ahb_clk",
201 			.parent_names = (const char *[]){
202 				"pcnoc_clk_src",
203 			},
204 			.flags = CLK_SET_RATE_PARENT,
205 			.num_parents = 1,
206 			.ops = &clk_branch2_ops,
207 		},
208 	},
209 };
210 
211 static struct clk_branch gcc_audio_pwm_clk = {
212 	.halt_reg = 0x1b00C,
213 	.clkr = {
214 		.enable_reg = 0x1b00C,
215 		.enable_mask = BIT(0),
216 		.hw.init = &(struct clk_init_data){
217 			.name = "gcc_audio_pwm_clk",
218 			.parent_names = (const char *[]){
219 				"audio_clk_src",
220 			},
221 			.flags = CLK_SET_RATE_PARENT,
222 			.num_parents = 1,
223 			.ops = &clk_branch2_ops,
224 		},
225 	},
226 };
227 
228 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
229 	F(19050000, P_FEPLL200, 10.5, 1, 1),
230 	{ }
231 };
232 
233 static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
234 	.cmd_rcgr = 0x200c,
235 	.hid_width = 5,
236 	.parent_map = gcc_xo_200_map,
237 	.freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk,
238 	.clkr.hw.init = &(struct clk_init_data){
239 		.name = "blsp1_qup1_i2c_apps_clk_src",
240 		.parent_names = gcc_xo_200,
241 		.num_parents = 2,
242 		.ops = &clk_rcg2_ops,
243 	},
244 };
245 
246 static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
247 	.halt_reg = 0x2008,
248 	.clkr = {
249 		.enable_reg = 0x2008,
250 		.enable_mask = BIT(0),
251 		.hw.init = &(struct clk_init_data){
252 			.name = "gcc_blsp1_qup1_i2c_apps_clk",
253 			.parent_names = (const char *[]){
254 				"blsp1_qup1_i2c_apps_clk_src",
255 			},
256 			.num_parents = 1,
257 			.ops = &clk_branch2_ops,
258 			.flags = CLK_SET_RATE_PARENT,
259 		},
260 	},
261 };
262 
263 static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
264 	.cmd_rcgr = 0x3000,
265 	.hid_width = 5,
266 	.parent_map = gcc_xo_200_map,
267 	.freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk,
268 	.clkr.hw.init = &(struct clk_init_data){
269 		.name = "blsp1_qup2_i2c_apps_clk_src",
270 		.parent_names = gcc_xo_200,
271 		.num_parents = 2,
272 		.ops = &clk_rcg2_ops,
273 	},
274 };
275 
276 static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
277 	.halt_reg = 0x3010,
278 	.clkr = {
279 		.enable_reg = 0x3010,
280 		.enable_mask = BIT(0),
281 		.hw.init = &(struct clk_init_data){
282 			.name = "gcc_blsp1_qup2_i2c_apps_clk",
283 			.parent_names = (const char *[]){
284 				"blsp1_qup2_i2c_apps_clk_src",
285 			},
286 			.num_parents = 1,
287 			.ops = &clk_branch2_ops,
288 			.flags = CLK_SET_RATE_PARENT,
289 		},
290 	},
291 };
292 
293 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_spi_apps_clk[] = {
294 	F(960000, P_XO, 12, 1, 4),
295 	F(4800000, P_XO, 1, 1, 10),
296 	F(9600000, P_XO, 1, 1, 5),
297 	F(15000000, P_XO, 1, 1, 3),
298 	F(19200000, P_XO, 1, 2, 5),
299 	F(24000000, P_XO, 1, 1, 2),
300 	F(48000000, P_XO, 1, 0, 0),
301 	{ }
302 };
303 
304 static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
305 	.cmd_rcgr = 0x2024,
306 	.mnd_width = 8,
307 	.hid_width = 5,
308 	.parent_map = gcc_xo_200_spi_map,
309 	.freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk,
310 	.clkr.hw.init = &(struct clk_init_data){
311 		.name = "blsp1_qup1_spi_apps_clk_src",
312 		.parent_names = gcc_xo_200_spi,
313 		.num_parents = 2,
314 		.ops = &clk_rcg2_ops,
315 	},
316 };
317 
318 static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
319 	.halt_reg = 0x2004,
320 	.clkr = {
321 		.enable_reg = 0x2004,
322 		.enable_mask = BIT(0),
323 		.hw.init = &(struct clk_init_data){
324 			.name = "gcc_blsp1_qup1_spi_apps_clk",
325 			.parent_names = (const char *[]){
326 				"blsp1_qup1_spi_apps_clk_src",
327 			},
328 			.num_parents = 1,
329 			.ops = &clk_branch2_ops,
330 			.flags = CLK_SET_RATE_PARENT,
331 		},
332 	},
333 };
334 
335 static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
336 	.cmd_rcgr = 0x3014,
337 	.mnd_width = 8,
338 	.hid_width = 5,
339 	.freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk,
340 	.parent_map = gcc_xo_200_spi_map,
341 	.clkr.hw.init = &(struct clk_init_data){
342 		.name = "blsp1_qup2_spi_apps_clk_src",
343 		.parent_names = gcc_xo_200_spi,
344 		.num_parents = 2,
345 		.ops = &clk_rcg2_ops,
346 	},
347 };
348 
349 static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
350 	.halt_reg = 0x300c,
351 	.clkr = {
352 		.enable_reg = 0x300c,
353 		.enable_mask = BIT(0),
354 		.hw.init = &(struct clk_init_data){
355 			.name = "gcc_blsp1_qup2_spi_apps_clk",
356 			.parent_names = (const char *[]){
357 				"blsp1_qup2_spi_apps_clk_src",
358 			},
359 			.num_parents = 1,
360 			.ops = &clk_branch2_ops,
361 			.flags = CLK_SET_RATE_PARENT,
362 		},
363 	},
364 };
365 
366 static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] = {
367 	F(1843200, P_FEPLL200, 1, 144, 15625),
368 	F(3686400, P_FEPLL200, 1, 288, 15625),
369 	F(7372800, P_FEPLL200, 1, 576, 15625),
370 	F(14745600, P_FEPLL200, 1, 1152, 15625),
371 	F(16000000, P_FEPLL200, 1, 2, 25),
372 	F(24000000, P_XO, 1, 1, 2),
373 	F(32000000, P_FEPLL200, 1, 4, 25),
374 	F(40000000, P_FEPLL200, 1, 1, 5),
375 	F(46400000, P_FEPLL200, 1, 29, 125),
376 	F(48000000, P_XO, 1, 0, 0),
377 	{ }
378 };
379 
380 static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
381 	.cmd_rcgr = 0x2044,
382 	.mnd_width = 16,
383 	.hid_width = 5,
384 	.freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk,
385 	.parent_map = gcc_xo_200_spi_map,
386 	.clkr.hw.init = &(struct clk_init_data){
387 		.name = "blsp1_uart1_apps_clk_src",
388 		.parent_names = gcc_xo_200_spi,
389 		.num_parents = 2,
390 		.ops = &clk_rcg2_ops,
391 	},
392 };
393 
394 static struct clk_branch gcc_blsp1_uart1_apps_clk = {
395 	.halt_reg = 0x203c,
396 	.clkr = {
397 		.enable_reg = 0x203c,
398 		.enable_mask = BIT(0),
399 		.hw.init = &(struct clk_init_data){
400 			.name = "gcc_blsp1_uart1_apps_clk",
401 			.parent_names = (const char *[]){
402 				"blsp1_uart1_apps_clk_src",
403 			},
404 			.flags = CLK_SET_RATE_PARENT,
405 			.num_parents = 1,
406 			.ops = &clk_branch2_ops,
407 		},
408 	},
409 };
410 
411 static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
412 	.cmd_rcgr = 0x3034,
413 	.mnd_width = 16,
414 	.hid_width = 5,
415 	.freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk,
416 	.parent_map = gcc_xo_200_spi_map,
417 	.clkr.hw.init = &(struct clk_init_data){
418 		.name = "blsp1_uart2_apps_clk_src",
419 		.parent_names = gcc_xo_200_spi,
420 		.num_parents = 2,
421 		.ops = &clk_rcg2_ops,
422 	},
423 };
424 
425 static struct clk_branch gcc_blsp1_uart2_apps_clk = {
426 	.halt_reg = 0x302c,
427 	.clkr = {
428 		.enable_reg = 0x302c,
429 		.enable_mask = BIT(0),
430 		.hw.init = &(struct clk_init_data){
431 			.name = "gcc_blsp1_uart2_apps_clk",
432 			.parent_names = (const char *[]){
433 				"blsp1_uart2_apps_clk_src",
434 			},
435 			.num_parents = 1,
436 			.ops = &clk_branch2_ops,
437 			.flags = CLK_SET_RATE_PARENT,
438 		},
439 	},
440 };
441 
442 static const struct freq_tbl ftbl_gcc_gp_clk[] = {
443 	F(1250000,  P_FEPLL200, 1, 16, 0),
444 	F(2500000,  P_FEPLL200, 1,  8, 0),
445 	F(5000000,  P_FEPLL200, 1,  4, 0),
446 	{ }
447 };
448 
449 static struct clk_rcg2 gp1_clk_src = {
450 	.cmd_rcgr = 0x8004,
451 	.mnd_width = 8,
452 	.hid_width = 5,
453 	.freq_tbl = ftbl_gcc_gp_clk,
454 	.parent_map = gcc_xo_200_map,
455 	.clkr.hw.init = &(struct clk_init_data){
456 		.name = "gp1_clk_src",
457 		.parent_names = gcc_xo_200,
458 		.num_parents = 2,
459 		.ops = &clk_rcg2_ops,
460 	},
461 };
462 
463 static struct clk_branch gcc_gp1_clk = {
464 	.halt_reg = 0x8000,
465 	.clkr = {
466 		.enable_reg = 0x8000,
467 		.enable_mask = BIT(0),
468 		.hw.init = &(struct clk_init_data){
469 			.name = "gcc_gp1_clk",
470 			.parent_names = (const char *[]){
471 				"gp1_clk_src",
472 			},
473 			.num_parents = 1,
474 			.ops = &clk_branch2_ops,
475 			.flags = CLK_SET_RATE_PARENT,
476 		},
477 	},
478 };
479 
480 static struct clk_rcg2 gp2_clk_src = {
481 	.cmd_rcgr = 0x9004,
482 	.mnd_width = 8,
483 	.hid_width = 5,
484 	.freq_tbl = ftbl_gcc_gp_clk,
485 	.parent_map = gcc_xo_200_map,
486 	.clkr.hw.init = &(struct clk_init_data){
487 		.name = "gp2_clk_src",
488 		.parent_names = gcc_xo_200,
489 		.num_parents = 2,
490 		.ops = &clk_rcg2_ops,
491 	},
492 };
493 
494 static struct clk_branch gcc_gp2_clk = {
495 	.halt_reg = 0x9000,
496 	.clkr = {
497 		.enable_reg = 0x9000,
498 		.enable_mask = BIT(0),
499 		.hw.init = &(struct clk_init_data){
500 			.name = "gcc_gp2_clk",
501 			.parent_names = (const char *[]){
502 				"gp2_clk_src",
503 			},
504 			.num_parents = 1,
505 			.ops = &clk_branch2_ops,
506 			.flags = CLK_SET_RATE_PARENT,
507 		},
508 	},
509 };
510 
511 static struct clk_rcg2 gp3_clk_src = {
512 	.cmd_rcgr = 0xa004,
513 	.mnd_width = 8,
514 	.hid_width = 5,
515 	.freq_tbl = ftbl_gcc_gp_clk,
516 	.parent_map = gcc_xo_200_map,
517 	.clkr.hw.init = &(struct clk_init_data){
518 		.name = "gp3_clk_src",
519 		.parent_names = gcc_xo_200,
520 		.num_parents = 2,
521 		.ops = &clk_rcg2_ops,
522 	},
523 };
524 
525 static struct clk_branch gcc_gp3_clk = {
526 	.halt_reg = 0xa000,
527 	.clkr = {
528 		.enable_reg = 0xa000,
529 		.enable_mask = BIT(0),
530 		.hw.init = &(struct clk_init_data){
531 			.name = "gcc_gp3_clk",
532 			.parent_names = (const char *[]){
533 				"gp3_clk_src",
534 			},
535 			.num_parents = 1,
536 			.ops = &clk_branch2_ops,
537 			.flags = CLK_SET_RATE_PARENT,
538 		},
539 	},
540 };
541 
542 static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = {
543 	F(144000,    P_XO,			1,  3, 240),
544 	F(400000,    P_XO,			1,  1, 0),
545 	F(20000000,  P_FEPLL500,		1,  1, 25),
546 	F(25000000,  P_FEPLL500,		1,  1, 20),
547 	F(50000000,  P_FEPLL500,		1,  1, 10),
548 	F(100000000, P_FEPLL500,		1,  1, 5),
549 	F(192000000, P_DDRPLL,			1,  0, 0),
550 	{ }
551 };
552 
553 static struct clk_rcg2  sdcc1_apps_clk_src = {
554 	.cmd_rcgr = 0x18004,
555 	.hid_width = 5,
556 	.freq_tbl = ftbl_gcc_sdcc1_apps_clk,
557 	.parent_map = gcc_xo_sdcc1_500_map,
558 	.clkr.hw.init = &(struct clk_init_data){
559 		.name = "sdcc1_apps_clk_src",
560 		.parent_names = gcc_xo_sdcc1_500,
561 		.num_parents = 3,
562 		.ops = &clk_rcg2_ops,
563 		.flags = CLK_SET_RATE_PARENT,
564 	},
565 };
566 
567 static const struct freq_tbl ftbl_gcc_apps_clk[] = {
568 	F(48000000,  P_XO,         1, 0, 0),
569 	F(200000000, P_FEPLL200,   1, 0, 0),
570 	F(384000000, P_DDRPLLAPSS, 1, 0, 0),
571 	F(413000000, P_DDRPLLAPSS, 1, 0, 0),
572 	F(448000000, P_DDRPLLAPSS, 1, 0, 0),
573 	F(488000000, P_DDRPLLAPSS, 1, 0, 0),
574 	F(500000000, P_FEPLL500,   1, 0, 0),
575 	F(512000000, P_DDRPLLAPSS, 1, 0, 0),
576 	F(537000000, P_DDRPLLAPSS, 1, 0, 0),
577 	F(565000000, P_DDRPLLAPSS, 1, 0, 0),
578 	F(597000000, P_DDRPLLAPSS, 1, 0, 0),
579 	F(632000000, P_DDRPLLAPSS, 1, 0, 0),
580 	F(672000000, P_DDRPLLAPSS, 1, 0, 0),
581 	F(716000000, P_DDRPLLAPSS, 1, 0, 0),
582 	{ }
583 };
584 
585 static struct clk_rcg2 apps_clk_src = {
586 	.cmd_rcgr = 0x1900c,
587 	.hid_width = 5,
588 	.freq_tbl = ftbl_gcc_apps_clk,
589 	.parent_map = gcc_xo_ddr_500_200_map,
590 	.clkr.hw.init = &(struct clk_init_data){
591 		.name = "apps_clk_src",
592 		.parent_names = gcc_xo_ddr_500_200,
593 		.num_parents = 4,
594 		.ops = &clk_rcg2_ops,
595 		.flags = CLK_SET_RATE_PARENT,
596 	},
597 };
598 
599 static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] = {
600 	F(48000000, P_XO,	   1, 0, 0),
601 	F(100000000, P_FEPLL200,   2, 0, 0),
602 	{ }
603 };
604 
605 static struct clk_rcg2 apps_ahb_clk_src = {
606 	.cmd_rcgr = 0x19014,
607 	.hid_width = 5,
608 	.parent_map = gcc_xo_200_500_map,
609 	.freq_tbl = ftbl_gcc_apps_ahb_clk,
610 	.clkr.hw.init = &(struct clk_init_data){
611 		.name = "apps_ahb_clk_src",
612 		.parent_names = gcc_xo_200_500,
613 		.num_parents = 3,
614 		.ops = &clk_rcg2_ops,
615 	},
616 };
617 
618 static struct clk_branch gcc_apss_ahb_clk = {
619 	.halt_reg = 0x19004,
620 	.halt_check = BRANCH_HALT_VOTED,
621 	.clkr = {
622 		.enable_reg = 0x6000,
623 		.enable_mask = BIT(14),
624 		.hw.init = &(struct clk_init_data){
625 			.name = "gcc_apss_ahb_clk",
626 			.parent_names = (const char *[]){
627 				"apps_ahb_clk_src",
628 			},
629 			.num_parents = 1,
630 			.ops = &clk_branch2_ops,
631 			.flags = CLK_SET_RATE_PARENT,
632 		},
633 	},
634 };
635 
636 static struct clk_branch gcc_blsp1_ahb_clk = {
637 	.halt_reg = 0x1008,
638 	.halt_check = BRANCH_HALT_VOTED,
639 	.clkr = {
640 		.enable_reg = 0x6000,
641 		.enable_mask = BIT(10),
642 		.hw.init = &(struct clk_init_data){
643 			.name = "gcc_blsp1_ahb_clk",
644 			.parent_names = (const char *[]){
645 				"pcnoc_clk_src",
646 			},
647 			.num_parents = 1,
648 			.ops = &clk_branch2_ops,
649 		},
650 	},
651 };
652 
653 static struct clk_branch gcc_dcd_xo_clk = {
654 	.halt_reg = 0x2103c,
655 	.clkr = {
656 		.enable_reg = 0x2103c,
657 		.enable_mask = BIT(0),
658 		.hw.init = &(struct clk_init_data){
659 			.name = "gcc_dcd_xo_clk",
660 			.parent_names = (const char *[]){
661 				"xo",
662 			},
663 			.num_parents = 1,
664 			.ops = &clk_branch2_ops,
665 		},
666 	},
667 };
668 
669 static struct clk_branch gcc_boot_rom_ahb_clk = {
670 	.halt_reg = 0x1300c,
671 	.clkr = {
672 		.enable_reg = 0x1300c,
673 		.enable_mask = BIT(0),
674 		.hw.init = &(struct clk_init_data){
675 			.name = "gcc_boot_rom_ahb_clk",
676 			.parent_names = (const char *[]){
677 				"pcnoc_clk_src",
678 			},
679 			.num_parents = 1,
680 			.ops = &clk_branch2_ops,
681 			.flags = CLK_SET_RATE_PARENT,
682 		},
683 	},
684 };
685 
686 static struct clk_branch gcc_crypto_ahb_clk = {
687 	.halt_reg = 0x16024,
688 	.halt_check = BRANCH_HALT_VOTED,
689 	.clkr = {
690 		.enable_reg = 0x6000,
691 		.enable_mask = BIT(0),
692 		.hw.init = &(struct clk_init_data){
693 			.name = "gcc_crypto_ahb_clk",
694 			.parent_names = (const char *[]){
695 				"pcnoc_clk_src",
696 			},
697 			.num_parents = 1,
698 			.ops = &clk_branch2_ops,
699 		},
700 	},
701 };
702 
703 static struct clk_branch gcc_crypto_axi_clk = {
704 	.halt_reg = 0x16020,
705 	.halt_check = BRANCH_HALT_VOTED,
706 	.clkr = {
707 		.enable_reg = 0x6000,
708 		.enable_mask = BIT(1),
709 		.hw.init = &(struct clk_init_data){
710 			.name = "gcc_crypto_axi_clk",
711 			.parent_names = (const char *[]){
712 				"fepll125",
713 			},
714 			.num_parents = 1,
715 			.ops = &clk_branch2_ops,
716 		},
717 	},
718 };
719 
720 static struct clk_branch gcc_crypto_clk = {
721 	.halt_reg = 0x1601c,
722 	.halt_check = BRANCH_HALT_VOTED,
723 	.clkr = {
724 		.enable_reg = 0x6000,
725 		.enable_mask = BIT(2),
726 		.hw.init = &(struct clk_init_data){
727 			.name = "gcc_crypto_clk",
728 			.parent_names = (const char *[]){
729 				"fepll125",
730 			},
731 			.num_parents = 1,
732 			.ops = &clk_branch2_ops,
733 		},
734 	},
735 };
736 
737 static struct clk_branch gcc_ess_clk = {
738 	.halt_reg = 0x12010,
739 	.clkr = {
740 		.enable_reg = 0x12010,
741 		.enable_mask = BIT(0),
742 		.hw.init = &(struct clk_init_data){
743 			.name = "gcc_ess_clk",
744 			.parent_names = (const char *[]){
745 				"fephy_125m_dly_clk_src",
746 			},
747 			.num_parents = 1,
748 			.ops = &clk_branch2_ops,
749 			.flags = CLK_SET_RATE_PARENT,
750 		},
751 	},
752 };
753 
754 static struct clk_branch gcc_imem_axi_clk = {
755 	.halt_reg = 0xe004,
756 	.halt_check = BRANCH_HALT_VOTED,
757 	.clkr = {
758 		.enable_reg = 0x6000,
759 		.enable_mask = BIT(17),
760 		.hw.init = &(struct clk_init_data){
761 			.name = "gcc_imem_axi_clk",
762 			.parent_names = (const char *[]){
763 				"fepll200",
764 			},
765 			.num_parents = 1,
766 			.ops = &clk_branch2_ops,
767 		},
768 	},
769 };
770 
771 static struct clk_branch gcc_imem_cfg_ahb_clk = {
772 	.halt_reg = 0xe008,
773 	.clkr = {
774 		.enable_reg = 0xe008,
775 		.enable_mask = BIT(0),
776 		.hw.init = &(struct clk_init_data){
777 			.name = "gcc_imem_cfg_ahb_clk",
778 			.parent_names = (const char *[]){
779 				"pcnoc_clk_src",
780 			},
781 			.num_parents = 1,
782 			.ops = &clk_branch2_ops,
783 		},
784 	},
785 };
786 
787 static struct clk_branch gcc_pcie_ahb_clk = {
788 	.halt_reg = 0x1d00c,
789 	.clkr = {
790 		.enable_reg = 0x1d00c,
791 		.enable_mask = BIT(0),
792 		.hw.init = &(struct clk_init_data){
793 			.name = "gcc_pcie_ahb_clk",
794 			.parent_names = (const char *[]){
795 				"pcnoc_clk_src",
796 			},
797 			.num_parents = 1,
798 			.ops = &clk_branch2_ops,
799 		},
800 	},
801 };
802 
803 static struct clk_branch gcc_pcie_axi_m_clk = {
804 	.halt_reg = 0x1d004,
805 	.clkr = {
806 		.enable_reg = 0x1d004,
807 		.enable_mask = BIT(0),
808 		.hw.init = &(struct clk_init_data){
809 			.name = "gcc_pcie_axi_m_clk",
810 			.parent_names = (const char *[]){
811 				"fepll200",
812 			},
813 			.num_parents = 1,
814 			.ops = &clk_branch2_ops,
815 		},
816 	},
817 };
818 
819 static struct clk_branch gcc_pcie_axi_s_clk = {
820 	.halt_reg = 0x1d008,
821 	.clkr = {
822 		.enable_reg = 0x1d008,
823 		.enable_mask = BIT(0),
824 		.hw.init = &(struct clk_init_data){
825 			.name = "gcc_pcie_axi_s_clk",
826 			.parent_names = (const char *[]){
827 				"fepll200",
828 			},
829 			.num_parents = 1,
830 			.ops = &clk_branch2_ops,
831 		},
832 	},
833 };
834 
835 static struct clk_branch gcc_prng_ahb_clk = {
836 	.halt_reg = 0x13004,
837 	.halt_check = BRANCH_HALT_VOTED,
838 	.clkr = {
839 		.enable_reg = 0x6000,
840 		.enable_mask = BIT(8),
841 		.hw.init = &(struct clk_init_data){
842 			.name = "gcc_prng_ahb_clk",
843 			.parent_names = (const char *[]){
844 				"pcnoc_clk_src",
845 			},
846 			.num_parents = 1,
847 			.ops = &clk_branch2_ops,
848 		},
849 	},
850 };
851 
852 static struct clk_branch gcc_qpic_ahb_clk = {
853 	.halt_reg = 0x1c008,
854 	.clkr = {
855 		.enable_reg = 0x1c008,
856 		.enable_mask = BIT(0),
857 		.hw.init = &(struct clk_init_data){
858 			.name = "gcc_qpic_ahb_clk",
859 			.parent_names = (const char *[]){
860 				"pcnoc_clk_src",
861 			},
862 			.num_parents = 1,
863 			.ops = &clk_branch2_ops,
864 		},
865 	},
866 };
867 
868 static struct clk_branch gcc_qpic_clk = {
869 	.halt_reg = 0x1c004,
870 	.clkr = {
871 		.enable_reg = 0x1c004,
872 		.enable_mask = BIT(0),
873 		.hw.init = &(struct clk_init_data){
874 			.name = "gcc_qpic_clk",
875 			.parent_names = (const char *[]){
876 				"pcnoc_clk_src",
877 			},
878 			.num_parents = 1,
879 			.ops = &clk_branch2_ops,
880 		},
881 	},
882 };
883 
884 static struct clk_branch gcc_sdcc1_ahb_clk = {
885 	.halt_reg = 0x18010,
886 	.clkr = {
887 		.enable_reg = 0x18010,
888 		.enable_mask = BIT(0),
889 		.hw.init = &(struct clk_init_data){
890 			.name = "gcc_sdcc1_ahb_clk",
891 			.parent_names = (const char *[]){
892 				"pcnoc_clk_src",
893 			},
894 			.num_parents = 1,
895 			.ops = &clk_branch2_ops,
896 		},
897 	},
898 };
899 
900 static struct clk_branch gcc_sdcc1_apps_clk = {
901 	.halt_reg = 0x1800c,
902 	.clkr = {
903 		.enable_reg = 0x1800c,
904 		.enable_mask = BIT(0),
905 		.hw.init = &(struct clk_init_data){
906 			.name = "gcc_sdcc1_apps_clk",
907 			.parent_names = (const char *[]){
908 				"sdcc1_apps_clk_src",
909 			},
910 			.num_parents = 1,
911 			.ops = &clk_branch2_ops,
912 			.flags = CLK_SET_RATE_PARENT,
913 		},
914 	},
915 };
916 
917 static struct clk_branch gcc_tlmm_ahb_clk = {
918 	.halt_reg = 0x5004,
919 	.halt_check = BRANCH_HALT_VOTED,
920 	.clkr = {
921 		.enable_reg = 0x6000,
922 		.enable_mask = BIT(5),
923 		.hw.init = &(struct clk_init_data){
924 			.name = "gcc_tlmm_ahb_clk",
925 			.parent_names = (const char *[]){
926 				"pcnoc_clk_src",
927 			},
928 			.num_parents = 1,
929 			.ops = &clk_branch2_ops,
930 		},
931 	},
932 };
933 
934 static struct clk_branch gcc_usb2_master_clk = {
935 	.halt_reg = 0x1e00c,
936 	.clkr = {
937 		.enable_reg = 0x1e00c,
938 		.enable_mask = BIT(0),
939 		.hw.init = &(struct clk_init_data){
940 			.name = "gcc_usb2_master_clk",
941 			.parent_names = (const char *[]){
942 				"pcnoc_clk_src",
943 			},
944 			.num_parents = 1,
945 			.ops = &clk_branch2_ops,
946 		},
947 	},
948 };
949 
950 static struct clk_branch gcc_usb2_sleep_clk = {
951 	.halt_reg = 0x1e010,
952 	.clkr = {
953 		.enable_reg = 0x1e010,
954 		.enable_mask = BIT(0),
955 		.hw.init = &(struct clk_init_data){
956 			.name = "gcc_usb2_sleep_clk",
957 			.parent_names = (const char *[]){
958 				"gcc_sleep_clk_src",
959 			},
960 			.num_parents = 1,
961 			.ops = &clk_branch2_ops,
962 		},
963 	},
964 };
965 
966 static struct clk_branch gcc_usb2_mock_utmi_clk = {
967 	.halt_reg = 0x1e014,
968 	.clkr = {
969 		.enable_reg = 0x1e014,
970 		.enable_mask = BIT(0),
971 		.hw.init = &(struct clk_init_data){
972 			.name = "gcc_usb2_mock_utmi_clk",
973 			.parent_names = (const char *[]){
974 				"usb30_mock_utmi_clk_src",
975 			},
976 			.num_parents = 1,
977 			.ops = &clk_branch2_ops,
978 			.flags = CLK_SET_RATE_PARENT,
979 		},
980 	},
981 };
982 
983 static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
984 	F(2000000, P_FEPLL200, 10, 0, 0),
985 	{ }
986 };
987 
988 static struct clk_rcg2 usb30_mock_utmi_clk_src = {
989 	.cmd_rcgr = 0x1e000,
990 	.hid_width = 5,
991 	.parent_map = gcc_xo_200_map,
992 	.freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
993 	.clkr.hw.init = &(struct clk_init_data){
994 		.name = "usb30_mock_utmi_clk_src",
995 		.parent_names = gcc_xo_200,
996 		.num_parents = 2,
997 		.ops = &clk_rcg2_ops,
998 	},
999 };
1000 
1001 static struct clk_branch gcc_usb3_master_clk = {
1002 	.halt_reg = 0x1e028,
1003 	.clkr = {
1004 		.enable_reg = 0x1e028,
1005 		.enable_mask = BIT(0),
1006 		.hw.init = &(struct clk_init_data){
1007 			.name = "gcc_usb3_master_clk",
1008 			.parent_names = (const char *[]){
1009 				"fepll125",
1010 			},
1011 			.num_parents = 1,
1012 			.ops = &clk_branch2_ops,
1013 		},
1014 	},
1015 };
1016 
1017 static struct clk_branch gcc_usb3_sleep_clk = {
1018 	.halt_reg = 0x1e02C,
1019 	.clkr = {
1020 		.enable_reg = 0x1e02C,
1021 		.enable_mask = BIT(0),
1022 		.hw.init = &(struct clk_init_data){
1023 			.name = "gcc_usb3_sleep_clk",
1024 			.parent_names = (const char *[]){
1025 				"gcc_sleep_clk_src",
1026 			},
1027 			.num_parents = 1,
1028 			.ops = &clk_branch2_ops,
1029 		},
1030 	},
1031 };
1032 
1033 static struct clk_branch gcc_usb3_mock_utmi_clk = {
1034 	.halt_reg = 0x1e030,
1035 	.clkr = {
1036 		.enable_reg = 0x1e030,
1037 		.enable_mask = BIT(0),
1038 		.hw.init = &(struct clk_init_data){
1039 			.name = "gcc_usb3_mock_utmi_clk",
1040 			.parent_names = (const char *[]){
1041 				"usb30_mock_utmi_clk_src",
1042 			},
1043 			.num_parents = 1,
1044 			.ops = &clk_branch2_ops,
1045 			.flags = CLK_SET_RATE_PARENT,
1046 		},
1047 	},
1048 };
1049 
1050 static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = {
1051 	F(125000000, P_FEPLL125DLY, 1, 0, 0),
1052 	{ }
1053 };
1054 
1055 static struct clk_rcg2 fephy_125m_dly_clk_src = {
1056 	.cmd_rcgr = 0x12000,
1057 	.hid_width = 5,
1058 	.parent_map = gcc_xo_125_dly_map,
1059 	.freq_tbl = ftbl_gcc_fephy_dly_clk,
1060 	.clkr.hw.init = &(struct clk_init_data){
1061 		.name = "fephy_125m_dly_clk_src",
1062 		.parent_names = gcc_xo_125_dly,
1063 		.num_parents = 2,
1064 		.ops = &clk_rcg2_ops,
1065 	},
1066 };
1067 
1068 
1069 static const struct freq_tbl ftbl_gcc_wcss2g_clk[] = {
1070 	F(48000000, P_XO, 1, 0, 0),
1071 	F(250000000, P_FEPLLWCSS2G, 1, 0, 0),
1072 	{ }
1073 };
1074 
1075 static struct clk_rcg2 wcss2g_clk_src = {
1076 	.cmd_rcgr = 0x1f000,
1077 	.hid_width = 5,
1078 	.freq_tbl = ftbl_gcc_wcss2g_clk,
1079 	.parent_map = gcc_xo_wcss2g_map,
1080 	.clkr.hw.init = &(struct clk_init_data){
1081 		.name = "wcss2g_clk_src",
1082 		.parent_names = gcc_xo_wcss2g,
1083 		.num_parents = 2,
1084 		.ops = &clk_rcg2_ops,
1085 		.flags = CLK_SET_RATE_PARENT,
1086 	},
1087 };
1088 
1089 static struct clk_branch gcc_wcss2g_clk = {
1090 	.halt_reg = 0x1f00C,
1091 	.clkr = {
1092 		.enable_reg = 0x1f00C,
1093 		.enable_mask = BIT(0),
1094 		.hw.init = &(struct clk_init_data){
1095 			.name = "gcc_wcss2g_clk",
1096 			.parent_names = (const char *[]){
1097 				"wcss2g_clk_src",
1098 			},
1099 			.num_parents = 1,
1100 			.ops = &clk_branch2_ops,
1101 			.flags = CLK_SET_RATE_PARENT,
1102 		},
1103 	},
1104 };
1105 
1106 static struct clk_branch gcc_wcss2g_ref_clk = {
1107 	.halt_reg = 0x1f00C,
1108 	.clkr = {
1109 		.enable_reg = 0x1f00C,
1110 		.enable_mask = BIT(0),
1111 		.hw.init = &(struct clk_init_data){
1112 			.name = "gcc_wcss2g_ref_clk",
1113 			.parent_names = (const char *[]){
1114 				"xo",
1115 			},
1116 			.num_parents = 1,
1117 			.ops = &clk_branch2_ops,
1118 			.flags = CLK_SET_RATE_PARENT,
1119 		},
1120 	},
1121 };
1122 
1123 static struct clk_branch gcc_wcss2g_rtc_clk = {
1124 	.halt_reg = 0x1f010,
1125 	.clkr = {
1126 		.enable_reg = 0x1f010,
1127 		.enable_mask = BIT(0),
1128 		.hw.init = &(struct clk_init_data){
1129 			.name = "gcc_wcss2g_rtc_clk",
1130 			.parent_names = (const char *[]){
1131 				"gcc_sleep_clk_src",
1132 			},
1133 			.num_parents = 1,
1134 			.ops = &clk_branch2_ops,
1135 		},
1136 	},
1137 };
1138 
1139 static const struct freq_tbl ftbl_gcc_wcss5g_clk[] = {
1140 	F(48000000, P_XO, 1, 0, 0),
1141 	F(250000000, P_FEPLLWCSS5G, 1, 0, 0),
1142 	{ }
1143 };
1144 
1145 static struct clk_rcg2 wcss5g_clk_src = {
1146 	.cmd_rcgr = 0x20000,
1147 	.hid_width = 5,
1148 	.parent_map = gcc_xo_wcss5g_map,
1149 	.freq_tbl = ftbl_gcc_wcss5g_clk,
1150 	.clkr.hw.init = &(struct clk_init_data){
1151 		.name = "wcss5g_clk_src",
1152 		.parent_names = gcc_xo_wcss5g,
1153 		.num_parents = 2,
1154 		.ops = &clk_rcg2_ops,
1155 	},
1156 };
1157 
1158 static struct clk_branch gcc_wcss5g_clk = {
1159 	.halt_reg = 0x2000c,
1160 	.clkr = {
1161 		.enable_reg = 0x2000c,
1162 		.enable_mask = BIT(0),
1163 		.hw.init = &(struct clk_init_data){
1164 			.name = "gcc_wcss5g_clk",
1165 			.parent_names = (const char *[]){
1166 				"wcss5g_clk_src",
1167 			},
1168 			.num_parents = 1,
1169 			.ops = &clk_branch2_ops,
1170 			.flags = CLK_SET_RATE_PARENT,
1171 		},
1172 	},
1173 };
1174 
1175 static struct clk_branch gcc_wcss5g_ref_clk = {
1176 	.halt_reg = 0x2000c,
1177 	.clkr = {
1178 		.enable_reg = 0x2000c,
1179 		.enable_mask = BIT(0),
1180 		.hw.init = &(struct clk_init_data){
1181 			.name = "gcc_wcss5g_ref_clk",
1182 			.parent_names = (const char *[]){
1183 				"xo",
1184 			},
1185 			.num_parents = 1,
1186 			.ops = &clk_branch2_ops,
1187 			.flags = CLK_SET_RATE_PARENT,
1188 		},
1189 	},
1190 };
1191 
1192 static struct clk_branch gcc_wcss5g_rtc_clk = {
1193 	.halt_reg = 0x20010,
1194 	.clkr = {
1195 		.enable_reg = 0x20010,
1196 		.enable_mask = BIT(0),
1197 		.hw.init = &(struct clk_init_data){
1198 			.name = "gcc_wcss5g_rtc_clk",
1199 			.parent_names = (const char *[]){
1200 				"gcc_sleep_clk_src",
1201 			},
1202 			.num_parents = 1,
1203 			.ops = &clk_branch2_ops,
1204 			.flags = CLK_SET_RATE_PARENT,
1205 		},
1206 	},
1207 };
1208 
1209 /* Calculates the VCO rate for FEPLL. */
1210 static u64 clk_fepll_vco_calc_rate(struct clk_fepll *pll_div,
1211 				   unsigned long parent_rate)
1212 {
1213 	const struct clk_fepll_vco *pll_vco = pll_div->pll_vco;
1214 	u32 fdbkdiv, refclkdiv, cdiv;
1215 	u64 vco;
1216 
1217 	regmap_read(pll_div->cdiv.clkr.regmap, pll_vco->reg, &cdiv);
1218 	refclkdiv = (cdiv >> pll_vco->refclkdiv_shift) &
1219 		    (BIT(pll_vco->refclkdiv_width) - 1);
1220 	fdbkdiv = (cdiv >> pll_vco->fdbkdiv_shift) &
1221 		  (BIT(pll_vco->fdbkdiv_width) - 1);
1222 
1223 	vco = parent_rate / refclkdiv;
1224 	vco *= 2;
1225 	vco *= fdbkdiv;
1226 
1227 	return vco;
1228 }
1229 
1230 static const struct clk_fepll_vco gcc_apss_ddrpll_vco = {
1231 	.fdbkdiv_shift = 16,
1232 	.fdbkdiv_width = 8,
1233 	.refclkdiv_shift = 24,
1234 	.refclkdiv_width = 5,
1235 	.reg = 0x2e020,
1236 };
1237 
1238 static const struct clk_fepll_vco gcc_fepll_vco = {
1239 	.fdbkdiv_shift = 16,
1240 	.fdbkdiv_width = 8,
1241 	.refclkdiv_shift = 24,
1242 	.refclkdiv_width = 5,
1243 	.reg = 0x2f020,
1244 };
1245 
1246 /*
1247  * Round rate function for APSS CPU PLL Clock divider.
1248  * It looks up the frequency table and returns the next higher frequency
1249  * supported in hardware.
1250  */
1251 static long clk_cpu_div_round_rate(struct clk_hw *hw, unsigned long rate,
1252 				   unsigned long *p_rate)
1253 {
1254 	struct clk_fepll *pll = to_clk_fepll(hw);
1255 	struct clk_hw *p_hw;
1256 	const struct freq_tbl *f;
1257 
1258 	f = qcom_find_freq(pll->freq_tbl, rate);
1259 	if (!f)
1260 		return -EINVAL;
1261 
1262 	p_hw = clk_hw_get_parent_by_index(hw, f->src);
1263 	*p_rate = clk_hw_get_rate(p_hw);
1264 
1265 	return f->freq;
1266 };
1267 
1268 /*
1269  * Clock set rate function for APSS CPU PLL Clock divider.
1270  * It looks up the frequency table and updates the PLL divider to corresponding
1271  * divider value.
1272  */
1273 static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate,
1274 				unsigned long parent_rate)
1275 {
1276 	struct clk_fepll *pll = to_clk_fepll(hw);
1277 	const struct freq_tbl *f;
1278 	u32 mask;
1279 
1280 	f = qcom_find_freq(pll->freq_tbl, rate);
1281 	if (!f)
1282 		return -EINVAL;
1283 
1284 	mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift;
1285 	regmap_update_bits(pll->cdiv.clkr.regmap,
1286 			   pll->cdiv.reg, mask,
1287 			   f->pre_div << pll->cdiv.shift);
1288 	/*
1289 	 * There is no status bit which can be checked for successful CPU
1290 	 * divider update operation so using delay for the same.
1291 	 */
1292 	udelay(1);
1293 
1294 	return 0;
1295 };
1296 
1297 /*
1298  * Clock frequency calculation function for APSS CPU PLL Clock divider.
1299  * This clock divider is nonlinear so this function calculates the actual
1300  * divider and returns the output frequency by dividing VCO Frequency
1301  * with this actual divider value.
1302  */
1303 static unsigned long
1304 clk_cpu_div_recalc_rate(struct clk_hw *hw,
1305 			unsigned long parent_rate)
1306 {
1307 	struct clk_fepll *pll = to_clk_fepll(hw);
1308 	u32 cdiv, pre_div;
1309 	u64 rate;
1310 
1311 	regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
1312 	cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);
1313 
1314 	/*
1315 	 * Some dividers have value in 0.5 fraction so multiply both VCO
1316 	 * frequency(parent_rate) and pre_div with 2 to make integer
1317 	 * calculation.
1318 	 */
1319 	if (cdiv > 10)
1320 		pre_div = (cdiv + 1) * 2;
1321 	else
1322 		pre_div = cdiv + 12;
1323 
1324 	rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
1325 	do_div(rate, pre_div);
1326 
1327 	return rate;
1328 };
1329 
1330 static const struct clk_ops clk_regmap_cpu_div_ops = {
1331 	.round_rate = clk_cpu_div_round_rate,
1332 	.set_rate = clk_cpu_div_set_rate,
1333 	.recalc_rate = clk_cpu_div_recalc_rate,
1334 };
1335 
1336 static const struct freq_tbl ftbl_apss_ddr_pll[] = {
1337 	{ 384000000, P_XO, 0xd, 0, 0 },
1338 	{ 413000000, P_XO, 0xc, 0, 0 },
1339 	{ 448000000, P_XO, 0xb, 0, 0 },
1340 	{ 488000000, P_XO, 0xa, 0, 0 },
1341 	{ 512000000, P_XO, 0x9, 0, 0 },
1342 	{ 537000000, P_XO, 0x8, 0, 0 },
1343 	{ 565000000, P_XO, 0x7, 0, 0 },
1344 	{ 597000000, P_XO, 0x6, 0, 0 },
1345 	{ 632000000, P_XO, 0x5, 0, 0 },
1346 	{ 672000000, P_XO, 0x4, 0, 0 },
1347 	{ 716000000, P_XO, 0x3, 0, 0 },
1348 	{ 768000000, P_XO, 0x2, 0, 0 },
1349 	{ 823000000, P_XO, 0x1, 0, 0 },
1350 	{ 896000000, P_XO, 0x0, 0, 0 },
1351 	{ }
1352 };
1353 
1354 static struct clk_fepll gcc_apss_cpu_plldiv_clk = {
1355 	.cdiv.reg = 0x2e020,
1356 	.cdiv.shift = 4,
1357 	.cdiv.width = 4,
1358 	.cdiv.clkr = {
1359 		.enable_reg = 0x2e000,
1360 		.enable_mask = BIT(0),
1361 		.hw.init = &(struct clk_init_data){
1362 			.name = "ddrpllapss",
1363 			.parent_names = (const char *[]){
1364 				"xo",
1365 			},
1366 			.num_parents = 1,
1367 			.ops = &clk_regmap_cpu_div_ops,
1368 		},
1369 	},
1370 	.freq_tbl = ftbl_apss_ddr_pll,
1371 	.pll_vco = &gcc_apss_ddrpll_vco,
1372 };
1373 
1374 /* Calculates the rate for PLL divider.
1375  * If the divider value is not fixed then it gets the actual divider value
1376  * from divider table. Then, it calculate the clock rate by dividing the
1377  * parent rate with actual divider value.
1378  */
1379 static unsigned long
1380 clk_regmap_clk_div_recalc_rate(struct clk_hw *hw,
1381 			       unsigned long parent_rate)
1382 {
1383 	struct clk_fepll *pll = to_clk_fepll(hw);
1384 	u32 cdiv, pre_div = 1;
1385 	u64 rate;
1386 	const struct clk_div_table *clkt;
1387 
1388 	if (pll->fixed_div) {
1389 		pre_div = pll->fixed_div;
1390 	} else {
1391 		regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
1392 		cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);
1393 
1394 		for (clkt = pll->div_table; clkt->div; clkt++) {
1395 			if (clkt->val == cdiv)
1396 				pre_div = clkt->div;
1397 		}
1398 	}
1399 
1400 	rate = clk_fepll_vco_calc_rate(pll, parent_rate);
1401 	do_div(rate, pre_div);
1402 
1403 	return rate;
1404 };
1405 
1406 static const struct clk_ops clk_fepll_div_ops = {
1407 	.recalc_rate = clk_regmap_clk_div_recalc_rate,
1408 };
1409 
1410 static struct clk_fepll gcc_apss_sdcc_clk = {
1411 	.fixed_div = 28,
1412 	.cdiv.clkr = {
1413 		.hw.init = &(struct clk_init_data){
1414 			.name = "ddrpllsdcc",
1415 			.parent_names = (const char *[]){
1416 				"xo",
1417 			},
1418 			.num_parents = 1,
1419 			.ops = &clk_fepll_div_ops,
1420 		},
1421 	},
1422 	.pll_vco = &gcc_apss_ddrpll_vco,
1423 };
1424 
1425 static struct clk_fepll gcc_fepll125_clk = {
1426 	.fixed_div = 32,
1427 	.cdiv.clkr = {
1428 		.hw.init = &(struct clk_init_data){
1429 			.name = "fepll125",
1430 			.parent_names = (const char *[]){
1431 				"xo",
1432 			},
1433 			.num_parents = 1,
1434 			.ops = &clk_fepll_div_ops,
1435 		},
1436 	},
1437 	.pll_vco = &gcc_fepll_vco,
1438 };
1439 
1440 static struct clk_fepll gcc_fepll125dly_clk = {
1441 	.fixed_div = 32,
1442 	.cdiv.clkr = {
1443 		.hw.init = &(struct clk_init_data){
1444 			.name = "fepll125dly",
1445 			.parent_names = (const char *[]){
1446 				"xo",
1447 			},
1448 			.num_parents = 1,
1449 			.ops = &clk_fepll_div_ops,
1450 		},
1451 	},
1452 	.pll_vco = &gcc_fepll_vco,
1453 };
1454 
1455 static struct clk_fepll gcc_fepll200_clk = {
1456 	.fixed_div = 20,
1457 	.cdiv.clkr = {
1458 		.hw.init = &(struct clk_init_data){
1459 			.name = "fepll200",
1460 			.parent_names = (const char *[]){
1461 				"xo",
1462 			},
1463 			.num_parents = 1,
1464 			.ops = &clk_fepll_div_ops,
1465 		},
1466 	},
1467 	.pll_vco = &gcc_fepll_vco,
1468 };
1469 
1470 static struct clk_fepll gcc_fepll500_clk = {
1471 	.fixed_div = 8,
1472 	.cdiv.clkr = {
1473 		.hw.init = &(struct clk_init_data){
1474 			.name = "fepll500",
1475 			.parent_names = (const char *[]){
1476 				"xo",
1477 			},
1478 			.num_parents = 1,
1479 			.ops = &clk_fepll_div_ops,
1480 		},
1481 	},
1482 	.pll_vco = &gcc_fepll_vco,
1483 };
1484 
1485 static const struct clk_div_table fepllwcss_clk_div_table[] = {
1486 	{ 0, 15 },
1487 	{ 1, 16 },
1488 	{ 2, 18 },
1489 	{ 3, 20 },
1490 	{ },
1491 };
1492 
1493 static struct clk_fepll gcc_fepllwcss2g_clk = {
1494 	.cdiv.reg = 0x2f020,
1495 	.cdiv.shift = 8,
1496 	.cdiv.width = 2,
1497 	.cdiv.clkr = {
1498 		.hw.init = &(struct clk_init_data){
1499 			.name = "fepllwcss2g",
1500 			.parent_names = (const char *[]){
1501 				"xo",
1502 			},
1503 			.num_parents = 1,
1504 			.ops = &clk_fepll_div_ops,
1505 		},
1506 	},
1507 	.div_table = fepllwcss_clk_div_table,
1508 	.pll_vco = &gcc_fepll_vco,
1509 };
1510 
1511 static struct clk_fepll gcc_fepllwcss5g_clk = {
1512 	.cdiv.reg = 0x2f020,
1513 	.cdiv.shift = 12,
1514 	.cdiv.width = 2,
1515 	.cdiv.clkr = {
1516 		.hw.init = &(struct clk_init_data){
1517 			.name = "fepllwcss5g",
1518 			.parent_names = (const char *[]){
1519 				"xo",
1520 			},
1521 			.num_parents = 1,
1522 			.ops = &clk_fepll_div_ops,
1523 		},
1524 	},
1525 	.div_table = fepllwcss_clk_div_table,
1526 	.pll_vco = &gcc_fepll_vco,
1527 };
1528 
1529 static const struct freq_tbl ftbl_gcc_pcnoc_ahb_clk[] = {
1530 	F(48000000,  P_XO,	 1, 0, 0),
1531 	F(100000000, P_FEPLL200, 2, 0, 0),
1532 	{ }
1533 };
1534 
1535 static struct clk_rcg2 gcc_pcnoc_ahb_clk_src = {
1536 	.cmd_rcgr = 0x21024,
1537 	.hid_width = 5,
1538 	.parent_map = gcc_xo_200_500_map,
1539 	.freq_tbl = ftbl_gcc_pcnoc_ahb_clk,
1540 	.clkr.hw.init = &(struct clk_init_data){
1541 		.name = "gcc_pcnoc_ahb_clk_src",
1542 		.parent_names = gcc_xo_200_500,
1543 		.num_parents = 3,
1544 		.ops = &clk_rcg2_ops,
1545 	},
1546 };
1547 
1548 static struct clk_branch pcnoc_clk_src = {
1549 	.halt_reg = 0x21030,
1550 	.clkr = {
1551 		.enable_reg = 0x21030,
1552 		.enable_mask = BIT(0),
1553 		.hw.init = &(struct clk_init_data){
1554 			.name = "pcnoc_clk_src",
1555 			.parent_names = (const char *[]){
1556 				"gcc_pcnoc_ahb_clk_src",
1557 			},
1558 			.num_parents = 1,
1559 			.ops = &clk_branch2_ops,
1560 			.flags = CLK_SET_RATE_PARENT |
1561 				CLK_IS_CRITICAL,
1562 		},
1563 	},
1564 };
1565 
1566 static struct clk_regmap *gcc_ipq4019_clocks[] = {
1567 	[AUDIO_CLK_SRC] = &audio_clk_src.clkr,
1568 	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
1569 	[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
1570 	[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
1571 	[BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
1572 	[BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
1573 	[BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
1574 	[GCC_USB3_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
1575 	[GCC_APPS_CLK_SRC] = &apps_clk_src.clkr,
1576 	[GCC_APPS_AHB_CLK_SRC] = &apps_ahb_clk_src.clkr,
1577 	[GP1_CLK_SRC] = &gp1_clk_src.clkr,
1578 	[GP2_CLK_SRC] = &gp2_clk_src.clkr,
1579 	[GP3_CLK_SRC] = &gp3_clk_src.clkr,
1580 	[SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
1581 	[FEPHY_125M_DLY_CLK_SRC] = &fephy_125m_dly_clk_src.clkr,
1582 	[WCSS2G_CLK_SRC] = &wcss2g_clk_src.clkr,
1583 	[WCSS5G_CLK_SRC] = &wcss5g_clk_src.clkr,
1584 	[GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr,
1585 	[GCC_AUDIO_AHB_CLK] = &gcc_audio_ahb_clk.clkr,
1586 	[GCC_AUDIO_PWM_CLK] = &gcc_audio_pwm_clk.clkr,
1587 	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
1588 	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
1589 	[GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
1590 	[GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
1591 	[GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
1592 	[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
1593 	[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
1594 	[GCC_DCD_XO_CLK] = &gcc_dcd_xo_clk.clkr,
1595 	[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
1596 	[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
1597 	[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
1598 	[GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
1599 	[GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
1600 	[GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
1601 	[GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
1602 	[GCC_ESS_CLK] = &gcc_ess_clk.clkr,
1603 	[GCC_IMEM_AXI_CLK] = &gcc_imem_axi_clk.clkr,
1604 	[GCC_IMEM_CFG_AHB_CLK] = &gcc_imem_cfg_ahb_clk.clkr,
1605 	[GCC_PCIE_AHB_CLK] = &gcc_pcie_ahb_clk.clkr,
1606 	[GCC_PCIE_AXI_M_CLK] = &gcc_pcie_axi_m_clk.clkr,
1607 	[GCC_PCIE_AXI_S_CLK] = &gcc_pcie_axi_s_clk.clkr,
1608 	[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
1609 	[GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr,
1610 	[GCC_QPIC_CLK] = &gcc_qpic_clk.clkr,
1611 	[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
1612 	[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
1613 	[GCC_TLMM_AHB_CLK] = &gcc_tlmm_ahb_clk.clkr,
1614 	[GCC_USB2_MASTER_CLK] = &gcc_usb2_master_clk.clkr,
1615 	[GCC_USB2_SLEEP_CLK] = &gcc_usb2_sleep_clk.clkr,
1616 	[GCC_USB2_MOCK_UTMI_CLK] = &gcc_usb2_mock_utmi_clk.clkr,
1617 	[GCC_USB3_MASTER_CLK] = &gcc_usb3_master_clk.clkr,
1618 	[GCC_USB3_SLEEP_CLK] = &gcc_usb3_sleep_clk.clkr,
1619 	[GCC_USB3_MOCK_UTMI_CLK] = &gcc_usb3_mock_utmi_clk.clkr,
1620 	[GCC_WCSS2G_CLK] = &gcc_wcss2g_clk.clkr,
1621 	[GCC_WCSS2G_REF_CLK] = &gcc_wcss2g_ref_clk.clkr,
1622 	[GCC_WCSS2G_RTC_CLK] = &gcc_wcss2g_rtc_clk.clkr,
1623 	[GCC_WCSS5G_CLK] = &gcc_wcss5g_clk.clkr,
1624 	[GCC_WCSS5G_REF_CLK] = &gcc_wcss5g_ref_clk.clkr,
1625 	[GCC_WCSS5G_RTC_CLK] = &gcc_wcss5g_rtc_clk.clkr,
1626 	[GCC_SDCC_PLLDIV_CLK] = &gcc_apss_sdcc_clk.cdiv.clkr,
1627 	[GCC_FEPLL125_CLK] = &gcc_fepll125_clk.cdiv.clkr,
1628 	[GCC_FEPLL125DLY_CLK] = &gcc_fepll125dly_clk.cdiv.clkr,
1629 	[GCC_FEPLL200_CLK] = &gcc_fepll200_clk.cdiv.clkr,
1630 	[GCC_FEPLL500_CLK] = &gcc_fepll500_clk.cdiv.clkr,
1631 	[GCC_FEPLL_WCSS2G_CLK] = &gcc_fepllwcss2g_clk.cdiv.clkr,
1632 	[GCC_FEPLL_WCSS5G_CLK] = &gcc_fepllwcss5g_clk.cdiv.clkr,
1633 	[GCC_APSS_CPU_PLLDIV_CLK] = &gcc_apss_cpu_plldiv_clk.cdiv.clkr,
1634 	[GCC_PCNOC_AHB_CLK_SRC] = &gcc_pcnoc_ahb_clk_src.clkr,
1635 	[GCC_PCNOC_AHB_CLK] = &pcnoc_clk_src.clkr,
1636 };
1637 
1638 static const struct qcom_reset_map gcc_ipq4019_resets[] = {
1639 	[WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 },
1640 	[WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 },
1641 	[WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 },
1642 	[WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 },
1643 	[WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 },
1644 	[WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 },
1645 	[WIFI1_CPU_INIT_RESET] = { 0x20008, 5 },
1646 	[WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 },
1647 	[WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 },
1648 	[WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 },
1649 	[WIFI1_CORE_WARM_RESET] = { 0x20008, 1 },
1650 	[WIFI1_CORE_COLD_RESET] = { 0x20008, 0 },
1651 	[USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 },
1652 	[USB3_HSPHY_POR_ARES] = { 0x1e038, 4 },
1653 	[USB3_HSPHY_S_ARES] = { 0x1e038, 2 },
1654 	[USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 },
1655 	[USB2_HSPHY_S_ARES] = { 0x1e01c, 2 },
1656 	[PCIE_PHY_AHB_ARES] = { 0x1d010, 11 },
1657 	[PCIE_AHB_ARES] = { 0x1d010, 10 },
1658 	[PCIE_PWR_ARES] = { 0x1d010, 9 },
1659 	[PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 },
1660 	[PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 },
1661 	[PCIE_PHY_ARES] = { 0x1d010, 6 },
1662 	[PCIE_PARF_XPU_ARES] = { 0x1d010, 5 },
1663 	[PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 },
1664 	[PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 },
1665 	[PCIE_PIPE_ARES] = { 0x1d010, 2 },
1666 	[PCIE_AXI_S_ARES] = { 0x1d010, 1 },
1667 	[PCIE_AXI_M_ARES] = { 0x1d010, 0 },
1668 	[ESS_RESET] = { 0x12008, 0},
1669 	[GCC_BLSP1_BCR] = {0x01000, 0},
1670 	[GCC_BLSP1_QUP1_BCR] = {0x02000, 0},
1671 	[GCC_BLSP1_UART1_BCR] = {0x02038, 0},
1672 	[GCC_BLSP1_QUP2_BCR] = {0x03008, 0},
1673 	[GCC_BLSP1_UART2_BCR] = {0x03028, 0},
1674 	[GCC_BIMC_BCR] = {0x04000, 0},
1675 	[GCC_TLMM_BCR] = {0x05000, 0},
1676 	[GCC_IMEM_BCR] = {0x0E000, 0},
1677 	[GCC_ESS_BCR] = {0x12008, 0},
1678 	[GCC_PRNG_BCR] = {0x13000, 0},
1679 	[GCC_BOOT_ROM_BCR] = {0x13008, 0},
1680 	[GCC_CRYPTO_BCR] = {0x16000, 0},
1681 	[GCC_SDCC1_BCR] = {0x18000, 0},
1682 	[GCC_SEC_CTRL_BCR] = {0x1A000, 0},
1683 	[GCC_AUDIO_BCR] = {0x1B008, 0},
1684 	[GCC_QPIC_BCR] = {0x1C000, 0},
1685 	[GCC_PCIE_BCR] = {0x1D000, 0},
1686 	[GCC_USB2_BCR] = {0x1E008, 0},
1687 	[GCC_USB2_PHY_BCR] = {0x1E018, 0},
1688 	[GCC_USB3_BCR] = {0x1E024, 0},
1689 	[GCC_USB3_PHY_BCR] = {0x1E034, 0},
1690 	[GCC_SYSTEM_NOC_BCR] = {0x21000, 0},
1691 	[GCC_PCNOC_BCR] = {0x2102C, 0},
1692 	[GCC_DCD_BCR] = {0x21038, 0},
1693 	[GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0},
1694 	[GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0},
1695 	[GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0},
1696 	[GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0},
1697 	[GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0},
1698 	[GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0},
1699 	[GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0},
1700 	[GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0},
1701 	[GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0},
1702 	[GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0},
1703 	[GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0},
1704 	[GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0},
1705 	[GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0},
1706 	[GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0},
1707 	[GCC_TCSR_BCR] = {0x22000, 0},
1708 	[GCC_MPM_BCR] = {0x24000, 0},
1709 	[GCC_SPDM_BCR] = {0x25000, 0},
1710 };
1711 
1712 static const struct regmap_config gcc_ipq4019_regmap_config = {
1713 	.reg_bits	= 32,
1714 	.reg_stride	= 4,
1715 	.val_bits	= 32,
1716 	.max_register	= 0x2ffff,
1717 	.fast_io	= true,
1718 };
1719 
1720 static const struct qcom_cc_desc gcc_ipq4019_desc = {
1721 	.config = &gcc_ipq4019_regmap_config,
1722 	.clks = gcc_ipq4019_clocks,
1723 	.num_clks = ARRAY_SIZE(gcc_ipq4019_clocks),
1724 	.resets = gcc_ipq4019_resets,
1725 	.num_resets = ARRAY_SIZE(gcc_ipq4019_resets),
1726 };
1727 
1728 static const struct of_device_id gcc_ipq4019_match_table[] = {
1729 	{ .compatible = "qcom,gcc-ipq4019" },
1730 	{ }
1731 };
1732 MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table);
1733 
1734 static int
1735 gcc_ipq4019_cpu_clk_notifier_fn(struct notifier_block *nb,
1736 				unsigned long action, void *data)
1737 {
1738 	int err = 0;
1739 
1740 	if (action == PRE_RATE_CHANGE)
1741 		err = clk_rcg2_ops.set_parent(&apps_clk_src.clkr.hw,
1742 					      gcc_ipq4019_cpu_safe_parent);
1743 
1744 	return notifier_from_errno(err);
1745 }
1746 
1747 static struct notifier_block gcc_ipq4019_cpu_clk_notifier = {
1748 	.notifier_call = gcc_ipq4019_cpu_clk_notifier_fn,
1749 };
1750 
1751 static int gcc_ipq4019_probe(struct platform_device *pdev)
1752 {
1753 	int err;
1754 
1755 	err = qcom_cc_probe(pdev, &gcc_ipq4019_desc);
1756 	if (err)
1757 		return err;
1758 
1759 	return clk_notifier_register(apps_clk_src.clkr.hw.clk,
1760 				     &gcc_ipq4019_cpu_clk_notifier);
1761 }
1762 
1763 static int gcc_ipq4019_remove(struct platform_device *pdev)
1764 {
1765 	return clk_notifier_unregister(apps_clk_src.clkr.hw.clk,
1766 				       &gcc_ipq4019_cpu_clk_notifier);
1767 }
1768 
1769 static struct platform_driver gcc_ipq4019_driver = {
1770 	.probe		= gcc_ipq4019_probe,
1771 	.remove		= gcc_ipq4019_remove,
1772 	.driver		= {
1773 		.name	= "qcom,gcc-ipq4019",
1774 		.of_match_table = gcc_ipq4019_match_table,
1775 	},
1776 };
1777 
1778 static int __init gcc_ipq4019_init(void)
1779 {
1780 	return platform_driver_register(&gcc_ipq4019_driver);
1781 }
1782 core_initcall(gcc_ipq4019_init);
1783 
1784 static void __exit gcc_ipq4019_exit(void)
1785 {
1786 	platform_driver_unregister(&gcc_ipq4019_driver);
1787 }
1788 module_exit(gcc_ipq4019_exit);
1789 
1790 MODULE_ALIAS("platform:gcc-ipq4019");
1791 MODULE_LICENSE("GPL v2");
1792 MODULE_DESCRIPTION("QCOM GCC IPQ4019 driver");
1793