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