linux/drivers/clk/qcom/gcc-ipq4019.c
<<
>>
Prefs
   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
  34enum {
  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 */
  53struct 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 */
  71struct 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
  80static struct parent_map gcc_xo_200_500_map[] = {
  81        { P_XO, 0 },
  82        { P_FEPLL200, 1 },
  83        { P_FEPLL500, 2 },
  84};
  85
  86static const char * const gcc_xo_200_500[] = {
  87        "xo",
  88        "fepll200",
  89        "fepll500",
  90};
  91
  92static struct parent_map gcc_xo_200_map[] = {
  93        {  P_XO, 0 },
  94        {  P_FEPLL200, 1 },
  95};
  96
  97static const char * const gcc_xo_200[] = {
  98        "xo",
  99        "fepll200",
 100};
 101
 102static struct parent_map gcc_xo_200_spi_map[] = {
 103        {  P_XO, 0 },
 104        {  P_FEPLL200, 2 },
 105};
 106
 107static const char * const gcc_xo_200_spi[] = {
 108        "xo",
 109        "fepll200",
 110};
 111
 112static struct parent_map gcc_xo_sdcc1_500_map[] = {
 113        {  P_XO, 0 },
 114        {  P_DDRPLL, 1 },
 115        {  P_FEPLL500, 2 },
 116};
 117
 118static const char * const gcc_xo_sdcc1_500[] = {
 119        "xo",
 120        "ddrpllsdcc",
 121        "fepll500",
 122};
 123
 124static struct parent_map gcc_xo_wcss2g_map[] = {
 125        {  P_XO, 0 },
 126        {  P_FEPLLWCSS2G, 1 },
 127};
 128
 129static const char * const gcc_xo_wcss2g[] = {
 130        "xo",
 131        "fepllwcss2g",
 132};
 133
 134static struct parent_map gcc_xo_wcss5g_map[] = {
 135        {  P_XO, 0 },
 136        {  P_FEPLLWCSS5G, 1 },
 137};
 138
 139static const char * const gcc_xo_wcss5g[] = {
 140        "xo",
 141        "fepllwcss5g",
 142};
 143
 144static struct parent_map gcc_xo_125_dly_map[] = {
 145        {  P_XO, 0 },
 146        {  P_FEPLL125DLY, 1 },
 147};
 148
 149static const char * const gcc_xo_125_dly[] = {
 150        "xo",
 151        "fepll125dly",
 152};
 153
 154static 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 */
 166static const int gcc_ipq4019_cpu_safe_parent = 2;
 167static const char * const gcc_xo_ddr_500_200[] = {
 168        "xo",
 169        "fepll200",
 170        "fepll500",
 171        "ddrpllapss",
 172};
 173
 174static 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
 180static 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
 194static 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
 211static 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
 228static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
 229        F(19050000, P_FEPLL200, 10.5, 1, 1),
 230        { }
 231};
 232
 233static 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
 246static 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
 263static 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
 276static 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
 293static 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
 304static 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
 318static 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
 335static 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
 349static 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
 366static 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
 380static 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
 394static 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
 411static 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
 425static 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
 442static 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
 449static 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
 463static 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
 480static 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
 494static 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
 511static 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
 525static 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
 542static 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
 553static 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
 567static 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
 585static 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
 599static 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
 605static 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
 618static 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
 636static 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
 653static 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
 669static 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
 686static 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
 703static 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
 720static 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
 737static 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
 754static 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
 771static 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
 787static 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
 803static 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
 819static 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
 835static 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
 852static 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
 868static 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
 884static 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
 900static 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
 917static 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
 934static 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
 950static 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
 966static 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
 983static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
 984        F(2000000, P_FEPLL200, 10, 0, 0),
 985        { }
 986};
 987
 988static 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
