597 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.4 */5 6#include <linux/clk-provider.h>7#include <linux/mod_devicetable.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/regmap.h>11 12#include <dt-bindings/clock/qcom,sm8550-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 "common.h"20#include "gdsc.h"21#include "reset.h"22 23enum {24 DT_BI_TCXO,25 DT_GPLL0_OUT_MAIN,26 DT_GPLL0_OUT_MAIN_DIV,27};28 29enum {30 P_BI_TCXO,31 P_GPLL0_OUT_MAIN,32 P_GPLL0_OUT_MAIN_DIV,33 P_GPU_CC_PLL0_OUT_MAIN,34 P_GPU_CC_PLL1_OUT_MAIN,35};36 37static const struct pll_vco lucid_ole_vco[] = {38 { 249600000, 2000000000, 0 },39};40 41static const struct alpha_pll_config gpu_cc_pll0_config = {42 .l = 0x1e,43 .alpha = 0xbaaa,44 .config_ctl_val = 0x20485699,45 .config_ctl_hi_val = 0x00182261,46 .config_ctl_hi1_val = 0x82aa299c,47 .test_ctl_val = 0x00000000,48 .test_ctl_hi_val = 0x00000003,49 .test_ctl_hi1_val = 0x00009000,50 .test_ctl_hi2_val = 0x00000034,51 .user_ctl_val = 0x00000000,52 .user_ctl_hi_val = 0x00000005,53};54 55static struct clk_alpha_pll gpu_cc_pll0 = {56 .offset = 0x0,57 .vco_table = lucid_ole_vco,58 .num_vco = ARRAY_SIZE(lucid_ole_vco),59 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],60 .clkr = {61 .hw.init = &(const struct clk_init_data) {62 .name = "gpu_cc_pll0",63 .parent_data = &(const struct clk_parent_data) {64 .index = DT_BI_TCXO,65 },66 .num_parents = 1,67 .ops = &clk_alpha_pll_lucid_evo_ops,68 },69 },70};71 72static const struct alpha_pll_config gpu_cc_pll1_config = {73 .l = 0x16,74 .alpha = 0xeaaa,75 .config_ctl_val = 0x20485699,76 .config_ctl_hi_val = 0x00182261,77 .config_ctl_hi1_val = 0x82aa299c,78 .test_ctl_val = 0x00000000,79 .test_ctl_hi_val = 0x00000003,80 .test_ctl_hi1_val = 0x00009000,81 .test_ctl_hi2_val = 0x00000034,82 .user_ctl_val = 0x00000000,83 .user_ctl_hi_val = 0x00000005,84};85 86static struct clk_alpha_pll gpu_cc_pll1 = {87 .offset = 0x1000,88 .vco_table = lucid_ole_vco,89 .num_vco = ARRAY_SIZE(lucid_ole_vco),90 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],91 .clkr = {92 .hw.init = &(const struct clk_init_data) {93 .name = "gpu_cc_pll1",94 .parent_data = &(const struct clk_parent_data) {95 .index = DT_BI_TCXO,96 },97 .num_parents = 1,98 .ops = &clk_alpha_pll_lucid_evo_ops,99 },100 },101};102 103static const struct parent_map gpu_cc_parent_map_0[] = {104 { P_BI_TCXO, 0 },105 { P_GPLL0_OUT_MAIN, 5 },106 { P_GPLL0_OUT_MAIN_DIV, 6 },107};108 109static const struct clk_parent_data gpu_cc_parent_data_0[] = {110 { .index = DT_BI_TCXO },111 { .index = DT_GPLL0_OUT_MAIN },112 { .index = DT_GPLL0_OUT_MAIN_DIV },113};114 115static const struct parent_map gpu_cc_parent_map_1[] = {116 { P_BI_TCXO, 0 },117 { P_GPU_CC_PLL0_OUT_MAIN, 1 },118 { P_GPU_CC_PLL1_OUT_MAIN, 3 },119 { P_GPLL0_OUT_MAIN, 5 },120 { P_GPLL0_OUT_MAIN_DIV, 6 },121};122 123static const struct clk_parent_data gpu_cc_parent_data_1[] = {124 { .index = DT_BI_TCXO },125 { .hw = &gpu_cc_pll0.clkr.hw },126 { .hw = &gpu_cc_pll1.clkr.hw },127 { .index = DT_GPLL0_OUT_MAIN },128 { .index = DT_GPLL0_OUT_MAIN_DIV },129};130 131static const struct parent_map gpu_cc_parent_map_2[] = {132 { P_BI_TCXO, 0 },133 { P_GPU_CC_PLL1_OUT_MAIN, 3 },134 { P_GPLL0_OUT_MAIN, 5 },135 { P_GPLL0_OUT_MAIN_DIV, 6 },136};137 138static const struct clk_parent_data gpu_cc_parent_data_2[] = {139 { .index = DT_BI_TCXO },140 { .hw = &gpu_cc_pll1.clkr.hw },141 { .index = DT_GPLL0_OUT_MAIN },142 { .index = DT_GPLL0_OUT_MAIN_DIV },143};144 145static const struct parent_map gpu_cc_parent_map_3[] = {146 { P_BI_TCXO, 0 },147};148 149static const struct clk_parent_data gpu_cc_parent_data_3[] = {150 { .index = DT_BI_TCXO },151};152 153static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {154 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),155 { }156};157 158static struct clk_rcg2 gpu_cc_ff_clk_src = {159 .cmd_rcgr = 0x9474,160 .mnd_width = 0,161 .hid_width = 5,162 .parent_map = gpu_cc_parent_map_0,163 .freq_tbl = ftbl_gpu_cc_ff_clk_src,164 .clkr.hw.init = &(const struct clk_init_data) {165 .name = "gpu_cc_ff_clk_src",166 .parent_data = gpu_cc_parent_data_0,167 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),168 .flags = CLK_SET_RATE_PARENT,169 .ops = &clk_rcg2_shared_ops,170 },171};172 173static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {174 F(19200000, P_BI_TCXO, 1, 0, 0),175 F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),176 F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),177 { }178};179 180static struct clk_rcg2 gpu_cc_gmu_clk_src = {181 .cmd_rcgr = 0x9318,182 .mnd_width = 0,183 .hid_width = 5,184 .parent_map = gpu_cc_parent_map_1,185 .freq_tbl = ftbl_gpu_cc_gmu_clk_src,186 .clkr.hw.init = &(const struct clk_init_data) {187 .name = "gpu_cc_gmu_clk_src",188 .parent_data = gpu_cc_parent_data_1,189 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),190 .flags = CLK_SET_RATE_PARENT,191 .ops = &clk_rcg2_shared_ops,192 },193};194 195static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = {196 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),197 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),198 F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),199 { }200};201 202static struct clk_rcg2 gpu_cc_hub_clk_src = {203 .cmd_rcgr = 0x93ec,204 .mnd_width = 0,205 .hid_width = 5,206 .parent_map = gpu_cc_parent_map_2,207 .freq_tbl = ftbl_gpu_cc_hub_clk_src,208 .clkr.hw.init = &(const struct clk_init_data) {209 .name = "gpu_cc_hub_clk_src",210 .parent_data = gpu_cc_parent_data_2,211 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),212 .flags = CLK_SET_RATE_PARENT,213 .ops = &clk_rcg2_shared_ops,214 },215};216 217static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = {218 F(19200000, P_BI_TCXO, 1, 0, 0),219 { }220};221 222static struct clk_rcg2 gpu_cc_xo_clk_src = {223 .cmd_rcgr = 0x9010,224 .mnd_width = 0,225 .hid_width = 5,226 .parent_map = gpu_cc_parent_map_3,227 .freq_tbl = ftbl_gpu_cc_xo_clk_src,228 .clkr.hw.init = &(const struct clk_init_data) {229 .name = "gpu_cc_xo_clk_src",230 .parent_data = gpu_cc_parent_data_3,231 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3),232 .flags = CLK_SET_RATE_PARENT,233 .ops = &clk_rcg2_shared_ops,234 },235};236 237static struct clk_regmap_div gpu_cc_demet_div_clk_src = {238 .reg = 0x9054,239 .shift = 0,240 .width = 4,241 .clkr.hw.init = &(const struct clk_init_data) {242 .name = "gpu_cc_demet_div_clk_src",243 .parent_hws = (const struct clk_hw*[]) {244 &gpu_cc_xo_clk_src.clkr.hw,245 },246 .num_parents = 1,247 .flags = CLK_SET_RATE_PARENT,248 .ops = &clk_regmap_div_ro_ops,249 },250};251 252static struct clk_regmap_div gpu_cc_xo_div_clk_src = {253 .reg = 0x9050,254 .shift = 0,255 .width = 4,256 .clkr.hw.init = &(const struct clk_init_data) {257 .name = "gpu_cc_xo_div_clk_src",258 .parent_hws = (const struct clk_hw*[]) {259 &gpu_cc_xo_clk_src.clkr.hw,260 },261 .num_parents = 1,262 .flags = CLK_SET_RATE_PARENT,263 .ops = &clk_regmap_div_ro_ops,264 },265};266 267static struct clk_branch gpu_cc_ahb_clk = {268 .halt_reg = 0x911c,269 .halt_check = BRANCH_HALT_DELAY,270 .clkr = {271 .enable_reg = 0x911c,272 .enable_mask = BIT(0),273 .hw.init = &(const struct clk_init_data) {274 .name = "gpu_cc_ahb_clk",275 .parent_hws = (const struct clk_hw*[]) {276 &gpu_cc_hub_clk_src.clkr.hw,277 },278 .num_parents = 1,279 .flags = CLK_SET_RATE_PARENT,280 .ops = &clk_branch2_ops,281 },282 },283};284 285static struct clk_branch gpu_cc_crc_ahb_clk = {286 .halt_reg = 0x9120,287 .halt_check = BRANCH_HALT_VOTED,288 .clkr = {289 .enable_reg = 0x9120,290 .enable_mask = BIT(0),291 .hw.init = &(const struct clk_init_data) {292 .name = "gpu_cc_crc_ahb_clk",293 .parent_hws = (const struct clk_hw*[]) {294 &gpu_cc_hub_clk_src.clkr.hw,295 },296 .num_parents = 1,297 .flags = CLK_SET_RATE_PARENT,298 .ops = &clk_branch2_ops,299 },300 },301};302 303static struct clk_branch gpu_cc_cx_ff_clk = {304 .halt_reg = 0x914c,305 .halt_check = BRANCH_HALT,306 .clkr = {307 .enable_reg = 0x914c,308 .enable_mask = BIT(0),309 .hw.init = &(const struct clk_init_data) {310 .name = "gpu_cc_cx_ff_clk",311 .parent_hws = (const struct clk_hw*[]) {312 &gpu_cc_ff_clk_src.clkr.hw,313 },314 .num_parents = 1,315 .flags = CLK_SET_RATE_PARENT,316 .ops = &clk_branch2_ops,317 },318 },319};320 321static struct clk_branch gpu_cc_cx_gmu_clk = {322 .halt_reg = 0x913c,323 .halt_check = BRANCH_HALT_VOTED,324 .clkr = {325 .enable_reg = 0x913c,326 .enable_mask = BIT(0),327 .hw.init = &(const struct clk_init_data) {328 .name = "gpu_cc_cx_gmu_clk",329 .parent_hws = (const struct clk_hw*[]) {330 &gpu_cc_gmu_clk_src.clkr.hw,331 },332 .num_parents = 1,333 .flags = CLK_SET_RATE_PARENT,334 .ops = &clk_branch2_aon_ops,335 },336 },337};338 339static struct clk_branch gpu_cc_cxo_clk = {340 .halt_reg = 0x9144,341 .halt_check = BRANCH_HALT,342 .clkr = {343 .enable_reg = 0x9144,344 .enable_mask = BIT(0),345 .hw.init = &(const struct clk_init_data) {346 .name = "gpu_cc_cxo_clk",347 .parent_hws = (const struct clk_hw*[]) {348 &gpu_cc_xo_clk_src.clkr.hw,349 },350 .num_parents = 1,351 .flags = CLK_SET_RATE_PARENT,352 .ops = &clk_branch2_ops,353 },354 },355};356 357static struct clk_branch gpu_cc_freq_measure_clk = {358 .halt_reg = 0x9008,359 .halt_check = BRANCH_HALT,360 .clkr = {361 .enable_reg = 0x9008,362 .enable_mask = BIT(0),363 .hw.init = &(const struct clk_init_data) {364 .name = "gpu_cc_freq_measure_clk",365 .parent_hws = (const struct clk_hw*[]) {366 &gpu_cc_xo_div_clk_src.clkr.hw,367 },368 .num_parents = 1,369 .flags = CLK_SET_RATE_PARENT,370 .ops = &clk_branch2_ops,371 },372 },373};374 375static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {376 .halt_reg = 0x7000,377 .halt_check = BRANCH_HALT_VOTED,378 .clkr = {379 .enable_reg = 0x7000,380 .enable_mask = BIT(0),381 .hw.init = &(const struct clk_init_data) {382 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",383 .ops = &clk_branch2_ops,384 },385 },386};387 388static struct clk_branch gpu_cc_hub_aon_clk = {389 .halt_reg = 0x93e8,390 .halt_check = BRANCH_HALT,391 .clkr = {392 .enable_reg = 0x93e8,393 .enable_mask = BIT(0),394 .hw.init = &(const struct clk_init_data) {395 .name = "gpu_cc_hub_aon_clk",396 .parent_hws = (const struct clk_hw*[]) {397 &gpu_cc_hub_clk_src.clkr.hw,398 },399 .num_parents = 1,400 .flags = CLK_SET_RATE_PARENT,401 .ops = &clk_branch2_aon_ops,402 },403 },404};405 406static struct clk_branch gpu_cc_hub_cx_int_clk = {407 .halt_reg = 0x9148,408 .halt_check = BRANCH_HALT_VOTED,409 .clkr = {410 .enable_reg = 0x9148,411 .enable_mask = BIT(0),412 .hw.init = &(const struct clk_init_data) {413 .name = "gpu_cc_hub_cx_int_clk",414 .parent_hws = (const struct clk_hw*[]) {415 &gpu_cc_hub_clk_src.clkr.hw,416 },417 .num_parents = 1,418 .flags = CLK_SET_RATE_PARENT,419 .ops = &clk_branch2_aon_ops,420 },421 },422};423 424static struct clk_branch gpu_cc_memnoc_gfx_clk = {425 .halt_reg = 0x9150,426 .halt_check = BRANCH_HALT_VOTED,427 .clkr = {428 .enable_reg = 0x9150,429 .enable_mask = BIT(0),430 .hw.init = &(const struct clk_init_data) {431 .name = "gpu_cc_memnoc_gfx_clk",432 .ops = &clk_branch2_ops,433 },434 },435};436 437static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {438 .halt_reg = 0x9288,439 .halt_check = BRANCH_HALT,440 .clkr = {441 .enable_reg = 0x9288,442 .enable_mask = BIT(0),443 .hw.init = &(const struct clk_init_data) {444 .name = "gpu_cc_mnd1x_0_gfx3d_clk",445 .ops = &clk_branch2_ops,446 },447 },448};449 450static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {451 .halt_reg = 0x928c,452 .halt_check = BRANCH_HALT,453 .clkr = {454 .enable_reg = 0x928c,455 .enable_mask = BIT(0),456 .hw.init = &(const struct clk_init_data) {457 .name = "gpu_cc_mnd1x_1_gfx3d_clk",458 .ops = &clk_branch2_ops,459 },460 },461};462 463static struct clk_branch gpu_cc_sleep_clk = {464 .halt_reg = 0x9134,465 .halt_check = BRANCH_HALT_VOTED,466 .clkr = {467 .enable_reg = 0x9134,468 .enable_mask = BIT(0),469 .hw.init = &(const struct clk_init_data) {470 .name = "gpu_cc_sleep_clk",471 .ops = &clk_branch2_ops,472 },473 },474};475 476static struct gdsc gpu_cc_cx_gdsc = {477 .gdscr = 0x9108,478 .gds_hw_ctrl = 0x953c,479 .en_rest_wait_val = 0x2,480 .en_few_wait_val = 0x2,481 .clk_dis_wait_val = 0xf,482 .pd = {483 .name = "gpu_cc_cx_gdsc",484 },485 .pwrsts = PWRSTS_OFF_ON,486 .flags = RETAIN_FF_ENABLE | VOTABLE,487};488 489static struct gdsc gpu_cc_gx_gdsc = {490 .gdscr = 0x905c,491 .clamp_io_ctrl = 0x9504,492 .en_rest_wait_val = 0x2,493 .en_few_wait_val = 0x2,494 .clk_dis_wait_val = 0xf,495 .pd = {496 .name = "gpu_cc_gx_gdsc",497 .power_on = gdsc_gx_do_nothing_enable,498 },499 .pwrsts = PWRSTS_OFF_ON,500 .flags = CLAMP_IO | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,501};502 503static struct clk_regmap *gpu_cc_sm8550_clocks[] = {504 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,505 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,506 [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,507 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,508 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,509 [GPU_CC_DEMET_DIV_CLK_SRC] = &gpu_cc_demet_div_clk_src.clkr,510 [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,511 [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,512 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,513 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,514 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,515 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,516 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,517 [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,518 [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,519 [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,520 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,521 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,522 [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,523 [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr,524 [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr,525};526 527static struct gdsc *gpu_cc_sm8550_gdscs[] = {528 [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc,529 [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc,530};531 532static const struct qcom_reset_map gpu_cc_sm8550_resets[] = {533 [GPUCC_GPU_CC_ACD_BCR] = { 0x9358 },534 [GPUCC_GPU_CC_CX_BCR] = { 0x9104 },535 [GPUCC_GPU_CC_FAST_HUB_BCR] = { 0x93e4 },536 [GPUCC_GPU_CC_FF_BCR] = { 0x9470 },537 [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x9198 },538 [GPUCC_GPU_CC_GMU_BCR] = { 0x9314 },539 [GPUCC_GPU_CC_GX_BCR] = { 0x9058 },540 [GPUCC_GPU_CC_XO_BCR] = { 0x9000 },541};542 543static const struct regmap_config gpu_cc_sm8550_regmap_config = {544 .reg_bits = 32,545 .reg_stride = 4,546 .val_bits = 32,547 .max_register = 0x9988,548 .fast_io = true,549};550 551static const struct qcom_cc_desc gpu_cc_sm8550_desc = {552 .config = &gpu_cc_sm8550_regmap_config,553 .clks = gpu_cc_sm8550_clocks,554 .num_clks = ARRAY_SIZE(gpu_cc_sm8550_clocks),555 .resets = gpu_cc_sm8550_resets,556 .num_resets = ARRAY_SIZE(gpu_cc_sm8550_resets),557 .gdscs = gpu_cc_sm8550_gdscs,558 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8550_gdscs),559};560 561static const struct of_device_id gpu_cc_sm8550_match_table[] = {562 { .compatible = "qcom,sm8550-gpucc" },563 { }564};565MODULE_DEVICE_TABLE(of, gpu_cc_sm8550_match_table);566 567static int gpu_cc_sm8550_probe(struct platform_device *pdev)568{569 struct regmap *regmap;570 571 regmap = qcom_cc_map(pdev, &gpu_cc_sm8550_desc);572 if (IS_ERR(regmap))573 return PTR_ERR(regmap);574 575 clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);576 clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);577 578 /* Keep some clocks always-on */579 qcom_branch_set_clk_en(regmap, 0x9004); /* GPU_CC_CXO_AON_CLK */580 qcom_branch_set_clk_en(regmap, 0x900c); /* GPU_CC_DEMET_CLK */581 582 return qcom_cc_really_probe(&pdev->dev, &gpu_cc_sm8550_desc, regmap);583}584 585static struct platform_driver gpu_cc_sm8550_driver = {586 .probe = gpu_cc_sm8550_probe,587 .driver = {588 .name = "gpu_cc-sm8550",589 .of_match_table = gpu_cc_sm8550_match_table,590 },591};592 593module_platform_driver(gpu_cc_sm8550_driver);594 595MODULE_DESCRIPTION("QTI GPUCC SM8550 Driver");596MODULE_LICENSE("GPL");597