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