1001static 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
1017static 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
1033static 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
1050static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = {
1051        F(125000000, P_FEPLL125DLY, 1, 0, 0),
1052        { }
1053};
1054
1055static 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
1069static 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
1075static 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
1089static 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
1106static 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
1123static 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
1139static 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
1145static 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
1158static 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
1175static 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
1192static 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. */
1210static 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
1230static 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
1238static 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 */
1251static 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 */
1273static 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
1280        f = qcom_find_freq(pll->freq_tbl, rate);
1281        if (!f)
1282                return -EINVAL;
1283
1284        mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift;
1285        regmap_update_bits(pll->cdiv.clkr.regmap,
1286                           pll->cdiv.reg, mask,
1287                           f->pre_div << pll->cdiv.shift);
1288        /*
1289         * There is no status bit which can be checked for successful CPU
1290         * divider update operation so using delay for the same.
1291         */
1292        udelay(1);
1293
1294        return 0;
1295};
1296
1297/*
1298 * Clock frequency calculation function for APSS CPU PLL Clock divider.
1299 * This clock divider is nonlinear so this function calculates the actual
1300 * divider and returns the output frequency by dividing VCO Frequency
1301 * with this actual divider value.
1302 */
1303static unsigned long
1304clk_cpu_div_recalc_rate(struct clk_hw *hw,
1305                        unsigned long parent_rate)
1306{
1307        struct clk_fepll *pll = to_clk_fepll(hw);
1308        u32 cdiv, pre_div;
1309        u64 rate;
1310
1311        regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
1312        cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);
1313
1314        /*
1315         * Some dividers have value in 0.5 fraction so multiply both VCO
1316         * frequency(parent_rate) and pre_div with 2 to make integer
1317         * calculation.
1318         */
1319        if (cdiv > 10)
1320                pre_div = (cdiv + 1) * 2;
1321        else
1322                pre_div = cdiv + 12;
1323
1324        rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
1325        do_div(rate, pre_div);
1326
1327        return rate;
1328};
1329
1330static const struct clk_ops clk_regmap_cpu_div_ops = {
1331        .round_rate = clk_cpu_div_round_rate,
1332        .set_rate = clk_cpu_div_set_rate,
1333        .recalc_rate = clk_cpu_div_recalc_rate,
1334};
1335
1336static const struct freq_tbl ftbl_apss_ddr_pll[] = {
1337        { 384000000, P_XO, 0xd, 0, 0 },
1338        { 413000000, P_XO, 0xc, 0, 0 },
1339        { 448000000, P_XO, 0xb, 0, 0 },
1340        { 488000000, P_XO, 0xa, 0, 0 },
1341        { 512000000, P_XO, 0x9, 0, 0 },
1342        { 537000000, P_XO, 0x8, 0, 0 },
1343        { 565000000, P_XO, 0x7, 0, 0 },
1344        { 597000000, P_XO, 0x6, 0, 0 },
1345        { 632000000, P_XO, 0x5, 0, 0 },
1346        { 672000000, P_XO, 0x4, 0, 0 },
1347        { 716000000, P_XO, 0x3, 0, 0 },
1348        { 768000000, P_XO, 0x2, 0, 0 },
1349        { 823000000, P_XO, 0x1, 0, 0 },
1350        { 896000000, P_XO, 0x0, 0, 0 },
1351        { }
1352};
1353
1354static struct clk_fepll gcc_apss_cpu_plldiv_clk = {
1355        .cdiv.reg = 0x2e020,
1356        .cdiv.shift = 4,
1357        .cdiv.width = 4,
1358        .cdiv.clkr = {
1359                .enable_reg = 0x2e000,
1360                .enable_mask = BIT(0),
1361                .hw.init = &(struct clk_init_data){
1362                        .name = "ddrpllapss",
1363                        .parent_names = (const char *[]){
1364                                "xo",
1365                        },
1366                        .num_parents = 1,
1367                        .ops = &clk_regmap_cpu_div_ops,
1368                },
1369        },
1370        .freq_tbl = ftbl_apss_ddr_pll,
1371        .pll_vco = &gcc_apss_ddrpll_vco,
1372};
1373
1374/* Calculates the rate for PLL divider.
1375 * If the divider value is not fixed then it gets the actual divider value
1376 * from divider table. Then, it calculate the clock rate by dividing the
1377 * parent rate with actual divider value.
1378 */
1379static unsigned long
1380clk_regmap_clk_div_recalc_rate(struct clk_hw *hw,
1381                               unsigned long parent_rate)
1382{
1383        struct clk_fepll *pll = to_clk_fepll(hw);
1384        u32 cdiv, pre_div = 1;
1385        u64 rate;
1386        const struct clk_div_table *clkt;
1387
1388        if (pll->fixed_div) {
1389                pre_div = pll->fixed_div;
1390        } else {
1391                regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
1392                cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);
1393
1394                for (clkt = pll->div_table; clkt->div; clkt++) {
1395                        if (clkt->val == cdiv)
1396                                pre_div = clkt->div;
1397                }
1398        }
1399
1400        rate = clk_fepll_vco_calc_rate(pll, parent_rate);
1401        do_div(rate, pre_div);
1402
1403        return rate;
1404};
1405
1406static const struct clk_ops clk_fepll_div_ops = {
1407        .recalc_rate = clk_regmap_clk_div_recalc_rate,
1408};
1409
1410static struct clk_fepll gcc_apss_sdcc_clk = {
1411        .fixed_div = 28,
1412        .cdiv.clkr = {
1413                .hw.init = &(struct clk_init_data){
1414                        .name = "ddrpllsdcc",
1415                        .parent_names = (const char *[]){
1416                                "xo",
1417                        },
1418                        .num_parents = 1,
1419                        .ops = &clk_fepll_div_ops,
1420                },
1421        },
1422        .pll_vco = &gcc_apss_ddrpll_vco,
1423};
1424
1425static struct clk_fepll gcc_fepll125_clk = {
1426        .fixed_div = 32,
1427        .cdiv.clkr = {
1428                .hw.init = &(struct clk_init_data){
1429                        .name = "fepll125",
1430                        .parent_names = (const char *[]){
1431                                "xo",
1432                        },
1433                        .num_parents = 1,
1434                        .ops = &clk_fepll_div_ops,
1435                },
1436        },
1437        .pll_vco = &gcc_fepll_vco,
1438};
1439
1440static struct clk_fepll gcc_fepll125dly_clk = {
1441        .fixed_div = 32,
1442        .cdiv.clkr = {
1443                .hw.init = &(struct clk_init_data){
1444                        .name = "fepll125dly",
1445                        .parent_names = (const char *[]){
1446                                "xo",
1447                        },
1448                        .num_parents = 1,
1449                        .ops = &clk_fepll_div_ops,
1450                },
1451        },
1452        .pll_vco = &gcc_fepll_vco,
1453};
1454
1455static struct clk_fepll gcc_fepll200_clk = {
1456        .fixed_div = 20,
1457        .cdiv.clkr = {
1458                .hw.init = &(struct clk_init_data){
1459                        .name = "fepll200",
1460                        .parent_names = (const char *[]){
1461                                "xo",
1462                        },
1463                        .num_parents = 1,
1464                        .ops = &clk_fepll_div_ops,
1465                },
1466        },
1467        .pll_vco = &gcc_fepll_vco,
1468};
1469
1470static struct clk_fepll gcc_fepll500_clk = {
1471        .fixed_div = 8,
1472        .cdiv.clkr = {
1473                .hw.init = &(struct clk_init_data){
1474                        .name = "fepll500",
1475                        .parent_names = (const char *[]){
1476                                "xo",
1477                        },
1478                        .num_parents = 1,
1479                        .ops = &clk_fepll_div_ops,
1480                },
1481        },
1482        .pll_vco = &gcc_fepll_vco,
1483};
1484
1485static const struct clk_div_table fepllwcss_clk_div_table[] = {
1486        { 0, 15 },
1487        { 1, 16 },
1488        { 2, 18 },
1489        { 3, 20 },
1490        { },
1491};
1492
1493static struct clk_fepll gcc_fepllwcss2g_clk = {
1494        .cdiv.reg = 0x2f020,
1495        .cdiv.shift = 8,
1496        .cdiv.width = 2,
1497        .cdiv.clkr = {
1498                .hw.init = &(struct clk_init_data){
1499                        .name = "fepllwcss2g",
1500                        .parent_names = (const char *[]){
1501                                "xo",
1502                        },
1503                        .num_parents = 1,
1504                        .ops = &clk_fepll_div_ops,
1505                },
1506        },
1507        .div_table = fepllwcss_clk_div_table,
1508        .pll_vco = &gcc_fepll_vco,
1509};
1510
1511static struct clk_fepll gcc_fepllwcss5g_clk = {
1512        .cdiv.reg = 0x2f020,
1513        .cdiv.shift = 12,
1514        .cdiv.width = 2,
1515        .cdiv.clkr = {
1516                .hw.init = &(struct clk_init_data){
1517                        .name = "fepllwcss5g",
1518                        .parent_names = (const char *[]){
1519                                "xo",
1520                        },
1521                        .num_parents = 1,
1522                        .ops = &clk_fepll_div_ops,
1523                },
1524        },
1525        .div_table = fepllwcss_clk_div_table,
1526        .pll_vco = &gcc_fepll_vco,
1527};
1528
1529static const struct freq_tbl ftbl_gcc_pcnoc_ahb_clk[] = {
1530        F(48000000,  P_XO,       1, 0, 0),
1531        F(100000000, P_FEPLL200, 2, 0, 0),
1532        { }
1533};
1534
1535static struct clk_rcg2 gcc_pcnoc_ahb_clk_src = {
1536        .cmd_rcgr = 0x21024,
1537        .hid_width = 5,
1538        .parent_map = gcc_xo_200_500_map,
1539        .freq_tbl = ftbl_gcc_pcnoc_ahb_clk,
1540        .clkr.hw.init = &(struct clk_init_data){
1541                .name = "gcc_pcnoc_ahb_clk_src",
1542                .parent_names = gcc_xo_200_500,
1543                .num_parents = 3,
1544                .ops = &clk_rcg2_ops,
1545        },
1546};
1547
1548static struct clk_branch pcnoc_clk_src = {
1549        .halt_reg = 0x21030,
1550        .clkr = {
1551                .enable_reg = 0x21030,
1552                .enable_mask = BIT(0),
1553                .hw.init = &(struct clk_init_data){
1554                        .name = "pcnoc_clk_src",
1555                        .parent_names = (const char *[]){
1556                                "gcc_pcnoc_ahb_clk_src",
1557                        },
1558                        .num_parents = 1,
1559                        .ops = &clk_branch2_ops,
1560                        .flags = CLK_SET_RATE_PARENT |
1561                                CLK_IS_CRITICAL,
1562                },
1563        },
1564};
1565
1566static struct clk_regmap *gcc_ipq4019_clocks[] = {
1567        [AUDIO_CLK_SRC] = &audio_clk_src.clkr,
1568        [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
1569        [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
1570        [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
1571        [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
1572        [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
1573        [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
1574        [GCC_USB3_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
1575        [GCC_APPS_CLK_SRC] = &apps_clk_src.clkr,
1576        [GCC_APPS_AHB_CLK_SRC] = &apps_ahb_clk_src.clkr,
1577        [GP1_CLK_SRC] = &gp1_clk_src.clkr,
1578        [GP2_CLK_SRC] = &gp2_clk_src.clkr,
1579        [GP3_CLK_SRC] = &gp3_clk_src.clkr,
1580        [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
1581        [FEPHY_125M_DLY_CLK_SRC] = &fephy_125m_dly_clk_src.clkr,
1582        [WCSS2G_CLK_SRC] = &wcss2g_clk_src.clkr,
1583        [WCSS5G_CLK_SRC] = &wcss5g_clk_src.clkr,
1584        [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr,
1585        [GCC_AUDIO_AHB_CLK] = &gcc_audio_ahb_clk.clkr,
1586        [GCC_AUDIO_PWM_CLK] = &gcc_audio_pwm_clk.clkr,
1587        [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
1588        [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
1589        [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
1590        [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
1591        [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
1592        [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
1593        [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
1594        [GCC_DCD_XO_CLK] = &gcc_dcd_xo_clk.clkr,
1595        [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
1596        [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
1597        [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
1598        [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
1599        [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
1600        [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
1601        [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
1602        [GCC_ESS_CLK] = &gcc_ess_clk.clkr,
1603        [GCC_IMEM_AXI_CLK] = &gcc_imem_axi_clk.clkr,
1604        [GCC_IMEM_CFG_AHB_CLK] = &gcc_imem_cfg_ahb_clk.clkr,
1605        [GCC_PCIE_AHB_CLK] = &gcc_pcie_ahb_clk.clkr,
1606        [GCC_PCIE_AXI_M_CLK] = &gcc_pcie_axi_m_clk.clkr,
1607        [GCC_PCIE_AXI_S_CLK] = &gcc_pcie_axi_s_clk.clkr,
1608        [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
1609        [GCC_QPIC_AHB_CLK] = &gcc_qpic_ahb_clk.clkr,
1610        [GCC_QPIC_CLK] = &gcc_qpic_clk.clkr,
1611        [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
1612        [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
1613        [GCC_TLMM_AHB_CLK] = &gcc_tlmm_ahb_clk.clkr,
1614        [GCC_USB2_MASTER_CLK] = &gcc_usb2_master_clk.clkr,
1615        [GCC_USB2_SLEEP_CLK] = &gcc_usb2_sleep_clk.clkr,
1616        [GCC_USB2_MOCK_UTMI_CLK] = &gcc_usb2_mock_utmi_clk.clkr,
1617        [GCC_USB3_MASTER_CLK] = &gcc_usb3_master_clk.clkr,
1618        [GCC_USB3_SLEEP_CLK] = &gcc_usb3_sleep_clk.clkr,
1619        [GCC_USB3_MOCK_UTMI_CLK] = &gcc_usb3_mock_utmi_clk.clkr,
1620        [GCC_WCSS2G_CLK] = &gcc_wcss2g_clk.clkr,
1621        [GCC_WCSS2G_REF_CLK] = &gcc_wcss2g_ref_clk.clkr,
1622        [GCC_WCSS2G_RTC_CLK] = &gcc_wcss2g_rtc_clk.clkr,
1623        [GCC_WCSS5G_CLK] = &gcc_wcss5g_clk.clkr,
1624        [GCC_WCSS5G_REF_CLK] = &gcc_wcss5g_ref_clk.clkr,
1625        [GCC_WCSS5G_RTC_CLK] = &gcc_wcss5g_rtc_clk.clkr,
1626        [GCC_SDCC_PLLDIV_CLK] = &gcc_apss_sdcc_clk.cdiv.clkr,
1627        [GCC_FEPLL125_CLK] = &gcc_fepll125_clk.cdiv.clkr,
1628        [GCC_FEPLL125DLY_CLK] = &gcc_fepll125dly_clk.cdiv.clkr,
1629        [GCC_FEPLL200_CLK] = &gcc_fepll200_clk.cdiv.clkr,
1630        [GCC_FEPLL500_CLK] = &gcc_fepll500_clk.cdiv.clkr,
1631        [GCC_FEPLL_WCSS2G_CLK] = &gcc_fepllwcss2g_clk.cdiv.clkr,
1632        [GCC_FEPLL_WCSS5G_CLK] = &gcc_fepllwcss5g_clk.cdiv.clkr,
1633        [GCC_APSS_CPU_PLLDIV_CLK] = &gcc_apss_cpu_plldiv_clk.cdiv.clkr,
1634        [GCC_PCNOC_AHB_CLK_SRC] = &gcc_pcnoc_ahb_clk_src.clkr,
1635        [GCC_PCNOC_AHB_CLK] = &pcnoc_clk_src.clkr,
1636};
1637
1638static const struct qcom_reset_map gcc_ipq4019_resets[] = {
1639        [WIFI0_CPU_INIT_RESET] = { 0x1f008, 5 },
1640        [WIFI0_RADIO_SRIF_RESET] = { 0x1f008, 4 },
1641        [WIFI0_RADIO_WARM_RESET] = { 0x1f008, 3 },
1642        [WIFI0_RADIO_COLD_RESET] = { 0x1f008, 2 },
1643        [WIFI0_CORE_WARM_RESET] = { 0x1f008, 1 },
1644        [WIFI0_CORE_COLD_RESET] = { 0x1f008, 0 },
1645        [WIFI1_CPU_INIT_RESET] = { 0x20008, 5 },
1646        [WIFI1_RADIO_SRIF_RESET] = { 0x20008, 4 },
1647        [WIFI1_RADIO_WARM_RESET] = { 0x20008, 3 },
1648        [WIFI1_RADIO_COLD_RESET] = { 0x20008, 2 },
1649        [WIFI1_CORE_WARM_RESET] = { 0x20008, 1 },
1650        [WIFI1_CORE_COLD_RESET] = { 0x20008, 0 },
1651        [USB3_UNIPHY_PHY_ARES] = { 0x1e038, 5 },
1652        [USB3_HSPHY_POR_ARES] = { 0x1e038, 4 },
1653        [USB3_HSPHY_S_ARES] = { 0x1e038, 2 },
1654        [USB2_HSPHY_POR_ARES] = { 0x1e01c, 4 },
1655        [USB2_HSPHY_S_ARES] = { 0x1e01c, 2 },
1656        [PCIE_PHY_AHB_ARES] = { 0x1d010, 11 },
1657        [PCIE_AHB_ARES] = { 0x1d010, 10 },
1658        [PCIE_PWR_ARES] = { 0x1d010, 9 },
1659        [PCIE_PIPE_STICKY_ARES] = { 0x1d010, 8 },
1660        [PCIE_AXI_M_STICKY_ARES] = { 0x1d010, 7 },
1661        [PCIE_PHY_ARES] = { 0x1d010, 6 },
1662        [PCIE_PARF_XPU_ARES] = { 0x1d010, 5 },
1663        [PCIE_AXI_S_XPU_ARES] = { 0x1d010, 4 },
1664        [PCIE_AXI_M_VMIDMT_ARES] = { 0x1d010, 3 },
1665        [PCIE_PIPE_ARES] = { 0x1d010, 2 },
1666        [PCIE_AXI_S_ARES] = { 0x1d010, 1 },
1667        [PCIE_AXI_M_ARES] = { 0x1d010, 0 },
1668        [ESS_RESET] = { 0x12008, 0},
1669        [GCC_BLSP1_BCR] = {0x01000, 0},
1670        [GCC_BLSP1_QUP1_BCR] = {0x02000, 0},
1671        [GCC_BLSP1_UART1_BCR] = {0x02038, 0},
1672        [GCC_BLSP1_QUP2_BCR] = {0x03008, 0},
1673        [GCC_BLSP1_UART2_BCR] = {0x03028, 0},
1674        [GCC_BIMC_BCR] = {0x04000, 0},
1675        [GCC_TLMM_BCR] = {0x05000, 0},
1676        [GCC_IMEM_BCR] = {0x0E000, 0},
1677        [GCC_ESS_BCR] = {0x12008, 0},
1678        [GCC_PRNG_BCR] = {0x13000, 0},
1679        [GCC_BOOT_ROM_BCR] = {0x13008, 0},
1680        [GCC_CRYPTO_BCR] = {0x16000, 0},
1681        [GCC_SDCC1_BCR] = {0x18000, 0},
1682        [GCC_SEC_CTRL_BCR] = {0x1A000, 0},
1683        [GCC_AUDIO_BCR] = {0x1B008, 0},
1684        [GCC_QPIC_BCR] = {0x1C000, 0},
1685        [GCC_PCIE_BCR] = {0x1D000, 0},
1686        [GCC_USB2_BCR] = {0x1E008, 0},
1687        [GCC_USB2_PHY_BCR] = {0x1E018, 0},
1688        [GCC_USB3_BCR] = {0x1E024, 0},
1689        [GCC_USB3_PHY_BCR] = {0x1E034, 0},
1690        [GCC_SYSTEM_NOC_BCR] = {0x21000, 0},
1691        [GCC_PCNOC_BCR] = {0x2102C, 0},
1692        [GCC_DCD_BCR] = {0x21038, 0},
1693        [GCC_SNOC_BUS_TIMEOUT0_BCR] = {0x21064, 0},
1694        [GCC_SNOC_BUS_TIMEOUT1_BCR] = {0x2106C, 0},
1695        [GCC_SNOC_BUS_TIMEOUT2_BCR] = {0x21074, 0},
1696        [GCC_SNOC_BUS_TIMEOUT3_BCR] = {0x2107C, 0},
1697        [GCC_PCNOC_BUS_TIMEOUT0_BCR] = {0x21084, 0},
1698        [GCC_PCNOC_BUS_TIMEOUT1_BCR] = {0x2108C, 0},
1699        [GCC_PCNOC_BUS_TIMEOUT2_BCR] = {0x21094, 0},
1700        [GCC_PCNOC_BUS_TIMEOUT3_BCR] = {0x2109C, 0},
1701        [GCC_PCNOC_BUS_TIMEOUT4_BCR] = {0x210A4, 0},
1702        [GCC_PCNOC_BUS_TIMEOUT5_BCR] = {0x210AC, 0},
1703        [GCC_PCNOC_BUS_TIMEOUT6_BCR] = {0x210B4, 0},
1704        [GCC_PCNOC_BUS_TIMEOUT7_BCR] = {0x210BC, 0},
1705        [GCC_PCNOC_BUS_TIMEOUT8_BCR] = {0x210C4, 0},
1706        [GCC_PCNOC_BUS_TIMEOUT9_BCR] = {0x210CC, 0},
1707        [GCC_TCSR_BCR] = {0x22000, 0},
1708        [GCC_MPM_BCR] = {0x24000, 0},
1709        [GCC_SPDM_BCR] = {0x25000, 0},
1710};
1711
1712static const struct regmap_config gcc_ipq4019_regmap_config = {
1713        .reg_bits       = 32,
1714        .reg_stride     = 4,
1715        .val_bits       = 32,
1716        .max_register   = 0x2ffff,
1717        .fast_io        = true,
1718};
1719
1720static const struct qcom_cc_desc gcc_ipq4019_desc = {
1721        .config = &gcc_ipq4019_regmap_config,
1722        .clks = gcc_ipq4019_clocks,
1723        .num_clks = ARRAY_SIZE(gcc_ipq4019_clocks),
1724        .resets = gcc_ipq4019_resets,
1725        .num_resets = ARRAY_SIZE(gcc_ipq4019_resets),
1726};
1727
1728static const struct of_device_id gcc_ipq4019_match_table[] = {
1729        { .compatible = "qcom,gcc-ipq4019" },
1730        { }
1731};
1732MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table);
1733
1734static int
1735gcc_ipq4019_cpu_clk_notifier_fn(struct notifier_block *nb,
1736                                unsigned long action, void *data)
1737{
1738        int err = 0;
1739
1740        if (action == PRE_RATE_CHANGE)
1741                err = clk_rcg2_ops.set_parent(&apps_clk_src.clkr.hw,
1742                                              gcc_ipq4019_cpu_safe_parent);
1743
1744        return notifier_from_errno(err);
1745}
1746
1747static struct notifier_block gcc_ipq4019_cpu_clk_notifier = {
1748        .notifier_call = gcc_ipq4019_cpu_clk_notifier_fn,
1749};
1750
1751static int gcc_ipq4019_probe(struct platform_device *pdev)
1752{
1753        int err;
1754
1755        err = qcom_cc_probe(pdev, &gcc_ipq4019_desc);
1756        if (err)
1757                return err;
1758
1759        return clk_notifier_register(apps_clk_src.clkr.hw.clk,
1760                                     &gcc_ipq4019_cpu_clk_notifier);
1761}
1762
1763static int gcc_ipq4019_remove(struct platform_device *pdev)
1764{
1765        return clk_notifier_unregister(apps_clk_src.clkr.hw.clk,
1766                                       &gcc_ipq4019_cpu_clk_notifier);
1767}
1768
1769static struct platform_driver gcc_ipq4019_driver = {
1770        .probe          = gcc_ipq4019_probe,
1771        .remove         = gcc_ipq4019_remove,
1772        .driver         = {
1773                .name   = "qcom,gcc-ipq4019",
1774                .of_match_table = gcc_ipq4019_match_table,
1775        },
1776};
1777
1778static int __init gcc_ipq4019_init(void)
1779{
1780        return platform_driver_register(&gcc_ipq4019_driver);
1781}
1782core_initcall(gcc_ipq4019_init);
1783
1784static void __exit gcc_ipq4019_exit(void)
1785{
1786        platform_driver_unregister(&gcc_ipq4019_driver);
1787}
1788module_exit(gcc_ipq4019_exit);
1789
1790MODULE_ALIAS("platform:gcc-ipq4019");
1791MODULE_LICENSE("GPL v2");
1792MODULE_DESCRIPTION("QCOM GCC IPQ4019 driver");
1793