Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: qcom: gpucc-qcs615: Add QCS615 graphics clock controller driver

Add support for the graphics clock controller for graphics clients to
be able to request for the clocks on QCS615 platform.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Taniya Das <quic_tdas@quicinc.com>
Link: https://lore.kernel.org/r/20250702-qcs615-mm-v10-clock-controllers-v11-7-9c216e1615ab@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Taniya Das and committed by
Bjorn Andersson
f4b5b408 3590dfbd

+540
+8
drivers/clk/qcom/Kconfig
··· 548 548 Say Y if you want to use multimedia devices or peripheral 549 549 devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc. 550 550 551 + config QCS_GPUCC_615 552 + tristate "QCS615 Graphics clock controller" 553 + select QCS_GCC_615 554 + help 555 + Support for the graphics clock controller on QCS615 devices. 556 + Say Y if you want to support graphics controller devices and 557 + functionality such as 3D graphics. 558 + 551 559 config SC_CAMCC_7180 552 560 tristate "SC7180 Camera Clock Controller" 553 561 depends on ARM64 || COMPILE_TEST
+1
drivers/clk/qcom/Makefile
··· 78 78 obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o 79 79 obj-$(CONFIG_QCS_GCC_615) += gcc-qcs615.o 80 80 obj-$(CONFIG_QCS_GCC_8300) += gcc-qcs8300.o 81 + obj-$(CONFIG_QCS_GPUCC_615) += gpucc-qcs615.o 81 82 obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o 82 83 obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o 83 84 obj-$(CONFIG_QDU_ECPRICC_1000) += ecpricc-qdu1000.o
+531
drivers/clk/qcom/gpucc-qcs615.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include <linux/clk-provider.h> 7 + #include <linux/module.h> 8 + #include <linux/mod_devicetable.h> 9 + #include <linux/of.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/regmap.h> 12 + 13 + #include <dt-bindings/clock/qcom,qcs615-gpucc.h> 14 + 15 + #include "clk-alpha-pll.h" 16 + #include "clk-branch.h" 17 + #include "clk-pll.h" 18 + #include "clk-rcg.h" 19 + #include "clk-regmap.h" 20 + #include "clk-regmap-divider.h" 21 + #include "clk-regmap-mux.h" 22 + #include "common.h" 23 + #include "gdsc.h" 24 + #include "reset.h" 25 + 26 + enum { 27 + DT_BI_TCXO, 28 + DT_GPLL0_OUT_MAIN, 29 + DT_GPLL0_OUT_MAIN_DIV, 30 + }; 31 + 32 + enum { 33 + P_BI_TCXO, 34 + P_GPLL0_OUT_MAIN, 35 + P_GPLL0_OUT_MAIN_DIV, 36 + P_GPU_CC_PLL0_2X_CLK, 37 + P_CRC_DIV_PLL0_OUT_AUX2, 38 + P_GPU_CC_PLL0_OUT_MAIN, 39 + P_GPU_CC_PLL1_OUT_AUX, 40 + P_CRC_DIV_PLL1_OUT_AUX2, 41 + P_GPU_CC_PLL1_OUT_MAIN, 42 + }; 43 + 44 + static const struct pll_vco gpu_cc_pll0_vco[] = { 45 + { 1000000000, 2100000000, 0 }, 46 + }; 47 + 48 + static struct pll_vco gpu_cc_pll1_vco[] = { 49 + { 500000000, 1000000000, 2 }, 50 + }; 51 + 52 + /* 1020MHz configuration VCO - 0 */ 53 + static struct alpha_pll_config gpu_cc_pll0_config = { 54 + .l = 0x35, 55 + .config_ctl_val = 0x4001055b, 56 + .test_ctl_hi_val = 0x1, 57 + .test_ctl_hi_mask = 0x1, 58 + .alpha_hi = 0x20, 59 + .alpha = 0x00, 60 + .alpha_en_mask = BIT(24), 61 + .vco_val = 0x0, 62 + .vco_mask = GENMASK(21, 20), 63 + .aux2_output_mask = BIT(2), 64 + }; 65 + 66 + static struct clk_alpha_pll gpu_cc_pll0 = { 67 + .offset = 0x0, 68 + .config = &gpu_cc_pll0_config, 69 + .vco_table = gpu_cc_pll0_vco, 70 + .num_vco = ARRAY_SIZE(gpu_cc_pll0_vco), 71 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 72 + .clkr = { 73 + .hw.init = &(const struct clk_init_data) { 74 + .name = "gpu_cc_pll0", 75 + .parent_data = &(const struct clk_parent_data) { 76 + .index = DT_BI_TCXO, 77 + }, 78 + .num_parents = 1, 79 + .ops = &clk_alpha_pll_slew_ops, 80 + }, 81 + }, 82 + }; 83 + 84 + /* 930MHz configuration VCO - 2 */ 85 + static struct alpha_pll_config gpu_cc_pll1_config = { 86 + .l = 0x30, 87 + .config_ctl_val = 0x4001055b, 88 + .test_ctl_hi_val = 0x1, 89 + .test_ctl_hi_mask = 0x1, 90 + .alpha_hi = 0x70, 91 + .alpha = 0x00, 92 + .alpha_en_mask = BIT(24), 93 + .vco_val = BIT(21), 94 + .vco_mask = GENMASK(21, 20), 95 + .aux2_output_mask = BIT(2), 96 + }; 97 + 98 + static struct clk_alpha_pll gpu_cc_pll1 = { 99 + .offset = 0x100, 100 + .config = &gpu_cc_pll1_config, 101 + .vco_table = gpu_cc_pll1_vco, 102 + .num_vco = ARRAY_SIZE(gpu_cc_pll1_vco), 103 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], 104 + .clkr = { 105 + .hw.init = &(const struct clk_init_data) { 106 + .name = "gpu_cc_pll1", 107 + .parent_data = &(const struct clk_parent_data) { 108 + .index = DT_BI_TCXO, 109 + }, 110 + .num_parents = 1, 111 + .ops = &clk_alpha_pll_slew_ops, 112 + }, 113 + } 114 + }; 115 + 116 + /* Clock Ramp Controller */ 117 + static struct clk_fixed_factor crc_div_pll0 = { 118 + .mult = 1, 119 + .div = 2, 120 + .hw.init = &(struct clk_init_data){ 121 + .name = "crc_div_pll0", 122 + .parent_data = &(const struct clk_parent_data){ 123 + .hw = &gpu_cc_pll0.clkr.hw, 124 + }, 125 + .num_parents = 1, 126 + .flags = CLK_SET_RATE_PARENT, 127 + .ops = &clk_fixed_factor_ops, 128 + }, 129 + }; 130 + 131 + /* Clock Ramp Controller */ 132 + static struct clk_fixed_factor crc_div_pll1 = { 133 + .mult = 1, 134 + .div = 2, 135 + .hw.init = &(struct clk_init_data){ 136 + .name = "crc_div_pll1", 137 + .parent_data = &(const struct clk_parent_data){ 138 + .hw = &gpu_cc_pll1.clkr.hw, 139 + }, 140 + .num_parents = 1, 141 + .flags = CLK_SET_RATE_PARENT, 142 + .ops = &clk_fixed_factor_ops, 143 + }, 144 + }; 145 + 146 + static const struct parent_map gpu_cc_parent_map_0[] = { 147 + { P_BI_TCXO, 0 }, 148 + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 149 + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 150 + { P_GPLL0_OUT_MAIN, 5 }, 151 + { P_GPLL0_OUT_MAIN_DIV, 6 }, 152 + }; 153 + 154 + static const struct clk_parent_data gpu_cc_parent_data_0[] = { 155 + { .index = DT_BI_TCXO }, 156 + { .hw = &gpu_cc_pll0.clkr.hw }, 157 + { .hw = &gpu_cc_pll1.clkr.hw }, 158 + { .index = DT_GPLL0_OUT_MAIN }, 159 + { .index = DT_GPLL0_OUT_MAIN_DIV }, 160 + }; 161 + 162 + static const struct parent_map gpu_cc_parent_map_1[] = { 163 + { P_BI_TCXO, 0 }, 164 + { P_GPU_CC_PLL0_2X_CLK, 1 }, 165 + { P_CRC_DIV_PLL0_OUT_AUX2, 2 }, 166 + { P_GPU_CC_PLL1_OUT_AUX, 3 }, 167 + { P_CRC_DIV_PLL1_OUT_AUX2, 4 }, 168 + { P_GPLL0_OUT_MAIN, 5 }, 169 + }; 170 + 171 + static const struct clk_parent_data gpu_cc_parent_data_1[] = { 172 + { .index = DT_BI_TCXO }, 173 + { .hw = &gpu_cc_pll0.clkr.hw }, 174 + { .hw = &crc_div_pll0.hw }, 175 + { .hw = &gpu_cc_pll1.clkr.hw }, 176 + { .hw = &crc_div_pll1.hw }, 177 + { .index = DT_GPLL0_OUT_MAIN }, 178 + }; 179 + 180 + static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 181 + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 182 + { } 183 + }; 184 + 185 + static struct clk_rcg2 gpu_cc_gmu_clk_src = { 186 + .cmd_rcgr = 0x1120, 187 + .mnd_width = 0, 188 + .hid_width = 5, 189 + .parent_map = gpu_cc_parent_map_0, 190 + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 191 + .clkr.hw.init = &(const struct clk_init_data) { 192 + .name = "gpu_cc_gmu_clk_src", 193 + .parent_data = gpu_cc_parent_data_0, 194 + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 195 + .ops = &clk_rcg2_shared_ops, 196 + }, 197 + }; 198 + 199 + static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { 200 + F(290000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0), 201 + F(350000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0), 202 + F(435000000, P_CRC_DIV_PLL1_OUT_AUX2, 1, 0, 0), 203 + F(500000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 204 + F(550000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 205 + F(650000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 206 + F(700000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 207 + F(745000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 208 + F(845000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 209 + F(895000000, P_CRC_DIV_PLL0_OUT_AUX2, 1, 0, 0), 210 + { } 211 + }; 212 + 213 + static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = { 214 + .cmd_rcgr = 0x101c, 215 + .mnd_width = 0, 216 + .hid_width = 5, 217 + .parent_map = gpu_cc_parent_map_1, 218 + .freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src, 219 + .clkr.hw.init = &(const struct clk_init_data) { 220 + .name = "gpu_cc_gx_gfx3d_clk_src", 221 + .parent_data = gpu_cc_parent_data_1, 222 + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 223 + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 224 + .ops = &clk_rcg2_shared_ops, 225 + }, 226 + }; 227 + 228 + static struct clk_branch gpu_cc_crc_ahb_clk = { 229 + .halt_reg = 0x107c, 230 + .halt_check = BRANCH_HALT_VOTED, 231 + .clkr = { 232 + .enable_reg = 0x107c, 233 + .enable_mask = BIT(0), 234 + .hw.init = &(const struct clk_init_data) { 235 + .name = "gpu_cc_crc_ahb_clk", 236 + .ops = &clk_branch2_ops, 237 + }, 238 + }, 239 + }; 240 + 241 + static struct clk_branch gpu_cc_cx_gfx3d_clk = { 242 + .halt_reg = 0x10a4, 243 + .halt_check = BRANCH_HALT_DELAY, 244 + .clkr = { 245 + .enable_reg = 0x10a4, 246 + .enable_mask = BIT(0), 247 + .hw.init = &(const struct clk_init_data) { 248 + .name = "gpu_cc_cx_gfx3d_clk", 249 + .parent_hws = (const struct clk_hw*[]) { 250 + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 251 + }, 252 + .num_parents = 1, 253 + .flags = CLK_SET_RATE_PARENT, 254 + .ops = &clk_branch2_ops, 255 + }, 256 + }, 257 + }; 258 + 259 + static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = { 260 + .halt_reg = 0x10a8, 261 + .halt_check = BRANCH_HALT_DELAY, 262 + .clkr = { 263 + .enable_reg = 0x10a8, 264 + .enable_mask = BIT(0), 265 + .hw.init = &(const struct clk_init_data) { 266 + .name = "gpu_cc_cx_gfx3d_slv_clk", 267 + .parent_hws = (const struct clk_hw*[]) { 268 + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 269 + }, 270 + .num_parents = 1, 271 + .flags = CLK_SET_RATE_PARENT, 272 + .ops = &clk_branch2_ops, 273 + }, 274 + }, 275 + }; 276 + 277 + static struct clk_branch gpu_cc_cx_gmu_clk = { 278 + .halt_reg = 0x1098, 279 + .halt_check = BRANCH_HALT, 280 + .clkr = { 281 + .enable_reg = 0x1098, 282 + .enable_mask = BIT(0), 283 + .hw.init = &(const struct clk_init_data) { 284 + .name = "gpu_cc_cx_gmu_clk", 285 + .parent_hws = (const struct clk_hw*[]) { 286 + &gpu_cc_gmu_clk_src.clkr.hw, 287 + }, 288 + .num_parents = 1, 289 + .flags = CLK_SET_RATE_PARENT, 290 + .ops = &clk_branch2_ops, 291 + }, 292 + }, 293 + }; 294 + 295 + static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 296 + .halt_reg = 0x108c, 297 + .halt_check = BRANCH_HALT_VOTED, 298 + .clkr = { 299 + .enable_reg = 0x108c, 300 + .enable_mask = BIT(0), 301 + .hw.init = &(const struct clk_init_data) { 302 + .name = "gpu_cc_cx_snoc_dvm_clk", 303 + .ops = &clk_branch2_ops, 304 + }, 305 + }, 306 + }; 307 + 308 + static struct clk_branch gpu_cc_cxo_aon_clk = { 309 + .halt_reg = 0x1004, 310 + .halt_check = BRANCH_HALT_VOTED, 311 + .clkr = { 312 + .enable_reg = 0x1004, 313 + .enable_mask = BIT(0), 314 + .hw.init = &(struct clk_init_data){ 315 + .name = "gpu_cc_cxo_aon_clk", 316 + .ops = &clk_branch2_ops, 317 + }, 318 + }, 319 + }; 320 + 321 + static struct clk_branch gpu_cc_cxo_clk = { 322 + .halt_reg = 0x109c, 323 + .halt_check = BRANCH_HALT, 324 + .clkr = { 325 + .enable_reg = 0x109c, 326 + .enable_mask = BIT(0), 327 + .hw.init = &(const struct clk_init_data) { 328 + .name = "gpu_cc_cxo_clk", 329 + .ops = &clk_branch2_ops, 330 + }, 331 + }, 332 + }; 333 + 334 + static struct clk_branch gpu_cc_gx_gfx3d_clk = { 335 + .halt_reg = 0x1054, 336 + .halt_check = BRANCH_HALT_SKIP, 337 + .clkr = { 338 + .enable_reg = 0x1054, 339 + .enable_mask = BIT(0), 340 + .hw.init = &(const struct clk_init_data) { 341 + .name = "gpu_cc_gx_gfx3d_clk", 342 + .parent_hws = (const struct clk_hw*[]) { 343 + &gpu_cc_gx_gfx3d_clk_src.clkr.hw, 344 + }, 345 + .num_parents = 1, 346 + .flags = CLK_SET_RATE_PARENT, 347 + .ops = &clk_branch2_ops, 348 + }, 349 + }, 350 + }; 351 + 352 + static struct clk_branch gpu_cc_gx_gmu_clk = { 353 + .halt_reg = 0x1064, 354 + .halt_check = BRANCH_HALT, 355 + .clkr = { 356 + .enable_reg = 0x1064, 357 + .enable_mask = BIT(0), 358 + .hw.init = &(const struct clk_init_data) { 359 + .name = "gpu_cc_gx_gmu_clk", 360 + .parent_hws = (const struct clk_hw*[]) { 361 + &gpu_cc_gmu_clk_src.clkr.hw, 362 + }, 363 + .num_parents = 1, 364 + .flags = CLK_SET_RATE_PARENT, 365 + .ops = &clk_branch2_ops, 366 + }, 367 + }, 368 + }; 369 + 370 + static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 371 + .halt_reg = 0x5000, 372 + .halt_check = BRANCH_VOTED, 373 + .clkr = { 374 + .enable_reg = 0x5000, 375 + .enable_mask = BIT(0), 376 + .hw.init = &(const struct clk_init_data) { 377 + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 378 + .ops = &clk_branch2_ops, 379 + }, 380 + }, 381 + }; 382 + 383 + static struct clk_branch gpu_cc_sleep_clk = { 384 + .halt_reg = 0x1090, 385 + .halt_check = BRANCH_HALT_VOTED, 386 + .clkr = { 387 + .enable_reg = 0x1090, 388 + .enable_mask = BIT(0), 389 + .hw.init = &(const struct clk_init_data) { 390 + .name = "gpu_cc_sleep_clk", 391 + .ops = &clk_branch2_ops, 392 + }, 393 + }, 394 + }; 395 + 396 + static struct clk_hw *gpu_cc_qcs615_hws[] = { 397 + [CRC_DIV_PLL0] = &crc_div_pll0.hw, 398 + [CRC_DIV_PLL1] = &crc_div_pll1.hw, 399 + }; 400 + 401 + static struct gdsc cx_gdsc = { 402 + .gdscr = 0x106c, 403 + .gds_hw_ctrl = 0x1540, 404 + .en_rest_wait_val = 0x2, 405 + .en_few_wait_val = 0x2, 406 + .clk_dis_wait_val = 0x8, 407 + .pd = { 408 + .name = "cx_gdsc", 409 + }, 410 + .pwrsts = PWRSTS_OFF_ON, 411 + .flags = POLL_CFG_GDSCR, 412 + }; 413 + 414 + static struct gdsc gx_gdsc = { 415 + .gdscr = 0x100c, 416 + .en_rest_wait_val = 0x2, 417 + .en_few_wait_val = 0x2, 418 + .clk_dis_wait_val = 0x2, 419 + .pd = { 420 + .name = "gx_gdsc", 421 + }, 422 + .pwrsts = PWRSTS_OFF_ON, 423 + .flags = POLL_CFG_GDSCR, 424 + }; 425 + 426 + static struct clk_regmap *gpu_cc_qcs615_clocks[] = { 427 + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 428 + [GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr, 429 + [GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr, 430 + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 431 + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 432 + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 433 + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 434 + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 435 + [GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr, 436 + [GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr, 437 + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 438 + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 439 + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 440 + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 441 + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, 442 + }; 443 + 444 + static struct gdsc *gpu_cc_qcs615_gdscs[] = { 445 + [CX_GDSC] = &cx_gdsc, 446 + [GX_GDSC] = &gx_gdsc, 447 + }; 448 + 449 + static const struct qcom_reset_map gpu_cc_qcs615_resets[] = { 450 + [GPU_CC_CX_BCR] = { 0x1068 }, 451 + [GPU_CC_GFX3D_AON_BCR] = { 0x10a0 }, 452 + [GPU_CC_GMU_BCR] = { 0x111c }, 453 + [GPU_CC_GX_BCR] = { 0x1008 }, 454 + [GPU_CC_XO_BCR] = { 0x1000 }, 455 + }; 456 + 457 + static struct clk_alpha_pll *gpu_cc_qcs615_plls[] = { 458 + &gpu_cc_pll0, 459 + &gpu_cc_pll1, 460 + }; 461 + 462 + static u32 gpu_cc_qcs615_critical_cbcrs[] = { 463 + 0x1078, /* GPU_CC_AHB_CLK */ 464 + }; 465 + 466 + static const struct regmap_config gpu_cc_qcs615_regmap_config = { 467 + .reg_bits = 32, 468 + .reg_stride = 4, 469 + .val_bits = 32, 470 + .max_register = 0x7008, 471 + .fast_io = true, 472 + }; 473 + 474 + static void clk_qcs615_regs_crc_configure(struct device *dev, struct regmap *regmap) 475 + { 476 + /* Recommended WAKEUP/SLEEP settings for the gpu_cc_cx_gmu_clk */ 477 + regmap_update_bits(regmap, gpu_cc_cx_gmu_clk.clkr.enable_reg, 0xff0, 0xff0); 478 + 479 + /* 480 + * After POR, Clock Ramp Controller(CRC) will be in bypass mode. 481 + * Software needs to do the following operation to enable the CRC 482 + * for GFX3D clock and divide the input clock by div by 2. 483 + */ 484 + regmap_update_bits(regmap, 0x1028, 0x00015011, 0x00015011); 485 + regmap_update_bits(regmap, 0x1024, 0x00800000, 0x00800000); 486 + } 487 + 488 + static struct qcom_cc_driver_data gpu_cc_qcs615_driver_data = { 489 + .alpha_plls = gpu_cc_qcs615_plls, 490 + .num_alpha_plls = ARRAY_SIZE(gpu_cc_qcs615_plls), 491 + .clk_cbcrs = gpu_cc_qcs615_critical_cbcrs, 492 + .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_qcs615_critical_cbcrs), 493 + .clk_regs_configure = clk_qcs615_regs_crc_configure, 494 + }; 495 + 496 + static const struct qcom_cc_desc gpu_cc_qcs615_desc = { 497 + .config = &gpu_cc_qcs615_regmap_config, 498 + .clks = gpu_cc_qcs615_clocks, 499 + .num_clks = ARRAY_SIZE(gpu_cc_qcs615_clocks), 500 + .clk_hws = gpu_cc_qcs615_hws, 501 + .num_clk_hws = ARRAY_SIZE(gpu_cc_qcs615_hws), 502 + .resets = gpu_cc_qcs615_resets, 503 + .num_resets = ARRAY_SIZE(gpu_cc_qcs615_resets), 504 + .gdscs = gpu_cc_qcs615_gdscs, 505 + .num_gdscs = ARRAY_SIZE(gpu_cc_qcs615_gdscs), 506 + .driver_data = &gpu_cc_qcs615_driver_data, 507 + }; 508 + 509 + static const struct of_device_id gpu_cc_qcs615_match_table[] = { 510 + { .compatible = "qcom,qcs615-gpucc" }, 511 + { } 512 + }; 513 + MODULE_DEVICE_TABLE(of, gpu_cc_qcs615_match_table); 514 + 515 + static int gpu_cc_qcs615_probe(struct platform_device *pdev) 516 + { 517 + return qcom_cc_probe(pdev, &gpu_cc_qcs615_desc); 518 + } 519 + 520 + static struct platform_driver gpu_cc_qcs615_driver = { 521 + .probe = gpu_cc_qcs615_probe, 522 + .driver = { 523 + .name = "gpucc-qcs615", 524 + .of_match_table = gpu_cc_qcs615_match_table, 525 + }, 526 + }; 527 + 528 + module_platform_driver(gpu_cc_qcs615_driver); 529 + 530 + MODULE_DESCRIPTION("QTI GPUCC QCS615 Driver"); 531 + MODULE_LICENSE("GPL");