linux/drivers/clk/qcom/videocc-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,videocc-sdm845.h>
  12
  13#include "common.h"
  14#include "clk-alpha-pll.h"
  15#include "clk-branch.h"
  16#include "clk-rcg.h"
  17#include "clk-regmap.h"
  18#include "clk-pll.h"
  19#include "gdsc.h"
  20
  21enum {
  22        P_BI_TCXO,
  23        P_CORE_BI_PLL_TEST_SE,
  24        P_VIDEO_PLL0_OUT_EVEN,
  25        P_VIDEO_PLL0_OUT_MAIN,
  26        P_VIDEO_PLL0_OUT_ODD,
  27};
  28
  29static const struct parent_map video_cc_parent_map_0[] = {
  30        { P_BI_TCXO, 0 },
  31        { P_VIDEO_PLL0_OUT_MAIN, 1 },
  32        { P_VIDEO_PLL0_OUT_EVEN, 2 },
  33        { P_VIDEO_PLL0_OUT_ODD, 3 },
  34        { P_CORE_BI_PLL_TEST_SE, 4 },
  35};
  36
  37static const char * const video_cc_parent_names_0[] = {
  38        "bi_tcxo",
  39        "video_pll0",
  40        "video_pll0_out_even",
  41        "video_pll0_out_odd",
  42        "core_bi_pll_test_se",
  43};
  44
  45static const struct alpha_pll_config video_pll0_config = {
  46        .l = 0x10,
  47        .alpha = 0xaaab,
  48};
  49
  50static struct clk_alpha_pll video_pll0 = {
  51        .offset = 0x42c,
  52        .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
  53        .clkr = {
  54                .hw.init = &(struct clk_init_data){
  55                        .name = "video_pll0",
  56                        .parent_names = (const char *[]){ "bi_tcxo" },
  57                        .num_parents = 1,
  58                        .ops = &clk_alpha_pll_fabia_ops,
  59                },
  60        },
  61};
  62
  63static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = {
  64        F(100000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0),
  65        F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
  66        F(330000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
  67        F(404000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
  68        F(444000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
  69        F(533000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
  70        { }
  71};
  72
  73static struct clk_rcg2 video_cc_venus_clk_src = {
  74        .cmd_rcgr = 0x7f0,
  75        .mnd_width = 0,
  76        .hid_width = 5,
  77        .parent_map = video_cc_parent_map_0,
  78        .freq_tbl = ftbl_video_cc_venus_clk_src,
  79        .clkr.hw.init = &(struct clk_init_data){
  80                .name = "video_cc_venus_clk_src",
  81                .parent_names = video_cc_parent_names_0,
  82                .num_parents = 5,
  83                .flags = CLK_SET_RATE_PARENT,
  84                .ops = &clk_rcg2_shared_ops,
  85        },
  86};
  87
  88static struct clk_branch video_cc_apb_clk = {
  89        .halt_reg = 0x990,
  90        .halt_check = BRANCH_HALT,
  91        .clkr = {
  92                .enable_reg = 0x990,
  93                .enable_mask = BIT(0),
  94                .hw.init = &(struct clk_init_data){
  95                        .name = "video_cc_apb_clk",
  96                        .ops = &clk_branch2_ops,
  97                },
  98        },
  99};
 100
 101static struct clk_branch video_cc_at_clk = {
 102        .halt_reg = 0x9f0,
 103        .halt_check = BRANCH_HALT,
 104        .clkr = {
 105                .enable_reg = 0x9f0,
 106                .enable_mask = BIT(0),
 107                .hw.init = &(struct clk_init_data){
 108                        .name = "video_cc_at_clk",
 109                        .ops = &clk_branch2_ops,
 110                },
 111        },
 112};
 113
 114static struct clk_branch video_cc_qdss_trig_clk = {
 115        .halt_reg = 0x970,
 116        .halt_check = BRANCH_HALT,
 117        .clkr = {
 118                .enable_reg = 0x970,
 119                .enable_mask = BIT(0),
 120                .hw.init = &(struct clk_init_data){
 121                        .name = "video_cc_qdss_trig_clk",
 122                        .ops = &clk_branch2_ops,
 123                },
 124        },
 125};
 126
 127static struct clk_branch video_cc_qdss_tsctr_div8_clk = {
 128        .halt_reg = 0x9d0,
 129        .halt_check = BRANCH_HALT,
 130        .clkr = {
 131                .enable_reg = 0x9d0,
 132                .enable_mask = BIT(0),
 133                .hw.init = &(struct clk_init_data){
 134                        .name = "video_cc_qdss_tsctr_div8_clk",
 135                        .ops = &clk_branch2_ops,
 136                },
 137        },
 138};
 139
 140static struct clk_branch video_cc_vcodec0_axi_clk = {
 141        .halt_reg = 0x930,
 142        .halt_check = BRANCH_HALT,
 143        .clkr = {
 144                .enable_reg = 0x930,
 145                .enable_mask = BIT(0),
 146                .hw.init = &(struct clk_init_data){
 147                        .name = "video_cc_vcodec0_axi_clk",
 148                        .ops = &clk_branch2_ops,
 149                },
 150        },
 151};
 152
 153static struct clk_branch video_cc_vcodec0_core_clk = {
 154        .halt_reg = 0x890,
 155        .halt_check = BRANCH_VOTED,
 156        .clkr = {
 157                .enable_reg = 0x890,
 158                .enable_mask = BIT(0),
 159                .hw.init = &(struct clk_init_data){
 160                        .name = "video_cc_vcodec0_core_clk",
 161                        .parent_names = (const char *[]){
 162                                "video_cc_venus_clk_src",
 163                        },
 164                        .num_parents = 1,
 165                        .flags = CLK_SET_RATE_PARENT,
 166                        .ops = &clk_branch2_ops,
 167                },
 168        },
 169};
 170
 171static struct clk_branch video_cc_vcodec1_axi_clk = {
 172        .halt_reg = 0x950,
 173        .halt_check = BRANCH_HALT,
 174        .clkr = {
 175                .enable_reg = 0x950,
 176                .enable_mask = BIT(0),
 177                .hw.init = &(struct clk_init_data){
 178                        .name = "video_cc_vcodec1_axi_clk",
 179                        .ops = &clk_branch2_ops,
 180                },
 181        },
 182};
 183
 184static struct clk_branch video_cc_vcodec1_core_clk = {
 185        .halt_reg = 0x8d0,
 186        .halt_check = BRANCH_VOTED,
 187        .clkr = {
 188                .enable_reg = 0x8d0,
 189                .enable_mask = BIT(0),
 190                .hw.init = &(struct clk_init_data){
 191                        .name = "video_cc_vcodec1_core_clk",
 192                        .parent_names = (const char *[]){
 193                                "video_cc_venus_clk_src",
 194                        },
 195                        .num_parents = 1,
 196                        .flags = CLK_SET_RATE_PARENT,
 197                        .ops = &clk_branch2_ops,
 198                },
 199        },
 200};
 201
 202static struct clk_branch video_cc_venus_ahb_clk = {
 203        .halt_reg = 0x9b0,
 204        .halt_check = BRANCH_HALT,
 205        .clkr = {
 206                .enable_reg = 0x9b0,
 207                .enable_mask = BIT(0),
 208                .hw.init = &(struct clk_init_data){
 209                        .name = "video_cc_venus_ahb_clk",
 210                        .ops = &clk_branch2_ops,
 211                },
 212        },
 213};
 214
 215static struct clk_branch video_cc_venus_ctl_axi_clk = {
 216        .halt_reg = 0x910,
 217        .halt_check = BRANCH_HALT,
 218        .clkr = {
 219                .enable_reg = 0x910,
 220                .enable_mask = BIT(0),
 221                .hw.init = &(struct clk_init_data){
 222                        .name = "video_cc_venus_ctl_axi_clk",
 223                        .ops = &clk_branch2_ops,
 224                },
 225        },
 226};
 227
 228static struct clk_branch video_cc_venus_ctl_core_clk = {
 229        .halt_reg = 0x850,
 230        .halt_check = BRANCH_HALT,
 231        .clkr = {
 232                .enable_reg = 0x850,
 233                .enable_mask = BIT(0),
 234                .hw.init = &(struct clk_init_data){
 235                        .name = "video_cc_venus_ctl_core_clk",
 236                        .parent_names = (const char *[]){
 237                                "video_cc_venus_clk_src",
 238                        },
 239                        .num_parents = 1,
 240                        .flags = CLK_SET_RATE_PARENT,
 241                        .ops = &clk_branch2_ops,
 242                },
 243        },
 244};
 245
 246static struct gdsc venus_gdsc = {
 247        .gdscr = 0x814,
 248        .pd = {
 249                .name = "venus_gdsc",
 250        },
 251        .cxcs = (unsigned int []){ 0x850, 0x910 },
 252        .cxc_count = 2,
 253        .pwrsts = PWRSTS_OFF_ON,
 254        .flags = POLL_CFG_GDSCR,
 255};
 256
 257static struct gdsc vcodec0_gdsc = {
 258        .gdscr = 0x874,
 259        .pd = {
 260                .name = "vcodec0_gdsc",
 261        },
 262        .cxcs = (unsigned int []){ 0x890, 0x930 },
 263        .cxc_count = 2,
 264        .flags = HW_CTRL | POLL_CFG_GDSCR,
 265        .pwrsts = PWRSTS_OFF_ON,
 266};
 267
 268static struct gdsc vcodec1_gdsc = {
 269        .gdscr = 0x8b4,
 270        .pd = {
 271                .name = "vcodec1_gdsc",
 272        },
 273        .cxcs = (unsigned int []){ 0x8d0, 0x950 },
 274        .cxc_count = 2,
 275        .flags = HW_CTRL | POLL_CFG_GDSCR,
 276        .pwrsts = PWRSTS_OFF_ON,
 277};
 278
 279static struct clk_regmap *video_cc_sdm845_clocks[] = {
 280        [VIDEO_CC_APB_CLK] = &video_cc_apb_clk.clkr,
 281        [VIDEO_CC_AT_CLK] = &video_cc_at_clk.clkr,
 282        [VIDEO_CC_QDSS_TRIG_CLK] = &video_cc_qdss_trig_clk.clkr,
 283        [VIDEO_CC_QDSS_TSCTR_DIV8_CLK] = &video_cc_qdss_tsctr_div8_clk.clkr,
 284        [VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr,
 285        [VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr,
 286        [VIDEO_CC_VCODEC1_AXI_CLK] = &video_cc_vcodec1_axi_clk.clkr,
 287        [VIDEO_CC_VCODEC1_CORE_CLK] = &video_cc_vcodec1_core_clk.clkr,
 288        [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,
 289        [VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr,
 290        [VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr,
 291        [VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr,
 292        [VIDEO_PLL0] = &video_pll0.clkr,
 293};
 294
 295static struct gdsc *video_cc_sdm845_gdscs[] = {
 296        [VENUS_GDSC] = &venus_gdsc,
 297        [VCODEC0_GDSC] = &vcodec0_gdsc,
 298        [VCODEC1_GDSC] = &vcodec1_gdsc,
 299};
 300
 301static const struct regmap_config video_cc_sdm845_regmap_config = {
 302        .reg_bits       = 32,
 303        .reg_stride     = 4,
 304        .val_bits       = 32,
 305        .max_register   = 0xb90,
 306        .fast_io        = true,
 307};
 308
 309static const struct qcom_cc_desc video_cc_sdm845_desc = {
 310        .config = &video_cc_sdm845_regmap_config,
 311        .clks = video_cc_sdm845_clocks,
 312        .num_clks = ARRAY_SIZE(video_cc_sdm845_clocks),
 313        .gdscs = video_cc_sdm845_gdscs,
 314        .num_gdscs = ARRAY_SIZE(video_cc_sdm845_gdscs),
 315};
 316
 317static const struct of_device_id video_cc_sdm845_match_table[] = {
 318        { .compatible = "qcom,sdm845-videocc" },
 319        { }
 320};
 321MODULE_DEVICE_TABLE(of, video_cc_sdm845_match_table);
 322
 323static int video_cc_sdm845_probe(struct platform_device *pdev)
 324{
 325        struct regmap *regmap;
 326
 327        regmap = qcom_cc_map(pdev, &video_cc_sdm845_desc);
 328        if (IS_ERR(regmap))
 329                return PTR_ERR(regmap);
 330
 331        clk_fabia_pll_configure(&video_pll0, regmap, &video_pll0_config);
 332
 333        return qcom_cc_really_probe(pdev, &video_cc_sdm845_desc, regmap);
 334}
 335
 336static struct platform_driver video_cc_sdm845_driver = {
 337        .probe          = video_cc_sdm845_probe,
 338        .driver         = {
 339                .name   = "sdm845-videocc",
 340                .of_match_table = video_cc_sdm845_match_table,
 341        },
 342};
 343
 344static int __init video_cc_sdm845_init(void)
 345{
 346        return platform_driver_register(&video_cc_sdm845_driver);
 347}
 348subsys_initcall(video_cc_sdm845_init);
 349
 350static void __exit video_cc_sdm845_exit(void)
 351{
 352        platform_driver_unregister(&video_cc_sdm845_driver);
 353}
 354module_exit(video_cc_sdm845_exit);
 355
 356MODULE_LICENSE("GPL v2");
 357