xref: /openbmc/linux/drivers/clk/qcom/dispcc-sm6115.c (revision 22b6e7f3)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Based on dispcc-qcm2290.c
4  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
5  * Copyright (c) 2021, Linaro Ltd.
6  */
7 
8 #include <linux/err.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 
15 #include <dt-bindings/clock/qcom,sm6115-dispcc.h>
16 
17 #include "clk-alpha-pll.h"
18 #include "clk-branch.h"
19 #include "clk-rcg.h"
20 #include "clk-regmap.h"
21 #include "clk-regmap-divider.h"
22 #include "common.h"
23 #include "gdsc.h"
24 
25 enum {
26 	DT_BI_TCXO,
27 	DT_SLEEP_CLK,
28 	DT_DSI0_PHY_PLL_OUT_BYTECLK,
29 	DT_DSI0_PHY_PLL_OUT_DSICLK,
30 	DT_GPLL0_DISP_DIV,
31 };
32 
33 enum {
34 	P_BI_TCXO,
35 	P_DISP_CC_PLL0_OUT_MAIN,
36 	P_DSI0_PHY_PLL_OUT_BYTECLK,
37 	P_DSI0_PHY_PLL_OUT_DSICLK,
38 	P_GPLL0_OUT_MAIN,
39 	P_SLEEP_CLK,
40 };
41 
42 static const struct clk_parent_data parent_data_tcxo = { .index = DT_BI_TCXO };
43 
44 static const struct pll_vco spark_vco[] = {
45 	{ 500000000, 1000000000, 2 },
46 };
47 
48 /* 768MHz configuration */
49 static const struct alpha_pll_config disp_cc_pll0_config = {
50 	.l = 0x28,
51 	.alpha = 0x0,
52 	.alpha_en_mask = BIT(24),
53 	.vco_val = 0x2 << 20,
54 	.vco_mask = GENMASK(21, 20),
55 	.main_output_mask = BIT(0),
56 	.config_ctl_val = 0x4001055B,
57 };
58 
59 static struct clk_alpha_pll disp_cc_pll0 = {
60 	.offset = 0x0,
61 	.vco_table = spark_vco,
62 	.num_vco = ARRAY_SIZE(spark_vco),
63 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
64 	.clkr = {
65 		.hw.init = &(struct clk_init_data){
66 			.name = "disp_cc_pll0",
67 			.parent_data = &parent_data_tcxo,
68 			.num_parents = 1,
69 			.ops = &clk_alpha_pll_ops,
70 		},
71 	},
72 };
73 
74 static const struct clk_div_table post_div_table_disp_cc_pll0_out_main[] = {
75 	{ 0x0, 1 },
76 	{ }
77 };
78 static struct clk_alpha_pll_postdiv disp_cc_pll0_out_main = {
79 	.offset = 0x0,
80 	.post_div_shift = 8,
81 	.post_div_table = post_div_table_disp_cc_pll0_out_main,
82 	.num_post_div = ARRAY_SIZE(post_div_table_disp_cc_pll0_out_main),
83 	.width = 4,
84 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
85 	.clkr.hw.init = &(struct clk_init_data){
86 		.name = "disp_cc_pll0_out_main",
87 		.parent_hws = (const struct clk_hw*[]){
88 			&disp_cc_pll0.clkr.hw,
89 		},
90 		.num_parents = 1,
91 		.flags = CLK_SET_RATE_PARENT,
92 		.ops = &clk_alpha_pll_postdiv_ops,
93 	},
94 };
95 
96 static const struct parent_map disp_cc_parent_map_0[] = {
97 	{ P_BI_TCXO, 0 },
98 	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
99 };
100 
101 static const struct clk_parent_data disp_cc_parent_data_0[] = {
102 	{ .index = DT_BI_TCXO },
103 	{ .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
104 };
105 
106 static const struct parent_map disp_cc_parent_map_1[] = {
107 	{ P_BI_TCXO, 0 },
108 };
109 
110 static const struct clk_parent_data disp_cc_parent_data_1[] = {
111 	{ .index = DT_BI_TCXO },
112 };
113 
114 static const struct parent_map disp_cc_parent_map_2[] = {
115 	{ P_BI_TCXO, 0 },
116 	{ P_GPLL0_OUT_MAIN, 4 },
117 };
118 
119 static const struct clk_parent_data disp_cc_parent_data_2[] = {
120 	{ .index = DT_BI_TCXO },
121 	{ .index = DT_GPLL0_DISP_DIV },
122 };
123 
124 static const struct parent_map disp_cc_parent_map_3[] = {
125 	{ P_BI_TCXO, 0 },
126 	{ P_DISP_CC_PLL0_OUT_MAIN, 1 },
127 };
128 
129 static const struct clk_parent_data disp_cc_parent_data_3[] = {
130 	{ .index = DT_BI_TCXO },
131 	{ .hw = &disp_cc_pll0_out_main.clkr.hw },
132 };
133 
134 static const struct parent_map disp_cc_parent_map_4[] = {
135 	{ P_BI_TCXO, 0 },
136 	{ P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
137 };
138 
139 static const struct clk_parent_data disp_cc_parent_data_4[] = {
140 	{ .index = DT_BI_TCXO },
141 	{ .index = DT_DSI0_PHY_PLL_OUT_DSICLK },
142 };
143 
144 static const struct parent_map disp_cc_parent_map_5[] = {
145 	{ P_SLEEP_CLK, 0 },
146 };
147 
148 static const struct clk_parent_data disp_cc_parent_data_5[] = {
149 	{ .index = DT_SLEEP_CLK, },
150 };
151 
152 static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
153 	.cmd_rcgr = 0x20bc,
154 	.mnd_width = 0,
155 	.hid_width = 5,
156 	.parent_map = disp_cc_parent_map_0,
157 	.clkr.hw.init = &(struct clk_init_data){
158 		.name = "disp_cc_mdss_byte0_clk_src",
159 		.parent_data = disp_cc_parent_data_0,
160 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
161 		/* For set_rate and set_parent to succeed, parent(s) must be enabled */
162 		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE | CLK_GET_RATE_NOCACHE,
163 		.ops = &clk_byte2_ops,
164 	},
165 };
166 
167 static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
168 	.reg = 0x20d4,
169 	.shift = 0,
170 	.width = 2,
171 	.clkr.hw.init = &(struct clk_init_data) {
172 		.name = "disp_cc_mdss_byte0_div_clk_src",
173 		.parent_hws = (const struct clk_hw*[]){
174 			&disp_cc_mdss_byte0_clk_src.clkr.hw,
175 		},
176 		.num_parents = 1,
177 		.ops = &clk_regmap_div_ops,
178 	},
179 };
180 
181 static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
182 	F(19200000, P_BI_TCXO, 1, 0, 0),
183 	F(37500000, P_GPLL0_OUT_MAIN, 8, 0, 0),
184 	F(75000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
185 	{ }
186 };
187 
188 static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {
189 	.cmd_rcgr = 0x2154,
190 	.mnd_width = 0,
191 	.hid_width = 5,
192 	.parent_map = disp_cc_parent_map_2,
193 	.freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
194 	.clkr.hw.init = &(struct clk_init_data){
195 		.name = "disp_cc_mdss_ahb_clk_src",
196 		.parent_data = disp_cc_parent_data_2,
197 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
198 		.ops = &clk_rcg2_shared_ops,
199 	},
200 };
201 
202 static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {
203 	F(19200000, P_BI_TCXO, 1, 0, 0),
204 	{ }
205 };
206 
207 static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
208 	.cmd_rcgr = 0x20d8,
209 	.mnd_width = 0,
210 	.hid_width = 5,
211 	.parent_map = disp_cc_parent_map_0,
212 	.freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
213 	.clkr.hw.init = &(struct clk_init_data){
214 		.name = "disp_cc_mdss_esc0_clk_src",
215 		.parent_data = disp_cc_parent_data_0,
216 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
217 		.ops = &clk_rcg2_ops,
218 	},
219 };
220 
221 static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
222 	F(19200000, P_BI_TCXO, 1, 0, 0),
223 	F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0),
224 	F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
225 	F(307200000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
226 	F(384000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
227 	{ }
228 };
229 
230 static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
231 	.cmd_rcgr = 0x2074,
232 	.mnd_width = 0,
233 	.hid_width = 5,
234 	.parent_map = disp_cc_parent_map_3,
235 	.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
236 	.clkr.hw.init = &(struct clk_init_data){
237 		.name = "disp_cc_mdss_mdp_clk_src",
238 		.parent_data = disp_cc_parent_data_3,
239 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
240 		.flags = CLK_SET_RATE_PARENT,
241 		.ops = &clk_rcg2_shared_ops,
242 	},
243 };
244 
245 static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
246 	.cmd_rcgr = 0x205c,
247 	.mnd_width = 8,
248 	.hid_width = 5,
249 	.parent_map = disp_cc_parent_map_4,
250 	.clkr.hw.init = &(struct clk_init_data){
251 		.name = "disp_cc_mdss_pclk0_clk_src",
252 		.parent_data = disp_cc_parent_data_4,
253 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
254 		/* For set_rate and set_parent to succeed, parent(s) must be enabled */
255 		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE | CLK_GET_RATE_NOCACHE,
256 		.ops = &clk_pixel_ops,
257 	},
258 };
259 
260 static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
261 	F(19200000, P_BI_TCXO, 1, 0, 0),
262 	F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0),
263 	F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
264 	F(307200000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
265 	{ }
266 };
267 
268 static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
269 	.cmd_rcgr = 0x208c,
270 	.mnd_width = 0,
271 	.hid_width = 5,
272 	.parent_map = disp_cc_parent_map_3,
273 	.freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
274 	.clkr.hw.init = &(struct clk_init_data){
275 		.name = "disp_cc_mdss_rot_clk_src",
276 		.parent_data = disp_cc_parent_data_3,
277 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
278 		.flags = CLK_SET_RATE_PARENT,
279 		.ops = &clk_rcg2_shared_ops,
280 	},
281 };
282 
283 static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
284 	.cmd_rcgr = 0x20a4,
285 	.mnd_width = 0,
286 	.hid_width = 5,
287 	.parent_map = disp_cc_parent_map_1,
288 	.freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
289 	.clkr.hw.init = &(struct clk_init_data){
290 		.name = "disp_cc_mdss_vsync_clk_src",
291 		.parent_data = disp_cc_parent_data_1,
292 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
293 		.flags = CLK_SET_RATE_PARENT,
294 		.ops = &clk_rcg2_shared_ops,
295 	},
296 };
297 
298 static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = {
299 	F(32764, P_SLEEP_CLK, 1, 0, 0),
300 	{ }
301 };
302 
303 static struct clk_rcg2 disp_cc_sleep_clk_src = {
304 	.cmd_rcgr = 0x6050,
305 	.mnd_width = 0,
306 	.hid_width = 5,
307 	.parent_map = disp_cc_parent_map_5,
308 	.freq_tbl = ftbl_disp_cc_sleep_clk_src,
309 	.clkr.hw.init = &(struct clk_init_data){
310 		.name = "disp_cc_sleep_clk_src",
311 		.parent_data = disp_cc_parent_data_5,
312 		.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
313 		.ops = &clk_rcg2_ops,
314 	},
315 };
316 
317 static struct clk_branch disp_cc_mdss_ahb_clk = {
318 	.halt_reg = 0x2044,
319 	.halt_check = BRANCH_HALT,
320 	.clkr = {
321 		.enable_reg = 0x2044,
322 		.enable_mask = BIT(0),
323 		.hw.init = &(struct clk_init_data){
324 			.name = "disp_cc_mdss_ahb_clk",
325 			.parent_hws = (const struct clk_hw*[]){
326 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
327 			},
328 			.num_parents = 1,
329 			.flags = CLK_SET_RATE_PARENT,
330 			.ops = &clk_branch2_ops,
331 		},
332 	},
333 };
334 
335 static struct clk_branch disp_cc_mdss_byte0_clk = {
336 	.halt_reg = 0x2024,
337 	.halt_check = BRANCH_HALT,
338 	.clkr = {
339 		.enable_reg = 0x2024,
340 		.enable_mask = BIT(0),
341 		.hw.init = &(struct clk_init_data){
342 			.name = "disp_cc_mdss_byte0_clk",
343 			.parent_hws = (const struct clk_hw*[]){
344 				&disp_cc_mdss_byte0_clk_src.clkr.hw,
345 			},
346 			.num_parents = 1,
347 			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
348 			.ops = &clk_branch2_ops,
349 		},
350 	},
351 };
352 
353 static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
354 	.halt_reg = 0x2028,
355 	.halt_check = BRANCH_HALT,
356 	.clkr = {
357 		.enable_reg = 0x2028,
358 		.enable_mask = BIT(0),
359 		.hw.init = &(struct clk_init_data){
360 			.name = "disp_cc_mdss_byte0_intf_clk",
361 			.parent_hws = (const struct clk_hw*[]){
362 				&disp_cc_mdss_byte0_div_clk_src.clkr.hw,
363 			},
364 			.num_parents = 1,
365 			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
366 			.ops = &clk_branch2_ops,
367 		},
368 	},
369 };
370 
371 static struct clk_branch disp_cc_mdss_esc0_clk = {
372 	.halt_reg = 0x202c,
373 	.halt_check = BRANCH_HALT,
374 	.clkr = {
375 		.enable_reg = 0x202c,
376 		.enable_mask = BIT(0),
377 		.hw.init = &(struct clk_init_data){
378 			.name = "disp_cc_mdss_esc0_clk",
379 			.parent_hws = (const struct clk_hw*[]){
380 				&disp_cc_mdss_esc0_clk_src.clkr.hw,
381 			},
382 			.num_parents = 1,
383 			.flags = CLK_SET_RATE_PARENT,
384 			.ops = &clk_branch2_ops,
385 		},
386 	},
387 };
388 
389 static struct clk_branch disp_cc_mdss_mdp_clk = {
390 	.halt_reg = 0x2008,
391 	.halt_check = BRANCH_HALT,
392 	.clkr = {
393 		.enable_reg = 0x2008,
394 		.enable_mask = BIT(0),
395 		.hw.init = &(struct clk_init_data){
396 			.name = "disp_cc_mdss_mdp_clk",
397 			.parent_hws = (const struct clk_hw*[]){
398 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
399 			},
400 			.num_parents = 1,
401 			.flags = CLK_SET_RATE_PARENT,
402 			.ops = &clk_branch2_ops,
403 		},
404 	},
405 };
406 
407 static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
408 	.halt_reg = 0x2018,
409 	.halt_check = BRANCH_HALT_VOTED,
410 	.clkr = {
411 		.enable_reg = 0x2018,
412 		.enable_mask = BIT(0),
413 		.hw.init = &(struct clk_init_data){
414 			.name = "disp_cc_mdss_mdp_lut_clk",
415 			.parent_hws = (const struct clk_hw*[]){
416 				&disp_cc_mdss_mdp_clk_src.clkr.hw,
417 			},
418 			.num_parents = 1,
419 			.flags = CLK_SET_RATE_PARENT,
420 			.ops = &clk_branch2_ops,
421 		},
422 	},
423 };
424 
425 static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {
426 	.halt_reg = 0x4004,
427 	.halt_check = BRANCH_HALT_VOTED,
428 	.clkr = {
429 		.enable_reg = 0x4004,
430 		.enable_mask = BIT(0),
431 		.hw.init = &(struct clk_init_data){
432 			.name = "disp_cc_mdss_non_gdsc_ahb_clk",
433 			.parent_hws = (const struct clk_hw*[]){
434 				&disp_cc_mdss_ahb_clk_src.clkr.hw,
435 			},
436 			.num_parents = 1,
437 			.flags = CLK_SET_RATE_PARENT,
438 			.ops = &clk_branch2_ops,
439 		},
440 	},
441 };
442 
443 static struct clk_branch disp_cc_mdss_pclk0_clk = {
444 	.halt_reg = 0x2004,
445 	.halt_check = BRANCH_HALT,
446 	.clkr = {
447 		.enable_reg = 0x2004,
448 		.enable_mask = BIT(0),
449 		.hw.init = &(struct clk_init_data){
450 			.name = "disp_cc_mdss_pclk0_clk",
451 			.parent_hws = (const struct clk_hw*[]){
452 				&disp_cc_mdss_pclk0_clk_src.clkr.hw,
453 			},
454 			.num_parents = 1,
455 			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
456 			.ops = &clk_branch2_ops,
457 		},
458 	},
459 };
460 
461 static struct clk_branch disp_cc_mdss_rot_clk = {
462 	.halt_reg = 0x2010,
463 	.halt_check = BRANCH_HALT,
464 	.clkr = {
465 		.enable_reg = 0x2010,
466 		.enable_mask = BIT(0),
467 		.hw.init = &(struct clk_init_data){
468 			.name = "disp_cc_mdss_rot_clk",
469 			.parent_hws = (const struct clk_hw*[]) {
470 				&disp_cc_mdss_rot_clk_src.clkr.hw,
471 			},
472 			.num_parents = 1,
473 			.flags = CLK_SET_RATE_PARENT,
474 			.ops = &clk_branch2_ops,
475 		},
476 	},
477 };
478 
479 static struct clk_branch disp_cc_mdss_vsync_clk = {
480 	.halt_reg = 0x2020,
481 	.halt_check = BRANCH_HALT,
482 	.clkr = {
483 		.enable_reg = 0x2020,
484 		.enable_mask = BIT(0),
485 		.hw.init = &(struct clk_init_data){
486 			.name = "disp_cc_mdss_vsync_clk",
487 			.parent_hws = (const struct clk_hw*[]){
488 				&disp_cc_mdss_vsync_clk_src.clkr.hw,
489 			},
490 			.num_parents = 1,
491 			.flags = CLK_SET_RATE_PARENT,
492 			.ops = &clk_branch2_ops,
493 		},
494 	},
495 };
496 
497 static struct clk_branch disp_cc_sleep_clk = {
498 	.halt_reg = 0x6068,
499 	.halt_check = BRANCH_HALT,
500 	.clkr = {
501 		.enable_reg = 0x6068,
502 		.enable_mask = BIT(0),
503 		.hw.init = &(struct clk_init_data){
504 			.name = "disp_cc_sleep_clk",
505 			.parent_hws = (const struct clk_hw*[]){
506 				&disp_cc_sleep_clk_src.clkr.hw,
507 			},
508 			.num_parents = 1,
509 			.flags = CLK_SET_RATE_PARENT,
510 			.ops = &clk_branch2_ops,
511 		},
512 	},
513 };
514 
515 static struct gdsc mdss_gdsc = {
516 	.gdscr = 0x3000,
517 	.pd = {
518 		.name = "mdss_gdsc",
519 	},
520 	.pwrsts = PWRSTS_OFF_ON,
521 	.flags = HW_CTRL,
522 };
523 
524 static struct gdsc *disp_cc_sm6115_gdscs[] = {
525 	[MDSS_GDSC] = &mdss_gdsc,
526 };
527 
528 static struct clk_regmap *disp_cc_sm6115_clocks[] = {
529 	[DISP_CC_PLL0] = &disp_cc_pll0.clkr,
530 	[DISP_CC_PLL0_OUT_MAIN] = &disp_cc_pll0_out_main.clkr,
531 	[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
532 	[DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,
533 	[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
534 	[DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
535 	[DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,
536 	[DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
537 	[DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
538 	[DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
539 	[DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
540 	[DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
541 	[DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
542 	[DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
543 	[DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
544 	[DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
545 	[DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
546 	[DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
547 	[DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
548 	[DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
549 	[DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr,
550 	[DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr,
551 };
552 
553 static const struct regmap_config disp_cc_sm6115_regmap_config = {
554 	.reg_bits = 32,
555 	.reg_stride = 4,
556 	.val_bits = 32,
557 	.max_register = 0x10000,
558 	.fast_io = true,
559 };
560 
561 static const struct qcom_cc_desc disp_cc_sm6115_desc = {
562 	.config = &disp_cc_sm6115_regmap_config,
563 	.clks = disp_cc_sm6115_clocks,
564 	.num_clks = ARRAY_SIZE(disp_cc_sm6115_clocks),
565 	.gdscs = disp_cc_sm6115_gdscs,
566 	.num_gdscs = ARRAY_SIZE(disp_cc_sm6115_gdscs),
567 };
568 
569 static const struct of_device_id disp_cc_sm6115_match_table[] = {
570 	{ .compatible = "qcom,sm6115-dispcc" },
571 	{ }
572 };
573 MODULE_DEVICE_TABLE(of, disp_cc_sm6115_match_table);
574 
575 static int disp_cc_sm6115_probe(struct platform_device *pdev)
576 {
577 	struct regmap *regmap;
578 	int ret;
579 
580 	regmap = qcom_cc_map(pdev, &disp_cc_sm6115_desc);
581 	if (IS_ERR(regmap))
582 		return PTR_ERR(regmap);
583 
584 	clk_alpha_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
585 
586 	/* Keep DISP_CC_XO_CLK always-ON */
587 	regmap_update_bits(regmap, 0x604c, BIT(0), BIT(0));
588 
589 	ret = qcom_cc_really_probe(pdev, &disp_cc_sm6115_desc, regmap);
590 	if (ret) {
591 		dev_err(&pdev->dev, "Failed to register DISP CC clocks\n");
592 		return ret;
593 	}
594 
595 	return ret;
596 }
597 
598 static struct platform_driver disp_cc_sm6115_driver = {
599 	.probe = disp_cc_sm6115_probe,
600 	.driver = {
601 		.name = "dispcc-sm6115",
602 		.of_match_table = disp_cc_sm6115_match_table,
603 	},
604 };
605 
606 module_platform_driver(disp_cc_sm6115_driver);
607 MODULE_DESCRIPTION("Qualcomm SM6115 Display Clock controller");
608 MODULE_LICENSE("GPL");
609