linux/drivers/clk/qcom/gpucc-sdm845.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2018, 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-sdm845.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 "gdsc.h"
  20
  21#define CX_GMU_CBCR_SLEEP_MASK          0xf
  22#define CX_GMU_CBCR_SLEEP_SHIFT         4
  23#define CX_GMU_CBCR_WAKE_MASK           0xf
  24#define CX_GMU_CBCR_WAKE_SHIFT          8
  25#define CLK_DIS_WAIT_SHIFT              12
  26#define CLK_DIS_WAIT_MASK               (0xf << CLK_DIS_WAIT_SHIFT)
  27
  28enum {
  29        P_BI_TCXO,
  30        P_GPLL0_OUT_MAIN,
  31        P_GPLL0_OUT_MAIN_DIV,
  32        P_GPU_CC_PLL1_OUT_MAIN,
  33};
  34
  35static const struct alpha_pll_config gpu_cc_pll1_config = {
  36        .l = 0x1a,
  37        .alpha = 0xaab,
  38};
  39
  40static struct clk_alpha_pll gpu_cc_pll1 = {
  41        .offset = 0x100,
  42        .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
  43        .clkr = {
  44                .hw.init = &(struct clk_init_data){
  45                        .name = "gpu_cc_pll1",
  46                        .parent_data = &(const struct clk_parent_data){
  47                                .fw_name = "bi_tcxo", .name = "bi_tcxo",
  48                        },
  49                        .num_parents = 1,
  50                        .ops = &clk_alpha_pll_fabia_ops,
  51                },
  52        },
  53};
  54
  55static const struct parent_map gpu_cc_parent_map_0[] = {
  56        { P_BI_TCXO, 0 },
  57        { P_GPU_CC_PLL1_OUT_MAIN, 3 },
  58        { P_GPLL0_OUT_MAIN, 5 },
  59        { P_GPLL0_OUT_MAIN_DIV, 6 },
  60};
  61
  62static const struct clk_parent_data gpu_cc_parent_data_0[] = {
  63        { .fw_name = "bi_tcxo", .name = "bi_tcxo" },
  64        { .hw = &gpu_cc_pll1.clkr.hw },
  65        { .fw_name = "gcc_gpu_gpll0_clk_src", .name = "gcc_gpu_gpll0_clk_src" },
  66        { .fw_name = "gcc_gpu_gpll0_div_clk_src", .name = "gcc_gpu_gpll0_div_clk_src" },
  67};
  68
  69static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
  70        F(19200000, P_BI_TCXO, 1, 0, 0),
  71        F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
  72        F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
  73        { }
  74};
  75
  76static struct clk_rcg2 gpu_cc_gmu_clk_src = {
  77        .cmd_rcgr = 0x1120,
  78        .mnd_width = 0,
  79        .hid_width = 5,
  80        .parent_map = gpu_cc_parent_map_0,
  81        .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
  82        .clkr.hw.init = &(struct clk_init_data){
  83                .name = "gpu_cc_gmu_clk_src",
  84                .parent_data = gpu_cc_parent_data_0,
  85                .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
  86                .ops = &clk_rcg2_shared_ops,
  87        },
  88};
  89
  90static struct clk_branch gpu_cc_cx_gmu_clk = {
  91        .halt_reg = 0x1098,
  92        .halt_check = BRANCH_HALT,
  93        .clkr = {
  94                .enable_reg = 0x1098,
  95                .enable_mask = BIT(0),
  96                .hw.init = &(struct clk_init_data){
  97                        .name = "gpu_cc_cx_gmu_clk",
  98                        .parent_hws = (const struct clk_hw*[]){
  99                                &gpu_cc_gmu_clk_src.clkr.hw,
 100                        },
 101                        .num_parents = 1,
 102                        .flags = CLK_SET_RATE_PARENT,
 103                        .ops = &clk_branch2_ops,
 104                },
 105        },
 106};
 107
 108static struct clk_branch gpu_cc_cxo_clk = {
 109        .halt_reg = 0x109c,
 110        .halt_check = BRANCH_HALT,
 111        .clkr = {
 112                .enable_reg = 0x109c,
 113                .enable_mask = BIT(0),
 114                .hw.init = &(struct clk_init_data){
 115                        .name = "gpu_cc_cxo_clk",
 116                        .ops = &clk_branch2_ops,
 117                },
 118        },
 119};
 120
 121static struct gdsc gpu_cx_gdsc = {
 122        .gdscr = 0x106c,
 123        .gds_hw_ctrl = 0x1540,
 124        .pd = {
 125                .name = "gpu_cx_gdsc",
 126        },
 127        .pwrsts = PWRSTS_OFF_ON,
 128        .flags = VOTABLE,
 129};
 130
 131static struct gdsc gpu_gx_gdsc = {
 132        .gdscr = 0x100c,
 133        .clamp_io_ctrl = 0x1508,
 134        .pd = {
 135                .name = "gpu_gx_gdsc",
 136                .power_on = gdsc_gx_do_nothing_enable,
 137        },
 138        .pwrsts = PWRSTS_OFF_ON,
 139        .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR,
 140};
 141
 142static struct clk_regmap *gpu_cc_sdm845_clocks[] = {
 143        [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
 144        [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
 145        [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
 146        [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
 147};
 148
 149static struct gdsc *gpu_cc_sdm845_gdscs[] = {
 150        [GPU_CX_GDSC] = &gpu_cx_gdsc,
 151        [GPU_GX_GDSC] = &gpu_gx_gdsc,
 152};
 153
 154static const struct regmap_config gpu_cc_sdm845_regmap_config = {
 155        .reg_bits       = 32,
 156        .reg_stride     = 4,
 157        .val_bits       = 32,
 158        .max_register   = 0x8008,
 159        .fast_io        = true,
 160};
 161
 162static const struct qcom_cc_desc gpu_cc_sdm845_desc = {
 163        .config = &gpu_cc_sdm845_regmap_config,
 164        .clks = gpu_cc_sdm845_clocks,
 165        .num_clks = ARRAY_SIZE(gpu_cc_sdm845_clocks),
 166        .gdscs = gpu_cc_sdm845_gdscs,
 167        .num_gdscs = ARRAY_SIZE(gpu_cc_sdm845_gdscs),
 168};
 169
 170static const struct of_device_id gpu_cc_sdm845_match_table[] = {
 171        { .compatible = "qcom,sdm845-gpucc" },
 172        { }
 173};
 174MODULE_DEVICE_TABLE(of, gpu_cc_sdm845_match_table);
 175
 176static int gpu_cc_sdm845_probe(struct platform_device *pdev)
 177{
 178        struct regmap *regmap;
 179        unsigned int value, mask;
 180
 181        regmap = qcom_cc_map(pdev, &gpu_cc_sdm845_desc);
 182        if (IS_ERR(regmap))
 183                return PTR_ERR(regmap);
 184
 185        clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
 186
 187        /*
 188         * Configure gpu_cc_cx_gmu_clk with recommended
 189         * wakeup/sleep settings
 190         */
 191        mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT;
 192        mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT;
 193        value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT;
 194        regmap_update_bits(regmap, 0x1098, mask, value);
 195
 196        /* Configure clk_dis_wait for gpu_cx_gdsc */
 197        regmap_update_bits(regmap, 0x106c, CLK_DIS_WAIT_MASK,
 198                                                8 << CLK_DIS_WAIT_SHIFT);
 199
 200        return qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap);
 201}
 202
 203static struct platform_driver gpu_cc_sdm845_driver = {
 204        .probe = gpu_cc_sdm845_probe,
 205        .driver = {
 206                .name = "sdm845-gpucc",
 207                .of_match_table = gpu_cc_sdm845_match_table,
 208        },
 209};
 210
 211static int __init gpu_cc_sdm845_init(void)
 212{
 213        return platform_driver_register(&gpu_cc_sdm845_driver);
 214}
 215subsys_initcall(gpu_cc_sdm845_init);
 216
 217static void __exit gpu_cc_sdm845_exit(void)
 218{
 219        platform_driver_unregister(&gpu_cc_sdm845_driver);
 220}
 221module_exit(gpu_cc_sdm845_exit);
 222
 223MODULE_DESCRIPTION("QTI GPUCC SDM845 Driver");
 224MODULE_LICENSE("GPL v2");
 225