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