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