1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4 */ 5 6 #include <linux/clk-provider.h> 7 #include <linux/module.h> 8 #include <linux/of.h> 9 #include <linux/platform_device.h> 10 #include <linux/regmap.h> 11 12 #include <dt-bindings/clock/qcom,glymur-evacc.h> 13 14 #include "clk-alpha-pll.h" 15 #include "clk-branch.h" 16 #include "clk-pll.h" 17 #include "clk-rcg.h" 18 #include "clk-regmap.h" 19 #include "clk-regmap-divider.h" 20 #include "clk-regmap-mux.h" 21 #include "common.h" 22 #include "gdsc.h" 23 #include "reset.h" 24 25 enum { 26 DT_AHB_CLK, 27 DT_BI_TCXO, 28 DT_SLEEP_CLK, 29 }; 30 31 enum { 32 P_BI_TCXO, 33 P_EVA_CC_PLL0_OUT_MAIN, 34 P_SLEEP_CLK, 35 }; 36 37 static const struct pll_vco taycan_eko_t_vco[] = { 38 { 249600000, 2500000000, 0 }, 39 }; 40 41 /* 840.0 MHz Configuration */ 42 static const struct alpha_pll_config eva_cc_pll0_config = { 43 .l = 0x2b, 44 .alpha = 0xc000, 45 .config_ctl_val = 0x25c400e7, 46 .config_ctl_hi_val = 0x0a8060e0, 47 .config_ctl_hi1_val = 0xf51dea20, 48 .user_ctl_val = 0x00000008, 49 .user_ctl_hi_val = 0x00000002, 50 }; 51 52 static struct clk_alpha_pll eva_cc_pll0 = { 53 .offset = 0x0, 54 .config = &eva_cc_pll0_config, 55 .vco_table = taycan_eko_t_vco, 56 .num_vco = ARRAY_SIZE(taycan_eko_t_vco), 57 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TAYCAN_EKO_T], 58 .clkr = { 59 .hw.init = &(const struct clk_init_data) { 60 .name = "eva_cc_pll0", 61 .parent_data = &(const struct clk_parent_data) { 62 .index = DT_BI_TCXO, 63 }, 64 .num_parents = 1, 65 .ops = &clk_alpha_pll_taycan_eko_t_ops, 66 }, 67 }, 68 }; 69 70 static const struct parent_map eva_cc_parent_map_0[] = { 71 { P_BI_TCXO, 0 }, 72 }; 73 74 static const struct clk_parent_data eva_cc_parent_data_0[] = { 75 { .index = DT_BI_TCXO }, 76 }; 77 78 static const struct parent_map eva_cc_parent_map_1[] = { 79 { P_BI_TCXO, 0 }, 80 { P_EVA_CC_PLL0_OUT_MAIN, 1 }, 81 }; 82 83 static const struct clk_parent_data eva_cc_parent_data_1[] = { 84 { .index = DT_BI_TCXO }, 85 { .hw = &eva_cc_pll0.clkr.hw }, 86 }; 87 88 static const struct parent_map eva_cc_parent_map_2[] = { 89 { P_SLEEP_CLK, 0 }, 90 }; 91 92 static const struct clk_parent_data eva_cc_parent_data_2[] = { 93 { .index = DT_SLEEP_CLK }, 94 }; 95 96 static const struct freq_tbl ftbl_eva_cc_ahb_clk_src[] = { 97 F(19200000, P_BI_TCXO, 1, 0, 0), 98 { } 99 }; 100 101 static struct clk_rcg2 eva_cc_ahb_clk_src = { 102 .cmd_rcgr = 0x8018, 103 .mnd_width = 0, 104 .hid_width = 5, 105 .parent_map = eva_cc_parent_map_0, 106 .freq_tbl = ftbl_eva_cc_ahb_clk_src, 107 .hw_clk_ctrl = true, 108 .clkr = { 109 .hw.init = &(const struct clk_init_data) { 110 .name = "eva_cc_ahb_clk_src", 111 .parent_data = eva_cc_parent_data_0, 112 .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), 113 .flags = CLK_SET_RATE_PARENT, 114 .ops = &clk_rcg2_shared_ops, 115 }, 116 }, 117 }; 118 119 static const struct freq_tbl ftbl_eva_cc_mvs0_clk_src[] = { 120 F(840000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), 121 F(1050000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), 122 F(1350000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), 123 F(1500000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), 124 F(1650000000, P_EVA_CC_PLL0_OUT_MAIN, 1, 0, 0), 125 { } 126 }; 127 128 static struct clk_rcg2 eva_cc_mvs0_clk_src = { 129 .cmd_rcgr = 0x8000, 130 .mnd_width = 0, 131 .hid_width = 5, 132 .parent_map = eva_cc_parent_map_1, 133 .freq_tbl = ftbl_eva_cc_mvs0_clk_src, 134 .hw_clk_ctrl = true, 135 .clkr = { 136 .hw.init = &(const struct clk_init_data) { 137 .name = "eva_cc_mvs0_clk_src", 138 .parent_data = eva_cc_parent_data_1, 139 .num_parents = ARRAY_SIZE(eva_cc_parent_data_1), 140 .flags = CLK_SET_RATE_PARENT, 141 .ops = &clk_rcg2_shared_ops, 142 }, 143 }, 144 }; 145 146 static const struct freq_tbl ftbl_eva_cc_sleep_clk_src[] = { 147 F(32000, P_SLEEP_CLK, 1, 0, 0), 148 { } 149 }; 150 151 static struct clk_rcg2 eva_cc_sleep_clk_src = { 152 .cmd_rcgr = 0x80e0, 153 .mnd_width = 0, 154 .hid_width = 5, 155 .parent_map = eva_cc_parent_map_2, 156 .freq_tbl = ftbl_eva_cc_sleep_clk_src, 157 .hw_clk_ctrl = true, 158 .clkr = { 159 .hw.init = &(const struct clk_init_data) { 160 .name = "eva_cc_sleep_clk_src", 161 .parent_data = eva_cc_parent_data_2, 162 .num_parents = ARRAY_SIZE(eva_cc_parent_data_2), 163 .flags = CLK_SET_RATE_PARENT, 164 .ops = &clk_rcg2_shared_ops, 165 }, 166 }, 167 }; 168 169 static struct clk_rcg2 eva_cc_xo_clk_src = { 170 .cmd_rcgr = 0x80bc, 171 .mnd_width = 0, 172 .hid_width = 5, 173 .parent_map = eva_cc_parent_map_0, 174 .freq_tbl = ftbl_eva_cc_ahb_clk_src, 175 .hw_clk_ctrl = true, 176 .clkr = { 177 .hw.init = &(const struct clk_init_data) { 178 .name = "eva_cc_xo_clk_src", 179 .parent_data = eva_cc_parent_data_0, 180 .num_parents = ARRAY_SIZE(eva_cc_parent_data_0), 181 .flags = CLK_SET_RATE_PARENT, 182 .ops = &clk_rcg2_shared_ops, 183 }, 184 }, 185 }; 186 187 static struct clk_regmap_div eva_cc_mvs0_div_clk_src = { 188 .reg = 0x809c, 189 .shift = 0, 190 .width = 4, 191 .clkr.hw.init = &(const struct clk_init_data) { 192 .name = "eva_cc_mvs0_div_clk_src", 193 .parent_hws = (const struct clk_hw*[]) { 194 &eva_cc_mvs0_clk_src.clkr.hw, 195 }, 196 .num_parents = 1, 197 .flags = CLK_SET_RATE_PARENT, 198 .ops = &clk_regmap_div_ro_ops, 199 }, 200 }; 201 202 static struct clk_regmap_div eva_cc_mvs0c_div2_div_clk_src = { 203 .reg = 0x8060, 204 .shift = 0, 205 .width = 4, 206 .clkr.hw.init = &(const struct clk_init_data) { 207 .name = "eva_cc_mvs0c_div2_div_clk_src", 208 .parent_hws = (const struct clk_hw*[]) { 209 &eva_cc_mvs0_clk_src.clkr.hw, 210 }, 211 .num_parents = 1, 212 .flags = CLK_SET_RATE_PARENT, 213 .ops = &clk_regmap_div_ro_ops, 214 }, 215 }; 216 217 static struct clk_branch eva_cc_mvs0_clk = { 218 .halt_reg = 0x807c, 219 .halt_check = BRANCH_HALT_VOTED, 220 .hwcg_reg = 0x807c, 221 .hwcg_bit = 1, 222 .clkr = { 223 .enable_reg = 0x807c, 224 .enable_mask = BIT(0), 225 .hw.init = &(const struct clk_init_data) { 226 .name = "eva_cc_mvs0_clk", 227 .parent_hws = (const struct clk_hw*[]) { 228 &eva_cc_mvs0_div_clk_src.clkr.hw, 229 }, 230 .num_parents = 1, 231 .flags = CLK_SET_RATE_PARENT, 232 .ops = &clk_branch2_ops, 233 }, 234 }, 235 }; 236 237 static struct clk_branch eva_cc_mvs0_freerun_clk = { 238 .halt_reg = 0x808c, 239 .halt_check = BRANCH_HALT, 240 .clkr = { 241 .enable_reg = 0x808c, 242 .enable_mask = BIT(0), 243 .hw.init = &(const struct clk_init_data) { 244 .name = "eva_cc_mvs0_freerun_clk", 245 .parent_hws = (const struct clk_hw*[]) { 246 &eva_cc_mvs0_div_clk_src.clkr.hw, 247 }, 248 .num_parents = 1, 249 .flags = CLK_SET_RATE_PARENT, 250 .ops = &clk_branch2_ops, 251 }, 252 }, 253 }; 254 255 static struct clk_branch eva_cc_mvs0_shift_clk = { 256 .halt_reg = 0x80d8, 257 .halt_check = BRANCH_HALT_VOTED, 258 .hwcg_reg = 0x80d8, 259 .hwcg_bit = 1, 260 .clkr = { 261 .enable_reg = 0x80d8, 262 .enable_mask = BIT(0), 263 .hw.init = &(const struct clk_init_data) { 264 .name = "eva_cc_mvs0_shift_clk", 265 .parent_hws = (const struct clk_hw*[]) { 266 &eva_cc_xo_clk_src.clkr.hw, 267 }, 268 .num_parents = 1, 269 .flags = CLK_SET_RATE_PARENT, 270 .ops = &clk_branch2_ops, 271 }, 272 }, 273 }; 274 275 static struct clk_branch eva_cc_mvs0c_clk = { 276 .halt_reg = 0x804c, 277 .halt_check = BRANCH_HALT, 278 .clkr = { 279 .enable_reg = 0x804c, 280 .enable_mask = BIT(0), 281 .hw.init = &(const struct clk_init_data) { 282 .name = "eva_cc_mvs0c_clk", 283 .parent_hws = (const struct clk_hw*[]) { 284 &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, 285 }, 286 .num_parents = 1, 287 .flags = CLK_SET_RATE_PARENT, 288 .ops = &clk_branch2_ops, 289 }, 290 }, 291 }; 292 293 static struct clk_branch eva_cc_mvs0c_freerun_clk = { 294 .halt_reg = 0x805c, 295 .halt_check = BRANCH_HALT, 296 .clkr = { 297 .enable_reg = 0x805c, 298 .enable_mask = BIT(0), 299 .hw.init = &(const struct clk_init_data) { 300 .name = "eva_cc_mvs0c_freerun_clk", 301 .parent_hws = (const struct clk_hw*[]) { 302 &eva_cc_mvs0c_div2_div_clk_src.clkr.hw, 303 }, 304 .num_parents = 1, 305 .flags = CLK_SET_RATE_PARENT, 306 .ops = &clk_branch2_ops, 307 }, 308 }, 309 }; 310 311 static struct clk_branch eva_cc_mvs0c_shift_clk = { 312 .halt_reg = 0x80dc, 313 .halt_check = BRANCH_HALT_VOTED, 314 .hwcg_reg = 0x80dc, 315 .hwcg_bit = 1, 316 .clkr = { 317 .enable_reg = 0x80dc, 318 .enable_mask = BIT(0), 319 .hw.init = &(const struct clk_init_data) { 320 .name = "eva_cc_mvs0c_shift_clk", 321 .parent_hws = (const struct clk_hw*[]) { 322 &eva_cc_xo_clk_src.clkr.hw, 323 }, 324 .num_parents = 1, 325 .flags = CLK_SET_RATE_PARENT, 326 .ops = &clk_branch2_ops, 327 }, 328 }, 329 }; 330 331 static struct gdsc eva_cc_mvs0c_gdsc = { 332 .gdscr = 0x8034, 333 .en_rest_wait_val = 0x2, 334 .en_few_wait_val = 0x2, 335 .clk_dis_wait_val = 0x6, 336 .pd = { 337 .name = "eva_cc_mvs0c_gdsc", 338 }, 339 .pwrsts = PWRSTS_OFF_ON, 340 .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE, 341 }; 342 343 static struct gdsc eva_cc_mvs0_gdsc = { 344 .gdscr = 0x8068, 345 .en_rest_wait_val = 0x2, 346 .en_few_wait_val = 0x2, 347 .clk_dis_wait_val = 0x6, 348 .pd = { 349 .name = "eva_cc_mvs0_gdsc", 350 }, 351 .pwrsts = PWRSTS_OFF_ON, 352 .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE, 353 .parent = &eva_cc_mvs0c_gdsc.pd, 354 }; 355 356 static struct clk_regmap *eva_cc_glymur_clocks[] = { 357 [EVA_CC_AHB_CLK_SRC] = &eva_cc_ahb_clk_src.clkr, 358 [EVA_CC_MVS0_CLK] = &eva_cc_mvs0_clk.clkr, 359 [EVA_CC_MVS0_CLK_SRC] = &eva_cc_mvs0_clk_src.clkr, 360 [EVA_CC_MVS0_DIV_CLK_SRC] = &eva_cc_mvs0_div_clk_src.clkr, 361 [EVA_CC_MVS0_FREERUN_CLK] = &eva_cc_mvs0_freerun_clk.clkr, 362 [EVA_CC_MVS0_SHIFT_CLK] = &eva_cc_mvs0_shift_clk.clkr, 363 [EVA_CC_MVS0C_CLK] = &eva_cc_mvs0c_clk.clkr, 364 [EVA_CC_MVS0C_DIV2_DIV_CLK_SRC] = &eva_cc_mvs0c_div2_div_clk_src.clkr, 365 [EVA_CC_MVS0C_FREERUN_CLK] = &eva_cc_mvs0c_freerun_clk.clkr, 366 [EVA_CC_MVS0C_SHIFT_CLK] = &eva_cc_mvs0c_shift_clk.clkr, 367 [EVA_CC_PLL0] = &eva_cc_pll0.clkr, 368 [EVA_CC_SLEEP_CLK_SRC] = &eva_cc_sleep_clk_src.clkr, 369 [EVA_CC_XO_CLK_SRC] = &eva_cc_xo_clk_src.clkr, 370 }; 371 372 static struct gdsc *eva_cc_glymur_gdscs[] = { 373 [EVA_CC_MVS0_GDSC] = &eva_cc_mvs0_gdsc, 374 [EVA_CC_MVS0C_GDSC] = &eva_cc_mvs0c_gdsc, 375 }; 376 377 static const struct qcom_reset_map eva_cc_glymur_resets[] = { 378 [EVA_CC_INTERFACE_BCR] = { 0x80a0 }, 379 [EVA_CC_MVS0_BCR] = { 0x8064 }, 380 [EVA_CC_MVS0C_CLK_ARES] = { 0x804c, 2 }, 381 [EVA_CC_MVS0C_BCR] = { 0x8030 }, 382 [EVA_CC_MVS0C_FREERUN_CLK_ARES] = { 0x805c, 2 }, 383 }; 384 385 static struct clk_alpha_pll *eva_cc_glymur_plls[] = { 386 &eva_cc_pll0, 387 }; 388 389 static const u32 eva_cc_glymur_critical_cbcrs[] = { 390 0x80a4, /* EVA_CC_AHB_CLK */ 391 0x80f8, /* EVA_CC_SLEEP_CLK */ 392 0x80d4, /* EVA_CC_XO_CLK */ 393 }; 394 395 static const struct regmap_config eva_cc_glymur_regmap_config = { 396 .reg_bits = 32, 397 .reg_stride = 4, 398 .val_bits = 32, 399 .max_register = 0x9f50, 400 .fast_io = true, 401 }; 402 403 static void clk_glymur_regs_configure(struct device *dev, struct regmap *regmap) 404 { 405 /* 406 * Update CTRL_IN register as per HW recommendation to ensure clocks 407 * stay cycle‑aligned when the EVA core is ON. 408 */ 409 regmap_set_bits(regmap, 0x9f24, BIT(0)); 410 } 411 412 static const struct qcom_cc_driver_data eva_cc_glymur_driver_data = { 413 .alpha_plls = eva_cc_glymur_plls, 414 .num_alpha_plls = ARRAY_SIZE(eva_cc_glymur_plls), 415 .clk_cbcrs = eva_cc_glymur_critical_cbcrs, 416 .num_clk_cbcrs = ARRAY_SIZE(eva_cc_glymur_critical_cbcrs), 417 .clk_regs_configure = clk_glymur_regs_configure, 418 }; 419 420 static const struct qcom_cc_desc eva_cc_glymur_desc = { 421 .config = &eva_cc_glymur_regmap_config, 422 .clks = eva_cc_glymur_clocks, 423 .num_clks = ARRAY_SIZE(eva_cc_glymur_clocks), 424 .resets = eva_cc_glymur_resets, 425 .num_resets = ARRAY_SIZE(eva_cc_glymur_resets), 426 .gdscs = eva_cc_glymur_gdscs, 427 .num_gdscs = ARRAY_SIZE(eva_cc_glymur_gdscs), 428 .use_rpm = true, 429 .driver_data = &eva_cc_glymur_driver_data, 430 }; 431 432 static const struct of_device_id eva_cc_glymur_match_table[] = { 433 { .compatible = "qcom,glymur-evacc" }, 434 { } 435 }; 436 MODULE_DEVICE_TABLE(of, eva_cc_glymur_match_table); 437 438 static int eva_cc_glymur_probe(struct platform_device *pdev) 439 { 440 return qcom_cc_probe(pdev, &eva_cc_glymur_desc); 441 } 442 443 static struct platform_driver eva_cc_glymur_driver = { 444 .probe = eva_cc_glymur_probe, 445 .driver = { 446 .name = "evacc-glymur", 447 .of_match_table = eva_cc_glymur_match_table, 448 }, 449 }; 450 451 module_platform_driver(eva_cc_glymur_driver); 452 453 MODULE_DESCRIPTION("QTI EVACC Glymur Driver"); 454 MODULE_LICENSE("GPL"); 455