Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/err.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/clk-provider.h>
0013 #include <linux/regmap.h>
0014 #include <linux/reset-controller.h>
0015 #include <linux/math64.h>
0016 #include <linux/delay.h>
0017 #include <linux/clk.h>
0018 
0019 #include <dt-bindings/clock/qcom,gcc-ipq4019.h>
0020 
0021 #include "common.h"
0022 #include "clk-regmap.h"
0023 #include "clk-rcg.h"
0024 #include "clk-branch.h"
0025 #include "reset.h"
0026 #include "clk-regmap-divider.h"
0027 
0028 #define to_clk_regmap_div(_hw) container_of(to_clk_regmap(_hw),\
0029                     struct clk_regmap_div, clkr)
0030 
0031 #define to_clk_fepll(_hw) container_of(to_clk_regmap_div(_hw),\
0032                         struct clk_fepll, cdiv)
0033 
0034 enum {
0035     P_XO,
0036     P_FEPLL200,
0037     P_FEPLL500,
0038     P_DDRPLL,
0039     P_FEPLLWCSS2G,
0040     P_FEPLLWCSS5G,
0041     P_FEPLL125DLY,
0042     P_DDRPLLAPSS,
0043 };
0044 
0045 /*
0046  * struct clk_fepll_vco - vco feedback divider corresponds for FEPLL clocks
0047  * @fdbkdiv_shift: lowest bit for FDBKDIV
0048  * @fdbkdiv_width: number of bits in FDBKDIV
0049  * @refclkdiv_shift: lowest bit for REFCLKDIV
0050  * @refclkdiv_width: number of bits in REFCLKDIV
0051  * @reg: PLL_DIV register address
0052  */
0053 struct clk_fepll_vco {
0054     u32 fdbkdiv_shift;
0055     u32 fdbkdiv_width;
0056     u32 refclkdiv_shift;
0057     u32 refclkdiv_width;
0058     u32 reg;
0059 };
0060 
0061 /*
0062  * struct clk_fepll - clk divider corresponds to FEPLL clocks
0063  * @fixed_div: fixed divider value if divider is fixed
0064  * @parent_map: map from software's parent index to hardware's src_sel field
0065  * @cdiv: divider values for PLL_DIV
0066  * @pll_vco: vco feedback divider
0067  * @div_table: mapping for actual divider value to register divider value
0068  *             in case of non fixed divider
0069  * @freq_tbl: frequency table
0070  */
0071 struct clk_fepll {
0072     u32 fixed_div;
0073     const u8 *parent_map;
0074     struct clk_regmap_div cdiv;
0075     const struct clk_fepll_vco *pll_vco;
0076     const struct clk_div_table *div_table;
0077     const struct freq_tbl *freq_tbl;
0078 };
0079 
0080 static struct parent_map gcc_xo_200_500_map[] = {
0081     { P_XO, 0 },
0082     { P_FEPLL200, 1 },
0083     { P_FEPLL500, 2 },
0084 };
0085 
0086 static const char * const gcc_xo_200_500[] = {
0087     "xo",
0088     "fepll200",
0089     "fepll500",
0090 };
0091 
0092 static struct parent_map gcc_xo_200_map[] = {
0093     {  P_XO, 0 },
0094     {  P_FEPLL200, 1 },
0095 };
0096 
0097 static const char * const gcc_xo_200[] = {
0098     "xo",
0099     "fepll200",
0100 };
0101 
0102 static struct parent_map gcc_xo_200_spi_map[] = {
0103     {  P_XO, 0 },
0104     {  P_FEPLL200, 2 },
0105 };
0106 
0107 static const char * const gcc_xo_200_spi[] = {
0108     "xo",
0109     "fepll200",
0110 };
0111 
0112 static struct parent_map gcc_xo_sdcc1_500_map[] = {
0113     {  P_XO, 0 },
0114     {  P_DDRPLL, 1 },
0115     {  P_FEPLL500, 2 },
0116 };
0117 
0118 static const char * const gcc_xo_sdcc1_500[] = {
0119     "xo",
0120     "ddrpllsdcc",
0121     "fepll500",
0122 };
0123 
0124 static struct parent_map gcc_xo_wcss2g_map[] = {
0125     {  P_XO, 0 },
0126     {  P_FEPLLWCSS2G, 1 },
0127 };
0128 
0129 static const char * const gcc_xo_wcss2g[] = {
0130     "xo",
0131     "fepllwcss2g",
0132 };
0133 
0134 static struct parent_map gcc_xo_wcss5g_map[] = {
0135     {  P_XO, 0 },
0136     {  P_FEPLLWCSS5G, 1 },
0137 };
0138 
0139 static const char * const gcc_xo_wcss5g[] = {
0140     "xo",
0141     "fepllwcss5g",
0142 };
0143 
0144 static struct parent_map gcc_xo_125_dly_map[] = {
0145     {  P_XO, 0 },
0146     {  P_FEPLL125DLY, 1 },
0147 };
0148 
0149 static const char * const gcc_xo_125_dly[] = {
0150     "xo",
0151     "fepll125dly",
0152 };
0153 
0154 static struct parent_map gcc_xo_ddr_500_200_map[] = {
0155     {  P_XO, 0 },
0156     {  P_FEPLL200, 3 },
0157     {  P_FEPLL500, 2 },
0158     {  P_DDRPLLAPSS, 1 },
0159 };
0160 
0161 /*
0162  * Contains index for safe clock during APSS freq change.
0163  * fepll500 is being used as safe clock so initialize it
0164  * with its index in parents list gcc_xo_ddr_500_200.
0165  */
0166 static const int gcc_ipq4019_cpu_safe_parent = 2;
0167 static const char * const gcc_xo_ddr_500_200[] = {
0168     "xo",
0169     "fepll200",
0170     "fepll500",
0171     "ddrpllapss",
0172 };
0173 
0174 static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] = {
0175     F(48000000, P_XO, 1, 0, 0),
0176     F(200000000, P_FEPLL200, 1, 0, 0),
0177     { }
0178 };
0179 
0180 static struct clk_rcg2 audio_clk_src = {
0181     .cmd_rcgr = 0x1b000,
0182     .hid_width = 5,
0183     .parent_map = gcc_xo_200_map,
0184     .freq_tbl = ftbl_gcc_audio_pwm_clk,
0185     .clkr.hw.init = &(struct clk_init_data){
0186         .name = "audio_clk_src",
0187         .parent_names = gcc_xo_200,
0188         .num_parents = 2,
0189         .ops = &clk_rcg2_ops,
0190 
0191     },
0192 };
0193 
0194 static struct clk_branch gcc_audio_ahb_clk = {
0195     .halt_reg = 0x1b010,
0196     .clkr = {
0197         .enable_reg = 0x1b010,
0198         .enable_mask = BIT(0),
0199         .hw.init = &(struct clk_init_data){
0200             .name = "gcc_audio_ahb_clk",
0201             .parent_names = (const char *[]){
0202                 "pcnoc_clk_src",
0203             },
0204             .flags = CLK_SET_RATE_PARENT,
0205             .num_parents = 1,
0206             .ops = &clk_branch2_ops,
0207         },
0208     },
0209 };
0210 
0211 static struct clk_branch gcc_audio_pwm_clk = {
0212     .halt_reg = 0x1b00C,
0213     .clkr = {
0214         .enable_reg = 0x1b00C,
0215         .enable_mask = BIT(0),
0216         .hw.init = &(struct clk_init_data){
0217             .name = "gcc_audio_pwm_clk",
0218             .parent_names = (const char *[]){
0219                 "audio_clk_src",
0220             },
0221             .flags = CLK_SET_RATE_PARENT,
0222             .num_parents = 1,
0223             .ops = &clk_branch2_ops,
0224         },
0225     },
0226 };
0227 
0228 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
0229     F(19050000, P_FEPLL200, 10.5, 1, 1),
0230     { }
0231 };
0232 
0233 static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
0234     .cmd_rcgr = 0x200c,
0235     .hid_width = 5,
0236     .parent_map = gcc_xo_200_map,
0237     .freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk,
0238     .clkr.hw.init = &(struct clk_init_data){
0239         .name = "blsp1_qup1_i2c_apps_clk_src",
0240         .parent_names = gcc_xo_200,
0241         .num_parents = 2,
0242         .ops = &clk_rcg2_ops,
0243     },
0244 };
0245 
0246 static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
0247     .halt_reg = 0x2008,
0248     .clkr = {
0249         .enable_reg = 0x2008,
0250         .enable_mask = BIT(0),
0251         .hw.init = &(struct clk_init_data){
0252             .name = "gcc_blsp1_qup1_i2c_apps_clk",
0253             .parent_names = (const char *[]){
0254                 "blsp1_qup1_i2c_apps_clk_src",
0255             },
0256             .num_parents = 1,
0257             .ops = &clk_branch2_ops,
0258             .flags = CLK_SET_RATE_PARENT,
0259         },
0260     },
0261 };
0262 
0263 static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
0264     .cmd_rcgr = 0x3000,
0265     .hid_width = 5,
0266     .parent_map = gcc_xo_200_map,
0267     .freq_tbl = ftbl_gcc_blsp1_qup1_2_i2c_apps_clk,
0268     .clkr.hw.init = &(struct clk_init_data){
0269         .name = "blsp1_qup2_i2c_apps_clk_src",
0270         .parent_names = gcc_xo_200,
0271         .num_parents = 2,
0272         .ops = &clk_rcg2_ops,
0273     },
0274 };
0275 
0276 static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
0277     .halt_reg = 0x3010,
0278     .clkr = {
0279         .enable_reg = 0x3010,
0280         .enable_mask = BIT(0),
0281         .hw.init = &(struct clk_init_data){
0282             .name = "gcc_blsp1_qup2_i2c_apps_clk",
0283             .parent_names = (const char *[]){
0284                 "blsp1_qup2_i2c_apps_clk_src",
0285             },
0286             .num_parents = 1,
0287             .ops = &clk_branch2_ops,
0288             .flags = CLK_SET_RATE_PARENT,
0289         },
0290     },
0291 };
0292 
0293 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_spi_apps_clk[] = {
0294     F(960000, P_XO, 12, 1, 4),
0295     F(4800000, P_XO, 1, 1, 10),
0296     F(9600000, P_XO, 1, 1, 5),
0297     F(15000000, P_XO, 1, 1, 3),
0298     F(19200000, P_XO, 1, 2, 5),
0299     F(24000000, P_XO, 1, 1, 2),
0300     F(48000000, P_XO, 1, 0, 0),
0301     { }
0302 };
0303 
0304 static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
0305     .cmd_rcgr = 0x2024,
0306     .mnd_width = 8,
0307     .hid_width = 5,
0308     .parent_map = gcc_xo_200_spi_map,
0309     .freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk,
0310     .clkr.hw.init = &(struct clk_init_data){
0311         .name = "blsp1_qup1_spi_apps_clk_src",
0312         .parent_names = gcc_xo_200_spi,
0313         .num_parents = 2,
0314         .ops = &clk_rcg2_ops,
0315     },
0316 };
0317 
0318 static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
0319     .halt_reg = 0x2004,
0320     .clkr = {
0321         .enable_reg = 0x2004,
0322         .enable_mask = BIT(0),
0323         .hw.init = &(struct clk_init_data){
0324             .name = "gcc_blsp1_qup1_spi_apps_clk",
0325             .parent_names = (const char *[]){
0326                 "blsp1_qup1_spi_apps_clk_src",
0327             },
0328             .num_parents = 1,
0329             .ops = &clk_branch2_ops,
0330             .flags = CLK_SET_RATE_PARENT,
0331         },
0332     },
0333 };
0334 
0335 static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
0336     .cmd_rcgr = 0x3014,
0337     .mnd_width = 8,
0338     .hid_width = 5,
0339     .freq_tbl = ftbl_gcc_blsp1_qup1_2_spi_apps_clk,
0340     .parent_map = gcc_xo_200_spi_map,
0341     .clkr.hw.init = &(struct clk_init_data){
0342         .name = "blsp1_qup2_spi_apps_clk_src",
0343         .parent_names = gcc_xo_200_spi,
0344         .num_parents = 2,
0345         .ops = &clk_rcg2_ops,
0346     },
0347 };
0348 
0349 static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
0350     .halt_reg = 0x300c,
0351     .clkr = {
0352         .enable_reg = 0x300c,
0353         .enable_mask = BIT(0),
0354         .hw.init = &(struct clk_init_data){
0355             .name = "gcc_blsp1_qup2_spi_apps_clk",
0356             .parent_names = (const char *[]){
0357                 "blsp1_qup2_spi_apps_clk_src",
0358             },
0359             .num_parents = 1,
0360             .ops = &clk_branch2_ops,
0361             .flags = CLK_SET_RATE_PARENT,
0362         },
0363     },
0364 };
0365 
0366 static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] = {
0367     F(1843200, P_FEPLL200, 1, 144, 15625),
0368     F(3686400, P_FEPLL200, 1, 288, 15625),
0369     F(7372800, P_FEPLL200, 1, 576, 15625),
0370     F(14745600, P_FEPLL200, 1, 1152, 15625),
0371     F(16000000, P_FEPLL200, 1, 2, 25),
0372     F(24000000, P_XO, 1, 1, 2),
0373     F(32000000, P_FEPLL200, 1, 4, 25),
0374     F(40000000, P_FEPLL200, 1, 1, 5),
0375     F(46400000, P_FEPLL200, 1, 29, 125),
0376     F(48000000, P_XO, 1, 0, 0),
0377     { }
0378 };
0379 
0380 static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
0381     .cmd_rcgr = 0x2044,
0382     .mnd_width = 16,
0383     .hid_width = 5,
0384     .freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk,
0385     .parent_map = gcc_xo_200_spi_map,
0386     .clkr.hw.init = &(struct clk_init_data){
0387         .name = "blsp1_uart1_apps_clk_src",
0388         .parent_names = gcc_xo_200_spi,
0389         .num_parents = 2,
0390         .ops = &clk_rcg2_ops,
0391     },
0392 };
0393 
0394 static struct clk_branch gcc_blsp1_uart1_apps_clk = {
0395     .halt_reg = 0x203c,
0396     .clkr = {
0397         .enable_reg = 0x203c,
0398         .enable_mask = BIT(0),
0399         .hw.init = &(struct clk_init_data){
0400             .name = "gcc_blsp1_uart1_apps_clk",
0401             .parent_names = (const char *[]){
0402                 "blsp1_uart1_apps_clk_src",
0403             },
0404             .flags = CLK_SET_RATE_PARENT,
0405             .num_parents = 1,
0406             .ops = &clk_branch2_ops,
0407         },
0408     },
0409 };
0410 
0411 static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
0412     .cmd_rcgr = 0x3034,
0413     .mnd_width = 16,
0414     .hid_width = 5,
0415     .freq_tbl = ftbl_gcc_blsp1_uart1_2_apps_clk,
0416     .parent_map = gcc_xo_200_spi_map,
0417     .clkr.hw.init = &(struct clk_init_data){
0418         .name = "blsp1_uart2_apps_clk_src",
0419         .parent_names = gcc_xo_200_spi,
0420         .num_parents = 2,
0421         .ops = &clk_rcg2_ops,
0422     },
0423 };
0424 
0425 static struct clk_branch gcc_blsp1_uart2_apps_clk = {
0426     .halt_reg = 0x302c,
0427     .clkr = {
0428         .enable_reg = 0x302c,
0429         .enable_mask = BIT(0),
0430         .hw.init = &(struct clk_init_data){
0431             .name = "gcc_blsp1_uart2_apps_clk",
0432             .parent_names = (const char *[]){
0433                 "blsp1_uart2_apps_clk_src",
0434             },
0435             .num_parents = 1,
0436             .ops = &clk_branch2_ops,
0437             .flags = CLK_SET_RATE_PARENT,
0438         },
0439     },
0440 };
0441 
0442 static const struct freq_tbl ftbl_gcc_gp_clk[] = {
0443     F(1250000,  P_FEPLL200, 1, 16, 0),
0444     F(2500000,  P_FEPLL200, 1,  8, 0),
0445     F(5000000,  P_FEPLL200, 1,  4, 0),
0446     { }
0447 };
0448 
0449 static struct clk_rcg2 gp1_clk_src = {
0450     .cmd_rcgr = 0x8004,
0451     .mnd_width = 8,
0452     .hid_width = 5,
0453     .freq_tbl = ftbl_gcc_gp_clk,
0454     .parent_map = gcc_xo_200_map,
0455     .clkr.hw.init = &(struct clk_init_data){
0456         .name = "gp1_clk_src",
0457         .parent_names = gcc_xo_200,
0458         .num_parents = 2,
0459         .ops = &clk_rcg2_ops,
0460     },
0461 };
0462 
0463 static struct clk_branch gcc_gp1_clk = {
0464     .halt_reg = 0x8000,
0465     .clkr = {
0466         .enable_reg = 0x8000,
0467         .enable_mask = BIT(0),
0468         .hw.init = &(struct clk_init_data){
0469             .name = "gcc_gp1_clk",
0470             .parent_names = (const char *[]){
0471                 "gp1_clk_src",
0472             },
0473             .num_parents = 1,
0474             .ops = &clk_branch2_ops,
0475             .flags = CLK_SET_RATE_PARENT,
0476         },
0477     },
0478 };
0479 
0480 static struct clk_rcg2 gp2_clk_src = {
0481     .cmd_rcgr = 0x9004,
0482     .mnd_width = 8,
0483     .hid_width = 5,
0484     .freq_tbl = ftbl_gcc_gp_clk,
0485     .parent_map = gcc_xo_200_map,
0486     .clkr.hw.init = &(struct clk_init_data){
0487         .name = "gp2_clk_src",
0488         .parent_names = gcc_xo_200,
0489         .num_parents = 2,
0490         .ops = &clk_rcg2_ops,
0491     },
0492 };
0493 
0494 static struct clk_branch gcc_gp2_clk = {
0495     .halt_reg = 0x9000,
0496     .clkr = {
0497         .enable_reg = 0x9000,
0498         .enable_mask = BIT(0),
0499         .hw.init = &(struct clk_init_data){
0500             .name = "gcc_gp2_clk",
0501             .parent_names = (const char *[]){
0502                 "gp2_clk_src",
0503             },
0504             .num_parents = 1,
0505             .ops = &clk_branch2_ops,
0506             .flags = CLK_SET_RATE_PARENT,
0507         },
0508     },
0509 };
0510 
0511 static struct clk_rcg2 gp3_clk_src = {
0512     .cmd_rcgr = 0xa004,
0513     .mnd_width = 8,
0514     .hid_width = 5,
0515     .freq_tbl = ftbl_gcc_gp_clk,
0516     .parent_map = gcc_xo_200_map,
0517     .clkr.hw.init = &(struct clk_init_data){
0518         .name = "gp3_clk_src",
0519         .parent_names = gcc_xo_200,
0520         .num_parents = 2,
0521         .ops = &clk_rcg2_ops,
0522     },
0523 };
0524 
0525 static struct clk_branch gcc_gp3_clk = {
0526     .halt_reg = 0xa000,
0527     .clkr = {
0528         .enable_reg = 0xa000,
0529         .enable_mask = BIT(0),
0530         .hw.init = &(struct clk_init_data){
0531             .name = "gcc_gp3_clk",
0532             .parent_names = (const char *[]){
0533                 "gp3_clk_src",
0534             },
0535             .num_parents = 1,
0536             .ops = &clk_branch2_ops,
0537             .flags = CLK_SET_RATE_PARENT,
0538         },
0539     },
0540 };
0541 
0542 static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = {
0543     F(144000,    P_XO,          1,  3, 240),
0544     F(400000,    P_XO,          1,  1, 0),
0545     F(20000000,  P_FEPLL500,        1,  1, 25),
0546     F(25000000,  P_FEPLL500,        1,  1, 20),
0547     F(50000000,  P_FEPLL500,        1,  1, 10),
0548     F(100000000, P_FEPLL500,        1,  1, 5),
0549     F(192000000, P_DDRPLL,          1,  0, 0),
0550     { }
0551 };
0552 
0553 static struct clk_rcg2  sdcc1_apps_clk_src = {
0554     .cmd_rcgr = 0x18004,
0555     .hid_width = 5,
0556     .freq_tbl = ftbl_gcc_sdcc1_apps_clk,
0557     .parent_map = gcc_xo_sdcc1_500_map,
0558     .clkr.hw.init = &(struct clk_init_data){
0559         .name = "sdcc1_apps_clk_src",
0560         .parent_names = gcc_xo_sdcc1_500,
0561         .num_parents = 3,
0562         .ops = &clk_rcg2_ops,
0563         .flags = CLK_SET_RATE_PARENT,
0564     },
0565 };
0566 
0567 static const struct freq_tbl ftbl_gcc_apps_clk[] = {
0568     F(48000000,  P_XO,         1, 0, 0),
0569     F(200000000, P_FEPLL200,   1, 0, 0),
0570     F(384000000, P_DDRPLLAPSS, 1, 0, 0),
0571     F(413000000, P_DDRPLLAPSS, 1, 0, 0),
0572     F(448000000, P_DDRPLLAPSS, 1, 0, 0),
0573     F(488000000, P_DDRPLLAPSS, 1, 0, 0),
0574     F(500000000, P_FEPLL500,   1, 0, 0),
0575     F(512000000, P_DDRPLLAPSS, 1, 0, 0),
0576     F(537000000, P_DDRPLLAPSS, 1, 0, 0),
0577     F(565000000, P_DDRPLLAPSS, 1, 0, 0),
0578     F(597000000, P_DDRPLLAPSS, 1, 0, 0),
0579     F(632000000, P_DDRPLLAPSS, 1, 0, 0),
0580     F(672000000, P_DDRPLLAPSS, 1, 0, 0),
0581     F(716000000, P_DDRPLLAPSS, 1, 0, 0),
0582     { }
0583 };
0584 
0585 static struct clk_rcg2 apps_clk_src = {
0586     .cmd_rcgr = 0x1900c,
0587     .hid_width = 5,
0588     .freq_tbl = ftbl_gcc_apps_clk,
0589     .parent_map = gcc_xo_ddr_500_200_map,
0590     .clkr.hw.init = &(struct clk_init_data){
0591         .name = "apps_clk_src",
0592         .parent_names = gcc_xo_ddr_500_200,
0593         .num_parents = 4,
0594         .ops = &clk_rcg2_ops,
0595         .flags = CLK_SET_RATE_PARENT,
0596     },
0597 };
0598 
0599 static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] = {
0600     F(48000000, P_XO,      1, 0, 0),
0601     F(100000000, P_FEPLL200,   2, 0, 0),
0602     { }
0603 };
0604 
0605 static struct clk_rcg2 apps_ahb_clk_src = {
0606     .cmd_rcgr = 0x19014,
0607     .hid_width = 5,
0608     .parent_map = gcc_xo_200_500_map,
0609     .freq_tbl = ftbl_gcc_apps_ahb_clk,
0610     .clkr.hw.init = &(struct clk_init_data){
0611         .name = "apps_ahb_clk_src",
0612         .parent_names = gcc_xo_200_500,
0613         .num_parents = 3,
0614         .ops = &clk_rcg2_ops,
0615     },
0616 };
0617 
0618 static struct clk_branch gcc_apss_ahb_clk = {
0619     .halt_reg = 0x19004,
0620     .halt_check = BRANCH_HALT_VOTED,
0621     .clkr = {
0622         .enable_reg = 0x6000,
0623         .enable_mask = BIT(14),
0624         .hw.init = &(struct clk_init_data){
0625             .name = "gcc_apss_ahb_clk",
0626             .parent_names = (const char *[]){
0627                 "apps_ahb_clk_src",
0628             },
0629             .num_parents = 1,
0630             .ops = &clk_branch2_ops,
0631             .flags = CLK_SET_RATE_PARENT,
0632         },
0633     },
0634 };
0635 
0636 static struct clk_branch gcc_blsp1_ahb_clk = {
0637     .halt_reg = 0x1008,
0638     .halt_check = BRANCH_HALT_VOTED,
0639     .clkr = {
0640         .enable_reg = 0x6000,
0641         .enable_mask = BIT(10),
0642         .hw.init = &(struct clk_init_data){
0643             .name = "gcc_blsp1_ahb_clk",
0644             .parent_names = (const char *[]){
0645                 "pcnoc_clk_src",
0646             },
0647             .num_parents = 1,
0648             .ops = &clk_branch2_ops,
0649         },
0650     },
0651 };
0652 
0653 static struct clk_branch gcc_dcd_xo_clk = {
0654     .halt_reg = 0x2103c,
0655     .clkr = {
0656         .enable_reg = 0x2103c,
0657         .enable_mask = BIT(0),
0658         .hw.init = &(struct clk_init_data){
0659             .name = "gcc_dcd_xo_clk",
0660             .parent_names = (const char *[]){
0661                 "xo",
0662             },
0663             .num_parents = 1,
0664             .ops = &clk_branch2_ops,
0665         },
0666     },
0667 };
0668 
0669 static struct clk_branch gcc_boot_rom_ahb_clk = {
0670     .halt_reg = 0x1300c,
0671     .clkr = {
0672         .enable_reg = 0x1300c,
0673         .enable_mask = BIT(0),
0674         .hw.init = &(struct clk_init_data){
0675             .name = "gcc_boot_rom_ahb_clk",
0676             .parent_names = (const char *[]){
0677                 "pcnoc_clk_src",
0678             },
0679             .num_parents = 1,
0680             .ops = &clk_branch2_ops,
0681             .flags = CLK_SET_RATE_PARENT,
0682         },
0683     },
0684 };
0685 
0686 static struct clk_branch gcc_crypto_ahb_clk = {
0687     .halt_reg = 0x16024,
0688     .halt_check = BRANCH_HALT_VOTED,
0689     .clkr = {
0690         .enable_reg = 0x6000,
0691         .enable_mask = BIT(0),
0692         .hw.init = &(struct clk_init_data){
0693             .name = "gcc_crypto_ahb_clk",
0694             .parent_names = (const char *[]){
0695                 "pcnoc_clk_src",
0696             },
0697             .num_parents = 1,
0698             .ops = &clk_branch2_ops,
0699         },
0700     },
0701 };
0702 
0703 static struct clk_branch gcc_crypto_axi_clk = {
0704     .halt_reg = 0x16020,
0705     .halt_check = BRANCH_HALT_VOTED,
0706     .clkr = {
0707         .enable_reg = 0x6000,
0708         .enable_mask = BIT(1),
0709         .hw.init = &(struct clk_init_data){
0710             .name = "gcc_crypto_axi_clk",
0711             .parent_names = (const char *[]){
0712                 "fepll125",
0713             },
0714             .num_parents = 1,
0715             .ops = &clk_branch2_ops,
0716         },
0717     },
0718 };
0719 
0720 static struct clk_branch gcc_crypto_clk = {
0721     .halt_reg = 0x1601c,
0722     .halt_check = BRANCH_HALT_VOTED,
0723     .clkr = {
0724         .enable_reg = 0x6000,
0725         .enable_mask = BIT(2),
0726         .hw.init = &(struct clk_init_data){
0727             .name = "gcc_crypto_clk",
0728             .parent_names = (const char *[]){
0729                 "fepll125",
0730             },
0731             .num_parents = 1,
0732             .ops = &clk_branch2_ops,
0733         },
0734     },
0735 };
0736 
0737 static struct clk_branch gcc_ess_clk = {
0738     .halt_reg = 0x12010,
0739     .clkr = {
0740         .enable_reg = 0x12010,
0741         .enable_mask = BIT(0),
0742         .hw.init = &(struct clk_init_data){
0743             .name = "gcc_ess_clk",
0744             .parent_names = (const char *[]){
0745                 "fephy_125m_dly_clk_src",
0746             },
0747             .num_parents = 1,
0748             .ops = &clk_branch2_ops,
0749             .flags = CLK_SET_RATE_PARENT,
0750         },
0751     },
0752 };
0753 
0754 static struct clk_branch gcc_imem_axi_clk = {
0755     .halt_reg = 0xe004,
0756     .halt_check = BRANCH_HALT_VOTED,
0757     .clkr = {
0758         .enable_reg = 0x6000,
0759         .enable_mask = BIT(17),
0760         .hw.init = &(struct clk_init_data){
0761             .name = "gcc_imem_axi_clk",
0762             .parent_names = (const char *[]){
0763                 "fepll200",
0764             },
0765             .num_parents = 1,
0766             .ops = &clk_branch2_ops,
0767         },
0768     },
0769 };
0770 
0771 static struct clk_branch gcc_imem_cfg_ahb_clk = {
0772     .halt_reg = 0xe008,
0773     .clkr = {
0774         .enable_reg = 0xe008,
0775         .enable_mask = BIT(0),
0776         .hw.init = &(struct clk_init_data){
0777             .name = "gcc_imem_cfg_ahb_clk",
0778             .parent_names = (const char *[]){
0779                 "pcnoc_clk_src",
0780             },
0781             .num_parents = 1,
0782             .ops = &clk_branch2_ops,
0783         },
0784     },
0785 };
0786 
0787 static struct clk_branch gcc_pcie_ahb_clk = {
0788     .halt_reg = 0x1d00c,
0789     .clkr = {
0790         .enable_reg = 0x1d00c,
0791         .enable_mask = BIT(0),
0792         .hw.init = &(struct clk_init_data){
0793             .name = "gcc_pcie_ahb_clk",
0794             .parent_names = (const char *[]){
0795                 "pcnoc_clk_src",
0796             },
0797             .num_parents = 1,
0798             .ops = &clk_branch2_ops,
0799         },
0800     },
0801 };
0802 
0803 static struct clk_branch gcc_pcie_axi_m_clk = {
0804     .halt_reg = 0x1d004,
0805     .clkr = {
0806         .enable_reg = 0x1d004,
0807         .enable_mask = BIT(0),
0808         .hw.init = &(struct clk_init_data){
0809             .name = "gcc_pcie_axi_m_clk",
0810             .parent_names = (const char *[]){
0811                 "fepll200",
0812             },
0813             .num_parents = 1,
0814             .ops = &clk_branch2_ops,
0815         },
0816     },
0817 };
0818 
0819 static struct clk_branch gcc_pcie_axi_s_clk = {
0820     .halt_reg = 0x1d008,
0821     .clkr = {
0822         .enable_reg = 0x1d008,
0823         .enable_mask = BIT(0),
0824         .hw.init = &(struct clk_init_data){
0825             .name = "gcc_pcie_axi_s_clk",
0826             .parent_names = (const char *[]){
0827                 "fepll200",
0828             },
0829             .num_parents = 1,
0830             .ops = &clk_branch2_ops,
0831         },
0832     },
0833 };
0834 
0835 static struct clk_branch gcc_prng_ahb_clk = {
0836     .halt_reg = 0x13004,
0837     .halt_check = BRANCH_HALT_VOTED,
0838     .clkr = {
0839         .enable_reg = 0x6000,
0840         .enable_mask = BIT(8),
0841         .hw.init = &(struct clk_init_data){
0842             .name = "gcc_prng_ahb_clk",
0843             .parent_names = (const char *[]){
0844                 "pcnoc_clk_src",
0845             },
0846             .num_parents = 1,
0847             .ops = &clk_branch2_ops,
0848         },
0849     },
0850 };
0851 
0852 static struct clk_branch gcc_qpic_ahb_clk = {
0853     .halt_reg = 0x1c008,
0854     .clkr = {
0855         .enable_reg = 0x1c008,
0856         .enable_mask = BIT(0),
0857         .hw.init = &(struct clk_init_data){
0858             .name = "gcc_qpic_ahb_clk",
0859             .parent_names = (const char *[]){
0860                 "pcnoc_clk_src",
0861             },
0862             .num_parents = 1,
0863             .ops = &clk_branch2_ops,
0864         },
0865     },
0866 };
0867 
0868 static struct clk_branch gcc_qpic_clk = {
0869     .halt_reg = 0x1c004,
0870     .clkr = {
0871         .enable_reg = 0x1c004,
0872         .enable_mask = BIT(0),
0873         .hw.init = &(struct clk_init_data){
0874             .name = "gcc_qpic_clk",
0875             .parent_names = (const char *[]){
0876                 "pcnoc_clk_src",
0877             },
0878             .num_parents = 1,
0879             .ops = &clk_branch2_ops,
0880         },
0881     },
0882 };
0883 
0884 static struct clk_branch gcc_sdcc1_ahb_clk = {
0885     .halt_reg = 0x18010,
0886     .clkr = {
0887         .enable_reg = 0x18010,
0888         .enable_mask = BIT(0),
0889         .hw.init = &(struct clk_init_data){
0890             .name = "gcc_sdcc1_ahb_clk",
0891             .parent_names = (const char *[]){
0892                 "pcnoc_clk_src",
0893             },
0894             .num_parents = 1,
0895             .ops = &clk_branch2_ops,
0896         },
0897     },
0898 };
0899 
0900 static struct clk_branch gcc_sdcc1_apps_clk = {
0901     .halt_reg = 0x1800c,
0902     .clkr = {
0903         .enable_reg = 0x1800c,
0904         .enable_mask = BIT(0),
0905         .hw.init = &(struct clk_init_data){
0906             .name = "gcc_sdcc1_apps_clk",
0907             .parent_names = (const char *[]){
0908                 "sdcc1_apps_clk_src",
0909             },
0910             .num_parents = 1,
0911             .ops = &clk_branch2_ops,
0912             .flags = CLK_SET_RATE_PARENT,
0913         },
0914     },
0915 };
0916 
0917 static struct clk_branch gcc_tlmm_ahb_clk = {
0918     .halt_reg = 0x5004,
0919     .halt_check = BRANCH_HALT_VOTED,
0920     .clkr = {
0921         .enable_reg = 0x6000,
0922         .enable_mask = BIT(5),
0923         .hw.init = &(struct clk_init_data){
0924             .name = "gcc_tlmm_ahb_clk",
0925             .parent_names = (const char *[]){
0926                 "pcnoc_clk_src",
0927             },
0928             .num_parents = 1,
0929             .ops = &clk_branch2_ops,
0930         },
0931     },
0932 };
0933 
0934 static struct clk_branch gcc_usb2_master_clk = {
0935     .halt_reg = 0x1e00c,
0936     .clkr = {
0937         .enable_reg = 0x1e00c,
0938         .enable_mask = BIT(0),
0939         .hw.init = &(struct clk_init_data){
0940             .name = "gcc_usb2_master_clk",
0941             .parent_names = (const char *[]){
0942                 "pcnoc_clk_src",
0943             },
0944             .num_parents = 1,
0945             .ops = &clk_branch2_ops,
0946         },
0947     },
0948 };
0949 
0950 static struct clk_branch gcc_usb2_sleep_clk = {
0951     .halt_reg = 0x1e010,
0952     .clkr = {
0953         .enable_reg = 0x1e010,
0954         .enable_mask = BIT(0),
0955         .hw.init = &(struct clk_init_data){
0956             .name = "gcc_usb2_sleep_clk",
0957             .parent_names = (const char *[]){
0958                 "gcc_sleep_clk_src",
0959             },
0960             .num_parents = 1,
0961             .ops = &clk_branch2_ops,
0962         },
0963     },
0964 };
0965 
0966 static struct clk_branch gcc_usb2_mock_utmi_clk = {
0967     .halt_reg = 0x1e014,
0968     .clkr = {
0969         .enable_reg = 0x1e014,
0970         .enable_mask = BIT(0),
0971         .hw.init = &(struct clk_init_data){
0972             .name = "gcc_usb2_mock_utmi_clk",
0973             .parent_names = (const char *[]){
0974                 "usb30_mock_utmi_clk_src",
0975             },
0976             .num_parents = 1,
0977             .ops = &clk_branch2_ops,
0978             .flags = CLK_SET_RATE_PARENT,
0979         },
0980     },
0981 };
0982 
0983 static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
0984     F(2000000, P_FEPLL200, 10, 0, 0),
0985     { }
0986 };
0987 
0988 static struct clk_rcg2 usb30_mock_utmi_clk_src = {
0989     .cmd_rcgr = 0x1e000,
0990     .hid_width = 5,
0991     .parent_map = gcc_xo_200_map,
0992     .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
0993     .clkr.hw.init = &(struct clk_init_data){
0994         .name = "usb30_mock_utmi_clk_src",
0995         .parent_names = gcc_xo_200,
0996         .num_parents = 2,
0997         .ops = &clk_rcg2_ops,
0998     },
0999 };
1000 
1001 static struct clk_branch gcc_usb3_master_clk = {
1002     .halt_reg = 0x1e028,
1003     .clkr = {
1004         .enable_reg = 0x1e028,
1005         .enable_mask = BIT(0),
1006         .hw.init = &(struct clk_init_data){
1007             .name = "gcc_usb3_master_clk",
1008             .parent_names = (const char *[]){
1009                 "fepll125",
1010             },
1011             .num_parents = 1,
1012             .ops = &clk_branch2_ops,
1013         },
1014     },
1015 };
1016 
1017 static struct clk_branch gcc_usb3_sleep_clk = {
1018     .halt_reg = 0x1e02C,
1019     .clkr = {
1020         .enable_reg = 0x1e02C,
1021         .enable_mask = BIT(0),
1022         .hw.init = &(struct clk_init_data){
1023             .name = "gcc_usb3_sleep_clk",
1024             .parent_names = (const char *[]){
1025                 "gcc_sleep_clk_src",
1026             },
1027             .num_parents = 1,
1028             .ops = &clk_branch2_ops,
1029         },
1030     },
1031 };
1032 
1033 static struct clk_branch gcc_usb3_mock_utmi_clk = {
1034     .halt_reg = 0x1e030,
1035     .clkr = {
1036         .enable_reg = 0x1e030,
1037         .enable_mask = BIT(0),
1038         .hw.init = &(struct clk_init_data){
1039             .name = "gcc_usb3_mock_utmi_clk",
1040             .parent_names = (const char *[]){
1041                 "usb30_mock_utmi_clk_src",
1042             },
1043             .num_parents = 1,
1044             .ops = &clk_branch2_ops,
1045             .flags = CLK_SET_RATE_PARENT,
1046         },
1047     },
1048 };
1049 
1050 static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = {
1051     F(125000000, P_FEPLL125DLY, 1, 0, 0),
1052     { }
1053 };
1054 
1055 static struct clk_rcg2 fephy_125m_dly_clk_src = {
1056     .cmd_rcgr = 0x12000,
1057     .hid_width = 5,
1058     .parent_map = gcc_xo_125_dly_map,
1059     .freq_tbl = ftbl_gcc_fephy_dly_clk,
1060     .clkr.hw.init = &(struct clk_init_data){
1061         .name = "fephy_125m_dly_clk_src",
1062         .parent_names = gcc_xo_125_dly,
1063         .num_parents = 2,
1064         .ops = &clk_rcg2_ops,
1065     },
1066 };
1067 
1068 
1069 static const struct freq_tbl ftbl_gcc_wcss2g_clk[] = {
1070     F(48000000, P_XO, 1, 0, 0),
1071     F(250000000, P_FEPLLWCSS2G, 1, 0, 0),
1072     { }
1073 };
1074 
1075 static struct clk_rcg2 wcss2g_clk_src = {
1076     .cmd_rcgr = 0x1f000,
1077     .hid_width = 5,
1078     .freq_tbl = ftbl_gcc_wcss2g_clk,
1079     .parent_map = gcc_xo_wcss2g_map,
1080     .clkr.hw.init = &(struct clk_init_data){
1081         .name = "wcss2g_clk_src",
1082         .parent_names = gcc_xo_wcss2g,
1083         .num_parents = 2,
1084         .ops = &clk_rcg2_ops,
1085         .flags = CLK_SET_RATE_PARENT,
1086     },
1087 };
1088 
1089 static struct clk_branch gcc_wcss2g_clk = {
1090     .halt_reg = 0x1f00C,
1091     .clkr = {
1092         .enable_reg = 0x1f00C,
1093         .enable_mask = BIT(0),
1094         .hw.init = &(struct clk_init_data){
1095             .name = "gcc_wcss2g_clk",
1096             .parent_names = (const char *[]){
1097                 "wcss2g_clk_src",
1098             },
1099             .num_parents = 1,
1100             .ops = &clk_branch2_ops,
1101             .flags = CLK_SET_RATE_PARENT,
1102         },
1103     },
1104 };
1105 
1106 static struct clk_branch gcc_wcss2g_ref_clk = {
1107     .halt_reg = 0x1f00C,
1108     .clkr = {
1109         .enable_reg = 0x1f00C,
1110         .enable_mask = BIT(0),
1111         .hw.init = &(struct clk_init_data){
1112             .name = "gcc_wcss2g_ref_clk",
1113             .parent_names = (const char *[]){
1114                 "xo",
1115             },
1116             .num_parents = 1,
1117             .ops = &clk_branch2_ops,
1118             .flags = CLK_SET_RATE_PARENT,
1119         },
1120     },
1121 };
1122 
1123 static struct clk_branch gcc_wcss2g_rtc_clk = {
1124     .halt_reg = 0x1f010,
1125     .clkr = {
1126         .enable_reg = 0x1f010,
1127         .enable_mask = BIT(0),
1128         .hw.init = &(struct clk_init_data){
1129             .name = "gcc_wcss2g_rtc_clk",
1130             .parent_names = (const char *[]){
1131                 "gcc_sleep_clk_src",
1132             },
1133             .num_parents = 1,
1134             .ops = &clk_branch2_ops,
1135         },
1136     },
1137 };
1138 
1139 static const struct freq_tbl ftbl_gcc_wcss5g_clk[] = {
1140     F(48000000, P_XO, 1, 0, 0),
1141     F(250000000, P_FEPLLWCSS5G, 1, 0, 0),
1142     { }
1143 };
1144 
1145 static struct clk_rcg2 wcss5g_clk_src = {
1146     .cmd_rcgr = 0x20000,
1147     .hid_width = 5,
1148     .parent_map = gcc_xo_wcss5g_map,
1149     .freq_tbl = ftbl_gcc_wcss5g_clk,
1150     .clkr.hw.init = &(struct clk_init_data){
1151         .name = "wcss5g_clk_src",
1152         .parent_names = gcc_xo_wcss5g,
1153         .num_parents = 2,
1154         .ops = &clk_rcg2_ops,
1155     },
1156 };
1157 
1158 static struct clk_branch gcc_wcss5g_clk = {
1159     .halt_reg = 0x2000c,
1160     .clkr = {
1161         .enable_reg = 0x2000c,
1162         .enable_mask = BIT(0),
1163         .hw.init = &(struct clk_init_data){
1164             .name = "gcc_wcss5g_clk",
1165             .parent_names = (const char *[]){
1166                 "wcss5g_clk_src",
1167             },
1168             .num_parents = 1,
1169             .ops = &clk_branch2_ops,
1170             .flags = CLK_SET_RATE_PARENT,
1171         },
1172     },
1173 };
1174 
1175 static struct clk_branch gcc_wcss5g_ref_clk = {
1176     .halt_reg = 0x2000c,
1177     .clkr = {
1178         .enable_reg = 0x2000c,
1179         .enable_mask = BIT(0),
1180         .hw.init = &(struct clk_init_data){
1181             .name = "gcc_wcss5g_ref_clk",
1182             .parent_names = (const char *[]){
1183                 "xo",
1184             },
1185             .num_parents = 1,
1186             .ops = &clk_branch2_ops,
1187             .flags = CLK_SET_RATE_PARENT,
1188         },
1189     },
1190 };
1191 
1192 static struct clk_branch gcc_wcss5g_rtc_clk = {
1193     .halt_reg = 0x20010,
1194     .clkr = {
1195         .enable_reg = 0x20010,
1196         .enable_mask = BIT(0),
1197         .hw.init = &(struct clk_init_data){
1198             .name = "gcc_wcss5g_rtc_clk",
1199             .parent_names = (const char *[]){
1200                 "gcc_sleep_clk_src",
1201             },
1202             .num_parents = 1,
1203             .ops = &clk_branch2_ops,
1204             .flags = CLK_SET_RATE_PARENT,
1205         },
1206     },
1207 };
1208 
1209 /* Calculates the VCO rate for FEPLL. */
1210 static u64 clk_fepll_vco_calc_rate(struct clk_fepll *pll_div,
1211                    unsigned long parent_rate)
1212 {
1213     const struct clk_fepll_vco *pll_vco = pll_div->pll_vco;
1214     u32 fdbkdiv, refclkdiv, cdiv;
1215     u64 vco;
1216 
1217     regmap_read(pll_div->cdiv.clkr.regmap, pll_vco->reg, &cdiv);
1218     refclkdiv = (cdiv >> pll_vco->refclkdiv_shift) &
1219             (BIT(pll_vco->refclkdiv_width) - 1);
1220     fdbkdiv = (cdiv >> pll_vco->fdbkdiv_shift) &
1221           (BIT(pll_vco->fdbkdiv_width) - 1);
1222 
1223     vco = parent_rate / refclkdiv;
1224     vco *= 2;
1225     vco *= fdbkdiv;
1226 
1227     return vco;
1228 }
1229 
1230 static const struct clk_fepll_vco gcc_apss_ddrpll_vco = {
1231     .fdbkdiv_shift = 16,
1232     .fdbkdiv_width = 8,
1233     .refclkdiv_shift = 24,
1234     .refclkdiv_width = 5,
1235     .reg = 0x2e020,
1236 };
1237 
1238 static const struct clk_fepll_vco gcc_fepll_vco = {
1239     .fdbkdiv_shift = 16,
1240     .fdbkdiv_width = 8,
1241     .refclkdiv_shift = 24,
1242     .refclkdiv_width = 5,
1243     .reg = 0x2f020,
1244 };
1245 
1246 /*
1247  * Round rate function for APSS CPU PLL Clock divider.
1248  * It looks up the frequency table and returns the next higher frequency
1249  * supported in hardware.
1250  */
1251 static long clk_cpu_div_round_rate(struct clk_hw *hw, unsigned long rate,
1252                    unsigned long *p_rate)
1253 {
1254     struct clk_fepll *pll = to_clk_fepll(hw);
1255     struct clk_hw *p_hw;
1256     const struct freq_tbl *f;
1257 
1258     f = qcom_find_freq(pll->freq_tbl, rate);
1259     if (!f)
1260         return -EINVAL;
1261 
1262     p_hw = clk_hw_get_parent_by_index(hw, f->src);
1263     *p_rate = clk_hw_get_rate(p_hw);
1264 
1265     return f->freq;
1266 };
1267 
1268 /*
1269  * Clock set rate function for APSS CPU PLL Clock divider.
1270  * It looks up the frequency table and updates the PLL divider to corresponding
1271  * divider value.
1272  */
1273 static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate,
1274                 unsigned long parent_rate)
1275 {
1276     struct clk_fepll *pll = to_clk_fepll(hw);
1277     const struct freq_tbl *f;
1278     u32 mask;
1279 
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  */
1303 static unsigned long
1304 clk_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 
1330 static 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 
1336 static 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 
1354 static 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  */
1379 static unsigned long
1380 clk_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 
1406 static const struct clk_ops clk_fepll_div_ops = {
1407     .recalc_rate = clk_regmap_clk_div_recalc_rate,
1408 };
1409 
1410 static 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 
1425 static 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 
1440 static 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 
1455 static 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 
1470 static 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 
1485 static const struct clk_div_table fepllwcss_clk_div_table[] = {
1486     { 0, 15 },
1487     { 1, 16 },
1488     { 2, 18 },
1489     { 3, 20 },
1490     { },
1491 };
1492 
1493 static 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 
1511 static 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 
1529 static 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 
1535 static 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 
1548 static 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 
1566 static 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 
1638 static 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 
1712 static 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 
1720 static 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 
1728 static const struct of_device_id gcc_ipq4019_match_table[] = {
1729     { .compatible = "qcom,gcc-ipq4019" },
1730     { }
1731 };
1732 MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table);
1733 
1734 static int
1735 gcc_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 
1747 static struct notifier_block gcc_ipq4019_cpu_clk_notifier = {
1748     .notifier_call = gcc_ipq4019_cpu_clk_notifier_fn,
1749 };
1750 
1751 static 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 
1763 static 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 
1769 static 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 
1778 static int __init gcc_ipq4019_init(void)
1779 {
1780     return platform_driver_register(&gcc_ipq4019_driver);
1781 }
1782 core_initcall(gcc_ipq4019_init);
1783 
1784 static void __exit gcc_ipq4019_exit(void)
1785 {
1786     platform_driver_unregister(&gcc_ipq4019_driver);
1787 }
1788 module_exit(gcc_ipq4019_exit);
1789 
1790 MODULE_ALIAS("platform:gcc-ipq4019");
1791 MODULE_LICENSE("GPL v2");
1792 MODULE_DESCRIPTION("QCOM GCC IPQ4019 driver");