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

Configure Feed

Select the types of activity you want to include in your feed.

clk: qcom: Add SC8280XP GPU clock controller

Add driver for the GPU clock controller in the Qualcomm SC8280XP
platform.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@somainline.org>
[bjorn: Included kernel.h and lower-cased hex numbers]
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20220926173025.4747-3-quic_bjorande@quicinc.com

authored by

Bjorn Andersson and committed by
Bjorn Andersson
e55d937d 9f60eb3e

+470
+8
drivers/clk/qcom/Kconfig
··· 453 453 Say Y if you want to support graphics controller devices and 454 454 functionality such as 3D graphics. 455 455 456 + config SC_GPUCC_8280XP 457 + tristate "SC8280XP Graphics Clock Controller" 458 + select SC_GCC_8280XP 459 + help 460 + Support for the graphics clock controller on SC8280XP devices. 461 + Say Y if you want to support graphics controller devices and 462 + functionality such as 3D graphics. 463 + 456 464 config SC_LPASSCC_7280 457 465 tristate "SC7280 Low Power Audio Subsystem (LPASS) Clock Controller" 458 466 select SC_GCC_7280
+1
drivers/clk/qcom/Makefile
··· 72 72 obj-$(CONFIG_SC_GCC_8280XP) += gcc-sc8280xp.o 73 73 obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o 74 74 obj-$(CONFIG_SC_GPUCC_7280) += gpucc-sc7280.o 75 + obj-$(CONFIG_SC_GPUCC_8280XP) += gpucc-sc8280xp.o 75 76 obj-$(CONFIG_SC_LPASSCC_7280) += lpasscc-sc7280.o 76 77 obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o 77 78 obj-$(CONFIG_SC_LPASS_CORECC_7280) += lpasscorecc-sc7280.o lpassaudiocc-sc7280.o
+461
drivers/clk/qcom/gpucc-sc8280xp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #include <linux/clk-provider.h> 7 + #include <linux/kernel.h> 8 + #include <linux/module.h> 9 + #include <linux/platform_device.h> 10 + #include <linux/regmap.h> 11 + 12 + #include <dt-bindings/clock/qcom,gpucc-sc8280xp.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 "reset.h" 20 + #include "gdsc.h" 21 + 22 + /* Need to match the order of clocks in DT binding */ 23 + enum { 24 + DT_BI_TCXO, 25 + DT_GCC_GPU_GPLL0_CLK_SRC, 26 + DT_GCC_GPU_GPLL0_DIV_CLK_SRC, 27 + }; 28 + 29 + enum { 30 + P_BI_TCXO, 31 + P_GCC_GPU_GPLL0_CLK_SRC, 32 + P_GCC_GPU_GPLL0_DIV_CLK_SRC, 33 + P_GPU_CC_PLL0_OUT_MAIN, 34 + P_GPU_CC_PLL1_OUT_MAIN, 35 + }; 36 + 37 + static const struct clk_parent_data parent_data_tcxo = { .index = DT_BI_TCXO }; 38 + 39 + static const struct pll_vco lucid_5lpe_vco[] = { 40 + { 249600000, 1800000000, 0 }, 41 + }; 42 + 43 + static struct alpha_pll_config gpu_cc_pll0_config = { 44 + .l = 0x1c, 45 + .alpha = 0xa555, 46 + .config_ctl_val = 0x20485699, 47 + .config_ctl_hi_val = 0x00002261, 48 + .config_ctl_hi1_val = 0x2a9a699c, 49 + .test_ctl_val = 0x00000000, 50 + .test_ctl_hi_val = 0x00000000, 51 + .test_ctl_hi1_val = 0x01800000, 52 + .user_ctl_val = 0x00000000, 53 + .user_ctl_hi_val = 0x00000805, 54 + .user_ctl_hi1_val = 0x00000000, 55 + }; 56 + 57 + static struct clk_alpha_pll gpu_cc_pll0 = { 58 + .offset = 0x0, 59 + .vco_table = lucid_5lpe_vco, 60 + .num_vco = ARRAY_SIZE(lucid_5lpe_vco), 61 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 62 + .clkr = { 63 + .hw.init = &(const struct clk_init_data){ 64 + .name = "gpu_cc_pll0", 65 + .parent_data = &parent_data_tcxo, 66 + .num_parents = 1, 67 + .ops = &clk_alpha_pll_lucid_5lpe_ops, 68 + }, 69 + }, 70 + }; 71 + 72 + static struct alpha_pll_config gpu_cc_pll1_config = { 73 + .l = 0x1A, 74 + .alpha = 0xaaa, 75 + .config_ctl_val = 0x20485699, 76 + .config_ctl_hi_val = 0x00002261, 77 + .config_ctl_hi1_val = 0x2a9a699c, 78 + .test_ctl_val = 0x00000000, 79 + .test_ctl_hi_val = 0x00000000, 80 + .test_ctl_hi1_val = 0x01800000, 81 + .user_ctl_val = 0x00000000, 82 + .user_ctl_hi_val = 0x00000805, 83 + .user_ctl_hi1_val = 0x00000000, 84 + }; 85 + 86 + static struct clk_alpha_pll gpu_cc_pll1 = { 87 + .offset = 0x100, 88 + .vco_table = lucid_5lpe_vco, 89 + .num_vco = ARRAY_SIZE(lucid_5lpe_vco), 90 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 91 + .clkr = { 92 + .hw.init = &(const struct clk_init_data){ 93 + .name = "gpu_cc_pll1", 94 + .parent_data = &parent_data_tcxo, 95 + .num_parents = 1, 96 + .ops = &clk_alpha_pll_lucid_5lpe_ops, 97 + }, 98 + }, 99 + }; 100 + 101 + static const struct parent_map gpu_cc_parent_map_0[] = { 102 + { P_BI_TCXO, 0 }, 103 + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 104 + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 105 + { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 106 + { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 107 + }; 108 + 109 + static const struct clk_parent_data gpu_cc_parent_data_0[] = { 110 + { .index = DT_BI_TCXO }, 111 + { .hw = &gpu_cc_pll0.clkr.hw }, 112 + { .hw = &gpu_cc_pll1.clkr.hw }, 113 + { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 114 + { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 115 + }; 116 + 117 + static const struct parent_map gpu_cc_parent_map_1[] = { 118 + { P_BI_TCXO, 0 }, 119 + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 120 + { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 121 + { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 122 + }; 123 + 124 + static const struct clk_parent_data gpu_cc_parent_data_1[] = { 125 + { .index = DT_BI_TCXO }, 126 + { .hw = &gpu_cc_pll1.clkr.hw }, 127 + { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 128 + { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 129 + }; 130 + 131 + static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 132 + F(19200000, P_BI_TCXO, 1, 0, 0), 133 + F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0), 134 + F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), 135 + { } 136 + }; 137 + 138 + static struct clk_rcg2 gpu_cc_gmu_clk_src = { 139 + .cmd_rcgr = 0x1120, 140 + .mnd_width = 0, 141 + .hid_width = 5, 142 + .parent_map = gpu_cc_parent_map_0, 143 + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 144 + .clkr.hw.init = &(const struct clk_init_data){ 145 + .name = "gpu_cc_gmu_clk_src", 146 + .parent_data = gpu_cc_parent_data_0, 147 + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 148 + .ops = &clk_rcg2_shared_ops, 149 + }, 150 + }; 151 + 152 + static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { 153 + F(200000000, P_GCC_GPU_GPLL0_CLK_SRC, 3, 0, 0), 154 + F(300000000, P_GCC_GPU_GPLL0_CLK_SRC, 2, 0, 0), 155 + F(400000000, P_GCC_GPU_GPLL0_CLK_SRC, 1.5, 0, 0), 156 + { } 157 + }; 158 + 159 + static struct clk_rcg2 gpu_cc_hub_clk_src = { 160 + .cmd_rcgr = 0x117c, 161 + .mnd_width = 0, 162 + .hid_width = 5, 163 + .parent_map = gpu_cc_parent_map_1, 164 + .freq_tbl = ftbl_gpu_cc_hub_clk_src, 165 + .clkr.hw.init = &(const struct clk_init_data){ 166 + .name = "gpu_cc_hub_clk_src", 167 + .parent_data = gpu_cc_parent_data_1, 168 + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 169 + .ops = &clk_rcg2_shared_ops, 170 + }, 171 + }; 172 + 173 + static struct clk_regmap_div gpu_cc_hub_ahb_div_clk_src = { 174 + .reg = 0x11c0, 175 + .shift = 0, 176 + .width = 4, 177 + .clkr.hw.init = &(const struct clk_init_data) { 178 + .name = "gpu_cc_hub_ahb_div_clk_src", 179 + .parent_hws = (const struct clk_hw*[]){ 180 + &gpu_cc_hub_clk_src.clkr.hw, 181 + }, 182 + .num_parents = 1, 183 + .flags = CLK_SET_RATE_PARENT, 184 + .ops = &clk_regmap_div_ro_ops, 185 + }, 186 + }; 187 + 188 + static struct clk_regmap_div gpu_cc_hub_cx_int_div_clk_src = { 189 + .reg = 0x11bc, 190 + .shift = 0, 191 + .width = 4, 192 + .clkr.hw.init = &(const struct clk_init_data) { 193 + .name = "gpu_cc_hub_cx_int_div_clk_src", 194 + .parent_hws = (const struct clk_hw*[]){ 195 + &gpu_cc_hub_clk_src.clkr.hw, 196 + }, 197 + .num_parents = 1, 198 + .flags = CLK_SET_RATE_PARENT, 199 + .ops = &clk_regmap_div_ro_ops, 200 + }, 201 + }; 202 + 203 + static struct clk_branch gpu_cc_ahb_clk = { 204 + .halt_reg = 0x1078, 205 + .halt_check = BRANCH_HALT_DELAY, 206 + .clkr = { 207 + .enable_reg = 0x1078, 208 + .enable_mask = BIT(0), 209 + .hw.init = &(const struct clk_init_data){ 210 + .name = "gpu_cc_ahb_clk", 211 + .parent_hws = (const struct clk_hw*[]){ 212 + &gpu_cc_hub_ahb_div_clk_src.clkr.hw, 213 + }, 214 + .num_parents = 1, 215 + .flags = CLK_SET_RATE_PARENT, 216 + .ops = &clk_branch2_ops, 217 + }, 218 + }, 219 + }; 220 + 221 + static struct clk_branch gpu_cc_crc_ahb_clk = { 222 + .halt_reg = 0x107c, 223 + .halt_check = BRANCH_HALT_VOTED, 224 + .clkr = { 225 + .enable_reg = 0x107c, 226 + .enable_mask = BIT(0), 227 + .hw.init = &(const struct clk_init_data){ 228 + .name = "gpu_cc_crc_ahb_clk", 229 + .parent_hws = (const struct clk_hw*[]){ 230 + &gpu_cc_hub_ahb_div_clk_src.clkr.hw, 231 + }, 232 + .num_parents = 1, 233 + .flags = CLK_SET_RATE_PARENT, 234 + .ops = &clk_branch2_ops, 235 + }, 236 + }, 237 + }; 238 + 239 + static struct clk_branch gpu_cc_cx_gmu_clk = { 240 + .halt_reg = 0x1098, 241 + .halt_check = BRANCH_HALT, 242 + .clkr = { 243 + .enable_reg = 0x1098, 244 + .enable_mask = BIT(0), 245 + .hw.init = &(const struct clk_init_data){ 246 + .name = "gpu_cc_cx_gmu_clk", 247 + .parent_hws = (const struct clk_hw*[]){ 248 + &gpu_cc_gmu_clk_src.clkr.hw, 249 + }, 250 + .num_parents = 1, 251 + .flags = CLK_SET_RATE_PARENT, 252 + .ops = &clk_branch2_aon_ops, 253 + }, 254 + }, 255 + }; 256 + 257 + static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 258 + .halt_reg = 0x108c, 259 + .halt_check = BRANCH_HALT_VOTED, 260 + .clkr = { 261 + .enable_reg = 0x108c, 262 + .enable_mask = BIT(0), 263 + .hw.init = &(const struct clk_init_data){ 264 + .name = "gpu_cc_cx_snoc_dvm_clk", 265 + .ops = &clk_branch2_ops, 266 + }, 267 + }, 268 + }; 269 + 270 + static struct clk_branch gpu_cc_cxo_aon_clk = { 271 + .halt_reg = 0x1004, 272 + .halt_check = BRANCH_HALT_VOTED, 273 + .clkr = { 274 + .enable_reg = 0x1004, 275 + .enable_mask = BIT(0), 276 + .hw.init = &(const struct clk_init_data){ 277 + .name = "gpu_cc_cxo_aon_clk", 278 + .ops = &clk_branch2_ops, 279 + }, 280 + }, 281 + }; 282 + 283 + static struct clk_branch gpu_cc_gx_gmu_clk = { 284 + .halt_reg = 0x1064, 285 + .halt_check = BRANCH_HALT, 286 + .clkr = { 287 + .enable_reg = 0x1064, 288 + .enable_mask = BIT(0), 289 + .hw.init = &(const struct clk_init_data){ 290 + .name = "gpu_cc_gx_gmu_clk", 291 + .parent_hws = (const struct clk_hw*[]){ 292 + &gpu_cc_gmu_clk_src.clkr.hw, 293 + }, 294 + .num_parents = 1, 295 + .flags = CLK_SET_RATE_PARENT, 296 + .ops = &clk_branch2_ops, 297 + }, 298 + }, 299 + }; 300 + 301 + static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 302 + .halt_reg = 0x5000, 303 + .halt_check = BRANCH_HALT_VOTED, 304 + .clkr = { 305 + .enable_reg = 0x5000, 306 + .enable_mask = BIT(0), 307 + .hw.init = &(const struct clk_init_data){ 308 + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 309 + .ops = &clk_branch2_ops, 310 + }, 311 + }, 312 + }; 313 + 314 + static struct clk_branch gpu_cc_hub_aon_clk = { 315 + .halt_reg = 0x1178, 316 + .halt_check = BRANCH_HALT, 317 + .clkr = { 318 + .enable_reg = 0x1178, 319 + .enable_mask = BIT(0), 320 + .hw.init = &(const struct clk_init_data){ 321 + .name = "gpu_cc_hub_aon_clk", 322 + .parent_hws = (const struct clk_hw*[]){ 323 + &gpu_cc_hub_clk_src.clkr.hw, 324 + }, 325 + .num_parents = 1, 326 + .flags = CLK_SET_RATE_PARENT, 327 + .ops = &clk_branch2_aon_ops, 328 + }, 329 + }, 330 + }; 331 + 332 + static struct clk_branch gpu_cc_hub_cx_int_clk = { 333 + .halt_reg = 0x1204, 334 + .halt_check = BRANCH_HALT, 335 + .clkr = { 336 + .enable_reg = 0x1204, 337 + .enable_mask = BIT(0), 338 + .hw.init = &(const struct clk_init_data){ 339 + .name = "gpu_cc_hub_cx_int_clk", 340 + .parent_hws = (const struct clk_hw*[]){ 341 + &gpu_cc_hub_cx_int_div_clk_src.clkr.hw, 342 + }, 343 + .num_parents = 1, 344 + .flags = CLK_SET_RATE_PARENT, 345 + .ops = &clk_branch2_aon_ops, 346 + }, 347 + }, 348 + }; 349 + 350 + static struct clk_branch gpu_cc_sleep_clk = { 351 + .halt_reg = 0x1090, 352 + .halt_check = BRANCH_HALT_VOTED, 353 + .clkr = { 354 + .enable_reg = 0x1090, 355 + .enable_mask = BIT(0), 356 + .hw.init = &(const struct clk_init_data){ 357 + .name = "gpu_cc_sleep_clk", 358 + .ops = &clk_branch2_ops, 359 + }, 360 + }, 361 + }; 362 + 363 + static struct clk_regmap *gpu_cc_sc8280xp_clocks[] = { 364 + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 365 + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 366 + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 367 + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 368 + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 369 + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 370 + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 371 + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 372 + [GPU_CC_HUB_AHB_DIV_CLK_SRC] = &gpu_cc_hub_ahb_div_clk_src.clkr, 373 + [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, 374 + [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, 375 + [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, 376 + [GPU_CC_HUB_CX_INT_DIV_CLK_SRC] = &gpu_cc_hub_cx_int_div_clk_src.clkr, 377 + [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 378 + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 379 + [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr, 380 + }; 381 + 382 + static struct gdsc cx_gdsc = { 383 + .gdscr = 0x106c, 384 + .gds_hw_ctrl = 0x1540, 385 + .pd = { 386 + .name = "cx_gdsc", 387 + }, 388 + .pwrsts = PWRSTS_OFF_ON, 389 + .flags = VOTABLE | RETAIN_FF_ENABLE, 390 + }; 391 + 392 + static struct gdsc gx_gdsc = { 393 + .gdscr = 0x100c, 394 + .clamp_io_ctrl = 0x1508, 395 + .pd = { 396 + .name = "gx_gdsc", 397 + .power_on = gdsc_gx_do_nothing_enable, 398 + }, 399 + .pwrsts = PWRSTS_OFF_ON, 400 + .flags = CLAMP_IO | RETAIN_FF_ENABLE, 401 + }; 402 + 403 + static struct gdsc *gpu_cc_sc8280xp_gdscs[] = { 404 + [GPU_CC_CX_GDSC] = &cx_gdsc, 405 + [GPU_CC_GX_GDSC] = &gx_gdsc, 406 + }; 407 + 408 + static const struct regmap_config gpu_cc_sc8280xp_regmap_config = { 409 + .reg_bits = 32, 410 + .reg_stride = 4, 411 + .val_bits = 32, 412 + .max_register = 0x8030, 413 + .fast_io = true, 414 + }; 415 + 416 + static struct qcom_cc_desc gpu_cc_sc8280xp_desc = { 417 + .config = &gpu_cc_sc8280xp_regmap_config, 418 + .clks = gpu_cc_sc8280xp_clocks, 419 + .num_clks = ARRAY_SIZE(gpu_cc_sc8280xp_clocks), 420 + .gdscs = gpu_cc_sc8280xp_gdscs, 421 + .num_gdscs = ARRAY_SIZE(gpu_cc_sc8280xp_gdscs), 422 + }; 423 + 424 + static int gpu_cc_sc8280xp_probe(struct platform_device *pdev) 425 + { 426 + struct regmap *regmap; 427 + 428 + regmap = qcom_cc_map(pdev, &gpu_cc_sc8280xp_desc); 429 + if (IS_ERR(regmap)) 430 + return PTR_ERR(regmap); 431 + 432 + clk_lucid_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config); 433 + clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 434 + 435 + /* 436 + * Keep the clocks always-ON 437 + * GPU_CC_CB_CLK, GPU_CC_CXO_CLK 438 + */ 439 + regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0)); 440 + regmap_update_bits(regmap, 0x109c, BIT(0), BIT(0)); 441 + 442 + return qcom_cc_really_probe(pdev, &gpu_cc_sc8280xp_desc, regmap); 443 + } 444 + 445 + static const struct of_device_id gpu_cc_sc8280xp_match_table[] = { 446 + { .compatible = "qcom,sc8280xp-gpucc" }, 447 + { } 448 + }; 449 + MODULE_DEVICE_TABLE(of, gpu_cc_sc8280xp_match_table); 450 + 451 + static struct platform_driver gpu_cc_sc8280xp_driver = { 452 + .probe = gpu_cc_sc8280xp_probe, 453 + .driver = { 454 + .name = "gpu_cc-sc8280xp", 455 + .of_match_table = gpu_cc_sc8280xp_match_table, 456 + }, 457 + }; 458 + module_platform_driver(gpu_cc_sc8280xp_driver); 459 + 460 + MODULE_DESCRIPTION("Qualcomm SC8280XP GPU clock controller"); 461 + MODULE_LICENSE("GPL");