1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/mod_devicetable.h>
9 #include <linux/platform_device.h>
10 #include <linux/regmap.h>
11 
12 #include <dt-bindings/clock/qcom,sm4450-dispcc.h>
13 
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
16 #include "clk-pll.h"
17 #include "clk-rcg.h"
18 #include "clk-regmap.h"
19 #include "clk-regmap-divider.h"
20 #include "common.h"
21 #include "gdsc.h"
22 #include "reset.h"
23 
24 enum {
25 	DT_BI_TCXO,
26 	DT_BI_TCXO_AO,
27 	DT_AHB_CLK,
28 	DT_SLEEP_CLK,
29 
30 	DT_DSI0_PHY_PLL_OUT_BYTECLK,
31 	DT_DSI0_PHY_PLL_OUT_DSICLK,
32 };
33 
34 enum {
35 	P_BI_TCXO,
36 	P_DISP_CC_PLL0_OUT_MAIN,
37 	P_DISP_CC_PLL1_OUT_EVEN,
38 	P_DISP_CC_PLL1_OUT_MAIN,
39 	P_DSI0_PHY_PLL_OUT_BYTECLK,
40 	P_DSI0_PHY_PLL_OUT_DSICLK,
41 	P_SLEEP_CLK,
42 };
43 
44 static const struct pll_vco lucid_evo_vco[] = {
45 	{ 249600000, 2020000000, 0 },
46 };
47 
48 /* 600.0 MHz Configuration */
49 static const struct alpha_pll_config disp_cc_pll0_config = {
50 	.l = 0x1f,
51 	.alpha = 0x4000,
52 	.config_ctl_val = 0x20485699,
53 	.config_ctl_hi_val = 0x00182261,
54 	.config_ctl_hi1_val = 0x32aa299c,
55 	.user_ctl_val = 0x00000000,
56 	.user_ctl_hi_val = 0x00000805,
57 };
58 
59 static struct clk_alpha_pll disp_cc_pll0 = {
60 	.offset = 0x0,
61 	.vco_table = lucid_evo_vco,
62 	.num_vco = ARRAY_SIZE(lucid_evo_vco),
63 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
64 	.clkr = {
65 		.hw.init = &(const struct clk_init_data) {
66 			.name = "disp_cc_pll0",
67 			.parent_data = &(const struct clk_parent_data) {
68 				.index = DT_BI_TCXO,
69 			},
70 			.num_parents = 1,
71 			.ops = &clk_alpha_pll_lucid_evo_ops,
72 		},
73 	},
74 };
75 
76 static struct clk_alpha_pll disp_cc_pll1 = {
77 	.offset = 0x1000,
78 	.vco_table = lucid_evo_vco,
79 	.num_vco = ARRAY_SIZE(lucid_evo_vco),
80 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO],
81 	.clkr = {
82 		.hw.init = &(const struct clk_init_data) {
83 			.name = "disp_cc_pll1",
84 			.parent_data = &(const struct clk_parent_data) {
85 				.index = DT_BI_TCXO,
86 			},
87 			.num_parents = 1,
88 			.ops = &clk_alpha_pll_lucid_evo_ops,
89 		},
90 	},
91 };
92 
93 static const struct parent_map disp_cc_parent_map_0[] = {
94 	{ P_BI_TCXO, 0 },
95 	{ P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
96 	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 2 },
97 };
98 
99 static const struct clk_parent_data disp_cc_parent_data_0[] = {
100 	{ .index = DT_BI_TCXO },
101 	{ .index = DT_DSI0_PHY_PLL_OUT_DSICLK },
102 	{ .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
103 };
104 
105 static const struct parent_map disp_cc_parent_map_1[] = {
106 	{ P_BI_TCXO, 0 },
107 	{ P_DISP_CC_PLL0_OUT_MAIN, 1 },
108 	{ P_DISP_CC_PLL1_OUT_MAIN, 4 },
109 	{ P_DISP_CC_PLL1_OUT_EVEN, 6 },
110 };
111 
112 static const struct clk_parent_data disp_cc_parent_data_1[] = {
113 	{ .index = DT_BI_TCXO },
114 	{ .hw = &disp_cc_pll0.clkr.hw },
115 	{ .hw = &disp_cc_pll1.clkr.hw },
116 	{ .hw = &disp_cc_pll1.clkr.hw },
117 };
118 
119 static const struct parent_map disp_cc_parent_map_2[] = {
120 	{ P_BI_TCXO, 0 },
121 };
122 
123 static const struct clk_parent_data disp_cc_parent_data_2[] = {
124 	{ .index = DT_BI_TCXO },
125 };
126 
127 static const struct clk_parent_data disp_cc_parent_data_2_ao[] = {
128 	{ .index = DT_BI_TCXO_AO },
129 };
130 
131 static const struct parent_map disp_cc_parent_map_3[] = {
132 	{ P_BI_TCXO, 0 },
133 	{ P_DISP_CC_PLL1_OUT_MAIN, 4 },
134 	{ P_DISP_CC_PLL1_OUT_EVEN, 6 },
135 };
136 
137 static const struct clk_parent_data disp_cc_parent_data_3[] = {
138 	{ .index = DT_BI_TCXO },
139 	{ .hw = &disp_cc_pll1.clkr.hw },
140 	{ .hw = &disp_cc_pll1.clkr.hw },
141 };
142 
143 static const struct parent_map disp_cc_parent_map_4[] = {
144 	{ P_BI_TCXO, 0 },
145 	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 2 },
146 };
147 
148 static const struct clk_parent_data disp_cc_parent_data_4[] = {
149 	{ .index = DT_BI_TCXO },
150 	{ .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
151 };
152 
153 static const struct parent_map disp_cc_parent_map_5[] = {
154 	{ P_SLEEP_CLK, 0 },
155 };
156 
157 static const struct clk_parent_data disp_cc_parent_data_5[] = {
158 	{ .index = DT_SLEEP_CLK },
159 };
160 
161 static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
162 	F(19200000, P_BI_TCXO, 1, 0, 0),
163 	F(37500000, P_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0),
164 	F(75000000, P_DISP_CC_PLL1_OUT_MAIN, 8, 0, 0),
165 	{ }
166 };
167 
168 static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {
169 	.cmd_rcgr = 0x82a4,
170 	.mnd_width = 0,
171 	.hid_width = 5,
172 	.parent_map = disp_cc_parent_map_3,
173 	.freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
174 	.clkr.hw.init = &(const struct clk_init_data) {
175 		.name = "disp_cc_mdss_ahb_clk_src",
176 		.parent_data = disp_cc_parent_data_3,
177 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
178 		.flags = CLK_SET_RATE_PARENT,
179 		.ops = &clk_rcg2_shared_ops,
180 	},
181 };
182 
183 static const struct freq_tbl ftbl_disp_cc_mdss_byte0_clk_src[] = {
184 	F(19200000, P_BI_TCXO, 1, 0, 0),
185 	{ }
186 };
187 
188 static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
189 	.cmd_rcgr = 0x80f8,
190 	.mnd_width = 0,
191 	.hid_width = 5,
192 	.parent_map = disp_cc_parent_map_0,
193 	.freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
194 	.clkr.hw.init = &(const struct clk_init_data) {
195 		.name = "disp_cc_mdss_byte0_clk_src",
196 		.parent_data = disp_cc_parent_data_0,
197 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
198 		.flags = CLK_SET_RATE_PARENT,
199 		.ops = &clk_byte2_ops,
200 	},
201 };
202 
203 static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
204 	.cmd_rcgr = 0x8114,
205 	.mnd_width = 0,
206 	.hid_width = 5,
207 	.parent_map = disp_cc_parent_map_4,
208 	.freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
209 	.clkr.hw.init = &(const struct clk_init_data) {
210 		.name = "disp_cc_mdss_esc0_clk_src",
211 		.parent_data = disp_cc_parent_data_4,
212 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
213 		.flags = CLK_SET_RATE_PARENT,
214 		.ops = &clk_rcg2_shared_ops,
215 	},
216 };
217 
218 static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
219 	F(200000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
220 	F(325000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
221 	F(380000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
222 	F(506000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
223 	F(608000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
224 	{ }
225 };
226 
227 static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
228 	.cmd_rcgr = 0x80b0,
229 	.mnd_width = 0,
230 	.hid_width = 5,
231 	.parent_map = disp_cc_parent_map_1,
232 	.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
233 	.clkr.hw.init = &(const struct clk_init_data) {
234 		.name = "disp_cc_mdss_mdp_clk_src",
235 		.parent_data = disp_cc_parent_data_1,
236 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
237 		.flags = CLK_SET_RATE_PARENT,
238 		.ops = &clk_rcg2_shared_ops,
239 	},
240 };
241 
242 static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
243 	.cmd_rcgr = 0x8098,
244 	.mnd_width = 8,
245 	.hid_width = 5,
246 	.parent_map = disp_cc_parent_map_0,
247 	.freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
248 	.clkr.hw.init = &(const struct clk_init_data) {
249 		.name = "disp_cc_mdss_pclk0_clk_src",
250 		.parent_data = disp_cc_parent_data_0,
251 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
252 		.flags = CLK_SET_RATE_PARENT,
253 		.ops = &clk_pixel_ops,
254 	},
255 };
256 
257 static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
258 	F(200000000, P_DISP_CC_PLL1_OUT_MAIN, 3, 0, 0),
259 	F(300000000, P_DISP_CC_PLL1_OUT_MAIN, 2, 0, 0),
260 	{ }
261 };
262 
263 static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
264 	.cmd_rcgr = 0x80c8,
265 	.mnd_width = 0,
266 	.hid_width = 5,
267 	.parent_map = disp_cc_parent_map_1,
268 	.freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
269 	.clkr.hw.init = &(const struct clk_init_data) {
270 		.name = "disp_cc_mdss_rot_clk_src",
271 		.parent_data = disp_cc_parent_data_1,
272 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
273 		.flags = CLK_SET_RATE_PARENT,
274 		.ops = &clk_rcg2_shared_ops,
275 	},
276 };
277 
278 static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
279 	.cmd_rcgr = 0x80e0,
280 	.mnd_width = 0,
281 	.hid_width = 5,
282 	.parent_map = disp_cc_parent_map_2,
283 	.freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
284 	.clkr.hw.init = &(const struct clk_init_data) {
285 		.name = "disp_cc_mdss_vsync_clk_src",
286 		.parent_data = disp_cc_parent_data_2,
287 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
288 		.flags = CLK_SET_RATE_PARENT,
289 		.ops = &clk_rcg2_shared_ops,
290 	},
291 };
292 
293 static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = {
294 	F(32000, P_SLEEP_CLK, 1, 0, 0),
295 	{ }
296 };
297 
298 static struct clk_rcg2 disp_cc_sleep_clk_src = {
299 	.cmd_rcgr = 0xe058,
300 	.mnd_width = 0,
301 	.hid_width = 5,
302 	.parent_map = disp_cc_parent_map_5,
303 	.freq_tbl = ftbl_disp_cc_sleep_clk_src,
304 	.clkr.hw.init = &(const struct clk_init_data) {
305 		.name = "disp_cc_sleep_clk_src",
306 		.parent_data = disp_cc_parent_data_5,
307 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
308 		.flags = CLK_SET_RATE_PARENT,
309 		.ops = &clk_rcg2_shared_ops,
310 	},
311 };
312 
313 static struct clk_rcg2 disp_cc_xo_clk_src = {
314 	.cmd_rcgr = 0xe03c,
315 	.mnd_width = 0,
316 	.hid_width = 5,
317 	.parent_map = disp_cc_parent_map_2,
318 	.freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
319 	.clkr.hw.init = &(const struct clk_init_data) {
320 		.name = "disp_cc_xo_clk_src",
321 		.parent_data = disp_cc_parent_data_2_ao,
322 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2_ao),
323 		.flags = CLK_SET_RATE_PARENT,
324 		.ops = &clk_rcg2_shared_ops,
325 	},
326 };
327 
328 static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
329 	.reg = 0x8110,
330 	.shift = 0,
331 	.width = 4,
332 	.clkr.hw.init = &(const struct clk_init_data) {
333 		.name = "disp_cc_mdss_byte0_div_clk_src",
334 		.parent_hws = (const struct clk_hw*[]) {
335 			&disp_cc_mdss_byte0_clk_src.clkr.hw,
336 		},
337 		.num_parents = 1,
338 		.flags = CLK_SET_RATE_PARENT,
339 		.ops = &clk_regmap_div_ops,
340 	},
341 };
342 
343 static struct clk_branch disp_cc_mdss_ahb1_clk = {
344 	.halt_reg = 0xa020,
345 	.halt_check = BRANCH_HALT,
346 	.clkr = {
347 		.enable_reg = 0xa020,
348 		.enable_mask = BIT(0),
349 		.hw.init = &(const struct clk_init_data) {
350 			.name = "disp_cc_mdss_ahb1_clk",
351 			.parent_hws = (const struct clk_hw*[]) {
352 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
353 			},
354 			.num_parents = 1,
355 			.flags = CLK_SET_RATE_PARENT,
356 			.ops = &clk_branch2_ops,
357 		},
358 	},
359 };
360 
361 static struct clk_branch disp_cc_mdss_ahb_clk = {
362 	.halt_reg = 0x8094,
363 	.halt_check = BRANCH_HALT,
364 	.clkr = {
365 		.enable_reg = 0x8094,
366 		.enable_mask = BIT(0),
367 		.hw.init = &(const struct clk_init_data) {
368 			.name = "disp_cc_mdss_ahb_clk",
369 			.parent_hws = (const struct clk_hw*[]) {
370 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
371 			},
372 			.num_parents = 1,
373 			.flags = CLK_SET_RATE_PARENT,
374 			.ops = &clk_branch2_ops,
375 		},
376 	},
377 };
378 
379 static struct clk_branch disp_cc_mdss_byte0_clk = {
380 	.halt_reg = 0x8024,
381 	.halt_check = BRANCH_HALT,
382 	.clkr = {
383 		.enable_reg = 0x8024,
384 		.enable_mask = BIT(0),
385 		.hw.init = &(const struct clk_init_data) {
386 			.name = "disp_cc_mdss_byte0_clk",
387 			.parent_hws = (const struct clk_hw*[]) {
388 				&disp_cc_mdss_byte0_clk_src.clkr.hw,
389 			},
390 			.num_parents = 1,
391 			.flags = CLK_SET_RATE_PARENT,
392 			.ops = &clk_branch2_ops,
393 		},
394 	},
395 };
396 
397 static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
398 	.halt_reg = 0x8028,
399 	.halt_check = BRANCH_HALT,
400 	.clkr = {
401 		.enable_reg = 0x8028,
402 		.enable_mask = BIT(0),
403 		.hw.init = &(const struct clk_init_data) {
404 			.name = "disp_cc_mdss_byte0_intf_clk",
405 			.parent_hws = (const struct clk_hw*[]) {
406 				&disp_cc_mdss_byte0_div_clk_src.clkr.hw,
407 			},
408 			.num_parents = 1,
409 			.flags = CLK_SET_RATE_PARENT,
410 			.ops = &clk_branch2_ops,
411 		},
412 	},
413 };
414 
415 static struct clk_branch disp_cc_mdss_esc0_clk = {
416 	.halt_reg = 0x802c,
417 	.halt_check = BRANCH_HALT,
418 	.clkr = {
419 		.enable_reg = 0x802c,
420 		.enable_mask = BIT(0),
421 		.hw.init = &(const struct clk_init_data) {
422 			.name = "disp_cc_mdss_esc0_clk",
423 			.parent_hws = (const struct clk_hw*[]) {
424 				&disp_cc_mdss_esc0_clk_src.clkr.hw,
425 			},
426 			.num_parents = 1,
427 			.flags = CLK_SET_RATE_PARENT,
428 			.ops = &clk_branch2_ops,
429 		},
430 	},
431 };
432 
433 static struct clk_branch disp_cc_mdss_mdp1_clk = {
434 	.halt_reg = 0xa004,
435 	.halt_check = BRANCH_HALT,
436 	.clkr = {
437 		.enable_reg = 0xa004,
438 		.enable_mask = BIT(0),
439 		.hw.init = &(const struct clk_init_data) {
440 			.name = "disp_cc_mdss_mdp1_clk",
441 			.parent_hws = (const struct clk_hw*[]) {
442 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
443 			},
444 			.num_parents = 1,
445 			.flags = CLK_SET_RATE_PARENT,
446 			.ops = &clk_branch2_ops,
447 		},
448 	},
449 };
450 
451 static struct clk_branch disp_cc_mdss_mdp_clk = {
452 	.halt_reg = 0x8008,
453 	.halt_check = BRANCH_HALT,
454 	.clkr = {
455 		.enable_reg = 0x8008,
456 		.enable_mask = BIT(0),
457 		.hw.init = &(const struct clk_init_data) {
458 			.name = "disp_cc_mdss_mdp_clk",
459 			.parent_hws = (const struct clk_hw*[]) {
460 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
461 			},
462 			.num_parents = 1,
463 			.flags = CLK_SET_RATE_PARENT,
464 			.ops = &clk_branch2_ops,
465 		},
466 	},
467 };
468 
469 static struct clk_branch disp_cc_mdss_mdp_lut1_clk = {
470 	.halt_reg = 0xa014,
471 	.halt_check = BRANCH_HALT,
472 	.clkr = {
473 		.enable_reg = 0xa014,
474 		.enable_mask = BIT(0),
475 		.hw.init = &(const struct clk_init_data) {
476 			.name = "disp_cc_mdss_mdp_lut1_clk",
477 			.parent_hws = (const struct clk_hw*[]) {
478 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
479 			},
480 			.num_parents = 1,
481 			.flags = CLK_SET_RATE_PARENT,
482 			.ops = &clk_branch2_ops,
483 		},
484 	},
485 };
486 
487 static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
488 	.halt_reg = 0x8018,
489 	.halt_check = BRANCH_HALT_VOTED,
490 	.clkr = {
491 		.enable_reg = 0x8018,
492 		.enable_mask = BIT(0),
493 		.hw.init = &(const struct clk_init_data) {
494 			.name = "disp_cc_mdss_mdp_lut_clk",
495 			.parent_hws = (const struct clk_hw*[]) {
496 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
497 			},
498 			.num_parents = 1,
499 			.flags = CLK_SET_RATE_PARENT,
500 			.ops = &clk_branch2_ops,
501 		},
502 	},
503 };
504 
505 static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {
506 	.halt_reg = 0xc004,
507 	.halt_check = BRANCH_HALT_VOTED,
508 	.clkr = {
509 		.enable_reg = 0xc004,
510 		.enable_mask = BIT(0),
511 		.hw.init = &(const struct clk_init_data) {
512 			.name = "disp_cc_mdss_non_gdsc_ahb_clk",
513 			.parent_hws = (const struct clk_hw*[]) {
514 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
515 			},
516 			.num_parents = 1,
517 			.flags = CLK_SET_RATE_PARENT,
518 			.ops = &clk_branch2_ops,
519 		},
520 	},
521 };
522 
523 static struct clk_branch disp_cc_mdss_pclk0_clk = {
524 	.halt_reg = 0x8004,
525 	.halt_check = BRANCH_HALT,
526 	.clkr = {
527 		.enable_reg = 0x8004,
528 		.enable_mask = BIT(0),
529 		.hw.init = &(const struct clk_init_data) {
530 			.name = "disp_cc_mdss_pclk0_clk",
531 			.parent_hws = (const struct clk_hw*[]) {
532 				&disp_cc_mdss_pclk0_clk_src.clkr.hw,
533 			},
534 			.num_parents = 1,
535 			.flags = CLK_SET_RATE_PARENT,
536 			.ops = &clk_branch2_ops,
537 		},
538 	},
539 };
540 
541 static struct clk_branch disp_cc_mdss_rot1_clk = {
542 	.halt_reg = 0xa00c,
543 	.halt_check = BRANCH_HALT,
544 	.clkr = {
545 		.enable_reg = 0xa00c,
546 		.enable_mask = BIT(0),
547 		.hw.init = &(const struct clk_init_data) {
548 			.name = "disp_cc_mdss_rot1_clk",
549 			.parent_hws = (const struct clk_hw*[]) {
550 				&disp_cc_mdss_rot_clk_src.clkr.hw,
551 			},
552 			.num_parents = 1,
553 			.flags = CLK_SET_RATE_PARENT,
554 			.ops = &clk_branch2_ops,
555 		},
556 	},
557 };
558 
559 static struct clk_branch disp_cc_mdss_rot_clk = {
560 	.halt_reg = 0x8010,
561 	.halt_check = BRANCH_HALT,
562 	.clkr = {
563 		.enable_reg = 0x8010,
564 		.enable_mask = BIT(0),
565 		.hw.init = &(const struct clk_init_data) {
566 			.name = "disp_cc_mdss_rot_clk",
567 			.parent_hws = (const struct clk_hw*[]) {
568 				&disp_cc_mdss_rot_clk_src.clkr.hw,
569 			},
570 			.num_parents = 1,
571 			.flags = CLK_SET_RATE_PARENT,
572 			.ops = &clk_branch2_ops,
573 		},
574 	},
575 };
576 
577 static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {
578 	.halt_reg = 0xc00c,
579 	.halt_check = BRANCH_HALT,
580 	.clkr = {
581 		.enable_reg = 0xc00c,
582 		.enable_mask = BIT(0),
583 		.hw.init = &(const struct clk_init_data) {
584 			.name = "disp_cc_mdss_rscc_ahb_clk",
585 			.parent_hws = (const struct clk_hw*[]) {
586 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
587 			},
588 			.num_parents = 1,
589 			.flags = CLK_SET_RATE_PARENT,
590 			.ops = &clk_branch2_ops,
591 		},
592 	},
593 };
594 
595 static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {
596 	.halt_reg = 0xc008,
597 	.halt_check = BRANCH_HALT,
598 	.clkr = {
599 		.enable_reg = 0xc008,
600 		.enable_mask = BIT(0),
601 		.hw.init = &(const struct clk_init_data) {
602 			.name = "disp_cc_mdss_rscc_vsync_clk",
603 			.parent_hws = (const struct clk_hw*[]) {
604 				&disp_cc_mdss_vsync_clk_src.clkr.hw,
605 			},
606 			.num_parents = 1,
607 			.flags = CLK_SET_RATE_PARENT,
608 			.ops = &clk_branch2_ops,
609 		},
610 	},
611 };
612 
613 static struct clk_branch disp_cc_mdss_vsync1_clk = {
614 	.halt_reg = 0xa01c,
615 	.halt_check = BRANCH_HALT,
616 	.clkr = {
617 		.enable_reg = 0xa01c,
618 		.enable_mask = BIT(0),
619 		.hw.init = &(const struct clk_init_data) {
620 			.name = "disp_cc_mdss_vsync1_clk",
621 			.parent_hws = (const struct clk_hw*[]) {
622 				&disp_cc_mdss_vsync_clk_src.clkr.hw,
623 			},
624 			.num_parents = 1,
625 			.flags = CLK_SET_RATE_PARENT,
626 			.ops = &clk_branch2_ops,
627 		},
628 	},
629 };
630 
631 static struct clk_branch disp_cc_mdss_vsync_clk = {
632 	.halt_reg = 0x8020,
633 	.halt_check = BRANCH_HALT,
634 	.clkr = {
635 		.enable_reg = 0x8020,
636 		.enable_mask = BIT(0),
637 		.hw.init = &(const struct clk_init_data) {
638 			.name = "disp_cc_mdss_vsync_clk",
639 			.parent_hws = (const struct clk_hw*[]) {
640 				&disp_cc_mdss_vsync_clk_src.clkr.hw,
641 			},
642 			.num_parents = 1,
643 			.flags = CLK_SET_RATE_PARENT,
644 			.ops = &clk_branch2_ops,
645 		},
646 	},
647 };
648 
649 static struct gdsc disp_cc_mdss_core_gdsc = {
650 	.gdscr = 0x9000,
651 	.en_rest_wait_val = 0x2,
652 	.en_few_wait_val = 0x2,
653 	.clk_dis_wait_val = 0xf,
654 	.pd = {
655 		.name = "disp_cc_mdss_core_gdsc",
656 	},
657 	.pwrsts = PWRSTS_OFF_ON,
658 	.flags = HW_CTRL | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
659 };
660 
661 static struct gdsc disp_cc_mdss_core_int2_gdsc = {
662 	.gdscr = 0xb000,
663 	.en_rest_wait_val = 0x2,
664 	.en_few_wait_val = 0x2,
665 	.clk_dis_wait_val = 0xf,
666 	.pd = {
667 		.name = "disp_cc_mdss_core_int2_gdsc",
668 	},
669 	.pwrsts = PWRSTS_OFF_ON,
670 	.flags = HW_CTRL | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
671 };
672 
673 static struct clk_regmap *disp_cc_sm4450_clocks[] = {
674 	[DISP_CC_MDSS_AHB1_CLK] = &disp_cc_mdss_ahb1_clk.clkr,
675 	[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
676 	[DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,
677 	[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
678 	[DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
679 	[DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,
680 	[DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
681 	[DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
682 	[DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
683 	[DISP_CC_MDSS_MDP1_CLK] = &disp_cc_mdss_mdp1_clk.clkr,
684 	[DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
685 	[DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
686 	[DISP_CC_MDSS_MDP_LUT1_CLK] = &disp_cc_mdss_mdp_lut1_clk.clkr,
687 	[DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
688 	[DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
689 	[DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
690 	[DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
691 	[DISP_CC_MDSS_ROT1_CLK] = &disp_cc_mdss_rot1_clk.clkr,
692 	[DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
693 	[DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
694 	[DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,
695 	[DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,
696 	[DISP_CC_MDSS_VSYNC1_CLK] = &disp_cc_mdss_vsync1_clk.clkr,
697 	[DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
698 	[DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
699 	[DISP_CC_PLL0] = &disp_cc_pll0.clkr,
700 	[DISP_CC_PLL1] = &disp_cc_pll1.clkr,
701 	[DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr,
702 	[DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr,
703 };
704 
705 static struct gdsc *disp_cc_sm4450_gdscs[] = {
706 	[DISP_CC_MDSS_CORE_GDSC] = &disp_cc_mdss_core_gdsc,
707 	[DISP_CC_MDSS_CORE_INT2_GDSC] = &disp_cc_mdss_core_int2_gdsc,
708 };
709 
710 static const struct qcom_reset_map disp_cc_sm4450_resets[] = {
711 	[DISP_CC_MDSS_CORE_BCR] = { 0x8000 },
712 	[DISP_CC_MDSS_CORE_INT2_BCR] = { 0xa000 },
713 	[DISP_CC_MDSS_RSCC_BCR] = { 0xc000 },
714 };
715 
716 static const struct regmap_config disp_cc_sm4450_regmap_config = {
717 	.reg_bits = 32,
718 	.reg_stride = 4,
719 	.val_bits = 32,
720 	.max_register = 0x11008,
721 	.fast_io = true,
722 };
723 
724 static const struct qcom_cc_desc disp_cc_sm4450_desc = {
725 	.config = &disp_cc_sm4450_regmap_config,
726 	.clks = disp_cc_sm4450_clocks,
727 	.num_clks = ARRAY_SIZE(disp_cc_sm4450_clocks),
728 	.resets = disp_cc_sm4450_resets,
729 	.num_resets = ARRAY_SIZE(disp_cc_sm4450_resets),
730 	.gdscs = disp_cc_sm4450_gdscs,
731 	.num_gdscs = ARRAY_SIZE(disp_cc_sm4450_gdscs),
732 };
733 
734 static const struct of_device_id disp_cc_sm4450_match_table[] = {
735 	{ .compatible = "qcom,sm4450-dispcc" },
736 	{ }
737 };
738 MODULE_DEVICE_TABLE(of, disp_cc_sm4450_match_table);
739 
disp_cc_sm4450_probe(struct platform_device * pdev)740 static int disp_cc_sm4450_probe(struct platform_device *pdev)
741 {
742 	struct regmap *regmap;
743 
744 	regmap = qcom_cc_map(pdev, &disp_cc_sm4450_desc);
745 	if (IS_ERR(regmap))
746 		return PTR_ERR(regmap);
747 
748 	clk_lucid_evo_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
749 	clk_lucid_evo_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll0_config);
750 
751 	/* Keep some clocks always enabled */
752 	qcom_branch_set_clk_en(regmap, 0xe070); /* DISP_CC_SLEEP_CLK */
753 	qcom_branch_set_clk_en(regmap, 0xe054); /* DISP_CC_XO_CLK */
754 
755 	return qcom_cc_really_probe(&pdev->dev, &disp_cc_sm4450_desc, regmap);
756 }
757 
758 static struct platform_driver disp_cc_sm4450_driver = {
759 	.probe = disp_cc_sm4450_probe,
760 	.driver = {
761 		.name = "dispcc-sm4450",
762 		.of_match_table = disp_cc_sm4450_match_table,
763 	},
764 };
765 
766 module_platform_driver(disp_cc_sm4450_driver);
767 
768 MODULE_DESCRIPTION("QTI DISPCC SM4450 Driver");
769 MODULE_LICENSE("GPL");
770