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