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