linux/drivers/clk/qcom/gpucc-sm8150.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/module.h>
   8#include <linux/platform_device.h>
   9#include <linux/regmap.h>
  10
  11#include <dt-bindings/clock/qcom,gpucc-sm8150.h>
  12
  13#include "common.h"
  14#include "clk-alpha-pll.h"
  15#include "clk-branch.h"
  16#include "clk-pll.h"
  17#include "clk-rcg.h"
  18#include "clk-regmap.h"
  19#include "reset.h"
  20#include "gdsc.h"
  21
  22enum {
  23        P_BI_TCXO,
  24        P_GPLL0_OUT_MAIN,
  25        P_GPLL0_OUT_MAIN_DIV,
  26        P_GPU_CC_PLL1_OUT_MAIN,
  27};
  28
  29static const struct pll_vco trion_vco[] = {
  30        { 249600000, 2000000000, 0 },
  31};
  32
  33static struct alpha_pll_config gpu_cc_pll1_config = {
  34        .l = 0x1a,
  35        .alpha = 0xaaa,
  36        .config_ctl_val = 0x20485699,
  37        .config_ctl_hi_val = 0x00002267,
  38        .config_ctl_hi1_val = 0x00000024,
  39        .test_ctl_val = 0x00000000,
  40        .test_ctl_hi_val = 0x00000002,
  41        .test_ctl_hi1_val = 0x00000000,
  42        .user_ctl_val = 0x00000000,
  43        .user_ctl_hi_val = 0x00000805,
  44        .user_ctl_hi1_val = 0x000000d0,
  45};
  46
  47static struct clk_alpha_pll gpu_cc_pll1 = {
  48        .offset = 0x100,
  49        .vco_table = trion_vco,
  50        .num_vco = ARRAY_SIZE(trion_vco),
  51        .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
  52        .clkr = {
  53                .hw.init = &(struct clk_init_data){
  54                        .name = "gpu_cc_pll1",
  55                        .parent_data =  &(const struct clk_parent_data){
  56                                .fw_name = "bi_tcxo",
  57                        },
  58                        .num_parents = 1,
  59                        .ops = &clk_alpha_pll_trion_ops,
  60                },
  61        },
  62};
  63
  64static const struct parent_map gpu_cc_parent_map_0[] = {
  65        { P_BI_TCXO, 0 },
  66        { P_GPU_CC_PLL1_OUT_MAIN, 3 },
  67        { P_GPLL0_OUT_MAIN, 5 },
  68        { P_GPLL0_OUT_MAIN_DIV, 6 },
  69};
  70
  71static const struct clk_parent_data gpu_cc_parent_data_0[] = {
  72        { .fw_name = "bi_tcxo" },
  73        { .hw = &gpu_cc_pll1.clkr.hw },
  74        { .fw_name = "gcc_gpu_gpll0_clk_src" },
  75        { .fw_name = "gcc_gpu_gpll0_div_clk_src" },
  76};
  77
  78static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
  79        F(19200000, P_BI_TCXO, 1, 0, 0),
  80        F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
  81        F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
  82        { }
  83};
  84
  85static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src_sc8180x[] = {
  86        F(19200000, P_BI_TCXO, 1, 0, 0),
  87        F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
  88        F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
  89        F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
  90        { }
  91};
  92
  93static struct clk_rcg2 gpu_cc_gmu_clk_src = {
  94        .cmd_rcgr = 0x1120,
  95        .mnd_width = 0,
  96        .hid_width = 5,
  97        .parent_map = gpu_cc_parent_map_0,
  98        .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
  99        .clkr.hw.init = &(struct clk_init_data){
 100                .name = "gpu_cc_gmu_clk_src",
 101                .parent_data = gpu_cc_parent_data_0,
 102                .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
 103                .flags = CLK_SET_RATE_PARENT,
 104                .ops = &clk_rcg2_ops,
 105        },
 106};
 107
 108static struct clk_branch gpu_cc_ahb_clk = {
 109        .halt_reg = 0x1078,
 110        .halt_check = BRANCH_HALT_DELAY,
 111        .clkr = {
 112                .enable_reg = 0x1078,
 113                .enable_mask = BIT(0),
 114                .hw.init = &(struct clk_init_data){
 115                        .name = "gpu_cc_ahb_clk",
 116                        .ops = &clk_branch2_ops,
 117                },
 118        },
 119};
 120
 121static struct clk_branch gpu_cc_crc_ahb_clk = {
 122        .halt_reg = 0x107c,
 123        .halt_check = BRANCH_HALT,
 124        .clkr = {
 125                .enable_reg = 0x107c,
 126                .enable_mask = BIT(0),
 127                .hw.init = &(struct clk_init_data){
 128                        .name = "gpu_cc_crc_ahb_clk",
 129                        .ops = &clk_branch2_ops,
 130                },
 131        },
 132};
 133
 134static struct clk_branch gpu_cc_cx_apb_clk = {
 135        .halt_reg = 0x1088,
 136        .halt_check = BRANCH_HALT,
 137        .clkr = {
 138                .enable_reg = 0x1088,
 139                .enable_mask = BIT(0),
 140                .hw.init = &(struct clk_init_data){
 141                        .name = "gpu_cc_cx_apb_clk",
 142                        .ops = &clk_branch2_ops,
 143                },
 144        },
 145};
 146
 147static struct clk_branch gpu_cc_cx_gmu_clk = {
 148        .halt_reg = 0x1098,
 149        .halt_check = BRANCH_HALT,
 150        .clkr = {
 151                .enable_reg = 0x1098,
 152                .enable_mask = BIT(0),
 153                .hw.init = &(struct clk_init_data){
 154                        .name = "gpu_cc_cx_gmu_clk",
 155                        .parent_hws = (const struct clk_hw*[]){
 156                                &gpu_cc_gmu_clk_src.clkr.hw,
 157                        },
 158                        .num_parents = 1,
 159                        .flags = CLK_SET_RATE_PARENT,
 160                        .ops = &clk_branch2_ops,
 161                },
 162        },
 163};
 164
 165static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
 166        .halt_reg = 0x108c,
 167        .halt_check = BRANCH_HALT,
 168        .clkr = {
 169                .enable_reg = 0x108c,
 170                .enable_mask = BIT(0),
 171                .hw.init = &(struct clk_init_data){
 172                        .name = "gpu_cc_cx_snoc_dvm_clk",
 173                        .ops = &clk_branch2_ops,
 174                },
 175        },
 176};
 177
 178static struct clk_branch gpu_cc_cxo_aon_clk = {
 179        .halt_reg = 0x1004,
 180        .halt_check = BRANCH_HALT,
 181        .clkr = {
 182                .enable_reg = 0x1004,
 183                .enable_mask = BIT(0),
 184                .hw.init = &(struct clk_init_data){
 185                        .name = "gpu_cc_cxo_aon_clk",
 186                        .ops = &clk_branch2_ops,
 187                },
 188        },
 189};
 190
 191static struct clk_branch gpu_cc_cxo_clk = {
 192        .halt_reg = 0x109c,
 193        .halt_check = BRANCH_HALT,
 194        .clkr = {
 195                .enable_reg = 0x109c,
 196                .enable_mask = BIT(0),
 197                .hw.init = &(struct clk_init_data){
 198                        .name = "gpu_cc_cxo_clk",
 199                        .ops = &clk_branch2_ops,
 200                },
 201        },
 202};
 203
 204static struct clk_branch gpu_cc_gx_gmu_clk = {
 205        .halt_reg = 0x1064,
 206        .halt_check = BRANCH_HALT,
 207        .clkr = {
 208                .enable_reg = 0x1064,
 209                .enable_mask = BIT(0),
 210                .hw.init = &(struct clk_init_data){
 211                        .name = "gpu_cc_gx_gmu_clk",
 212                        .parent_hws = (const struct clk_hw*[]){
 213                                &gpu_cc_gmu_clk_src.clkr.hw,
 214                        },
 215                        .num_parents = 1,
 216                        .flags = CLK_SET_RATE_PARENT,
 217                        .ops = &clk_branch2_ops,
 218                },
 219        },
 220};
 221
 222static struct gdsc gpu_cx_gdsc = {
 223        .gdscr = 0x106c,
 224        .gds_hw_ctrl = 0x1540,
 225        .pd = {
 226                .name = "gpu_cx_gdsc",
 227        },
 228        .pwrsts = PWRSTS_OFF_ON,
 229        .flags = VOTABLE,
 230};
 231
 232static struct gdsc gpu_gx_gdsc = {
 233        .gdscr = 0x100c,
 234        .clamp_io_ctrl = 0x1508,
 235        .pd = {
 236                .name = "gpu_gx_gdsc",
 237                .power_on = gdsc_gx_do_nothing_enable,
 238        },
 239        .pwrsts = PWRSTS_OFF_ON,
 240        .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
 241};
 242
 243static struct clk_regmap *gpu_cc_sm8150_clocks[] = {
 244        [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
 245        [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
 246        [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
 247        [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
 248        [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
 249        [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
 250        [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
 251        [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
 252        [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
 253        [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
 254};
 255
 256static const struct qcom_reset_map gpu_cc_sm8150_resets[] = {
 257        [GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
 258        [GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
 259        [GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
 260        [GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 },
 261        [GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
 262};
 263
 264static struct gdsc *gpu_cc_sm8150_gdscs[] = {
 265        [GPU_CX_GDSC] = &gpu_cx_gdsc,
 266        [GPU_GX_GDSC] = &gpu_gx_gdsc,
 267};
 268
 269static const struct regmap_config gpu_cc_sm8150_regmap_config = {
 270        .reg_bits       = 32,
 271        .reg_stride     = 4,
 272        .val_bits       = 32,
 273        .max_register   = 0x8008,
 274        .fast_io        = true,
 275};
 276
 277static const struct qcom_cc_desc gpu_cc_sm8150_desc = {
 278        .config = &gpu_cc_sm8150_regmap_config,
 279        .clks = gpu_cc_sm8150_clocks,
 280        .num_clks = ARRAY_SIZE(gpu_cc_sm8150_clocks),
 281        .resets = gpu_cc_sm8150_resets,
 282        .num_resets = ARRAY_SIZE(gpu_cc_sm8150_resets),
 283        .gdscs = gpu_cc_sm8150_gdscs,
 284        .num_gdscs = ARRAY_SIZE(gpu_cc_sm8150_gdscs),
 285};
 286
 287static const struct of_device_id gpu_cc_sm8150_match_table[] = {
 288        { .compatible = "qcom,sc8180x-gpucc" },
 289        { .compatible = "qcom,sm8150-gpucc" },
 290        { }
 291};
 292MODULE_DEVICE_TABLE(of, gpu_cc_sm8150_match_table);
 293
 294static int gpu_cc_sm8150_probe(struct platform_device *pdev)
 295{
 296        struct regmap *regmap;
 297
 298        regmap = qcom_cc_map(pdev, &gpu_cc_sm8150_desc);
 299        if (IS_ERR(regmap))
 300                return PTR_ERR(regmap);
 301
 302        if (of_device_is_compatible(pdev->dev.of_node, "qcom,sc8180x-gpucc"))
 303                gpu_cc_gmu_clk_src.freq_tbl = ftbl_gpu_cc_gmu_clk_src_sc8180x;
 304
 305        clk_trion_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
 306
 307        return qcom_cc_really_probe(pdev, &gpu_cc_sm8150_desc, regmap);
 308}
 309
 310static struct platform_driver gpu_cc_sm8150_driver = {
 311        .probe = gpu_cc_sm8150_probe,
 312        .driver = {
 313                .name = "sm8150-gpucc",
 314                .of_match_table = gpu_cc_sm8150_match_table,
 315        },
 316};
 317
 318static int __init gpu_cc_sm8150_init(void)
 319{
 320        return platform_driver_register(&gpu_cc_sm8150_driver);
 321}
 322subsys_initcall(gpu_cc_sm8150_init);
 323
 324static void __exit gpu_cc_sm8150_exit(void)
 325{
 326        platform_driver_unregister(&gpu_cc_sm8150_driver);
 327}
 328module_exit(gpu_cc_sm8150_exit);
 329
 330MODULE_DESCRIPTION("QTI GPUCC SM8150 Driver");
 331MODULE_LICENSE("GPL v2");
 332