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 GPU clock controller driver for SM6375

Add support for the GPU clock controller found on SM6375.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20230208091340.124641-9-konrad.dybcio@linaro.org

authored by

Konrad Dybcio and committed by
Bjorn Andersson
8397e242 a6b18286

+479
+9
drivers/clk/qcom/Kconfig
··· 807 807 Say Y if you want to support graphics controller devices and 808 808 functionality such as 3D graphics. 809 809 810 + config SM_GPUCC_6375 811 + tristate "SM6375 Graphics Clock Controller" 812 + select SM_GCC_6375 813 + depends on ARM64 || COMPILE_TEST 814 + help 815 + Support for the graphics clock controller on SM6375 devices. 816 + Say Y if you want to support graphics controller devices and 817 + functionality such as 3D graphics. 818 + 810 819 config SM_GPUCC_6350 811 820 tristate "SM6350 Graphics Clock Controller" 812 821 select SM_GCC_6350
+1
drivers/clk/qcom/Makefile
··· 114 114 obj-$(CONFIG_SM_GCC_8550) += gcc-sm8550.o 115 115 obj-$(CONFIG_SM_GPUCC_6125) += gpucc-sm6125.o 116 116 obj-$(CONFIG_SM_GPUCC_6350) += gpucc-sm6350.o 117 + obj-$(CONFIG_SM_GPUCC_6375) += gpucc-sm6375.o 117 118 obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o 118 119 obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o 119 120 obj-$(CONFIG_SM_GPUCC_8350) += gpucc-sm8350.o
+469
drivers/clk/qcom/gpucc-sm6375.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 + * Copyright (c) 2023, Linaro Limited 5 + */ 6 + 7 + #include <linux/clk-provider.h> 8 + #include <linux/module.h> 9 + #include <linux/of_device.h> 10 + #include <linux/regmap.h> 11 + 12 + #include <dt-bindings/clock/qcom,sm6375-gpucc.h> 13 + 14 + #include "clk-alpha-pll.h" 15 + #include "clk-branch.h" 16 + #include "clk-rcg.h" 17 + #include "clk-regmap.h" 18 + #include "clk-regmap-divider.h" 19 + #include "clk-regmap-mux.h" 20 + #include "clk-regmap-phy-mux.h" 21 + #include "gdsc.h" 22 + #include "reset.h" 23 + 24 + enum { 25 + DT_BI_TCXO, 26 + DT_GCC_GPU_GPLL0_CLK_SRC, 27 + DT_GCC_GPU_GPLL0_DIV_CLK_SRC, 28 + DT_GCC_GPU_SNOC_DVM_GFX_CLK, 29 + }; 30 + 31 + enum { 32 + P_BI_TCXO, 33 + P_GCC_GPU_GPLL0_CLK_SRC, 34 + P_GCC_GPU_GPLL0_DIV_CLK_SRC, 35 + P_GPU_CC_PLL0_OUT_EVEN, 36 + P_GPU_CC_PLL0_OUT_MAIN, 37 + P_GPU_CC_PLL0_OUT_ODD, 38 + P_GPU_CC_PLL1_OUT_EVEN, 39 + P_GPU_CC_PLL1_OUT_MAIN, 40 + P_GPU_CC_PLL1_OUT_ODD, 41 + }; 42 + 43 + static struct pll_vco lucid_vco[] = { 44 + { 249600000, 2000000000, 0 }, 45 + }; 46 + 47 + /* 532MHz Configuration */ 48 + static const struct alpha_pll_config gpucc_pll0_config = { 49 + .l = 0x1b, 50 + .alpha = 0xb555, 51 + .config_ctl_val = 0x20485699, 52 + .config_ctl_hi_val = 0x00002261, 53 + .config_ctl_hi1_val = 0x329a299c, 54 + .user_ctl_val = 0x00000001, 55 + .user_ctl_hi_val = 0x00000805, 56 + .user_ctl_hi1_val = 0x00000000, 57 + }; 58 + 59 + static struct clk_alpha_pll gpucc_pll0 = { 60 + .offset = 0x0, 61 + .vco_table = lucid_vco, 62 + .num_vco = ARRAY_SIZE(lucid_vco), 63 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 64 + .clkr = { 65 + .hw.init = &(struct clk_init_data){ 66 + .name = "gpucc_pll0", 67 + .parent_data = &(const struct clk_parent_data){ 68 + .index = P_BI_TCXO, 69 + }, 70 + .num_parents = 1, 71 + .ops = &clk_alpha_pll_lucid_ops, 72 + }, 73 + }, 74 + }; 75 + 76 + /* 514MHz Configuration */ 77 + static const struct alpha_pll_config gpucc_pll1_config = { 78 + .l = 0x1a, 79 + .alpha = 0xc555, 80 + .config_ctl_val = 0x20485699, 81 + .config_ctl_hi_val = 0x00002261, 82 + .config_ctl_hi1_val = 0x329a299c, 83 + .user_ctl_val = 0x00000001, 84 + .user_ctl_hi_val = 0x00000805, 85 + .user_ctl_hi1_val = 0x00000000, 86 + }; 87 + 88 + static struct clk_alpha_pll gpucc_pll1 = { 89 + .offset = 0x100, 90 + .vco_table = lucid_vco, 91 + .num_vco = ARRAY_SIZE(lucid_vco), 92 + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], 93 + .clkr = { 94 + .hw.init = &(struct clk_init_data){ 95 + .name = "gpucc_pll1", 96 + .parent_data = &(const struct clk_parent_data){ 97 + .index = P_BI_TCXO, 98 + }, 99 + .num_parents = 1, 100 + .ops = &clk_alpha_pll_lucid_ops, 101 + }, 102 + }, 103 + }; 104 + 105 + static const struct parent_map gpucc_parent_map_0[] = { 106 + { P_BI_TCXO, 0 }, 107 + { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 108 + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 109 + { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 110 + { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 111 + }; 112 + 113 + static const struct clk_parent_data gpucc_parent_data_0[] = { 114 + { .index = P_BI_TCXO }, 115 + { .hw = &gpucc_pll0.clkr.hw }, 116 + { .hw = &gpucc_pll1.clkr.hw }, 117 + { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 118 + { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 119 + }; 120 + 121 + static const struct parent_map gpucc_parent_map_1[] = { 122 + { P_BI_TCXO, 0 }, 123 + { P_GPU_CC_PLL0_OUT_EVEN, 1 }, 124 + { P_GPU_CC_PLL0_OUT_ODD, 2 }, 125 + { P_GPU_CC_PLL1_OUT_EVEN, 3 }, 126 + { P_GPU_CC_PLL1_OUT_ODD, 4 }, 127 + { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 128 + }; 129 + 130 + static const struct clk_parent_data gpucc_parent_data_1[] = { 131 + { .index = P_BI_TCXO }, 132 + { .hw = &gpucc_pll0.clkr.hw }, 133 + { .hw = &gpucc_pll0.clkr.hw }, 134 + { .hw = &gpucc_pll1.clkr.hw }, 135 + { .hw = &gpucc_pll1.clkr.hw }, 136 + { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 137 + }; 138 + 139 + static const struct parent_map gpucc_parent_map_2[] = { 140 + { P_BI_TCXO, 0 }, 141 + { P_GCC_GPU_GPLL0_CLK_SRC, 5 }, 142 + { P_GCC_GPU_GPLL0_DIV_CLK_SRC, 6 }, 143 + }; 144 + 145 + static const struct clk_parent_data gpucc_parent_data_2[] = { 146 + { .index = P_BI_TCXO }, 147 + { .index = DT_GCC_GPU_GPLL0_CLK_SRC }, 148 + { .index = DT_GCC_GPU_GPLL0_DIV_CLK_SRC }, 149 + }; 150 + 151 + static const struct freq_tbl ftbl_gpucc_gmu_clk_src[] = { 152 + F(200000000, P_GCC_GPU_GPLL0_DIV_CLK_SRC, 1.5, 0, 0), 153 + { } 154 + }; 155 + 156 + static struct clk_rcg2 gpucc_gmu_clk_src = { 157 + .cmd_rcgr = 0x1120, 158 + .mnd_width = 0, 159 + .hid_width = 5, 160 + .parent_map = gpucc_parent_map_0, 161 + .freq_tbl = ftbl_gpucc_gmu_clk_src, 162 + .clkr.hw.init = &(struct clk_init_data){ 163 + .name = "gpucc_gmu_clk_src", 164 + .parent_data = gpucc_parent_data_0, 165 + .num_parents = ARRAY_SIZE(gpucc_parent_data_0), 166 + .ops = &clk_rcg2_shared_ops, 167 + }, 168 + }; 169 + 170 + static const struct freq_tbl ftbl_gpucc_gx_gfx3d_clk_src[] = { 171 + F(266000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 172 + F(390000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 173 + F(490000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 174 + F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 175 + F(770000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 176 + F(840000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 177 + F(900000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), 178 + { } 179 + }; 180 + 181 + static struct clk_rcg2 gpucc_gx_gfx3d_clk_src = { 182 + .cmd_rcgr = 0x101c, 183 + .mnd_width = 0, 184 + .hid_width = 5, 185 + .parent_map = gpucc_parent_map_1, 186 + .freq_tbl = ftbl_gpucc_gx_gfx3d_clk_src, 187 + .clkr.hw.init = &(struct clk_init_data){ 188 + .name = "gpucc_gx_gfx3d_clk_src", 189 + .parent_data = gpucc_parent_data_1, 190 + .num_parents = ARRAY_SIZE(gpucc_parent_data_1), 191 + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, 192 + .ops = &clk_rcg2_ops, 193 + }, 194 + }; 195 + 196 + static struct clk_branch gpucc_ahb_clk = { 197 + .halt_reg = 0x1078, 198 + .halt_check = BRANCH_HALT_DELAY, 199 + .clkr = { 200 + .enable_reg = 0x1078, 201 + .enable_mask = BIT(0), 202 + .hw.init = &(struct clk_init_data){ 203 + .name = "gpucc_ahb_clk", 204 + .flags = CLK_IS_CRITICAL, 205 + .ops = &clk_branch2_ops, 206 + }, 207 + }, 208 + }; 209 + 210 + static struct clk_branch gpucc_cx_gfx3d_clk = { 211 + .halt_reg = 0x10a4, 212 + .halt_check = BRANCH_HALT_DELAY, 213 + .clkr = { 214 + .enable_reg = 0x10a4, 215 + .enable_mask = BIT(0), 216 + .hw.init = &(struct clk_init_data){ 217 + .name = "gpucc_cx_gfx3d_clk", 218 + .parent_hws = (const struct clk_hw*[]) { 219 + &gpucc_gx_gfx3d_clk_src.clkr.hw, 220 + }, 221 + .num_parents = 1, 222 + .flags = CLK_SET_RATE_PARENT, 223 + .ops = &clk_branch2_ops, 224 + }, 225 + }, 226 + }; 227 + 228 + static struct clk_branch gpucc_cx_gfx3d_slv_clk = { 229 + .halt_reg = 0x10a8, 230 + .halt_check = BRANCH_HALT_DELAY, 231 + .clkr = { 232 + .enable_reg = 0x10a8, 233 + .enable_mask = BIT(0), 234 + .hw.init = &(struct clk_init_data){ 235 + .name = "gpucc_cx_gfx3d_slv_clk", 236 + .parent_hws = (const struct clk_hw*[]) { 237 + &gpucc_gx_gfx3d_clk_src.clkr.hw, 238 + }, 239 + .num_parents = 1, 240 + .flags = CLK_SET_RATE_PARENT, 241 + .ops = &clk_branch2_ops, 242 + }, 243 + }, 244 + }; 245 + 246 + static struct clk_branch gpucc_cx_gmu_clk = { 247 + .halt_reg = 0x1098, 248 + .halt_check = BRANCH_HALT, 249 + .clkr = { 250 + .enable_reg = 0x1098, 251 + .enable_mask = BIT(0), 252 + .hw.init = &(struct clk_init_data){ 253 + .name = "gpucc_cx_gmu_clk", 254 + .parent_hws = (const struct clk_hw*[]) { 255 + &gpucc_gmu_clk_src.clkr.hw, 256 + }, 257 + .num_parents = 1, 258 + .flags = CLK_SET_RATE_PARENT, 259 + .ops = &clk_branch2_ops, 260 + }, 261 + }, 262 + }; 263 + 264 + static struct clk_branch gpucc_cx_snoc_dvm_clk = { 265 + .halt_reg = 0x108c, 266 + .halt_check = BRANCH_HALT_DELAY, 267 + .clkr = { 268 + .enable_reg = 0x108c, 269 + .enable_mask = BIT(0), 270 + .hw.init = &(struct clk_init_data){ 271 + .name = "gpucc_cx_snoc_dvm_clk", 272 + .parent_data = &(const struct clk_parent_data){ 273 + .index = DT_GCC_GPU_SNOC_DVM_GFX_CLK, 274 + }, 275 + .num_parents = 1, 276 + .ops = &clk_branch2_ops, 277 + }, 278 + }, 279 + }; 280 + 281 + static struct clk_branch gpucc_cxo_aon_clk = { 282 + .halt_reg = 0x1004, 283 + .halt_check = BRANCH_HALT_DELAY, 284 + .clkr = { 285 + .enable_reg = 0x1004, 286 + .enable_mask = BIT(0), 287 + .hw.init = &(struct clk_init_data){ 288 + .name = "gpucc_cxo_aon_clk", 289 + .ops = &clk_branch2_ops, 290 + }, 291 + }, 292 + }; 293 + 294 + static struct clk_branch gpucc_cxo_clk = { 295 + .halt_reg = 0x109c, 296 + .halt_check = BRANCH_HALT, 297 + .clkr = { 298 + .enable_reg = 0x109c, 299 + .enable_mask = BIT(0), 300 + .hw.init = &(struct clk_init_data){ 301 + .name = "gpucc_cxo_clk", 302 + .ops = &clk_branch2_ops, 303 + }, 304 + }, 305 + }; 306 + 307 + static struct clk_branch gpucc_gx_cxo_clk = { 308 + .halt_reg = 0x1060, 309 + .halt_check = BRANCH_HALT_DELAY, 310 + .clkr = { 311 + .enable_reg = 0x1060, 312 + .enable_mask = BIT(0), 313 + .hw.init = &(struct clk_init_data){ 314 + .name = "gpucc_gx_cxo_clk", 315 + .flags = CLK_IS_CRITICAL, 316 + .ops = &clk_branch2_ops, 317 + }, 318 + }, 319 + }; 320 + 321 + static struct clk_branch gpucc_gx_gfx3d_clk = { 322 + .halt_reg = 0x1054, 323 + .halt_check = BRANCH_HALT_DELAY, 324 + .clkr = { 325 + .enable_reg = 0x1054, 326 + .enable_mask = BIT(0), 327 + .hw.init = &(struct clk_init_data){ 328 + .name = "gpucc_gx_gfx3d_clk", 329 + .parent_hws = (const struct clk_hw*[]) { 330 + &gpucc_gx_gfx3d_clk_src.clkr.hw, 331 + }, 332 + .num_parents = 1, 333 + .flags = CLK_SET_RATE_PARENT, 334 + .ops = &clk_branch2_ops, 335 + }, 336 + }, 337 + }; 338 + 339 + static struct clk_branch gpucc_gx_gmu_clk = { 340 + .halt_reg = 0x1064, 341 + .halt_check = BRANCH_HALT, 342 + .clkr = { 343 + .enable_reg = 0x1064, 344 + .enable_mask = BIT(0), 345 + .hw.init = &(struct clk_init_data){ 346 + .name = "gpucc_gx_gmu_clk", 347 + .parent_hws = (const struct clk_hw*[]) { 348 + &gpucc_gmu_clk_src.clkr.hw, 349 + }, 350 + .num_parents = 1, 351 + .flags = CLK_SET_RATE_PARENT, 352 + .ops = &clk_branch2_ops, 353 + }, 354 + }, 355 + }; 356 + 357 + static struct clk_branch gpucc_sleep_clk = { 358 + .halt_reg = 0x1090, 359 + .halt_check = BRANCH_HALT_VOTED, 360 + .clkr = { 361 + .enable_reg = 0x1090, 362 + .enable_mask = BIT(0), 363 + .hw.init = &(struct clk_init_data){ 364 + .name = "gpucc_sleep_clk", 365 + .ops = &clk_branch2_ops, 366 + }, 367 + }, 368 + }; 369 + 370 + static struct gdsc gpu_cx_gdsc = { 371 + .gdscr = 0x106c, 372 + .gds_hw_ctrl = 0x1540, 373 + .pd = { 374 + .name = "gpu_cx_gdsc", 375 + }, 376 + .pwrsts = PWRSTS_OFF_ON, 377 + .flags = VOTABLE, 378 + }; 379 + 380 + static struct gdsc gpu_gx_gdsc = { 381 + .gdscr = 0x100c, 382 + .clamp_io_ctrl = 0x1508, 383 + .resets = (unsigned int []){ GPU_GX_BCR, GPU_ACD_BCR, GPU_GX_ACD_MISC_BCR }, 384 + .reset_count = 3, 385 + .pd = { 386 + .name = "gpu_gx_gdsc", 387 + }, 388 + .pwrsts = PWRSTS_OFF_ON, 389 + .flags = CLAMP_IO | SW_RESET | AON_RESET, 390 + }; 391 + 392 + static struct clk_regmap *gpucc_sm6375_clocks[] = { 393 + [GPU_CC_AHB_CLK] = &gpucc_ahb_clk.clkr, 394 + [GPU_CC_CX_GFX3D_CLK] = &gpucc_cx_gfx3d_clk.clkr, 395 + [GPU_CC_CX_GFX3D_SLV_CLK] = &gpucc_cx_gfx3d_slv_clk.clkr, 396 + [GPU_CC_CX_GMU_CLK] = &gpucc_cx_gmu_clk.clkr, 397 + [GPU_CC_CX_SNOC_DVM_CLK] = &gpucc_cx_snoc_dvm_clk.clkr, 398 + [GPU_CC_CXO_AON_CLK] = &gpucc_cxo_aon_clk.clkr, 399 + [GPU_CC_CXO_CLK] = &gpucc_cxo_clk.clkr, 400 + [GPU_CC_GMU_CLK_SRC] = &gpucc_gmu_clk_src.clkr, 401 + [GPU_CC_GX_CXO_CLK] = &gpucc_gx_cxo_clk.clkr, 402 + [GPU_CC_GX_GFX3D_CLK] = &gpucc_gx_gfx3d_clk.clkr, 403 + [GPU_CC_GX_GFX3D_CLK_SRC] = &gpucc_gx_gfx3d_clk_src.clkr, 404 + [GPU_CC_GX_GMU_CLK] = &gpucc_gx_gmu_clk.clkr, 405 + [GPU_CC_PLL0] = &gpucc_pll0.clkr, 406 + [GPU_CC_PLL1] = &gpucc_pll1.clkr, 407 + [GPU_CC_SLEEP_CLK] = &gpucc_sleep_clk.clkr, 408 + }; 409 + 410 + static const struct qcom_reset_map gpucc_sm6375_resets[] = { 411 + [GPU_GX_BCR] = { 0x1008 }, 412 + [GPU_ACD_BCR] = { 0x1160 }, 413 + [GPU_GX_ACD_MISC_BCR] = { 0x8004 }, 414 + }; 415 + 416 + static struct gdsc *gpucc_sm6375_gdscs[] = { 417 + [GPU_CX_GDSC] = &gpu_cx_gdsc, 418 + [GPU_GX_GDSC] = &gpu_gx_gdsc, 419 + }; 420 + 421 + static const struct regmap_config gpucc_sm6375_regmap_config = { 422 + .reg_bits = 32, 423 + .reg_stride = 4, 424 + .val_bits = 32, 425 + .max_register = 0x9000, 426 + .fast_io = true, 427 + }; 428 + 429 + static const struct qcom_cc_desc gpucc_sm6375_desc = { 430 + .config = &gpucc_sm6375_regmap_config, 431 + .clks = gpucc_sm6375_clocks, 432 + .num_clks = ARRAY_SIZE(gpucc_sm6375_clocks), 433 + .resets = gpucc_sm6375_resets, 434 + .num_resets = ARRAY_SIZE(gpucc_sm6375_resets), 435 + .gdscs = gpucc_sm6375_gdscs, 436 + .num_gdscs = ARRAY_SIZE(gpucc_sm6375_gdscs), 437 + }; 438 + 439 + static const struct of_device_id gpucc_sm6375_match_table[] = { 440 + { .compatible = "qcom,sm6375-gpucc" }, 441 + { } 442 + }; 443 + MODULE_DEVICE_TABLE(of, gpucc_sm6375_match_table); 444 + 445 + static int gpucc_sm6375_probe(struct platform_device *pdev) 446 + { 447 + struct regmap *regmap; 448 + 449 + regmap = qcom_cc_map(pdev, &gpucc_sm6375_desc); 450 + if (IS_ERR(regmap)) 451 + return PTR_ERR(regmap); 452 + 453 + clk_lucid_pll_configure(&gpucc_pll0, regmap, &gpucc_pll0_config); 454 + clk_lucid_pll_configure(&gpucc_pll1, regmap, &gpucc_pll1_config); 455 + 456 + return qcom_cc_really_probe(pdev, &gpucc_sm6375_desc, regmap); 457 + } 458 + 459 + static struct platform_driver gpucc_sm6375_driver = { 460 + .probe = gpucc_sm6375_probe, 461 + .driver = { 462 + .name = "gpucc-sm6375", 463 + .of_match_table = gpucc_sm6375_match_table, 464 + }, 465 + }; 466 + module_platform_driver(gpucc_sm6375_driver); 467 + 468 + MODULE_DESCRIPTION("QTI GPUCC SM6375 Driver"); 469 + MODULE_LICENSE("GPL");