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