601 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.4 * Copyright (c) 2022, Linaro Limited5 */6 7#include <linux/clk-provider.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/regmap.h>11 12#include <dt-bindings/clock/qcom,sm6375-dispcc.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 DT_BI_TCXO,24 DT_GCC_DISP_GPLL0_CLK,25 DT_DSI0_PHY_PLL_OUT_BYTECLK,26 DT_DSI0_PHY_PLL_OUT_DSICLK,27};28 29enum {30 P_BI_TCXO,31 P_DISP_CC_PLL0_OUT_EVEN,32 P_DISP_CC_PLL0_OUT_MAIN,33 P_DSI0_PHY_PLL_OUT_BYTECLK,34 P_DSI0_PHY_PLL_OUT_DSICLK,35 P_GCC_DISP_GPLL0_CLK,36};37 38static const struct pll_vco lucid_vco[] = {39 { 249600000, 2000000000, 0 },40};41 42/* 615MHz */43static const struct alpha_pll_config disp_cc_pll0_config = {44 .l = 0x20,45 .alpha = 0x800,46 .config_ctl_val = 0x20485699,47 .config_ctl_hi_val = 0x00002261,48 .config_ctl_hi1_val = 0x329a299c,49 .user_ctl_val = 0x00000001,50 .user_ctl_hi_val = 0x00000805,51 .user_ctl_hi1_val = 0x00000000,52};53 54static struct clk_alpha_pll disp_cc_pll0 = {55 .offset = 0x0,56 .vco_table = lucid_vco,57 .num_vco = ARRAY_SIZE(lucid_vco),58 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],59 .clkr = {60 .hw.init = &(struct clk_init_data){61 .name = "disp_cc_pll0",62 .parent_data = &(const struct clk_parent_data){63 .index = DT_BI_TCXO,64 },65 .num_parents = 1,66 .ops = &clk_alpha_pll_lucid_ops,67 },68 },69};70 71static const struct parent_map disp_cc_parent_map_0[] = {72 { P_BI_TCXO, 0 },73 { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },74};75 76static const struct clk_parent_data disp_cc_parent_data_0[] = {77 { .index = DT_BI_TCXO },78 { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },79};80 81static const struct parent_map disp_cc_parent_map_1[] = {82 { P_BI_TCXO, 0 },83 { P_DISP_CC_PLL0_OUT_MAIN, 1 },84 { P_GCC_DISP_GPLL0_CLK, 4 },85 { P_DISP_CC_PLL0_OUT_EVEN, 5 },86};87 88static const struct clk_parent_data disp_cc_parent_data_1[] = {89 { .index = DT_BI_TCXO },90 { .hw = &disp_cc_pll0.clkr.hw },91 { .index = DT_GCC_DISP_GPLL0_CLK },92 { .hw = &disp_cc_pll0.clkr.hw },93};94 95static const struct parent_map disp_cc_parent_map_2[] = {96 { P_BI_TCXO, 0 },97 { P_GCC_DISP_GPLL0_CLK, 4 },98};99 100static const struct clk_parent_data disp_cc_parent_data_2[] = {101 { .index = DT_BI_TCXO },102 { .index = DT_GCC_DISP_GPLL0_CLK },103};104 105static const struct parent_map disp_cc_parent_map_3[] = {106 { P_BI_TCXO, 0 },107 { P_DSI0_PHY_PLL_OUT_DSICLK, 1 },108};109 110static const struct clk_parent_data disp_cc_parent_data_3[] = {111 { .index = DT_BI_TCXO },112 { .index = DT_DSI0_PHY_PLL_OUT_DSICLK },113};114 115static const struct parent_map disp_cc_parent_map_4[] = {116 { P_BI_TCXO, 0 },117};118 119static const struct clk_parent_data disp_cc_parent_data_4[] = {120 { .index = DT_BI_TCXO },121};122 123static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {124 F(19200000, P_BI_TCXO, 1, 0, 0),125 F(37500000, P_GCC_DISP_GPLL0_CLK, 8, 0, 0),126 F(75000000, P_GCC_DISP_GPLL0_CLK, 4, 0, 0),127 { }128};129 130static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {131 .cmd_rcgr = 0x115c,132 .mnd_width = 0,133 .hid_width = 5,134 .parent_map = disp_cc_parent_map_2,135 .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,136 .clkr.hw.init = &(struct clk_init_data){137 .name = "disp_cc_mdss_ahb_clk_src",138 .parent_data = disp_cc_parent_data_2,139 .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),140 .ops = &clk_rcg2_shared_ops,141 },142};143 144static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {145 .cmd_rcgr = 0x10c4,146 .mnd_width = 0,147 .hid_width = 5,148 .parent_map = disp_cc_parent_map_0,149 .clkr.hw.init = &(struct clk_init_data){150 .name = "disp_cc_mdss_byte0_clk_src",151 .parent_data = disp_cc_parent_data_0,152 .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),153 .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,154 .ops = &clk_byte2_ops,155 },156};157 158static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {159 F(19200000, P_BI_TCXO, 1, 0, 0),160 { }161};162 163static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {164 .cmd_rcgr = 0x10e0,165 .mnd_width = 0,166 .hid_width = 5,167 .parent_map = disp_cc_parent_map_0,168 .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,169 .clkr.hw.init = &(struct clk_init_data){170 .name = "disp_cc_mdss_esc0_clk_src",171 .parent_data = disp_cc_parent_data_0,172 .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),173 .ops = &clk_rcg2_shared_ops,174 },175};176 177static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {178 F(200000000, P_GCC_DISP_GPLL0_CLK, 1.5, 0, 0),179 F(300000000, P_GCC_DISP_GPLL0_CLK, 1, 0, 0),180 F(373500000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),181 F(470000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),182 F(560000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),183 { }184};185 186static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {187 .cmd_rcgr = 0x107c,188 .mnd_width = 0,189 .hid_width = 5,190 .parent_map = disp_cc_parent_map_1,191 .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,192 .clkr.hw.init = &(struct clk_init_data){193 .name = "disp_cc_mdss_mdp_clk_src",194 .parent_data = disp_cc_parent_data_1,195 .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),196 .flags = CLK_SET_RATE_PARENT,197 .ops = &clk_rcg2_shared_ops,198 },199};200 201static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {202 .cmd_rcgr = 0x1064,203 .mnd_width = 8,204 .hid_width = 5,205 .parent_map = disp_cc_parent_map_3,206 .clkr.hw.init = &(struct clk_init_data){207 .name = "disp_cc_mdss_pclk0_clk_src",208 .parent_data = disp_cc_parent_data_3,209 .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),210 .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,211 .ops = &clk_pixel_ops,212 },213};214 215static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {216 F(200000000, P_GCC_DISP_GPLL0_CLK, 1.5, 0, 0),217 F(300000000, P_GCC_DISP_GPLL0_CLK, 1, 0, 0),218 { }219};220 221static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {222 .cmd_rcgr = 0x1094,223 .mnd_width = 0,224 .hid_width = 5,225 .parent_map = disp_cc_parent_map_1,226 .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,227 .clkr.hw.init = &(struct clk_init_data){228 .name = "disp_cc_mdss_rot_clk_src",229 .parent_data = disp_cc_parent_data_1,230 .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),231 .ops = &clk_rcg2_shared_ops,232 },233};234 235static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {236 .cmd_rcgr = 0x10ac,237 .mnd_width = 0,238 .hid_width = 5,239 .parent_map = disp_cc_parent_map_4,240 .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,241 .clkr.hw.init = &(struct clk_init_data){242 .name = "disp_cc_mdss_vsync_clk_src",243 .parent_data = disp_cc_parent_data_4,244 .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),245 .ops = &clk_rcg2_ops,246 },247};248 249static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {250 .reg = 0x10dc,251 .shift = 0,252 .width = 4,253 .clkr.hw.init = &(struct clk_init_data) {254 .name = "disp_cc_mdss_byte0_div_clk_src",255 .parent_hws = (const struct clk_hw*[]) {256 &disp_cc_mdss_byte0_clk_src.clkr.hw,257 },258 .num_parents = 1,259 .ops = &clk_regmap_div_ops,260 },261};262 263static struct clk_branch disp_cc_mdss_ahb_clk = {264 .halt_reg = 0x104c,265 .halt_check = BRANCH_HALT,266 .clkr = {267 .enable_reg = 0x104c,268 .enable_mask = BIT(0),269 .hw.init = &(struct clk_init_data){270 .name = "disp_cc_mdss_ahb_clk",271 .parent_hws = (const struct clk_hw*[]){272 &disp_cc_mdss_ahb_clk_src.clkr.hw,273 },274 .num_parents = 1,275 .flags = CLK_SET_RATE_PARENT,276 .ops = &clk_branch2_ops,277 },278 },279};280 281static struct clk_branch disp_cc_mdss_byte0_clk = {282 .halt_reg = 0x102c,283 .halt_check = BRANCH_HALT,284 .clkr = {285 .enable_reg = 0x102c,286 .enable_mask = BIT(0),287 .hw.init = &(struct clk_init_data){288 .name = "disp_cc_mdss_byte0_clk",289 .parent_hws = (const struct clk_hw*[]){290 &disp_cc_mdss_byte0_clk_src.clkr.hw,291 },292 .num_parents = 1,293 .flags = CLK_SET_RATE_PARENT,294 .ops = &clk_branch2_ops,295 },296 },297};298 299static struct clk_branch disp_cc_mdss_byte0_intf_clk = {300 .halt_reg = 0x1030,301 .halt_check = BRANCH_HALT,302 .clkr = {303 .enable_reg = 0x1030,304 .enable_mask = BIT(0),305 .hw.init = &(struct clk_init_data){306 .name = "disp_cc_mdss_byte0_intf_clk",307 .parent_hws = (const struct clk_hw*[]){308 &disp_cc_mdss_byte0_div_clk_src.clkr.hw,309 },310 .num_parents = 1,311 .flags = CLK_SET_RATE_PARENT,312 .ops = &clk_branch2_ops,313 },314 },315};316 317static struct clk_branch disp_cc_mdss_esc0_clk = {318 .halt_reg = 0x1034,319 .halt_check = BRANCH_HALT,320 .clkr = {321 .enable_reg = 0x1034,322 .enable_mask = BIT(0),323 .hw.init = &(struct clk_init_data){324 .name = "disp_cc_mdss_esc0_clk",325 .parent_hws = (const struct clk_hw*[]){326 &disp_cc_mdss_esc0_clk_src.clkr.hw,327 },328 .num_parents = 1,329 .flags = CLK_SET_RATE_PARENT,330 .ops = &clk_branch2_ops,331 },332 },333};334 335static struct clk_branch disp_cc_mdss_mdp_clk = {336 .halt_reg = 0x1010,337 .halt_check = BRANCH_HALT,338 .clkr = {339 .enable_reg = 0x1010,340 .enable_mask = BIT(0),341 .hw.init = &(struct clk_init_data){342 .name = "disp_cc_mdss_mdp_clk",343 .parent_hws = (const struct clk_hw*[]){344 &disp_cc_mdss_mdp_clk_src.clkr.hw,345 },346 .num_parents = 1,347 .flags = CLK_SET_RATE_PARENT,348 .ops = &clk_branch2_ops,349 },350 },351};352 353static struct clk_branch disp_cc_mdss_mdp_lut_clk = {354 .halt_reg = 0x1020,355 .halt_check = BRANCH_HALT_VOTED,356 .clkr = {357 .enable_reg = 0x1020,358 .enable_mask = BIT(0),359 .hw.init = &(struct clk_init_data){360 .name = "disp_cc_mdss_mdp_lut_clk",361 .parent_hws = (const struct clk_hw*[]){362 &disp_cc_mdss_mdp_clk_src.clkr.hw,363 },364 .num_parents = 1,365 .flags = CLK_SET_RATE_PARENT,366 .ops = &clk_branch2_ops,367 },368 },369};370 371static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {372 .halt_reg = 0x2004,373 .halt_check = BRANCH_HALT_VOTED,374 .clkr = {375 .enable_reg = 0x2004,376 .enable_mask = BIT(0),377 .hw.init = &(struct clk_init_data){378 .name = "disp_cc_mdss_non_gdsc_ahb_clk",379 .parent_hws = (const struct clk_hw*[]){380 &disp_cc_mdss_ahb_clk_src.clkr.hw,381 },382 .num_parents = 1,383 .flags = CLK_SET_RATE_PARENT,384 .ops = &clk_branch2_ops,385 },386 },387};388 389static struct clk_branch disp_cc_mdss_pclk0_clk = {390 .halt_reg = 0x1168,391 .halt_check = BRANCH_HALT,392 .clkr = {393 .enable_reg = 0x1168,394 .enable_mask = BIT(0),395 .hw.init = &(struct clk_init_data){396 .name = "disp_cc_mdss_pclk0_clk",397 .parent_hws = (const struct clk_hw*[]){398 &disp_cc_mdss_pclk0_clk_src.clkr.hw,399 },400 .num_parents = 1,401 .flags = CLK_SET_RATE_PARENT,402 .ops = &clk_branch2_ops,403 },404 },405};406 407static struct clk_branch disp_cc_mdss_rot_clk = {408 .halt_reg = 0x1018,409 .halt_check = BRANCH_HALT,410 .clkr = {411 .enable_reg = 0x1018,412 .enable_mask = BIT(0),413 .hw.init = &(struct clk_init_data){414 .name = "disp_cc_mdss_rot_clk",415 .parent_hws = (const struct clk_hw*[]){416 &disp_cc_mdss_rot_clk_src.clkr.hw,417 },418 .num_parents = 1,419 .flags = CLK_SET_RATE_PARENT,420 .ops = &clk_branch2_ops,421 },422 },423};424 425static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {426 .halt_reg = 0x200c,427 .halt_check = BRANCH_HALT,428 .clkr = {429 .enable_reg = 0x200c,430 .enable_mask = BIT(0),431 .hw.init = &(struct clk_init_data){432 .name = "disp_cc_mdss_rscc_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 443static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {444 .halt_reg = 0x2008,445 .halt_check = BRANCH_HALT,446 .clkr = {447 .enable_reg = 0x2008,448 .enable_mask = BIT(0),449 .hw.init = &(struct clk_init_data){450 .name = "disp_cc_mdss_rscc_vsync_clk",451 .parent_hws = (const struct clk_hw*[]){452 &disp_cc_mdss_vsync_clk_src.clkr.hw,453 },454 .num_parents = 1,455 .flags = CLK_SET_RATE_PARENT,456 .ops = &clk_branch2_ops,457 },458 },459};460 461static struct clk_branch disp_cc_mdss_vsync_clk = {462 .halt_reg = 0x1028,463 .halt_check = BRANCH_HALT,464 .clkr = {465 .enable_reg = 0x1028,466 .enable_mask = BIT(0),467 .hw.init = &(struct clk_init_data){468 .name = "disp_cc_mdss_vsync_clk",469 .parent_hws = (const struct clk_hw*[]){470 &disp_cc_mdss_vsync_clk_src.clkr.hw,471 },472 .num_parents = 1,473 .flags = CLK_SET_RATE_PARENT,474 .ops = &clk_branch2_ops,475 },476 },477};478 479static struct clk_branch disp_cc_sleep_clk = {480 .halt_check = BRANCH_HALT,481 .clkr = {482 .enable_reg = 0x5004,483 .enable_mask = BIT(0),484 .hw.init = &(struct clk_init_data){485 .name = "disp_cc_sleep_clk",486 .flags = CLK_IS_CRITICAL,487 .ops = &clk_branch2_ops,488 },489 },490};491 492static struct clk_branch disp_cc_xo_clk = {493 .halt_check = BRANCH_HALT,494 .clkr = {495 .enable_reg = 0x5008,496 .enable_mask = BIT(0),497 .hw.init = &(struct clk_init_data){498 .name = "disp_cc_xo_clk",499 .flags = CLK_IS_CRITICAL,500 .ops = &clk_branch2_ops,501 },502 },503};504 505static struct gdsc mdss_gdsc = {506 .gdscr = 0x1004,507 .en_rest_wait_val = 0x2,508 .en_few_wait_val = 0x2,509 .clk_dis_wait_val = 0xf,510 .pd = {511 .name = "mdss_gdsc",512 },513 .pwrsts = PWRSTS_OFF_ON,514 .flags = HW_CTRL,515};516 517static struct clk_regmap *disp_cc_sm6375_clocks[] = {518 [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,519 [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,520 [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,521 [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,522 [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,523 [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,524 [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,525 [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,526 [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,527 [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,528 [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,529 [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,530 [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,531 [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,532 [DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,533 [DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,534 [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,535 [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,536 [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,537 [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,538 [DISP_CC_PLL0] = &disp_cc_pll0.clkr,539 [DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr,540 [DISP_CC_XO_CLK] = &disp_cc_xo_clk.clkr,541};542 543static const struct qcom_reset_map disp_cc_sm6375_resets[] = {544 [DISP_CC_MDSS_CORE_BCR] = { 0x1000 },545 [DISP_CC_MDSS_RSCC_BCR] = { 0x2000 },546};547 548static struct gdsc *disp_cc_sm6375_gdscs[] = {549 [MDSS_GDSC] = &mdss_gdsc,550};551 552static const struct regmap_config disp_cc_sm6375_regmap_config = {553 .reg_bits = 32,554 .reg_stride = 4,555 .val_bits = 32,556 .max_register = 0x10000,557 .fast_io = true,558};559 560static const struct qcom_cc_desc disp_cc_sm6375_desc = {561 .config = &disp_cc_sm6375_regmap_config,562 .clks = disp_cc_sm6375_clocks,563 .num_clks = ARRAY_SIZE(disp_cc_sm6375_clocks),564 .resets = disp_cc_sm6375_resets,565 .num_resets = ARRAY_SIZE(disp_cc_sm6375_resets),566 .gdscs = disp_cc_sm6375_gdscs,567 .num_gdscs = ARRAY_SIZE(disp_cc_sm6375_gdscs),568};569 570static const struct of_device_id disp_cc_sm6375_match_table[] = {571 { .compatible = "qcom,sm6375-dispcc" },572 { }573};574MODULE_DEVICE_TABLE(of, disp_cc_sm6375_match_table);575 576static int disp_cc_sm6375_probe(struct platform_device *pdev)577{578 struct regmap *regmap;579 580 regmap = qcom_cc_map(pdev, &disp_cc_sm6375_desc);581 if (IS_ERR(regmap))582 return PTR_ERR(regmap);583 584 clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);585 586 return qcom_cc_really_probe(&pdev->dev, &disp_cc_sm6375_desc, regmap);587}588 589static struct platform_driver disp_cc_sm6375_driver = {590 .probe = disp_cc_sm6375_probe,591 .driver = {592 .name = "disp_cc-sm6375",593 .of_match_table = disp_cc_sm6375_match_table,594 },595};596 597module_platform_driver(disp_cc_sm6375_driver);598 599MODULE_DESCRIPTION("QTI DISPCC SM6375 Driver");600MODULE_LICENSE("GPL");601