1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 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 21 enum { 22 P_BI_TCXO, 23 P_SLEEP_CLK, 24 P_VIDEO_PLL0_OUT_EVEN, 25 }; 26 27 static const struct pll_vco lucid_vco[] = { 28 { 249600000, 2000000000, 0 }, 29 }; 30 31 /* 400MHz Configuration */ 32 static 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 43 static 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 60 static const struct parent_map video_cc_parent_map_0[] = { 61 { P_BI_TCXO, 0 }, 62 { P_VIDEO_PLL0_OUT_EVEN, 3 }, 63 }; 64 65 static const struct clk_parent_data video_cc_parent_data_0[] = { 66 { .fw_name = "bi_tcxo" }, 67 { .hw = &video_pll0.clkr.hw }, 68 }; 69 70 static const struct parent_map video_cc_parent_map_1[] = { 71 { P_SLEEP_CLK, 0 }, 72 }; 73 74 static const struct clk_parent_data video_cc_parent_data_1[] = { 75 { .fw_name = "sleep_clk" }, 76 }; 77 78 static 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 87 static 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 102 static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { 103 F(32000, P_SLEEP_CLK, 1, 0, 0), 104 { } 105 }; 106 107 static 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 121 static 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 139 static 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 152 static 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 172 static 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 190 static 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 203 static 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 221 static 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 234 static 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 246 static 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 258 static 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 271 static struct gdsc *video_cc_sc7280_gdscs[] = { 272 [MVS0_GDSC] = &mvs0_gdsc, 273 [MVSC_GDSC] = &mvsc_gdsc, 274 }; 275 276 static 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 284 static 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 292 static const struct of_device_id video_cc_sc7280_match_table[] = { 293 { .compatible = "qcom,sc7280-videocc" }, 294 { } 295 }; 296 MODULE_DEVICE_TABLE(of, video_cc_sc7280_match_table); 297 298 static 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 311 static 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 319 module_platform_driver(video_cc_sc7280_driver); 320 321 MODULE_DESCRIPTION("QTI VIDEO_CC sc7280 Driver"); 322 MODULE_LICENSE("GPL v2"); 323