aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaniya Das <tdas@codeaurora.org>2018-07-23 06:54:35 -0400
committerStephen Boyd <sboyd@kernel.org>2018-08-01 11:08:12 -0400
commit81351776c9fbbbd0de1dc1542f30aacfe68efc4e (patch)
treed5e3770cf5cac16fe10b8cd0ab64bc9e4a6fcc1b
parent6c79d12e945e85556674a04cde13657a5d7943da (diff)
clk: qcom: Add display clock controller driver for SDM845
Add support for the display clock controller found on SDM845 based devices. This would allow display drivers to probe and control their clocks. Signed-off-by: Taniya Das <tdas@codeaurora.org> [sboyd@kernel.org: Remove CLK_GET_RATE_NOCACHE everywhere] Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/qcom/Kconfig10
-rw-r--r--drivers/clk/qcom/Makefile1
-rw-r--r--drivers/clk/qcom/dispcc-sdm845.c685
3 files changed, 696 insertions, 0 deletions
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 9c3480dcc38a..730057471932 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -245,6 +245,16 @@ config SDM_VIDEOCC_845
245 Say Y if you want to support video devices and functionality such as 245 Say Y if you want to support video devices and functionality such as
246 video encode and decode. 246 video encode and decode.
247 247
248config SDM_DISPCC_845
249 tristate "SDM845 Display Clock Controller"
250 select SDM_GCC_845
251 depends on COMMON_CLK_QCOM
252 help
253 Support for the display clock controller on Qualcomm Technologies, Inc
254 SDM845 devices.
255 Say Y if you want to support display devices and functionality such as
256 splash screen.
257
248config SPMI_PMIC_CLKDIV 258config SPMI_PMIC_CLKDIV
249 tristate "SPMI PMIC clkdiv Support" 259 tristate "SPMI PMIC clkdiv Support"
250 depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST 260 depends on (COMMON_CLK_QCOM && SPMI) || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 762c01137c2f..2b041b2db30a 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o
38obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o 38obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o
39obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o 39obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
40obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o 40obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
41obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
41obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o 42obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
42obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o 43obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
43obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o 44obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
new file mode 100644
index 000000000000..0cc4909b5dbe
--- /dev/null
+++ b/drivers/clk/qcom/dispcc-sdm845.c
@@ -0,0 +1,685 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/clk-provider.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9#include <linux/regmap.h>
10#include <linux/reset-controller.h>
11
12#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
13
14#include "clk-alpha-pll.h"
15#include "clk-branch.h"
16#include "clk-rcg.h"
17#include "clk-regmap-divider.h"
18#include "common.h"
19#include "gdsc.h"
20#include "reset.h"
21
22enum {
23 P_BI_TCXO,
24 P_CORE_BI_PLL_TEST_SE,
25 P_DISP_CC_PLL0_OUT_MAIN,
26 P_DSI0_PHY_PLL_OUT_BYTECLK,
27 P_DSI0_PHY_PLL_OUT_DSICLK,
28 P_DSI1_PHY_PLL_OUT_BYTECLK,
29 P_DSI1_PHY_PLL_OUT_DSICLK,
30 P_GPLL0_OUT_MAIN,
31 P_GPLL0_OUT_MAIN_DIV,
32};
33
34static const struct parent_map disp_cc_parent_map_0[] = {
35 { P_BI_TCXO, 0 },
36 { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
37 { P_DSI1_PHY_PLL_OUT_BYTECLK, 2 },
38 { P_CORE_BI_PLL_TEST_SE, 7 },
39};
40
41static const char * const disp_cc_parent_names_0[] = {
42 "bi_tcxo",
43 "dsi0_phy_pll_out_byteclk",
44 "dsi1_phy_pll_out_byteclk",
45 "core_bi_pll_test_se",
46};
47
48static const struct parent_map disp_cc_parent_map_2[] = {
49 { P_BI_TCXO, 0 },
50 { P_CORE_BI_PLL_TEST_SE, 7 },
51};
52
53static const char * const disp_cc_parent_names_2[] = {
54 "bi_tcxo",
55 "core_bi_pll_test_se",
56};
57
58static const struct parent_map disp_cc_parent_map_3[] = {
59 { P_BI_TCXO, 0 },
60 { P_DISP_CC_PLL0_OUT_MAIN, 1 },
61 { P_GPLL0_OUT_MAIN, 4 },
62 { P_GPLL0_OUT_MAIN_DIV, 5 },
63 { P_CORE_BI_PLL_TEST_SE, 7 },
64};
65
66static const char * const disp_cc_parent_names_3[] = {
67 "bi_tcxo",
68 "disp_cc_pll0",
69 "gcc_disp_gpll0_clk_src",
70 "gcc_disp_gpll0_div_clk_src",
71 "core_bi_pll_test_se",
72};
73
74static const struct parent_map disp_cc_parent_map_4[] = {
75 { P_BI_TCXO, 0 },
76 { P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
77 { P_DSI1_PHY_PLL_OUT_DSICLK, 2 },
78 { P_CORE_BI_PLL_TEST_SE, 7 },
79};
80
81static const char * const disp_cc_parent_names_4[] = {
82 "bi_tcxo",
83 "dsi0_phy_pll_out_dsiclk",
84 "dsi1_phy_pll_out_dsiclk",
85 "core_bi_pll_test_se",
86};
87
88static struct clk_alpha_pll disp_cc_pll0 = {
89 .offset = 0x0,
90 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
91 .clkr = {
92 .hw.init = &(struct clk_init_data){
93 .name = "disp_cc_pll0",
94 .parent_names = (const char *[]){ "bi_tcxo" },
95 .num_parents = 1,
96 .ops = &clk_alpha_pll_fabia_ops,
97 },
98 },
99};
100
101/* Return the HW recalc rate for idle use case */
102static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
103 .cmd_rcgr = 0x20d0,
104 .mnd_width = 0,
105 .hid_width = 5,
106 .parent_map = disp_cc_parent_map_0,
107 .clkr.hw.init = &(struct clk_init_data){
108 .name = "disp_cc_mdss_byte0_clk_src",
109 .parent_names = disp_cc_parent_names_0,
110 .num_parents = 4,
111 .flags = CLK_SET_RATE_PARENT,
112 .ops = &clk_byte2_ops,
113 },
114};
115
116/* Return the HW recalc rate for idle use case */
117static struct clk_rcg2 disp_cc_mdss_byte1_clk_src = {
118 .cmd_rcgr = 0x20ec,
119 .mnd_width = 0,
120 .hid_width = 5,
121 .parent_map = disp_cc_parent_map_0,
122 .clkr.hw.init = &(struct clk_init_data){
123 .name = "disp_cc_mdss_byte1_clk_src",
124 .parent_names = disp_cc_parent_names_0,
125 .num_parents = 4,
126 .flags = CLK_SET_RATE_PARENT,
127 .ops = &clk_byte2_ops,
128 },
129};
130
131static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {
132 F(19200000, P_BI_TCXO, 1, 0, 0),
133 { }
134};
135
136static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
137 .cmd_rcgr = 0x2108,
138 .mnd_width = 0,
139 .hid_width = 5,
140 .parent_map = disp_cc_parent_map_0,
141 .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
142 .clkr.hw.init = &(struct clk_init_data){
143 .name = "disp_cc_mdss_esc0_clk_src",
144 .parent_names = disp_cc_parent_names_0,
145 .num_parents = 4,
146 .ops = &clk_rcg2_ops,
147 },
148};
149
150static struct clk_rcg2 disp_cc_mdss_esc1_clk_src = {
151 .cmd_rcgr = 0x2120,
152 .mnd_width = 0,
153 .hid_width = 5,
154 .parent_map = disp_cc_parent_map_0,
155 .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
156 .clkr.hw.init = &(struct clk_init_data){
157 .name = "disp_cc_mdss_esc1_clk_src",
158 .parent_names = disp_cc_parent_names_0,
159 .num_parents = 4,
160 .ops = &clk_rcg2_ops,
161 },
162};
163
164static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
165 F(19200000, P_BI_TCXO, 1, 0, 0),
166 F(85714286, P_GPLL0_OUT_MAIN, 7, 0, 0),
167 F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
168 F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
169 F(171428571, P_GPLL0_OUT_MAIN, 3.5, 0, 0),
170 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
171 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
172 F(344000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
173 F(430000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
174 { }
175};
176
177static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
178 .cmd_rcgr = 0x2088,
179 .mnd_width = 0,
180 .hid_width = 5,
181 .parent_map = disp_cc_parent_map_3,
182 .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
183 .clkr.hw.init = &(struct clk_init_data){
184 .name = "disp_cc_mdss_mdp_clk_src",
185 .parent_names = disp_cc_parent_names_3,
186 .num_parents = 5,
187 .ops = &clk_rcg2_shared_ops,
188 },
189};
190
191/* Return the HW recalc rate for idle use case */
192static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
193 .cmd_rcgr = 0x2058,
194 .mnd_width = 8,
195 .hid_width = 5,
196 .parent_map = disp_cc_parent_map_4,
197 .clkr.hw.init = &(struct clk_init_data){
198 .name = "disp_cc_mdss_pclk0_clk_src",
199 .parent_names = disp_cc_parent_names_4,
200 .num_parents = 4,
201 .flags = CLK_SET_RATE_PARENT,
202 .ops = &clk_pixel_ops,
203 },
204};
205
206/* Return the HW recalc rate for idle use case */
207static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src = {
208 .cmd_rcgr = 0x2070,
209 .mnd_width = 8,
210 .hid_width = 5,
211 .parent_map = disp_cc_parent_map_4,
212 .clkr.hw.init = &(struct clk_init_data){
213 .name = "disp_cc_mdss_pclk1_clk_src",
214 .parent_names = disp_cc_parent_names_4,
215 .num_parents = 4,
216 .flags = CLK_SET_RATE_PARENT,
217 .ops = &clk_pixel_ops,
218 },
219};
220
221static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
222 F(19200000, P_BI_TCXO, 1, 0, 0),
223 F(171428571, P_GPLL0_OUT_MAIN, 3.5, 0, 0),
224 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
225 F(344000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
226 F(430000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
227 { }
228};
229
230static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
231 .cmd_rcgr = 0x20a0,
232 .mnd_width = 0,
233 .hid_width = 5,
234 .parent_map = disp_cc_parent_map_3,
235 .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
236 .clkr.hw.init = &(struct clk_init_data){
237 .name = "disp_cc_mdss_rot_clk_src",
238 .parent_names = disp_cc_parent_names_3,
239 .num_parents = 5,
240 .ops = &clk_rcg2_shared_ops,
241 },
242};
243
244static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
245 .cmd_rcgr = 0x20b8,
246 .mnd_width = 0,
247 .hid_width = 5,
248 .parent_map = disp_cc_parent_map_2,
249 .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
250 .clkr.hw.init = &(struct clk_init_data){
251 .name = "disp_cc_mdss_vsync_clk_src",
252 .parent_names = disp_cc_parent_names_2,
253 .num_parents = 2,
254 .ops = &clk_rcg2_ops,
255 },
256};
257
258static struct clk_branch disp_cc_mdss_ahb_clk = {
259 .halt_reg = 0x4004,
260 .halt_check = BRANCH_HALT,
261 .clkr = {
262 .enable_reg = 0x4004,
263 .enable_mask = BIT(0),
264 .hw.init = &(struct clk_init_data){
265 .name = "disp_cc_mdss_ahb_clk",
266 .ops = &clk_branch2_ops,
267 },
268 },
269};
270
271static struct clk_branch disp_cc_mdss_axi_clk = {
272 .halt_reg = 0x4008,
273 .halt_check = BRANCH_HALT,
274 .clkr = {
275 .enable_reg = 0x4008,
276 .enable_mask = BIT(0),
277 .hw.init = &(struct clk_init_data){
278 .name = "disp_cc_mdss_axi_clk",
279 .ops = &clk_branch2_ops,
280 },
281 },
282};
283
284/* Return the HW recalc rate for idle use case */
285static struct clk_branch disp_cc_mdss_byte0_clk = {
286 .halt_reg = 0x2028,
287 .halt_check = BRANCH_HALT,
288 .clkr = {
289 .enable_reg = 0x2028,
290 .enable_mask = BIT(0),
291 .hw.init = &(struct clk_init_data){
292 .name = "disp_cc_mdss_byte0_clk",
293 .parent_names = (const char *[]){
294 "disp_cc_mdss_byte0_clk_src",
295 },
296 .num_parents = 1,
297 .flags = CLK_SET_RATE_PARENT,
298 .ops = &clk_branch2_ops,
299 },
300 },
301};
302
303/* Return the HW recalc rate for idle use case */
304static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
305 .reg = 0x20e8,
306 .shift = 0,
307 .width = 2,
308 .clkr = {
309 .hw.init = &(struct clk_init_data){
310 .name = "disp_cc_mdss_byte0_div_clk_src",
311 .parent_names = (const char *[]){
312 "disp_cc_mdss_byte0_clk_src",
313 },
314 .num_parents = 1,
315 .ops = &clk_regmap_div_ops,
316 },
317 },
318};
319
320/* Return the HW recalc rate for idle use case */
321static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
322 .halt_reg = 0x202c,
323 .halt_check = BRANCH_HALT,
324 .clkr = {
325 .enable_reg = 0x202c,
326 .enable_mask = BIT(0),
327 .hw.init = &(struct clk_init_data){
328 .name = "disp_cc_mdss_byte0_intf_clk",
329 .parent_names = (const char *[]){
330 "disp_cc_mdss_byte0_div_clk_src",
331 },
332 .num_parents = 1,
333 .flags = CLK_SET_RATE_PARENT,
334 .ops = &clk_branch2_ops,
335 },
336 },
337};
338
339/* Return the HW recalc rate for idle use case */
340static struct clk_branch disp_cc_mdss_byte1_clk = {
341 .halt_reg = 0x2030,
342 .halt_check = BRANCH_HALT,
343 .clkr = {
344 .enable_reg = 0x2030,
345 .enable_mask = BIT(0),
346 .hw.init = &(struct clk_init_data){
347 .name = "disp_cc_mdss_byte1_clk",
348 .parent_names = (const char *[]){
349 "disp_cc_mdss_byte1_clk_src",
350 },
351 .num_parents = 1,
352 .flags = CLK_SET_RATE_PARENT,
353 .ops = &clk_branch2_ops,
354 },
355 },
356};
357
358/* Return the HW recalc rate for idle use case */
359static struct clk_regmap_div disp_cc_mdss_byte1_div_clk_src = {
360 .reg = 0x2104,
361 .shift = 0,
362 .width = 2,
363 .clkr = {
364 .hw.init = &(struct clk_init_data){
365 .name = "disp_cc_mdss_byte1_div_clk_src",
366 .parent_names = (const char *[]){
367 "disp_cc_mdss_byte1_clk_src",
368 },
369 .num_parents = 1,
370 .ops = &clk_regmap_div_ops,
371 },
372 },
373};
374
375/* Return the HW recalc rate for idle use case */
376static struct clk_branch disp_cc_mdss_byte1_intf_clk = {
377 .halt_reg = 0x2034,
378 .halt_check = BRANCH_HALT,
379 .clkr = {
380 .enable_reg = 0x2034,
381 .enable_mask = BIT(0),
382 .hw.init = &(struct clk_init_data){
383 .name = "disp_cc_mdss_byte1_intf_clk",
384 .parent_names = (const char *[]){
385 "disp_cc_mdss_byte1_div_clk_src",
386 },
387 .num_parents = 1,
388 .flags = CLK_SET_RATE_PARENT,
389 .ops = &clk_branch2_ops,
390 },
391 },
392};
393
394static struct clk_branch disp_cc_mdss_esc0_clk = {
395 .halt_reg = 0x2038,
396 .halt_check = BRANCH_HALT,
397 .clkr = {
398 .enable_reg = 0x2038,
399 .enable_mask = BIT(0),
400 .hw.init = &(struct clk_init_data){
401 .name = "disp_cc_mdss_esc0_clk",
402 .parent_names = (const char *[]){
403 "disp_cc_mdss_esc0_clk_src",
404 },
405 .num_parents = 1,
406 .flags = CLK_SET_RATE_PARENT,
407 .ops = &clk_branch2_ops,
408 },
409 },
410};
411
412static struct clk_branch disp_cc_mdss_esc1_clk = {
413 .halt_reg = 0x203c,
414 .halt_check = BRANCH_HALT,
415 .clkr = {
416 .enable_reg = 0x203c,
417 .enable_mask = BIT(0),
418 .hw.init = &(struct clk_init_data){
419 .name = "disp_cc_mdss_esc1_clk",
420 .parent_names = (const char *[]){
421 "disp_cc_mdss_esc1_clk_src",
422 },
423 .num_parents = 1,
424 .flags = CLK_SET_RATE_PARENT,
425 .ops = &clk_branch2_ops,
426 },
427 },
428};
429
430static struct clk_branch disp_cc_mdss_mdp_clk = {
431 .halt_reg = 0x200c,
432 .halt_check = BRANCH_HALT,
433 .clkr = {
434 .enable_reg = 0x200c,
435 .enable_mask = BIT(0),
436 .hw.init = &(struct clk_init_data){
437 .name = "disp_cc_mdss_mdp_clk",
438 .parent_names = (const char *[]){
439 "disp_cc_mdss_mdp_clk_src",
440 },
441 .num_parents = 1,
442 .flags = CLK_SET_RATE_PARENT,
443 .ops = &clk_branch2_ops,
444 },
445 },
446};
447
448static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
449 .halt_reg = 0x201c,
450 .halt_check = BRANCH_HALT,
451 .clkr = {
452 .enable_reg = 0x201c,
453 .enable_mask = BIT(0),
454 .hw.init = &(struct clk_init_data){
455 .name = "disp_cc_mdss_mdp_lut_clk",
456 .parent_names = (const char *[]){
457 "disp_cc_mdss_mdp_clk_src",
458 },
459 .num_parents = 1,
460 .ops = &clk_branch2_ops,
461 },
462 },
463};
464
465/* Return the HW recalc rate for idle use case */
466static struct clk_branch disp_cc_mdss_pclk0_clk = {
467 .halt_reg = 0x2004,
468 .halt_check = BRANCH_HALT,
469 .clkr = {
470 .enable_reg = 0x2004,
471 .enable_mask = BIT(0),
472 .hw.init = &(struct clk_init_data){
473 .name = "disp_cc_mdss_pclk0_clk",
474 .parent_names = (const char *[]){
475 "disp_cc_mdss_pclk0_clk_src",
476 },
477 .num_parents = 1,
478 .flags = CLK_SET_RATE_PARENT,
479 .ops = &clk_branch2_ops,
480 },
481 },
482};
483
484/* Return the HW recalc rate for idle use case */
485static struct clk_branch disp_cc_mdss_pclk1_clk = {
486 .halt_reg = 0x2008,
487 .halt_check = BRANCH_HALT,
488 .clkr = {
489 .enable_reg = 0x2008,
490 .enable_mask = BIT(0),
491 .hw.init = &(struct clk_init_data){
492 .name = "disp_cc_mdss_pclk1_clk",
493 .parent_names = (const char *[]){
494 "disp_cc_mdss_pclk1_clk_src",
495 },
496 .num_parents = 1,
497 .flags = CLK_SET_RATE_PARENT,
498 .ops = &clk_branch2_ops,
499 },
500 },
501};
502
503static struct clk_branch disp_cc_mdss_rot_clk = {
504 .halt_reg = 0x2014,
505 .halt_check = BRANCH_HALT,
506 .clkr = {
507 .enable_reg = 0x2014,
508 .enable_mask = BIT(0),
509 .hw.init = &(struct clk_init_data){
510 .name = "disp_cc_mdss_rot_clk",
511 .parent_names = (const char *[]){
512 "disp_cc_mdss_rot_clk_src",
513 },
514 .num_parents = 1,
515 .flags = CLK_SET_RATE_PARENT,
516 .ops = &clk_branch2_ops,
517 },
518 },
519};
520
521static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {
522 .halt_reg = 0x5004,
523 .halt_check = BRANCH_HALT,
524 .clkr = {
525 .enable_reg = 0x5004,
526 .enable_mask = BIT(0),
527 .hw.init = &(struct clk_init_data){
528 .name = "disp_cc_mdss_rscc_ahb_clk",
529 .ops = &clk_branch2_ops,
530 },
531 },
532};
533
534static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {
535 .halt_reg = 0x5008,
536 .halt_check = BRANCH_HALT,
537 .clkr = {
538 .enable_reg = 0x5008,
539 .enable_mask = BIT(0),
540 .hw.init = &(struct clk_init_data){
541 .name = "disp_cc_mdss_rscc_vsync_clk",
542 .parent_names = (const char *[]){
543 "disp_cc_mdss_vsync_clk_src",
544 },
545 .num_parents = 1,
546 .flags = CLK_SET_RATE_PARENT,
547 .ops = &clk_branch2_ops,
548 },
549 },
550};
551
552static struct clk_branch disp_cc_mdss_vsync_clk = {
553 .halt_reg = 0x2024,
554 .halt_check = BRANCH_HALT,
555 .clkr = {
556 .enable_reg = 0x2024,
557 .enable_mask = BIT(0),
558 .hw.init = &(struct clk_init_data){
559 .name = "disp_cc_mdss_vsync_clk",
560 .parent_names = (const char *[]){
561 "disp_cc_mdss_vsync_clk_src",
562 },
563 .num_parents = 1,
564 .flags = CLK_SET_RATE_PARENT,
565 .ops = &clk_branch2_ops,
566 },
567 },
568};
569
570static struct gdsc mdss_gdsc = {
571 .gdscr = 0x3000,
572 .pd = {
573 .name = "mdss_gdsc",
574 },
575 .pwrsts = PWRSTS_OFF_ON,
576 .flags = HW_CTRL | POLL_CFG_GDSCR,
577};
578
579static struct clk_regmap *disp_cc_sdm845_clocks[] = {
580 [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
581 [DISP_CC_MDSS_AXI_CLK] = &disp_cc_mdss_axi_clk.clkr,
582 [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
583 [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
584 [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
585 [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] =
586 &disp_cc_mdss_byte0_div_clk_src.clkr,
587 [DISP_CC_MDSS_BYTE1_CLK] = &disp_cc_mdss_byte1_clk.clkr,
588 [DISP_CC_MDSS_BYTE1_CLK_SRC] = &disp_cc_mdss_byte1_clk_src.clkr,
589 [DISP_CC_MDSS_BYTE1_INTF_CLK] = &disp_cc_mdss_byte1_intf_clk.clkr,
590 [DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] =
591 &disp_cc_mdss_byte1_div_clk_src.clkr,
592 [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
593 [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
594 [DISP_CC_MDSS_ESC1_CLK] = &disp_cc_mdss_esc1_clk.clkr,
595 [DISP_CC_MDSS_ESC1_CLK_SRC] = &disp_cc_mdss_esc1_clk_src.clkr,
596 [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
597 [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
598 [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
599 [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
600 [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
601 [DISP_CC_MDSS_PCLK1_CLK] = &disp_cc_mdss_pclk1_clk.clkr,
602 [DISP_CC_MDSS_PCLK1_CLK_SRC] = &disp_cc_mdss_pclk1_clk_src.clkr,
603 [DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
604 [DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
605 [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,
606 [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,
607 [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
608 [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
609 [DISP_CC_PLL0] = &disp_cc_pll0.clkr,
610};
611
612static const struct qcom_reset_map disp_cc_sdm845_resets[] = {
613 [DISP_CC_MDSS_RSCC_BCR] = { 0x5000 },
614};
615
616static struct gdsc *disp_cc_sdm845_gdscs[] = {
617 [MDSS_GDSC] = &mdss_gdsc,
618};
619
620static const struct regmap_config disp_cc_sdm845_regmap_config = {
621 .reg_bits = 32,
622 .reg_stride = 4,
623 .val_bits = 32,
624 .max_register = 0x10000,
625 .fast_io = true,
626};
627
628static const struct qcom_cc_desc disp_cc_sdm845_desc = {
629 .config = &disp_cc_sdm845_regmap_config,
630 .clks = disp_cc_sdm845_clocks,
631 .num_clks = ARRAY_SIZE(disp_cc_sdm845_clocks),
632 .resets = disp_cc_sdm845_resets,
633 .num_resets = ARRAY_SIZE(disp_cc_sdm845_resets),
634 .gdscs = disp_cc_sdm845_gdscs,
635 .num_gdscs = ARRAY_SIZE(disp_cc_sdm845_gdscs),
636};
637
638static const struct of_device_id disp_cc_sdm845_match_table[] = {
639 { .compatible = "qcom,sdm845-dispcc" },
640 { }
641};
642MODULE_DEVICE_TABLE(of, disp_cc_sdm845_match_table);
643
644static int disp_cc_sdm845_probe(struct platform_device *pdev)
645{
646 struct regmap *regmap;
647 struct alpha_pll_config disp_cc_pll0_config = {};
648
649 regmap = qcom_cc_map(pdev, &disp_cc_sdm845_desc);
650 if (IS_ERR(regmap))
651 return PTR_ERR(regmap);
652
653 disp_cc_pll0_config.l = 0x2c;
654 disp_cc_pll0_config.alpha = 0xcaaa;
655
656 clk_fabia_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
657
658 /* Enable hardware clock gating for DSI and MDP clocks */
659 regmap_update_bits(regmap, 0x8000, 0x7f0, 0x7f0);
660
661 return qcom_cc_really_probe(pdev, &disp_cc_sdm845_desc, regmap);
662}
663
664static struct platform_driver disp_cc_sdm845_driver = {
665 .probe = disp_cc_sdm845_probe,
666 .driver = {
667 .name = "disp_cc-sdm845",
668 .of_match_table = disp_cc_sdm845_match_table,
669 },
670};
671
672static int __init disp_cc_sdm845_init(void)
673{
674 return platform_driver_register(&disp_cc_sdm845_driver);
675}
676subsys_initcall(disp_cc_sdm845_init);
677
678static void __exit disp_cc_sdm845_exit(void)
679{
680 platform_driver_unregister(&disp_cc_sdm845_driver);
681}
682module_exit(disp_cc_sdm845_exit);
683
684MODULE_LICENSE("GPL v2");
685MODULE_DESCRIPTION("QTI DISPCC SDM845 Driver");