1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015 The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/err.h> 8 #include <linux/platform_device.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/of_device.h> 12 #include <linux/clk-provider.h> 13 #include <linux/regmap.h> 14 #include <linux/reset-controller.h> 15 #include <linux/math64.h> 16 #include <linux/delay.h> 17 #include <linux/clk.h> 18 19 #include <dt-bindings/clock/qcom,gcc-ipq4019.h> 20 21 #include "common.h" 22 #include "clk-regmap.h" 23 #include "clk-rcg.h" 24 #include "clk-branch.h" 25 #include "reset.h" 26 #include "clk-regmap-divider.h" 27 28 #define to_clk_regmap_div(_hw) container_of(to_clk_regmap(_hw),\ 29 struct clk_regmap_div, clkr) 30 31 #define to_clk_fepll(_hw) container_of(to_clk_regmap_div(_hw),\ 32 struct clk_fepll, cdiv) 33 34 enum { 35 P_XO, 36 P_FEPLL200, 37 P_FEPLL500, 38 P_DDRPLL, 39 P_FEPLLWCSS2G, 40 P_FEPLLWCSS5G, 41 P_FEPLL125DLY, 42 P_DDRPLLAPSS, 43 }; 44 45 /* 46 * struct clk_fepll_vco - vco feedback divider corresponds for FEPLL clocks 47 * @fdbkdiv_shift: lowest bit for FDBKDIV 48 * @fdbkdiv_width: number of bits in FDBKDIV 49 * @refclkdiv_shift: lowest bit for REFCLKDIV 50 * @refclkdiv_width: number of bits in REFCLKDIV 51 * @reg: PLL_DIV register address 52 */ 53 struct clk_fepll_vco { 54 u32 fdbkdiv_shift; 55 u32 fdbkdiv_width; 56 u32 refclkdiv_shift; 57 u32 refclkdiv_width; 58 u32 reg; 59 }; 60 61 /* 62 * struct clk_fepll - clk divider corresponds to FEPLL clocks 63 * @fixed_div: fixed divider value if divider is fixed 64 * @parent_map: map from software's parent index to hardware's src_sel field 65 * @cdiv: divider values for PLL_DIV 66 * @pll_vco: vco feedback divider 67 * @div_table: mapping for actual divider value to register divider value 68 * in case of non fixed divider 69 * @freq_tbl: frequency table 70 */ 71 struct clk_fepll { 72 u32 fixed_div; 73 const u8 *parent_map; 74 struct clk_regmap_div cdiv; 75 const struct clk_fepll_vco *pll_vco; 76 const struct clk_div_table *div_table; 77 const struct freq_tbl *freq_tbl; 78 }; 79 80 static struct parent_map gcc_xo_200_500_map[] = { 81 { P_XO, 0 }, 82 { P_FEPLL200, 1 }, 83 { P_FEPLL500, 2 }, 84 }; 85 86 static const char * const gcc_xo_200_500[] = { 87 "xo", 88 "fepll200", 89 "fepll500", 90 }; 91 92 static struct parent_map gcc_xo_200_map[] = { 93 { P_XO, 0 }, 94 { P_FEPLL200, 1 }, 95 }; 96 97 static const char * const gcc_xo_200[] = { 98 "xo", 99 "fepll200", 100 }; 101 102 static struct parent_map gcc_xo_200_spi_map[] = { 103 { P_XO, 0 }, 104 { P_FEPLL200, 2 }, 105 }; 106 107 static const char * const gcc_xo_200_spi[] = { 108 "xo", 109 "fepll200", 110 }; 111 112 static struct parent_map gcc_xo_sdcc1_500_map[] = { 113 { P_XO, 0 }, 114 { P_DDRPLL, 1 }, 115 { P_FEPLL500, 2 }, 116 }; 117 118 static const char * const gcc_xo_sdcc1_500[] = { 119 "xo", 120 "ddrpllsdcc", 121 "fepll500", 122 }; 123 124 static struct parent_map gcc_xo_wcss2g_map[] = { 125 { P_XO, 0 }, 126 { P_FEPLLWCSS2G, 1 }, 127 }; 128 129 static const char * const gcc_xo_wcss2g[] = { 130 "xo", 131 "fepllwcss2g", 132 }; 133 134 static struct parent_map gcc_xo_wcss5g_map[] = { 135 { P_XO, 0 }, 136 { P_FEPLLWCSS5G, 1 }, 137 }; 138 139 static const char * const gcc_xo_wcss5g[] = { 140 "xo", 141 "fepllwcss5g", 142 }; 143 144 static struct parent_map gcc_xo_125_dly_map[] = { 145 { P_XO, 0 }, 146 { P_FEPLL125DLY, 1 }, 147 }; 148 149 static const char * const gcc_xo_125_dly[] = { 150 "xo", 151 "fepll125dly", 152 }; 153 154 static struct parent_map gcc_xo_ddr_500_200_map[] = { 155 { P_XO, 0 }, 156 { P_FEPLL200, 3 }, 157 { P_FEPLL500, 2 }, 158 { P_DDRPLLAPSS, 1 }, 159 }; 160 161 /* 162 * Contains index for safe clock during APSS freq change. 163 * fepll500 is being used as safe clock so initialize it 164 * with its index in parents list gcc_xo_ddr_500_200. 165 */ 166 static const int gcc_ipq4019_cpu_safe_parent = 2; 167 static const char * const gcc_xo_ddr_500_200[] = { 168 "xo", 169 "fepll200", 170 "fepll500", 171 "ddrpllapss", 172 }; 173 174 static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] = { 175 F(48000000, P_XO, 1, 0, 0), 176 F(200000000, P_FEPLL200, 1, 0, 0), 177 { } 178 }; 179 180 static struct clk_rcg2 audio_clk_src = { 181 .cmd_rcgr = 0x1b000, 182 .hid_width = 5, 183 .parent_map = gcc_xo_200_map, 184 .freq_tbl = ftbl_gcc_audio_pwm_clk, 185 .clkr.hw.init = &(struct clk_init_data){ 186 .name = "audio_clk_src", 187 .parent_names = gcc_xo_200, 188 .num_parents = 2, 189 .ops = &clk_rcg2_ops, 190 191 }, 192 }; 193 194 static struct clk_branch gcc_audio_ahb_clk = { 195 .halt_reg = 0x1b010, 196 .clkr = { 197 .enable_reg = 0x1b010, 198 .enable_mask = BIT(0), 199 .hw.init = &(struct clk_init_data){ 200 .name = "gcc_audio_ahb_clk", 201 .parent_names = (const char *[]){ 202 "pcnoc_clk_src", 203 }, 204 .flags = CLK_SET_RATE_PARENT, 205 .num_parents = 1, 206 .ops = &clk_branch2_ops, 207 }, 208 }, 209 }; 210 211 static struct clk_branch gcc_audio_pwm_clk = { 212 .halt_reg = 0x1b00C, 213 .clkr = { 214 .enable_reg = 0x1b00C, 215 .enable_mask = BIT(0), 216 .hw.init = &(struct clk_init_data){ 217 .name = "gcc_audio_pwm_clk", 218 .parent_names = (const char *[]){ 219 "audio_clk_src", 220 }, 221 .flags = CLK_SET_RATE_PARENT, 222 .num_parents = 1, 223 .ops = &clk_branch2_ops, 224 }, 225 }, 226 }; 227 228 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = { 229 F(19050000, P_FEPLL200, 10.5, 1, 1), 230 { } 231 }; 232 233 static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { 234 .cmd_rcgr = 0x200c, 235 .hid_width = 5, 236 .parent_map = gcc_xo_200_map, 237 .freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk, 238 .clkr.hw.init = &(struct clk_init_data){ 239 .name = "blsp1_qup1_i2c_apps_clk_src", 240 .parent_names = gcc_xo_200, 241 .num_parents = 2, 242 .ops = &clk_rcg2_ops, 243 }, 244 }; 245 246 static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { 247 .halt_reg = 0x2008, 248 .clkr = { 249 .enable_reg = 0x2008, 250 .enable_mask = BIT(0), 251 .hw.init = &(struct clk_init_data){ 252 .name = "gcc_blsp1_qup1_i2c_apps_clk", 253 .parent_names = (const char *[]){ 254 "blsp1_qup1_i2c_apps_clk_src", 255 }, 256 .num_parents = 1, 257 .ops = &clk_branch2_ops, 258 .flags = CLK_SET_RATE_PARENT, 259 }, 260 }, 261 }; 262 263 static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = { 264 .cmd_rcgr = 0x3000, 265 .hid_width = 5, 266 .parent_map = gcc_xo_200_map, 267 .freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk, 268 .clkr.hw.init = &(struct clk_init_data){ 269 .name = "blsp1_qup2_i2c_apps_clk_src", 270 .parent_names = gcc_xo_200, 271 .num_parents = 2, 272 .ops = &clk_rcg2_ops, 273 }, 274 }; 275 276 static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { 277 .halt_reg = 0x3010, 278 .clkr = { 279 .enable_reg = 0x3010, 280 .enable_mask = BIT(0), 281 .hw.init = &(struct clk_init_data){ 282 .name = "gcc_blsp1_qup2_i2c_apps_clk", 283 .parent_names = (const char *[]){ 284 "blsp1_qup2_i2c_apps_clk_src", 285 }, 286 .num_parents = 1, 287 .ops = &clk_branch2_ops, 288 .flags = CLK_SET_RATE_PARENT, 289 }, 290 }, 291 }; 292 293 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_spi_apps_clk[] = { 294 F(960000, P_XO, 12, 1, 4), 295 F(4800000, P_XO, 1, 1, 10), 296 F(9600000, P_XO, 1, 1, 5), 297 F(15000000, P_XO, 1, 1, 3), 298 F(19200000, P_XO, 1, 2, 5), 299 F(24000000, P_XO, 1, 1, 2), 300 F(48000000, P_XO, 1, 0, 0), 301 { } 302 }; 303 304 static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = { 305 .cmd_rcgr = 0x2024, 306 .mnd_width = 8, 307 .hid_width = 5, 308 .parent_map = gcc_xo_200_spi_map, 309 .freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk, 310 .clkr.hw.init = &(struct clk_init_data){ 311 .name = "blsp1_qup1_spi_apps_clk_src", 312 .parent_names = gcc_xo_200_spi, 313 .num_parents = 2, 314 .ops = &clk_rcg2_ops, 315 }, 316 }; 317 318 static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { 319 .halt_reg = 0x2004, 320 .clkr = { 321 .enable_reg = 0x2004, 322 .enable_mask = BIT(0), 323 .hw.init = &(struct clk_init_data){ 324 .name = "gcc_blsp1_qup1_spi_apps_clk", 325 .parent_names = (const char *[]){ 326 "blsp1_qup1_spi_apps_clk_src", 327 }, 328 .num_parents = 1, 329 .ops = &clk_branch2_ops, 330 .flags = CLK_SET_RATE_PARENT, 331 }, 332 }, 333 }; 334 335 static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = { 336 .cmd_rcgr = 0x3014, 337 .mnd_width = 8, 338 .hid_width = 5, 339 .freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk, 340 .parent_map = gcc_xo_200_spi_map, 341 .clkr.hw.init = &(struct clk_init_data){ 342 .name = "blsp1_qup2_spi_apps_clk_src", 343 .parent_names = gcc_xo_200_spi, 344 .num_parents = 2, 345 .ops = &clk_rcg2_ops, 346 }, 347 }; 348 349 static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { 350 .halt_reg = 0x300c, 351 .clkr = { 352 .enable_reg = 0x300c, 353 .enable_mask = BIT(0), 354 .hw.init = &(struct clk_init_data){ 355 .name = "gcc_blsp1_qup2_spi_apps_clk", 356 .parent_names = (const char *[]){ 357 "blsp1_qup2_spi_apps_clk_src", 358 }, 359 .num_parents = 1, 360 .ops = &clk_branch2_ops, 361 .flags = CLK_SET_RATE_PARENT, 362 }, 363 }, 364 }; 365 366 static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] = { 367 F(1843200, P_FEPLL200, 1, 144, 15625), 368 F(3686400, P_FEPLL200, 1, 288, 15625), 369 F(7372800, P_FEPLL200, 1, 576, 15625), 370 F(14745600, P_FEPLL200, 1, 1152, 15625), 371 F(16000000, P_FEPLL200, 1, 2, 25), 372 F(24000000, P_XO, 1, 1, 2), 373 F(32000000, P_FEPLL200, 1, 4, 25), 374 F(40000000, P_FEPLL200, 1, 1, 5), 375 F(46400000, P_FEPLL200, 1, 29, 125), 376 F(48000000, P_XO, 1, 0, 0), 377 { } 378 }; 379 380 static struct clk_rcg2 blsp1_uart1_apps_clk_src = { 381 .cmd_rcgr = 0x2044, 382 .mnd_width = 16, 383 .hid_width = 5, 384 .freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk, 385 .parent_map = gcc_xo_200_spi_map, 386 .clkr.hw.init = &(struct clk_init_data){ 387 .name = "blsp1_uart1_apps_clk_src", 388 .parent_names = gcc_xo_200_spi, 389 .num_parents = 2, 390 .ops = &clk_rcg2_ops, 391 }, 392 }; 393 394 static struct clk_branch gcc_blsp1_uart1_apps_clk = { 395 .halt_reg = 0x203c, 396 .clkr = { 397 .enable_reg = 0x203c, 398 .enable_mask = BIT(0), 399 .hw.init = &(struct clk_init_data){ 400 .name = "gcc_blsp1_uart1_apps_clk", 401 .parent_names = (const char *[]){ 402 "blsp1_uart1_apps_clk_src", 403 }, 404 .flags = CLK_SET_RATE_PARENT, 405 .num_parents = 1, 406 .ops = &clk_branch2_ops, 407 }, 408 }, 409 }; 410 411 static struct clk_rcg2 blsp1_uart2_apps_clk_src = { 412 .cmd_rcgr = 0x3034, 413 .mnd_width = 16, 414 .hid_width = 5, 415 .freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk, 416 .parent_map = gcc_xo_200_spi_map, 417 .clkr.hw.init = &(struct clk_init_data){ 418 .name = "blsp1_uart2_apps_clk_src", 419 .parent_names = gcc_xo_200_spi, 420 .num_parents = 2, 421 .ops = &clk_rcg2_ops, 422 }, 423 }; 424 425 static struct clk_branch gcc_blsp1_uart2_apps_clk = { 426 .halt_reg = 0x302c, 427 .clkr = { 428 .enable_reg = 0x302c, 429 .enable_mask = BIT(0), 430 .hw.init = &(struct clk_init_data){ 431 .name = "gcc_blsp1_uart2_apps_clk", 432 .parent_names = (const char *[]){ 433 "blsp1_uart2_apps_clk_src", 434 }, 435 .num_parents = 1, 436 .ops = &clk_branch2_ops, 437 .flags = CLK_SET_RATE_PARENT, 438 }, 439 }, 440 }; 441 442 static const struct freq_tbl ftbl_gcc_gp_clk[] = { 443 F(1250000, P_FEPLL200, 1, 16, 0), 444 F(2500000, P_FEPLL200, 1, 8, 0), 445 F(5000000, P_FEPLL200, 1, 4, 0), 446 { } 447 }; 448 449 static struct clk_rcg2 gp1_clk_src = { 450 .cmd_rcgr = 0x8004, 451 .mnd_width = 8, 452 .hid_width = 5, 453 .freq_tbl = ftbl_gcc_gp_clk, 454 .parent_map = gcc_xo_200_map, 455 .clkr.hw.init = &(struct clk_init_data){ 456 .name = "gp1_clk_src", 457 .parent_names = gcc_xo_200, 458 .num_parents = 2, 459 .ops = &clk_rcg2_ops, 460 }, 461 }; 462 463 static struct clk_branch gcc_gp1_clk = { 464 .halt_reg = 0x8000, 465 .clkr = { 466 .enable_reg = 0x8000, 467 .enable_mask = BIT(0), 468 .hw.init = &(struct clk_init_data){ 469 .name = "gcc_gp1_clk", 470 .parent_names = (const char *[]){ 471 "gp1_clk_src", 472 }, 473 .num_parents = 1, 474 .ops = &clk_branch2_ops, 475 .flags = CLK_SET_RATE_PARENT, 476 }, 477 }, 478 }; 479 480 static struct clk_rcg2 gp2_clk_src = { 481 .cmd_rcgr = 0x9004, 482 .mnd_width = 8, 483 .hid_width = 5, 484 .freq_tbl = ftbl_gcc_gp_clk, 485 .parent_map = gcc_xo_200_map, 486 .clkr.hw.init = &(struct clk_init_data){ 487 .name = "gp2_clk_src", 488 .parent_names = gcc_xo_200, 489 .num_parents = 2, 490 .ops = &clk_rcg2_ops, 491 }, 492 }; 493 494 static struct clk_branch gcc_gp2_clk = { 495 .halt_reg = 0x9000, 496 .clkr = { 497 .enable_reg = 0x9000, 498 .enable_mask = BIT(0), 499 .hw.init = &(struct clk_init_data){ 500 .name = "gcc_gp2_clk", 501 .parent_names = (const char *[]){ 502 "gp2_clk_src", 503 }, 504 .num_parents = 1, 505 .ops = &clk_branch2_ops, 506 .flags = CLK_SET_RATE_PARENT, 507 }, 508 }, 509 }; 510 511 static struct clk_rcg2 gp3_clk_src = { 512 .cmd_rcgr = 0xa004, 513 .mnd_width = 8, 514 .hid_width = 5, 515 .freq_tbl = ftbl_gcc_gp_clk, 516 .parent_map = gcc_xo_200_map, 517 .clkr.hw.init = &(struct clk_init_data){ 518 .name = "gp3_clk_src", 519 .parent_names = gcc_xo_200, 520 .num_parents = 2, 521 .ops = &clk_rcg2_ops, 522 }, 523 }; 524 525 static struct clk_branch gcc_gp3_clk = { 526 .halt_reg = 0xa000, 527 .clkr = { 528 .enable_reg = 0xa000, 529 .enable_mask = BIT(0), 530 .hw.init = &(struct clk_init_data){ 531 .name = "gcc_gp3_clk", 532 .parent_names = (const char *[]){ 533 "gp3_clk_src", 534 }, 535 .num_parents = 1, 536 .ops = &clk_branch2_ops, 537 .flags = CLK_SET_RATE_PARENT, 538 }, 539 }, 540 }; 541 542 static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = { 543 F(144000, P_XO, 1, 3, 240), 544 F(400000, P_XO, 1, 1, 0), 545 F(20000000, P_FEPLL500, 1, 1, 25), 546 F(25000000, P_FEPLL500, 1, 1, 20), 547 F(50000000, P_FEPLL500, 1, 1, 10), 548 F(100000000, P_FEPLL500, 1, 1, 5), 549 F(192000000, P_DDRPLL, 1, 0, 0), 550 { } 551 }; 552 553 static struct clk_rcg2 sdcc1_apps_clk_src = { 554 .cmd_rcgr = 0x18004, 555 .hid_width = 5, 556 .freq_tbl = ftbl_gcc_sdcc1_apps_clk, 557 .parent_map = gcc_xo_sdcc1_500_map, 558 .clkr.hw.init = &(struct clk_init_data){ 559 .name = "sdcc1_apps_clk_src", 560 .parent_names = gcc_xo_sdcc1_500, 561 .num_parents = 3, 562 .ops = &clk_rcg2_ops, 563 .flags = CLK_SET_RATE_PARENT, 564 }, 565 }; 566 567 static const struct freq_tbl ftbl_gcc_apps_clk[] = { 568 F(48000000, P_XO, 1, 0, 0), 569 F(200000000, P_FEPLL200, 1, 0, 0), 570 F(384000000, P_DDRPLLAPSS, 1, 0, 0), 571 F(413000000, P_DDRPLLAPSS, 1, 0, 0), 572 F(448000000, P_DDRPLLAPSS, 1, 0, 0), 573 F(488000000, P_DDRPLLAPSS, 1, 0, 0), 574 F(500000000, P_FEPLL500, 1, 0, 0), 575 F(512000000, P_DDRPLLAPSS, 1, 0, 0), 576 F(537000000, P_DDRPLLAPSS, 1, 0, 0), 577 F(565000000, P_DDRPLLAPSS, 1, 0, 0), 578 F(597000000, P_DDRPLLAPSS, 1, 0, 0), 579 F(632000000, P_DDRPLLAPSS, 1, 0, 0), 580 F(672000000, P_DDRPLLAPSS, 1, 0, 0), 581 F(716000000, P_DDRPLLAPSS, 1, 0, 0), 582 { } 583 }; 584 585 static struct clk_rcg2 apps_clk_src = { 586 .cmd_rcgr = 0x1900c, 587 .hid_width = 5, 588 .freq_tbl = ftbl_gcc_apps_clk, 589 .parent_map = gcc_xo_ddr_500_200_map, 590 .clkr.hw.init = &(struct clk_init_data){ 591 .name = "apps_clk_src", 592 .parent_names = gcc_xo_ddr_500_200, 593 .num_parents = 4, 594 .ops = &clk_rcg2_ops, 595 .flags = CLK_SET_RATE_PARENT, 596 }, 597 }; 598 599 static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] = { 600 F(48000000, P_XO, 1, 0, 0), 601 F(100000000, P_FEPLL200, 2, 0, 0), 602 { } 603 }; 604 605 static struct clk_rcg2 apps_ahb_clk_src = { 606 .cmd_rcgr = 0x19014, 607 .hid_width = 5, 608 .parent_map = gcc_xo_200_500_map, 609 .freq_tbl = ftbl_gcc_apps_ahb_clk, 610 .clkr.hw.init = &(struct clk_init_data){ 611 .name = "apps_ahb_clk_src", 612 .parent_names = gcc_xo_200_500, 613 .num_parents = 3, 614 .ops = &clk_rcg2_ops, 615 }, 616 }; 617 618 static struct clk_branch gcc_apss_ahb_clk = { 619 .halt_reg = 0x19004, 620 .halt_check = BRANCH_HALT_VOTED, 621 .clkr = { 622 .enable_reg = 0x6000, 623 .enable_mask = BIT(14), 624 .hw.init = &(struct clk_init_data){ 625 .name = "gcc_apss_ahb_clk", 626 .parent_names = (const char *[]){ 627 "apps_ahb_clk_src", 628 }, 629 .num_parents = 1, 630 .ops = &clk_branch2_ops, 631 .flags = CLK_SET_RATE_PARENT, 632 }, 633 }, 634 }; 635 636 static struct clk_branch gcc_blsp1_ahb_clk = { 637 .halt_reg = 0x1008, 638 .halt_check = BRANCH_HALT_VOTED, 639 .clkr = { 640 .enable_reg = 0x6000, 641 .enable_mask = BIT(10), 642 .hw.init = &(struct clk_init_data){ 643 .name = "gcc_blsp1_ahb_clk", 644 .parent_names = (const char *[]){ 645 "pcnoc_clk_src", 646 }, 647 .num_parents = 1, 648 .ops = &clk_branch2_ops, 649 }, 650 }, 651 }; 652 653 static struct clk_branch gcc_dcd_xo_clk = { 654 .halt_reg = 0x2103c, 655 .clkr = { 656 .enable_reg = 0x2103c, 657 .enable_mask = BIT(0), 658 .hw.init = &(struct clk_init_data){ 659 .name = "gcc_dcd_xo_clk", 660 .parent_names = (const char *[]){ 661 "xo", 662 }, 663 .num_parents = 1, 664 .ops = &clk_branch2_ops, 665 }, 666 }, 667 }; 668 669 static struct clk_branch gcc_boot_rom_ahb_clk = { 670 .halt_reg = 0x1300c, 671 .clkr = { 672 .enable_reg = 0x1300c, 673 .enable_mask = BIT(0), 674 .hw.init = &(struct clk_init_data){ 675 .name = "gcc_boot_rom_ahb_clk", 676 .parent_names = (const char *[]){ 677 "pcnoc_clk_src", 678 }, 679 .num_parents = 1, 680 .ops = &clk_branch2_ops, 681 .flags = CLK_SET_RATE_PARENT, 682 }, 683 }, 684 }; 685 686 static struct clk_branch gcc_crypto_ahb_clk = { 687 .halt_reg = 0x16024, 688 .halt_check = BRANCH_HALT_VOTED, 689 .clkr = { 690 .enable_reg = 0x6000, 691 .enable_mask = BIT(0), 692 .hw.init = &(struct clk_init_data){ 693 .name = "gcc_crypto_ahb_clk", 694 .parent_names = (const char *[]){ 695 "pcnoc_clk_src", 696 }, 697 .num_parents = 1, 698 .ops = &clk_branch2_ops, 699 }, 700 }, 701 }; 702 703 static struct clk_branch gcc_crypto_axi_clk = { 704 .halt_reg = 0x16020, 705 .halt_check = BRANCH_HALT_VOTED, 706 .clkr = { 707 .enable_reg = 0x6000, 708 .enable_mask = BIT(1), 709 .hw.init = &(struct clk_init_data){ 710 .name = "gcc_crypto_axi_clk", 711 .parent_names = (const char *[]){ 712 "fepll125", 713 }, 714 .num_parents = 1, 715 .ops = &clk_branch2_ops, 716 }, 717 }, 718 }; 719 720 static struct clk_branch gcc_crypto_clk = { 721 .halt_reg = 0x1601c, 722 .halt_check = BRANCH_HALT_VOTED, 723 .clkr = { 724 .enable_reg = 0x6000, 725 .enable_mask = BIT(2), 726 .hw.init = &(struct clk_init_data){ 727 .name = "gcc_crypto_clk", 728 .parent_names = (const char *[]){ 729 "fepll125", 730 }, 731 .num_parents = 1, 732 .ops = &clk_branch2_ops, 733 }, 734 }, 735 }; 736 737 static struct clk_branch gcc_ess_clk = { 738 .halt_reg = 0x12010, 739 .clkr = { 740 .enable_reg = 0x12010, 741 .enable_mask = BIT(0), 742 .hw.init = &(struct clk_init_data){ 743 .name = "gcc_ess_clk", 744 .parent_names = (const char *[]){ 745 "fephy_125m_dly_clk_src", 746 }, 747 .num_parents = 1, 748 .ops = &clk_branch2_ops, 749 .flags = CLK_SET_RATE_PARENT, 750 }, 751 }, 752 }; 753 754 static struct clk_branch gcc_imem_axi_clk = { 755 .halt_reg = 0xe004, 756 .halt_check = BRANCH_HALT_VOTED, 757 .clkr = { 758 .enable_reg = 0x6000, 759 .enable_mask = BIT(17), 760 .hw.init = &(struct clk_init_data){ 761 .name = "gcc_imem_axi_clk", 762 .parent_names = (const char *[]){ 763 "fepll200", 764 }, 765 .num_parents = 1, 766 .ops = &clk_branch2_ops, 767 }, 768 }, 769 }; 770 771 static struct clk_branch gcc_imem_cfg_ahb_clk = { 772 .halt_reg = 0xe008, 773 .clkr = { 774 .enable_reg = 0xe008, 775 .enable_mask = BIT(0), 776 .hw.init = &(struct clk_init_data){ 777 .name = "gcc_imem_cfg_ahb_clk", 778 .parent_names = (const char *[]){ 779 "pcnoc_clk_src", 780 }, 781 .num_parents = 1, 782 .ops = &clk_branch2_ops, 783 }, 784 }, 785 }; 786 787 static struct clk_branch gcc_pcie_ahb_clk = { 788 .halt_reg = 0x1d00c, 789 .clkr = { 790 .enable_reg = 0x1d00c, 791 .enable_mask = BIT(0), 792 .hw.init = &(struct clk_init_data){ 793 .name = "gcc_pcie_ahb_clk", 794 .parent_names = (const char *[]){ 795 "pcnoc_clk_src", 796 }, 797 .num_parents = 1, 798 .ops = &clk_branch2_ops, 799 }, 800 }, 801 }; 802 803 static struct clk_branch gcc_pcie_axi_m_clk = { 804 .halt_reg = 0x1d004, 805 .clkr = { 806 .enable_reg = 0x1d004, 807 .enable_mask = BIT(0), 808 .hw.init = &(struct clk_init_data){ 809 .name = "gcc_pcie_axi_m_clk", 810 .parent_names = (const char *[]){ 811 "fepll200", 812 }, 813 .num_parents = 1, 814 .ops = &clk_branch2_ops, 815 }, 816 }, 817 }; 818 819 static struct clk_branch gcc_pcie_axi_s_clk = { 820 .halt_reg = 0x1d008, 821 .clkr = { 822 .enable_reg = 0x1d008, 823 .enable_mask = BIT(0), 824 .hw.init = &(struct clk_init_data){ 825 .name = "gcc_pcie_axi_s_clk", 826 .parent_names = (const char *[]){ 827 "fepll200", 828 }, 829 .num_parents = 1, 830 .ops = &clk_branch2_ops, 831 }, 832 }, 833 }; 834 835 static struct clk_branch gcc_prng_ahb_clk = { 836 .halt_reg = 0x13004, 837 .halt_check = BRANCH_HALT_VOTED, 838 .clkr = { 839 .enable_reg = 0x6000, 840 .enable_mask = BIT(8), 841 .hw.init = &(struct clk_init_data){ 842 .name = "gcc_prng_ahb_clk", 843 .parent_names = (const char *[]){ 844 "pcnoc_clk_src", 845 }, 846 .num_parents = 1, 847 .ops = &clk_branch2_ops, 848 }, 849 }, 850 }; 851 852 static struct clk_branch gcc_qpic_ahb_clk = { 853 .halt_reg = 0x1c008, 854 .clkr = { 855 .enable_reg = 0x1c008, 856 .enable_mask = BIT(0), 857 .hw.init = &(struct clk_init_data){ 858 .name = "gcc_qpic_ahb_clk", 859 .parent_names = (const char *[]){ 860 "pcnoc_clk_src", 861 }, 862 .num_parents = 1, 863 .ops = &clk_branch2_ops, 864 }, 865 }, 866 }; 867 868 static struct clk_branch gcc_qpic_clk = { 869 .halt_reg = 0x1c004, 870 .clkr = { 871 .enable_reg = 0x1c004, 872 .enable_mask = BIT(0), 873 .hw.init = &(struct clk_init_data){ 874 .name = "gcc_qpic_clk", 875 .parent_names = (const char *[]){ 876 "pcnoc_clk_src", 877 }, 878 .num_parents = 1, 879 .ops = &clk_branch2_ops, 880 }, 881 }, 882 }; 883 884 static struct clk_branch gcc_sdcc1_ahb_clk = { 885 .halt_reg = 0x18010, 886 .clkr = { 887 .enable_reg = 0x18010, 888 .enable_mask = BIT(0), 889 .hw.init = &(struct clk_init_data){ 890 .name = "gcc_sdcc1_ahb_clk", 891 .parent_names = (const char *[]){ 892 "pcnoc_clk_src", 893 }, 894 .num_parents = 1, 895 .ops = &clk_branch2_ops, 896 }, 897 }, 898 }; 899 900 static struct clk_branch gcc_sdcc1_apps_clk = { 901 .halt_reg = 0x1800c, 902 .clkr = { 903 .enable_reg = 0x1800c, 904 .enable_mask = BIT(0), 905 .hw.init = &(struct clk_init_data){ 906 .name = "gcc_sdcc1_apps_clk", 907 .parent_names = (const char *[]){ 908 "sdcc1_apps_clk_src", 909 }, 910 .num_parents = 1, 911 .ops = &clk_branch2_ops, 912 .flags = CLK_SET_RATE_PARENT, 913 }, 914 }, 915 }; 916 917 static struct clk_branch gcc_tlmm_ahb_clk = { 918 .halt_reg = 0x5004, 919 .halt_check = BRANCH_HALT_VOTED, 920 .clkr = { 921 .enable_reg = 0x6000, 922 .enable_mask = BIT(5), 923 .hw.init = &(struct clk_init_data){ 924 .name = "gcc_tlmm_ahb_clk", 925 .parent_names = (const char *[]){ 926 "pcnoc_clk_src", 927 }, 928 .num_parents = 1, 929 .ops = &clk_branch2_ops, 930 }, 931 }, 932 }; 933 934 static struct clk_branch gcc_usb2_master_clk = { 935 .halt_reg = 0x1e00c, 936 .clkr = { 937 .enable_reg = 0x1e00c, 938 .enable_mask = BIT(0), 939 .hw.init = &(struct clk_init_data){ 940 .name = "gcc_usb2_master_clk", 941 .parent_names = (const char *[]){ 942 "pcnoc_clk_src", 943 }, 944 .num_parents = 1, 945 .ops = &clk_branch2_ops, 946 }, 947 }, 948 }; 949 950 static struct clk_branch gcc_usb2_sleep_clk = { 951 .halt_reg = 0x1e010, 952 .clkr = { 953 .enable_reg = 0x1e010, 954 .enable_mask = BIT(0), 955 .hw.init = &(struct clk_init_data){ 956 .name = "gcc_usb2_sleep_clk", 957 .parent_names = (const char *[]){ 958 "gcc_sleep_clk_src", 959 }, 960 .num_parents = 1, 961 .ops = &clk_branch2_ops, 962 }, 963 }, 964 }; 965 966 static struct clk_branch gcc_usb2_mock_utmi_clk = { 967 .halt_reg = 0x1e014, 968 .clkr = { 969 .enable_reg = 0x1e014, 970 .enable_mask = BIT(0), 971 .hw.init = &(struct clk_init_data){ 972 .name = "gcc_usb2_mock_utmi_clk", 973 .parent_names = (const char *[]){ 974 "usb30_mock_utmi_clk_src", 975 }, 976 .num_parents = 1, 977 .ops = &clk_branch2_ops, 978 .flags = CLK_SET_RATE_PARENT, 979 }, 980 }, 981 }; 982 983 static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = { 984 F(2000000, P_FEPLL200, 10, 0, 0), 985 { } 986 }; 987 988 static struct clk_rcg2 usb30_mock_utmi_clk_src = { 989 .cmd_rcgr = 0x1e000, 990 .hid_width = 5, 991 .parent_map = gcc_xo_200_map, 992 .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk, 993 .clkr.hw.init = &(struct clk_init_data){ 994 .name = "usb30_mock_utmi_clk_src", 995 .parent_names = gcc_xo_200, 996 .num_parents = 2, 997 .ops = &clk_rcg2_ops, 998 }, 999 }; 1000 1001 static struct clk_branch gcc_usb3_master_clk = { 1002 .halt_reg = 0x1e028, 1003 .clkr = { 1004 .enable_reg = 0x1e028, 1005 .enable_mask = BIT(0), 1006 .hw.init = &(struct clk_init_data){ 1007 .name = "gcc_usb3_master_clk", 1008 .parent_names = (const char *[]){ 1009 "fepll125", 1010 }, 1011 .num_parents = 1, 1012 .ops = &clk_branch2_ops, 1013 }, 1014 }, 1015 }; 1016 1017 static struct clk_branch gcc_usb3_sleep_clk = { 1018 .halt_reg = 0x1e02C, 1019 .clkr = { 1020 .enable_reg = 0x1e02C, 1021 .enable_mask = BIT(0), 1022 .hw.init = &(struct clk_init_data){ 1023 .name = "gcc_usb3_sleep_clk", 1024 .parent_names = (const char *[]){ 1025 "gcc_sleep_clk_src", 1026 }, 1027 .num_parents = 1, 1028 .ops = &clk_branch2_ops, 1029 }, 1030 }, 1031 }; 1032 1033 static struct clk_branch gcc_usb3_mock_utmi_clk = { 1034 .halt_reg = 0x1e030, 1035 .clkr = { 1036 .enable_reg = 0x1e030, 1037 .enable_mask = BIT(0), 1038 .hw.init = &(struct clk_init_data){ 1039 .name = "gcc_usb3_mock_utmi_clk", 1040 .parent_names = (const char *[]){ 1041 "usb30_mock_utmi_clk_src", 1042 }, 1043 .num_parents = 1, 1044 .ops = &clk_branch2_ops, 1045 .flags = CLK_SET_RATE_PARENT, 1046 }, 1047 }, 1048 }; 1049 1050 static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = { 1051 F(125000000, P_FEPLL125DLY, 1, 0, 0), 1052 { } 1053 }; 1054 1055 static struct clk_rcg2 fephy_125m_dly_clk_src = { 1056 .cmd_rcgr = 0x12000, 1057 .hid_width = 5, 1058 .parent_map = gcc_xo_125_dly_map, 1059 .freq_tbl = ftbl_gcc_fephy_dly_clk, 1060 .clkr.hw.init = &(struct clk_init_data){ 1061 .name = "fephy_125m_dly_clk_src", 1062 .parent_names = gcc_xo_125_dly, 1063 .num_parents = 2, 1064 .ops = &clk_rcg2_ops, 1065 }, 1066 }; 1067 1068 1069 static const struct freq_tbl ftbl_gcc_wcss2g_clk[] = { 1070 F(48000000, P_XO, 1, 0, 0), 1071 F(250000000, P_FEPLLWCSS2G, 1, 0, 0), 1072 { } 1073 }; 1074 1075 static struct clk_rcg2 wcss2g_clk_src = { 1076 .cmd_rcgr = 0x1f000, 1077 .hid_width = 5, 1078 .freq_tbl = ftbl_gcc_wcss2g_clk, 1079 .parent_map = gcc_xo_wcss2g_map, 1080 .clkr.hw.init = &(struct clk_init_data){ 1081 .name = "wcss2g_clk_src", 1082 .parent_names = gcc_xo_wcss2g, 1083 .num_parents = 2, 1084 .ops = &clk_rcg2_ops, 1085 .flags = CLK_SET_RATE_PARENT, 1086 }, 1087 }; 1088 1089 static struct clk_branch gcc_wcss2g_clk = { 1090 .halt_reg = 0x1f00C, 1091 .clkr = { 1092 .enable_reg = 0x1f00C, 1093 .enable_mask = BIT(0), 1094 .hw.init = &(struct clk_init_data){ 1095 .name = "gcc_wcss2g_clk", 1096 .parent_names = (const char *[]){ 1097 "wcss2g_clk_src", 1098 }, 1099 .num_parents = 1, 1100 .ops = &clk_branch2_ops, 1101 .flags = CLK_SET_RATE_PARENT, 1102 }, 1103 }, 1104 }; 1105 1106 static struct clk_branch gcc_wcss2g_ref_clk = { 1107 .halt_reg = 0x1f00C, 1108 .clkr = { 1109 .enable_reg = 0x1f00C, 1110 .enable_mask = BIT(0), 1111 .hw.init = &(struct clk_init_data){ 1112 .name = "gcc_wcss2g_ref_clk", 1113 .parent_names = (const char *[]){ 1114 "xo", 1115 }, 1116 .num_parents = 1, 1117 .ops = &clk_branch2_ops, 1118 .flags = CLK_SET_RATE_PARENT, 1119 }, 1120 }, 1121 }; 1122 1123 static struct clk_branch gcc_wcss2g_rtc_clk = { 1124 .halt_reg = 0x1f010, 1125 .clkr = { 1126 .enable_reg = 0x1f010, 1127 .enable_mask = BIT(0), 1128 .hw.init = &(struct clk_init_data){ 1129 .name = "gcc_wcss2g_rtc_clk", 1130 .parent_names = (const char *[]){ 1131 "gcc_sleep_clk_src", 1132 }, 1133 .num_parents = 1, 1134 .ops = &clk_branch2_ops, 1135 }, 1136 }, 1137 }; 1138 1139 static const struct freq_tbl ftbl_gcc_wcss5g_clk[] = { 1140 F(48000000, P_XO, 1, 0, 0), 1141 F(250000000, P_FEPLLWCSS5G, 1, 0, 0), 1142 { } 1143 }; 1144 1145 static struct clk_rcg2 wcss5g_clk_src = { 1146 .cmd_rcgr = 0x20000, 1147 .hid_width = 5, 1148 .parent_map = gcc_xo_wcss5g_map, 1149 .freq_tbl = ftbl_gcc_wcss5g_clk, 1150 .clkr.hw.init = &(struct clk_init_data){ 1151 .name = "wcss5g_clk_src", 1152 .parent_names = gcc_xo_wcss5g, 1153 .num_parents = 2, 1154 .ops = &clk_rcg2_ops, 1155 }, 1156 }; 1157 1158 static struct clk_branch gcc_wcss5g_clk = { 1159 .halt_reg = 0x2000c, 1160 .clkr = { 1161 .enable_reg = 0x2000c, 1162 .enable_mask = BIT(0), 1163 .hw.init = &(struct clk_init_data){ 1164 .name = "gcc_wcss5g_clk", 1165 .parent_names = (const char *[]){ 1166 "wcss5g_clk_src", 1167 }, 1168 .num_parents = 1, 1169 .ops = &clk_branch2_ops, 1170 .flags = CLK_SET_RATE_PARENT, 1171 }, 1172 }, 1173 }; 1174 1175 static struct clk_branch gcc_wcss5g_ref_clk = { 1176 .halt_reg = 0x2000c, 1177 .clkr = { 1178 .enable_reg = 0x2000c, 1179 .enable_mask = BIT(0), 1180 .hw.init = &(struct clk_init_data){ 1181 .name = "gcc_wcss5g_ref_clk", 1182 .parent_names = (const char *[]){ 1183 "xo", 1184 }, 1185 .num_parents = 1, 1186 .ops = &clk_branch2_ops, 1187 .flags = CLK_SET_RATE_PARENT, 1188 }, 1189 }, 1190 }; 1191 1192 static struct clk_branch gcc_wcss5g_rtc_clk = { 1193 .halt_reg = 0x20010, 1194 .clkr = { 1195 .enable_reg = 0x20010, 1196 .enable_mask = BIT(0), 1197 .hw.init = &(struct clk_init_data){ 1198 .name = "gcc_wcss5g_rtc_clk", 1199 .parent_names = (const char *[]){ 1200 "gcc_sleep_clk_src", 1201 }, 1202 .num_parents = 1, 1203 .ops = &clk_branch2_ops, 1204 .flags = CLK_SET_RATE_PARENT, 1205 }, 1206 }, 1207 }; 1208 1209 /* Calculates the VCO rate for FEPLL. */ 1210 static u64 clk_fepll_vco_calc_rate(struct clk_fepll *pll_div, 1211 unsigned long parent_rate) 1212 { 1213 const struct clk_fepll_vco *pll_vco = pll_div->pll_vco; 1214 u32 fdbkdiv, refclkdiv, cdiv; 1215 u64 vco; 1216 1217 regmap_read(pll_div->cdiv.clkr.regmap, pll_vco->reg, &cdiv); 1218 refclkdiv = (cdiv >> pll_vco->refclkdiv_shift) & 1219 (BIT(pll_vco->refclkdiv_width) - 1); 1220 fdbkdiv = (cdiv >> pll_vco->fdbkdiv_shift) & 1221 (BIT(pll_vco->fdbkdiv_width) - 1); 1222 1223 vco = parent_rate / refclkdiv; 1224 vco *= 2; 1225 vco *= fdbkdiv; 1226 1227 return vco; 1228 } 1229 1230 static const struct clk_fepll_vco gcc_apss_ddrpll_vco = { 1231 .fdbkdiv_shift = 16, 1232 .fdbkdiv_width = 8, 1233 .refclkdiv_shift = 24, 1234 .refclkdiv_width = 5, 1235 .reg = 0x2e020, 1236 }; 1237 1238 static const struct clk_fepll_vco gcc_fepll_vco = { 1239 .fdbkdiv_shift = 16, 1240 .fdbkdiv_width = 8, 1241 .refclkdiv_shift = 24, 1242 .refclkdiv_width = 5, 1243 .reg = 0x2f020, 1244 }; 1245 1246 /* 1247 * Round rate function for APSS CPU PLL Clock divider. 1248 * It looks up the frequency table and returns the next higher frequency 1249 * supported in hardware. 1250 */ 1251 static long clk_cpu_div_round_rate(struct clk_hw *hw, unsigned long rate, 1252 unsigned long *p_rate) 1253 { 1254 struct clk_fepll *pll = to_clk_fepll(hw); 1255 struct clk_hw *p_hw; 1256 const struct freq_tbl *f; 1257 1258 f = qcom_find_freq(pll->freq_tbl, rate); 1259 if (!f) 1260 return -EINVAL; 1261 1262 p_hw = clk_hw_get_parent_by_index(hw, f->src); 1263 *p_rate = clk_hw_get_rate(p_hw); 1264 1265 return f->freq; 1266 }; 1267 1268 /* 1269 * Clock set rate function for APSS CPU PLL Clock divider. 1270 * It looks up the frequency table and updates the PLL divider to corresponding 1271 * divider value. 1272 */ 1273 static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate, 1274 unsigned long parent_rate) 1275 { 1276 struct clk_fepll *pll = to_clk_fepll(hw); 1277 const struct freq_tbl *f; 1278 u32 mask; 1279 int ret; 1280 1281 f = qcom_find_freq(pll->freq_tbl, rate); 1282 if (!f) 1283 return -EINVAL; 1284 1285 mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift; 1286 ret = regmap_update_bits(pll->cdiv.clkr.regmap, 1287 pll->cdiv.reg, mask, 1288 f->pre_div << pll->cdiv.shift); 1289 /* 1290 * There is no status bit which can be checked for successful CPU 1291 * divider update operation so using delay for the same. 1292 */ 1293 udelay(1); 1294 1295 return 0; 1296 }; 1297 1298 /* 1299 * Clock frequency calculation function for APSS CPU PLL Clock divider. 1300 * This clock divider is nonlinear so this function calculates the actual 1301 * divider and returns the output frequency by dividing VCO Frequency 1302 * with this actual divider value. 1303 */ 1304 static unsigned long 1305 clk_cpu_div_recalc_rate(struct clk_hw *hw, 1306 unsigned long parent_rate) 1307 { 1308 struct clk_fepll *pll = to_clk_fepll(hw); 1309 u32 cdiv, pre_div; 1310 u64 rate; 1311 1312 regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv); 1313 cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1); 1314 1315 /* 1316 * Some dividers have value in 0.5 fraction so multiply both VCO 1317 * frequency(parent_rate) and pre_div with 2 to make integer 1318 * calculation. 1319 */ 1320 if (cdiv > 10) 1321 pre_div = (cdiv + 1) * 2; 1322 else 1323 pre_div = cdiv + 12; 1324 1325 rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2; 1326 do_div(rate, pre_div); 1327 1328 return rate; 1329 }; 1330 1331 static const struct clk_ops clk_regmap_cpu_div_ops = { 1332 .round_rate = clk_cpu_div_round_rate, 1333 .set_rate = clk_cpu_div_set_rate, 1334 .recalc_rate = clk_cpu_div_recalc_rate, 1335 }; 1336 1337 static const struct freq_tbl ftbl_apss_ddr_pll[] = { 1338 { 384000000, P_XO, 0xd, 0, 0 }, 1339 { 413000000, P_XO, 0xc, 0, 0 }, 1340 { 448000000, P_XO, 0xb, 0, 0 }, 1341 { 488000000, P_XO, 0xa, 0, 0 }, 1342 { 512000000, P_XO, 0x9, 0, 0 }, 1343 { 537000000, P_XO, 0x8, 0, 0 }, 1344 { 565000000, P_XO, 0x7, 0, 0 }, 1345 { 597000000, P_XO, 0x6, 0, 0 }, 1346 { 632000000, P_XO, 0x5, 0, 0 }, 1347 { 672000000, P_XO, 0x4, 0, 0 }, 1348 { 716000000, P_XO, 0x3, 0, 0 }, 1349 { 768000000, P_XO, 0x2, 0, 0 }, 1350 { 823000000, P_XO, 0x1, 0, 0 }, 1351 { 896000000, P_XO, 0x0, 0, 0 }, 1352 { } 1353 }; 1354 1355 static struct clk_fepll gcc_apss_cpu_plldiv_clk = { 1356 .cdiv.reg = 0x2e020, 1357 .cdiv.shift = 4, 1358 .cdiv.width = 4, 1359 .cdiv.clkr = { 1360 .enable_reg = 0x2e000, 1361 .enable_mask = BIT(0), 1362 .hw.init = &(struct clk_init_data){ 1363 .name = "ddrpllapss", 1364 .parent_names = (const char *[]){ 1365 "xo", 1366 }, 1367 .num_parents = 1, 1368 .ops = &clk_regmap_cpu_div_ops, 1369 }, 1370 }, 1371 .freq_tbl = ftbl_apss_ddr_pll, 1372 .pll_vco = &gcc_apss_ddrpll_vco, 1373 }; 1374 1375 /* Calculates the rate for PLL divider. 1376 * If the divider value is not fixed then it gets the actual divider value 1377 * from divider table. Then, it calculate the clock rate by dividing the 1378 * parent rate with actual divider value. 1379 */ 1380 static unsigned long 1381 clk_regmap_clk_div_recalc_rate(struct clk_hw *hw, 1382 unsigned long parent_rate) 1383 { 1384 struct clk_fepll *pll = to_clk_fepll(hw); 1385 u32 cdiv, pre_div = 1; 1386 u64 rate; 1387 const struct clk_div_table *clkt; 1388 1389 if (pll->fixed_div) { 1390 pre_div = pll->fixed_div; 1391 } else { 1392 regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv); 1393 cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1); 1394 1395 for (clkt = pll->div_table; clkt->div; clkt++) { 1396 if (clkt->val == cdiv) 1397 pre_div = clkt->div; 1398 } 1399 } 1400 1401 rate = clk_fepll_vco_calc_rate(pll, parent_rate); 1402 do_div(rate, pre_div); 1403 1404 return rate; 1405 }; 1406 1407 static const struct clk_ops clk_fepll_div_ops = { 1408 .recalc_rate = clk_regmap_clk_div_recalc_rate, 1409 }; 1410 1411 static struct clk_fepll gcc_apss_sdcc_clk = { 1412 .fixed_div = 28, 1413 .cdiv.clkr = { 1414 .hw.init = &(struct clk_init_data){ 1415 .name = "ddrpllsdcc", 1416 .parent_names = (const char *[]){ 1417 "xo", 1418 }, 1419 .num_parents = 1, 1420 .ops = &clk_fepll_div_ops, 1421 }, 1422 }, 1423 .pll_vco = &gcc_apss_ddrpll_vco, 1424 }; 1425 1426 static struct clk_fepll gcc_fepll125_clk = { 1427 .fixed_div = 32, 1428 .cdiv.clkr = { 1429 .hw.init = &(struct clk_init_data){ 1430 .name = "fepll125", 1431 .parent_names = (const char *[]){ 1432 "xo", 1433 }, 1434 .num_parents = 1, 1435 .ops = &clk_fepll_div_ops, 1436 }, 1437 }, 1438 .pll_vco = &gcc_fepll_vco, 1439 }; 1440 1441 static struct clk_fepll gcc_fepll125dly_clk = { 1442 .fixed_div = 32, 1443 .cdiv.clkr = { 1444 .hw.init = &(struct clk_init_data){ 1445 .name = "fepll125dly", 1446 .parent_names = (const char *[]){ 1447 "xo", 1448 }, 1449 .num_parents = 1, 1450 .ops = &clk_fepll_div_ops, 1451 }, 1452 }, 1453 .pll_vco = &gcc_fepll_vco, 1454 }; 1455 1456 static struct clk_fepll gcc_fepll200_clk = { 1457 .fixed_div = 20, 1458 .cdiv.clkr = { 1459 .hw.init = &(struct clk_init_data){ 1460 .name = "fepll200", 1461 .parent_names = (const char *[]){ 1462 "xo", 1463 }, 1464 .num_parents = 1, 1465 .ops = &clk_fepll_div_ops, 1466 }, 1467 }, 1468 .pll_vco = &gcc_fepll_vco, 1469 }; 1470 1471 static struct clk_fepll gcc_fepll500_clk = { 1472 .fixed_div = 8, 1473 .cdiv.clkr = { 1474 .hw.init = &(struct clk_init_data){ 1475 .name = "fepll500", 1476 .parent_names = (const char *[]){ 1477 "xo", 1478 }, 1479 .num_parents = 1, 1480 .ops = &clk_fepll_div_ops, 1481 }, 1482 }, 1483 .pll_vco = &gcc_fepll_vco, 1484 }; 1485 1486 static const struct clk_div_table fepllwcss_clk_div_table[] = { 1487 { 0, 15 }, 1488 { 1, 16 }, 1489 { 2, 18 }, 1490 { 3, 20 }, 1491 { }, 1492 }; 1493 1494 static struct clk_fepll gcc_fepllwcss2g_clk = { 1495 .cdiv.reg = 0x2f020, 1496 .cdiv.shift = 8, 1497 .cdiv.width = 2, 1498 .cdiv.clkr = { 1499 .hw.init = &(struct clk_init_data){ 1500 .name = "fepllwcss2g", 1501 .parent_names = (const char *[]){ 1502 "xo", 1503 }, 1504 .num_parents = 1, 1505 .ops = &clk_fepll_div_ops, 1506 }, 1507 }, 1508 .div_table = fepllwcss_clk_div_table, 1509 .pll_vco = &gcc_fepll_vco, 1510 }; 1511 1512 static struct clk_fepll gcc_fepllwcss5g_clk = { 1513 .cdiv.reg = 0x2f020, 1514 .cdiv.shift = 12, 1515 .cdiv.width = 2, 1516 .cdiv.clkr = { 1517 .hw.init = &(struct clk_init_data){ 1518 .name = "fepllwcss5g", 1519 .parent_names = (const char *[]){ 1520 "xo", 1521 }, 1522 .num_parents = 1, 1523 .ops = &clk_fepll_div_ops, 1524 }, 1525 }, 1526 .div_table = fepllwcss_clk_div_table, 1527 .pll_vco = &gcc_fepll_vco, 1528 }; 1529 1530 static const struct freq_tbl ftbl_gcc_pcnoc_ahb_clk[] = { 1531 F(48000000, P_XO, 1, 0, 0), 1532 F(100000000, P_FEPLL200, 2, 0, 0), 1533 { } 1534 }; 1535 1536 static struct clk_rcg2 gcc_pcnoc_ahb_clk_src = { 1537 .cmd_rcgr = 0x21024, 1538 .hid_width = 5, 1539 .parent_map = gcc_xo_200_500_map, 1540 .freq_tbl = ftbl_gcc_pcnoc_ahb_clk, 1541 .clkr.hw.init = &(struct clk_init_data){ 1542 .name = "gcc_pcnoc_ahb_clk_src", 1543 .parent_names = gcc_xo_200_500, 1544 .num_parents = 3, 1545 .ops = &clk_rcg2_ops, 1546 }, 1547 }; 1548 1549 static struct clk_branch pcnoc_clk_src = { 1550 .halt_reg = 0x21030, 1551 .clkr = { 1552 .enable_reg = 0x21030, 1553 .enable_mask = BIT(0), 1554 .hw.init = &(struct clk_init_data){ 1555 .name = "pcnoc_clk_src", 1556 .parent_names = (const char *[]){ 1557 "gcc_pcnoc_ahb_clk_src", 1558 }, 1559 .num_parents = 1, 1560 .ops = &clk_branch2_ops, 1561 .flags = CLK_SET_RATE_PARENT | 1562 CLK_IS_CRITICAL, 1563 }, 1564 }, 1565 }; 1566 1567 static struct clk_regmap *gcc_ipq4019_clocks[] = { 1568 [AUDIO_CLK_SRC] = &audio_clk_src.clkr, 1569 [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, 1570 [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, 1571 [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, 1572 [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, 1573 [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, 1574 [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, 1575 [GCC_USB3_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr, 1576 [GCC_APPS_CLK_SRC] = &apps_clk_src.clkr, 1577 [GCC_APPS_AHB_CLK_SRC] = &apps_ahb_clk_src.clkr, 1578 [GP1_CLK_SRC] = &gp1_clk_src.clkr, 1579 [GP2_CLK_SRC] = &gp2_clk_src.clkr, 1580 [GP3_CLK_SRC] = &gp3_clk_src.clkr, 1581 [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, 1582 [FEPHY_125M_DLY_CLK_SRC] = &fephy_125m_dly_clk_src.clkr, 1583 [WCSS2G_CLK_SRC] = &wcss2g_clk_src.clkr, 1584 [WCSS5G_CLK_SRC] = &wcss5g_clk_src.clkr, 1585 [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr, 1586 [GCC_AUDIO_AHB_CLK] = &gcc_audio_ahb_clk.clkr, 1587 [GCC_AUDIO_PWM_CLK] = &gcc_audio_pwm_clk.clkr, 1588 [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, 1589 [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, 1590 [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, 1591 [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, 1592 [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, 1593 [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, 1594 [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, 1595 [GCC_DCD_XO_CLK] = &gcc_dcd_xo_clk.clkr, 1596 [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, 1597 [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, 1598 [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, 1599 [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, 1600 [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, 1601 [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, 1602 [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, 1603 [GCC_ESS_CLK] = &gcc_ess_clk.clkr, 1604 [GCC_IMEM_AXI_CLK] = &gcc_imem_axi_clk.clkr, 1605 [GCC_IMEM_CFG_AHB_CLK] = &gcc_imem_cfg_ahb_clk.clkr, 1606 [GCC_PCIE_AHB_CLK] = &gcc_pcie_ahb_clk.clkr, 1607 [GCC_PCIE_AXI_M_CLK] = &gcc_pcie_axi_m_clk.clkr, 1608 [GCC_PCIE_AXI_S_CLK] = &gcc_pcie_axi_s_clk.clkr, 1609 [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, 1610 [GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr, 1611 [GCC_QPIC_CLK] = &gcc_qpic_clk.clkr, 1612 [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, 1613 [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, 1614 [GCC_TLMM_AHB_CLK] = &gcc_tlmm_ahb_clk.clkr, 1615 [GCC_USB2_MASTER_CLK] = &gcc_usb2_master_clk.clkr, 1616 [GCC_USB2_SLEEP_CLK] = &gcc_usb2_sleep_clk.clkr, 1617 [GCC_USB2_MOCK_UTMI_CLK] = &gcc_usb2_mock_utmi_clk.clkr, 1618 [GCC_USB3_MASTER_CLK] = &gcc_usb3_master_clk.clkr, 1619 [GCC_USB3_SLEEP_CLK] = &gcc_usb3_sleep_clk.clkr, 1620 [GCC_USB3_MOCK_UTMI_CLK] = &gcc_usb3_mock_utmi_clk.clkr, 1621 [GCC_WCSS2G_CLK] = &gcc_wcss2g_clk.clkr, 1622 [GCC_WCSS2G_REF_CLK] = &gcc_wcss2g_ref_clk.clkr, 1623 [GCC_WCSS2G_RTC_CLK] = &gcc_wcss2g_rtc_clk.clkr, 1624 [GCC_WCSS5G_CLK] = &gcc_wcss5g_clk.clkr, 1625 [GCC_WCSS5G_REF_CLK] = &gcc_wcss5g_ref_clk.clkr, 1626 [GCC_WCSS5G_RTC_CLK] = &gcc_wcss5g_rtc_clk.clkr, 1627 [GCC_SDCC_PLLDIV_CLK] = &gcc_apss_sdcc_clk.cdiv.clkr, 1628 [GCC_FEPLL125_CLK] = &gcc_fepll125_clk.cdiv.clkr, 1629 [GCC_FEPLL125DLY_CLK] = &gcc_fepll125dly_clk.cdiv.clkr, 1630 [GCC_FEPLL200_CLK] = &gcc_fepll200_clk.cdiv.clkr, 1631 [GCC_FEPLL500_CLK] = &gcc_fepll500_clk.cdiv.clkr, 1632 [GCC_FEPLL_WCSS2G_CLK] = &gcc_fepllwcss2g_clk.cdiv.clkr, 1633 [GCC_FEPLL_WCSS5G_CLK] = &gcc_fepllwcss5g_clk.cdiv.clkr, 1634 [GCC_APSS_CPU_PLLDIV_CLK] = &gcc_apss_cpu_plldiv_clk.cdiv.clkr, 1635 [GCC_PCNOC_AHB_CLK_SRC] = &gcc_pcnoc_ahb_clk_src.clkr, 1636 [GCC_PCNOC_AHB_CLK] = &pcnoc_clk_src.clkr, 1637 }; 1638 1639 static const struct qcom_reset_map gcc_ipq4019_resets[] = { 1640 [WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 }, 1641 [WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 }, 1642 [WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 }, 1643 [WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 }, 1644 [WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 }, 1645 [WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 }, 1646 [WIFI1_CPU_INIT_RESET] = { 0x20008, 5 }, 1647 [WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 }, 1648 [WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 }, 1649 [WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 }, 1650 [WIFI1_CORE_WARM_RESET] = { 0x20008, 1 }, 1651 [WIFI1_CORE_COLD_RESET] = { 0x20008, 0 }, 1652 [USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 }, 1653 [USB3_HSPHY_POR_ARES] = { 0x1e038, 4 }, 1654 [USB3_HSPHY_S_ARES] = { 0x1e038, 2 }, 1655 [USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 }, 1656 [USB2_HSPHY_S_ARES] = { 0x1e01c, 2 }, 1657 [PCIE_PHY_AHB_ARES] = { 0x1d010, 11 }, 1658 [PCIE_AHB_ARES] = { 0x1d010, 10 }, 1659 [PCIE_PWR_ARES] = { 0x1d010, 9 }, 1660 [PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 }, 1661 [PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 }, 1662 [PCIE_PHY_ARES] = { 0x1d010, 6 }, 1663 [PCIE_PARF_XPU_ARES] = { 0x1d010, 5 }, 1664 [PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 }, 1665 [PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 }, 1666 [PCIE_PIPE_ARES] = { 0x1d010, 2 }, 1667 [PCIE_AXI_S_ARES] = { 0x1d010, 1 }, 1668 [PCIE_AXI_M_ARES] = { 0x1d010, 0 }, 1669 [ESS_RESET] = { 0x12008, 0}, 1670 [GCC_BLSP1_BCR] = {0x01000, 0}, 1671 [GCC_BLSP1_QUP1_BCR] = {0x02000, 0}, 1672 [GCC_BLSP1_UART1_BCR] = {0x02038, 0}, 1673 [GCC_BLSP1_QUP2_BCR] = {0x03008, 0}, 1674 [GCC_BLSP1_UART2_BCR] = {0x03028, 0}, 1675 [GCC_BIMC_BCR] = {0x04000, 0}, 1676 [GCC_TLMM_BCR] = {0x05000, 0}, 1677 [GCC_IMEM_BCR] = {0x0E000, 0}, 1678 [GCC_ESS_BCR] = {0x12008, 0}, 1679 [GCC_PRNG_BCR] = {0x13000, 0}, 1680 [GCC_BOOT_ROM_BCR] = {0x13008, 0}, 1681 [GCC_CRYPTO_BCR] = {0x16000, 0}, 1682 [GCC_SDCC1_BCR] = {0x18000, 0}, 1683 [GCC_SEC_CTRL_BCR] = {0x1A000, 0}, 1684 [GCC_AUDIO_BCR] = {0x1B008, 0}, 1685 [GCC_QPIC_BCR] = {0x1C000, 0}, 1686 [GCC_PCIE_BCR] = {0x1D000, 0}, 1687 [GCC_USB2_BCR] = {0x1E008, 0}, 1688 [GCC_USB2_PHY_BCR] = {0x1E018, 0}, 1689 [GCC_USB3_BCR] = {0x1E024, 0}, 1690 [GCC_USB3_PHY_BCR] = {0x1E034, 0}, 1691 [GCC_SYSTEM_NOC_BCR] = {0x21000, 0}, 1692 [GCC_PCNOC_BCR] = {0x2102C, 0}, 1693 [GCC_DCD_BCR] = {0x21038, 0}, 1694 [GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0}, 1695 [GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0}, 1696 [GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0}, 1697 [GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0}, 1698 [GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0}, 1699 [GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0}, 1700 [GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0}, 1701 [GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0}, 1702 [GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0}, 1703 [GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0}, 1704 [GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0}, 1705 [GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0}, 1706 [GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0}, 1707 [GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0}, 1708 [GCC_TCSR_BCR] = {0x22000, 0}, 1709 [GCC_MPM_BCR] = {0x24000, 0}, 1710 [GCC_SPDM_BCR] = {0x25000, 0}, 1711 }; 1712 1713 static const struct regmap_config gcc_ipq4019_regmap_config = { 1714 .reg_bits = 32, 1715 .reg_stride = 4, 1716 .val_bits = 32, 1717 .max_register = 0x2ffff, 1718 .fast_io = true, 1719 }; 1720 1721 static const struct qcom_cc_desc gcc_ipq4019_desc = { 1722 .config = &gcc_ipq4019_regmap_config, 1723 .clks = gcc_ipq4019_clocks, 1724 .num_clks = ARRAY_SIZE(gcc_ipq4019_clocks), 1725 .resets = gcc_ipq4019_resets, 1726 .num_resets = ARRAY_SIZE(gcc_ipq4019_resets), 1727 }; 1728 1729 static const struct of_device_id gcc_ipq4019_match_table[] = { 1730 { .compatible = "qcom,gcc-ipq4019" }, 1731 { } 1732 }; 1733 MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table); 1734 1735 static int 1736 gcc_ipq4019_cpu_clk_notifier_fn(struct notifier_block *nb, 1737 unsigned long action, void *data) 1738 { 1739 int err = 0; 1740 1741 if (action == PRE_RATE_CHANGE) 1742 err = clk_rcg2_ops.set_parent(&apps_clk_src.clkr.hw, 1743 gcc_ipq4019_cpu_safe_parent); 1744 1745 return notifier_from_errno(err); 1746 } 1747 1748 static struct notifier_block gcc_ipq4019_cpu_clk_notifier = { 1749 .notifier_call = gcc_ipq4019_cpu_clk_notifier_fn, 1750 }; 1751 1752 static int gcc_ipq4019_probe(struct platform_device *pdev) 1753 { 1754 int err; 1755 1756 err = qcom_cc_probe(pdev, &gcc_ipq4019_desc); 1757 if (err) 1758 return err; 1759 1760 return clk_notifier_register(apps_clk_src.clkr.hw.clk, 1761 &gcc_ipq4019_cpu_clk_notifier); 1762 } 1763 1764 static int gcc_ipq4019_remove(struct platform_device *pdev) 1765 { 1766 return clk_notifier_unregister(apps_clk_src.clkr.hw.clk, 1767 &gcc_ipq4019_cpu_clk_notifier); 1768 } 1769 1770 static struct platform_driver gcc_ipq4019_driver = { 1771 .probe = gcc_ipq4019_probe, 1772 .remove = gcc_ipq4019_remove, 1773 .driver = { 1774 .name = "qcom,gcc-ipq4019", 1775 .of_match_table = gcc_ipq4019_match_table, 1776 }, 1777 }; 1778 1779 static int __init gcc_ipq4019_init(void) 1780 { 1781 return platform_driver_register(&gcc_ipq4019_driver); 1782 } 1783 core_initcall(gcc_ipq4019_init); 1784 1785 static void __exit gcc_ipq4019_exit(void) 1786 { 1787 platform_driver_unregister(&gcc_ipq4019_driver); 1788 } 1789 module_exit(gcc_ipq4019_exit); 1790 1791 MODULE_ALIAS("platform:gcc-ipq4019"); 1792 MODULE_LICENSE("GPL v2"); 1793 MODULE_DESCRIPTION("QCOM GCC IPQ4019 driver"); 1794