323 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.4 * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include <linux/clk-provider.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/regmap.h>11 12#include <dt-bindings/clock/qcom,videocc-sc7280.h>13 14#include "clk-alpha-pll.h"15#include "clk-branch.h"16#include "clk-rcg.h"17#include "common.h"18#include "reset.h"19#include "gdsc.h"20 21enum {22 P_BI_TCXO,23 P_SLEEP_CLK,24 P_VIDEO_PLL0_OUT_EVEN,25};26 27static const struct pll_vco lucid_vco[] = {28 { 249600000, 2000000000, 0 },29};30 31/* 400MHz Configuration */32static const struct alpha_pll_config video_pll0_config = {33 .l = 0x14,34 .alpha = 0xD555,35 .config_ctl_val = 0x20485699,36 .config_ctl_hi_val = 0x00002261,37 .config_ctl_hi1_val = 0x329A299C,38 .user_ctl_val = 0x00000001,39 .user_ctl_hi_val = 0x00000805,40 .user_ctl_hi1_val = 0x00000000,41};42 43static struct clk_alpha_pll video_pll0 = {44 .offset = 0x0,45 .vco_table = lucid_vco,46 .num_vco = ARRAY_SIZE(lucid_vco),47 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],48 .clkr = {49 .hw.init = &(struct clk_init_data){50 .name = "video_pll0",51 .parent_data = &(const struct clk_parent_data){52 .fw_name = "bi_tcxo",53 },54 .num_parents = 1,55 .ops = &clk_alpha_pll_lucid_ops,56 },57 },58};59 60static const struct parent_map video_cc_parent_map_0[] = {61 { P_BI_TCXO, 0 },62 { P_VIDEO_PLL0_OUT_EVEN, 3 },63};64 65static const struct clk_parent_data video_cc_parent_data_0[] = {66 { .fw_name = "bi_tcxo" },67 { .hw = &video_pll0.clkr.hw },68};69 70static const struct parent_map video_cc_parent_map_1[] = {71 { P_SLEEP_CLK, 0 },72};73 74static const struct clk_parent_data video_cc_parent_data_1[] = {75 { .fw_name = "sleep_clk" },76};77 78static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = {79 F(133333333, P_VIDEO_PLL0_OUT_EVEN, 3, 0, 0),80 F(240000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),81 F(335000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),82 F(424000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),83 F(460000000, P_VIDEO_PLL0_OUT_EVEN, 2, 0, 0),84 { }85};86 87static struct clk_rcg2 video_cc_iris_clk_src = {88 .cmd_rcgr = 0x1000,89 .mnd_width = 0,90 .hid_width = 5,91 .parent_map = video_cc_parent_map_0,92 .freq_tbl = ftbl_video_cc_iris_clk_src,93 .clkr.hw.init = &(struct clk_init_data){94 .name = "video_cc_iris_clk_src",95 .parent_data = video_cc_parent_data_0,96 .num_parents = ARRAY_SIZE(video_cc_parent_data_0),97 .flags = CLK_SET_RATE_PARENT,98 .ops = &clk_rcg2_shared_ops,99 },100};101 102static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {103 F(32000, P_SLEEP_CLK, 1, 0, 0),104 { }105};106 107static struct clk_rcg2 video_cc_sleep_clk_src = {108 .cmd_rcgr = 0x701c,109 .mnd_width = 0,110 .hid_width = 5,111 .parent_map = video_cc_parent_map_1,112 .freq_tbl = ftbl_video_cc_sleep_clk_src,113 .clkr.hw.init = &(struct clk_init_data){114 .name = "video_cc_sleep_clk_src",115 .parent_data = video_cc_parent_data_1,116 .num_parents = ARRAY_SIZE(video_cc_parent_data_1),117 .ops = &clk_rcg2_ops,118 },119};120 121static struct clk_branch video_cc_iris_ahb_clk = {122 .halt_reg = 0x5004,123 .halt_check = BRANCH_HALT_VOTED,124 .clkr = {125 .enable_reg = 0x5004,126 .enable_mask = BIT(0),127 .hw.init = &(struct clk_init_data){128 .name = "video_cc_iris_ahb_clk",129 .parent_hws = (const struct clk_hw*[]){130 &video_cc_iris_clk_src.clkr.hw,131 },132 .num_parents = 1,133 .flags = CLK_SET_RATE_PARENT,134 .ops = &clk_branch2_ops,135 },136 },137};138 139static struct clk_branch video_cc_mvs0_axi_clk = {140 .halt_reg = 0x800c,141 .halt_check = BRANCH_HALT,142 .clkr = {143 .enable_reg = 0x800c,144 .enable_mask = BIT(0),145 .hw.init = &(struct clk_init_data){146 .name = "video_cc_mvs0_axi_clk",147 .ops = &clk_branch2_ops,148 },149 },150};151 152static struct clk_branch video_cc_mvs0_core_clk = {153 .halt_reg = 0x3010,154 .halt_check = BRANCH_HALT_VOTED,155 .hwcg_reg = 0x3010,156 .hwcg_bit = 1,157 .clkr = {158 .enable_reg = 0x3010,159 .enable_mask = BIT(0),160 .hw.init = &(struct clk_init_data){161 .name = "video_cc_mvs0_core_clk",162 .parent_hws = (const struct clk_hw*[]){163 &video_cc_iris_clk_src.clkr.hw,164 },165 .num_parents = 1,166 .flags = CLK_SET_RATE_PARENT,167 .ops = &clk_branch2_ops,168 },169 },170};171 172static struct clk_branch video_cc_mvsc_core_clk = {173 .halt_reg = 0x2014,174 .halt_check = BRANCH_HALT,175 .clkr = {176 .enable_reg = 0x2014,177 .enable_mask = BIT(0),178 .hw.init = &(struct clk_init_data){179 .name = "video_cc_mvsc_core_clk",180 .parent_hws = (const struct clk_hw*[]){181 &video_cc_iris_clk_src.clkr.hw,182 },183 .num_parents = 1,184 .flags = CLK_SET_RATE_PARENT,185 .ops = &clk_branch2_ops,186 },187 },188};189 190static struct clk_branch video_cc_mvsc_ctl_axi_clk = {191 .halt_reg = 0x8004,192 .halt_check = BRANCH_HALT,193 .clkr = {194 .enable_reg = 0x8004,195 .enable_mask = BIT(0),196 .hw.init = &(struct clk_init_data){197 .name = "video_cc_mvsc_ctl_axi_clk",198 .ops = &clk_branch2_ops,199 },200 },201};202 203static struct clk_branch video_cc_sleep_clk = {204 .halt_reg = 0x7034,205 .halt_check = BRANCH_HALT,206 .clkr = {207 .enable_reg = 0x7034,208 .enable_mask = BIT(0),209 .hw.init = &(struct clk_init_data){210 .name = "video_cc_sleep_clk",211 .parent_hws = (const struct clk_hw*[]){212 &video_cc_sleep_clk_src.clkr.hw,213 },214 .num_parents = 1,215 .flags = CLK_SET_RATE_PARENT,216 .ops = &clk_branch2_ops,217 },218 },219};220 221static struct clk_branch video_cc_venus_ahb_clk = {222 .halt_reg = 0x801c,223 .halt_check = BRANCH_HALT,224 .clkr = {225 .enable_reg = 0x801c,226 .enable_mask = BIT(0),227 .hw.init = &(struct clk_init_data){228 .name = "video_cc_venus_ahb_clk",229 .ops = &clk_branch2_ops,230 },231 },232};233 234static struct gdsc mvs0_gdsc = {235 .gdscr = 0x3004,236 .en_rest_wait_val = 0x2,237 .en_few_wait_val = 0x2,238 .clk_dis_wait_val = 0x6,239 .pd = {240 .name = "mvs0_gdsc",241 },242 .pwrsts = PWRSTS_OFF_ON,243 .flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,244};245 246static struct gdsc mvsc_gdsc = {247 .gdscr = 0x2004,248 .en_rest_wait_val = 0x2,249 .en_few_wait_val = 0x2,250 .clk_dis_wait_val = 0x6,251 .pd = {252 .name = "mvsc_gdsc",253 },254 .flags = RETAIN_FF_ENABLE,255 .pwrsts = PWRSTS_OFF_ON,256};257 258static struct clk_regmap *video_cc_sc7280_clocks[] = {259 [VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr,260 [VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr,261 [VIDEO_CC_MVS0_AXI_CLK] = &video_cc_mvs0_axi_clk.clkr,262 [VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr,263 [VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr,264 [VIDEO_CC_MVSC_CTL_AXI_CLK] = &video_cc_mvsc_ctl_axi_clk.clkr,265 [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,266 [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,267 [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,268 [VIDEO_PLL0] = &video_pll0.clkr,269};270 271static struct gdsc *video_cc_sc7280_gdscs[] = {272 [MVS0_GDSC] = &mvs0_gdsc,273 [MVSC_GDSC] = &mvsc_gdsc,274};275 276static const struct regmap_config video_cc_sc7280_regmap_config = {277 .reg_bits = 32,278 .reg_stride = 4,279 .val_bits = 32,280 .max_register = 0xb000,281 .fast_io = true,282};283 284static const struct qcom_cc_desc video_cc_sc7280_desc = {285 .config = &video_cc_sc7280_regmap_config,286 .clks = video_cc_sc7280_clocks,287 .num_clks = ARRAY_SIZE(video_cc_sc7280_clocks),288 .gdscs = video_cc_sc7280_gdscs,289 .num_gdscs = ARRAY_SIZE(video_cc_sc7280_gdscs),290};291 292static const struct of_device_id video_cc_sc7280_match_table[] = {293 { .compatible = "qcom,sc7280-videocc" },294 { }295};296MODULE_DEVICE_TABLE(of, video_cc_sc7280_match_table);297 298static int video_cc_sc7280_probe(struct platform_device *pdev)299{300 struct regmap *regmap;301 302 regmap = qcom_cc_map(pdev, &video_cc_sc7280_desc);303 if (IS_ERR(regmap))304 return PTR_ERR(regmap);305 306 clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);307 308 return qcom_cc_really_probe(&pdev->dev, &video_cc_sc7280_desc, regmap);309}310 311static struct platform_driver video_cc_sc7280_driver = {312 .probe = video_cc_sc7280_probe,313 .driver = {314 .name = "video_cc-sc7280",315 .of_match_table = video_cc_sc7280_match_table,316 },317};318 319module_platform_driver(video_cc_sc7280_driver);320 321MODULE_DESCRIPTION("QTI VIDEO_CC sc7280 Driver");322MODULE_LICENSE("GPL v2");323