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