1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2017-2020, The Linux Foundation. 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,gpucc-sm8150.h> 13 14 #include "common.h" 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 "reset.h" 21 #include "gdsc.h" 22 23 enum { 24 P_BI_TCXO, 25 P_GPLL0_OUT_MAIN, 26 P_GPLL0_OUT_MAIN_DIV, 27 P_GPU_CC_PLL1_OUT_MAIN, 28 }; 29 30 static const struct pll_vco trion_vco[] = { 31 { 249600000, 2000000000, 0 }, 32 }; 33 34 static struct alpha_pll_config gpu_cc_pll1_config = { 35 .l = 0x1a, 36 .alpha = 0xaaa, 37 .config_ctl_val = 0x20485699, 38 .config_ctl_hi_val = 0x00002267, 39 .config_ctl_hi1_val = 0x00000024, 40 .test_ctl_val = 0x00000000, 41 .test_ctl_hi_val = 0x00000000, 42 .test_ctl_hi1_val = 0x00000020, 43 .user_ctl_val = 0x00000000, 44 .user_ctl_hi_val = 0x00000805, 45 .user_ctl_hi1_val = 0x000000d0, 46 }; 47 48 static struct clk_alpha_pll gpu_cc_pll1 = { 49 .offset = 0x100, 50 .vco_table = trion_vco, 51 .num_vco = ARRAY_SIZE(trion_vco), 52 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], 53 .clkr = { 54 .hw.init = &(struct clk_init_data){ 55 .name = "gpu_cc_pll1", 56 .parent_data = &(const struct clk_parent_data){ 57 .fw_name = "bi_tcxo", 58 }, 59 .num_parents = 1, 60 .ops = &clk_alpha_pll_trion_ops, 61 }, 62 }, 63 }; 64 65 static const struct parent_map gpu_cc_parent_map_0[] = { 66 { P_BI_TCXO, 0 }, 67 { P_GPU_CC_PLL1_OUT_MAIN, 3 }, 68 { P_GPLL0_OUT_MAIN, 5 }, 69 { P_GPLL0_OUT_MAIN_DIV, 6 }, 70 }; 71 72 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 73 { .fw_name = "bi_tcxo" }, 74 { .hw = &gpu_cc_pll1.clkr.hw }, 75 { .fw_name = "gcc_gpu_gpll0_clk_src" }, 76 { .fw_name = "gcc_gpu_gpll0_div_clk_src" }, 77 }; 78 79 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 80 F(19200000, P_BI_TCXO, 1, 0, 0), 81 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), 82 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), 83 { } 84 }; 85 86 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src_sc8180x[] = { 87 F(19200000, P_BI_TCXO, 1, 0, 0), 88 F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), 89 F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0), 90 F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), 91 { } 92 }; 93 94 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 95 .cmd_rcgr = 0x1120, 96 .mnd_width = 0, 97 .hid_width = 5, 98 .parent_map = gpu_cc_parent_map_0, 99 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 100 .clkr.hw.init = &(struct clk_init_data){ 101 .name = "gpu_cc_gmu_clk_src", 102 .parent_data = gpu_cc_parent_data_0, 103 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 104 .flags = CLK_SET_RATE_PARENT, 105 .ops = &clk_rcg2_ops, 106 }, 107 }; 108 109 static struct clk_branch gpu_cc_ahb_clk = { 110 .halt_reg = 0x1078, 111 .halt_check = BRANCH_HALT_DELAY, 112 .clkr = { 113 .enable_reg = 0x1078, 114 .enable_mask = BIT(0), 115 .hw.init = &(struct clk_init_data){ 116 .name = "gpu_cc_ahb_clk", 117 .ops = &clk_branch2_ops, 118 }, 119 }, 120 }; 121 122 static struct clk_branch gpu_cc_crc_ahb_clk = { 123 .halt_reg = 0x107c, 124 .halt_check = BRANCH_HALT, 125 .clkr = { 126 .enable_reg = 0x107c, 127 .enable_mask = BIT(0), 128 .hw.init = &(struct clk_init_data){ 129 .name = "gpu_cc_crc_ahb_clk", 130 .ops = &clk_branch2_ops, 131 }, 132 }, 133 }; 134 135 static struct clk_branch gpu_cc_cx_apb_clk = { 136 .halt_reg = 0x1088, 137 .halt_check = BRANCH_HALT, 138 .clkr = { 139 .enable_reg = 0x1088, 140 .enable_mask = BIT(0), 141 .hw.init = &(struct clk_init_data){ 142 .name = "gpu_cc_cx_apb_clk", 143 .ops = &clk_branch2_ops, 144 }, 145 }, 146 }; 147 148 static struct clk_branch gpu_cc_cx_gmu_clk = { 149 .halt_reg = 0x1098, 150 .halt_check = BRANCH_HALT, 151 .clkr = { 152 .enable_reg = 0x1098, 153 .enable_mask = BIT(0), 154 .hw.init = &(struct clk_init_data){ 155 .name = "gpu_cc_cx_gmu_clk", 156 .parent_hws = (const struct clk_hw*[]){ 157 &gpu_cc_gmu_clk_src.clkr.hw, 158 }, 159 .num_parents = 1, 160 .flags = CLK_SET_RATE_PARENT, 161 .ops = &clk_branch2_ops, 162 }, 163 }, 164 }; 165 166 static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { 167 .halt_reg = 0x108c, 168 .halt_check = BRANCH_HALT, 169 .clkr = { 170 .enable_reg = 0x108c, 171 .enable_mask = BIT(0), 172 .hw.init = &(struct clk_init_data){ 173 .name = "gpu_cc_cx_snoc_dvm_clk", 174 .ops = &clk_branch2_ops, 175 }, 176 }, 177 }; 178 179 static struct clk_branch gpu_cc_cxo_aon_clk = { 180 .halt_reg = 0x1004, 181 .halt_check = BRANCH_HALT, 182 .clkr = { 183 .enable_reg = 0x1004, 184 .enable_mask = BIT(0), 185 .hw.init = &(struct clk_init_data){ 186 .name = "gpu_cc_cxo_aon_clk", 187 .ops = &clk_branch2_ops, 188 }, 189 }, 190 }; 191 192 static struct clk_branch gpu_cc_cxo_clk = { 193 .halt_reg = 0x109c, 194 .halt_check = BRANCH_HALT, 195 .clkr = { 196 .enable_reg = 0x109c, 197 .enable_mask = BIT(0), 198 .hw.init = &(struct clk_init_data){ 199 .name = "gpu_cc_cxo_clk", 200 .ops = &clk_branch2_ops, 201 }, 202 }, 203 }; 204 205 static struct clk_branch gpu_cc_gx_gmu_clk = { 206 .halt_reg = 0x1064, 207 .halt_check = BRANCH_HALT, 208 .clkr = { 209 .enable_reg = 0x1064, 210 .enable_mask = BIT(0), 211 .hw.init = &(struct clk_init_data){ 212 .name = "gpu_cc_gx_gmu_clk", 213 .parent_hws = (const struct clk_hw*[]){ 214 &gpu_cc_gmu_clk_src.clkr.hw, 215 }, 216 .num_parents = 1, 217 .flags = CLK_SET_RATE_PARENT, 218 .ops = &clk_branch2_ops, 219 }, 220 }, 221 }; 222 223 static struct gdsc gpu_cx_gdsc = { 224 .gdscr = 0x106c, 225 .gds_hw_ctrl = 0x1540, 226 .pd = { 227 .name = "gpu_cx_gdsc", 228 }, 229 .pwrsts = PWRSTS_OFF_ON, 230 .flags = VOTABLE, 231 }; 232 233 static struct gdsc gpu_gx_gdsc = { 234 .gdscr = 0x100c, 235 .clamp_io_ctrl = 0x1508, 236 .pd = { 237 .name = "gpu_gx_gdsc", 238 .power_on = gdsc_gx_do_nothing_enable, 239 }, 240 .pwrsts = PWRSTS_OFF_ON, 241 .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR, 242 }; 243 244 static struct clk_regmap *gpu_cc_sm8150_clocks[] = { 245 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 246 [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, 247 [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, 248 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 249 [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, 250 [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, 251 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 252 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 253 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 254 [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, 255 }; 256 257 static const struct qcom_reset_map gpu_cc_sm8150_resets[] = { 258 [GPUCC_GPU_CC_CX_BCR] = { 0x1068 }, 259 [GPUCC_GPU_CC_GMU_BCR] = { 0x111c }, 260 [GPUCC_GPU_CC_GX_BCR] = { 0x1008 }, 261 [GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 }, 262 [GPUCC_GPU_CC_XO_BCR] = { 0x1000 }, 263 }; 264 265 static struct gdsc *gpu_cc_sm8150_gdscs[] = { 266 [GPU_CX_GDSC] = &gpu_cx_gdsc, 267 [GPU_GX_GDSC] = &gpu_gx_gdsc, 268 }; 269 270 static const struct regmap_config gpu_cc_sm8150_regmap_config = { 271 .reg_bits = 32, 272 .reg_stride = 4, 273 .val_bits = 32, 274 .max_register = 0x8008, 275 .fast_io = true, 276 }; 277 278 static const struct qcom_cc_desc gpu_cc_sm8150_desc = { 279 .config = &gpu_cc_sm8150_regmap_config, 280 .clks = gpu_cc_sm8150_clocks, 281 .num_clks = ARRAY_SIZE(gpu_cc_sm8150_clocks), 282 .resets = gpu_cc_sm8150_resets, 283 .num_resets = ARRAY_SIZE(gpu_cc_sm8150_resets), 284 .gdscs = gpu_cc_sm8150_gdscs, 285 .num_gdscs = ARRAY_SIZE(gpu_cc_sm8150_gdscs), 286 }; 287 288 static const struct of_device_id gpu_cc_sm8150_match_table[] = { 289 { .compatible = "qcom,sc8180x-gpucc" }, 290 { .compatible = "qcom,sm8150-gpucc" }, 291 { } 292 }; 293 MODULE_DEVICE_TABLE(of, gpu_cc_sm8150_match_table); 294 295 static int gpu_cc_sm8150_probe(struct platform_device *pdev) 296 { 297 struct regmap *regmap; 298 299 regmap = qcom_cc_map(pdev, &gpu_cc_sm8150_desc); 300 if (IS_ERR(regmap)) 301 return PTR_ERR(regmap); 302 303 if (of_device_is_compatible(pdev->dev.of_node, "qcom,sc8180x-gpucc")) 304 gpu_cc_gmu_clk_src.freq_tbl = ftbl_gpu_cc_gmu_clk_src_sc8180x; 305 306 clk_trion_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); 307 308 return qcom_cc_really_probe(&pdev->dev, &gpu_cc_sm8150_desc, regmap); 309 } 310 311 static struct platform_driver gpu_cc_sm8150_driver = { 312 .probe = gpu_cc_sm8150_probe, 313 .driver = { 314 .name = "sm8150-gpucc", 315 .of_match_table = gpu_cc_sm8150_match_table, 316 }, 317 }; 318 319 module_platform_driver(gpu_cc_sm8150_driver); 320 321 MODULE_DESCRIPTION("QTI GPUCC SM8150 Driver"); 322 MODULE_LICENSE("GPL v2"); 323