1253dc75aSTaniya Das // SPDX-License-Identifier: GPL-2.0-only 2253dc75aSTaniya Das /* 3253dc75aSTaniya Das * Copyright (c) 2019, The Linux Foundation. All rights reserved. 4253dc75aSTaniya Das */ 5253dc75aSTaniya Das 6253dc75aSTaniya Das #include <linux/clk-provider.h> 7253dc75aSTaniya Das #include <linux/module.h> 8253dc75aSTaniya Das #include <linux/platform_device.h> 9253dc75aSTaniya Das #include <linux/regmap.h> 10253dc75aSTaniya Das 11253dc75aSTaniya Das #include <dt-bindings/clock/qcom,videocc-sc7180.h> 12253dc75aSTaniya Das 13253dc75aSTaniya Das #include "clk-alpha-pll.h" 14253dc75aSTaniya Das #include "clk-branch.h" 15253dc75aSTaniya Das #include "clk-rcg.h" 16253dc75aSTaniya Das #include "clk-regmap.h" 17253dc75aSTaniya Das #include "common.h" 18253dc75aSTaniya Das #include "gdsc.h" 19253dc75aSTaniya Das 20253dc75aSTaniya Das enum { 21253dc75aSTaniya Das P_BI_TCXO, 22253dc75aSTaniya Das P_CHIP_SLEEP_CLK, 23253dc75aSTaniya Das P_CORE_BI_PLL_TEST_SE, 24253dc75aSTaniya Das P_VIDEO_PLL0_OUT_EVEN, 25253dc75aSTaniya Das P_VIDEO_PLL0_OUT_MAIN, 26253dc75aSTaniya Das P_VIDEO_PLL0_OUT_ODD, 27253dc75aSTaniya Das }; 28253dc75aSTaniya Das 29253dc75aSTaniya Das static const struct pll_vco fabia_vco[] = { 30253dc75aSTaniya Das { 249600000, 2000000000, 0 }, 31253dc75aSTaniya Das }; 32253dc75aSTaniya Das 33253dc75aSTaniya Das static struct clk_alpha_pll video_pll0 = { 34253dc75aSTaniya Das .offset = 0x42c, 35253dc75aSTaniya Das .vco_table = fabia_vco, 36253dc75aSTaniya Das .num_vco = ARRAY_SIZE(fabia_vco), 37253dc75aSTaniya Das .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], 38253dc75aSTaniya Das .clkr = { 39253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 40253dc75aSTaniya Das .name = "video_pll0", 41253dc75aSTaniya Das .parent_data = &(const struct clk_parent_data){ 42253dc75aSTaniya Das .fw_name = "bi_tcxo", 43253dc75aSTaniya Das }, 44253dc75aSTaniya Das .num_parents = 1, 45253dc75aSTaniya Das .ops = &clk_alpha_pll_fabia_ops, 46253dc75aSTaniya Das }, 47253dc75aSTaniya Das }, 48253dc75aSTaniya Das }; 49253dc75aSTaniya Das 50253dc75aSTaniya Das static const struct parent_map video_cc_parent_map_1[] = { 51253dc75aSTaniya Das { P_BI_TCXO, 0 }, 52253dc75aSTaniya Das { P_VIDEO_PLL0_OUT_MAIN, 1 }, 53253dc75aSTaniya Das }; 54253dc75aSTaniya Das 55253dc75aSTaniya Das static const struct clk_parent_data video_cc_parent_data_1[] = { 56253dc75aSTaniya Das { .fw_name = "bi_tcxo" }, 57253dc75aSTaniya Das { .hw = &video_pll0.clkr.hw }, 58253dc75aSTaniya Das }; 59253dc75aSTaniya Das 60253dc75aSTaniya Das static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = { 61253dc75aSTaniya Das F(19200000, P_BI_TCXO, 1, 0, 0), 62253dc75aSTaniya Das F(150000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0), 63253dc75aSTaniya Das F(270000000, P_VIDEO_PLL0_OUT_MAIN, 2.5, 0, 0), 64253dc75aSTaniya Das F(340000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 65253dc75aSTaniya Das F(434000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 66253dc75aSTaniya Das F(500000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 67253dc75aSTaniya Das { } 68253dc75aSTaniya Das }; 69253dc75aSTaniya Das 70253dc75aSTaniya Das static struct clk_rcg2 video_cc_venus_clk_src = { 71253dc75aSTaniya Das .cmd_rcgr = 0x7f0, 72253dc75aSTaniya Das .mnd_width = 0, 73253dc75aSTaniya Das .hid_width = 5, 74253dc75aSTaniya Das .parent_map = video_cc_parent_map_1, 75253dc75aSTaniya Das .freq_tbl = ftbl_video_cc_venus_clk_src, 76253dc75aSTaniya Das .clkr.hw.init = &(struct clk_init_data){ 77253dc75aSTaniya Das .name = "video_cc_venus_clk_src", 78253dc75aSTaniya Das .parent_data = video_cc_parent_data_1, 79563528b8SDouglas Anderson .num_parents = ARRAY_SIZE(video_cc_parent_data_1), 80253dc75aSTaniya Das .flags = CLK_SET_RATE_PARENT, 81253dc75aSTaniya Das .ops = &clk_rcg2_shared_ops, 82253dc75aSTaniya Das }, 83253dc75aSTaniya Das }; 84253dc75aSTaniya Das 85253dc75aSTaniya Das static struct clk_branch video_cc_vcodec0_axi_clk = { 86253dc75aSTaniya Das .halt_reg = 0x9ec, 87253dc75aSTaniya Das .halt_check = BRANCH_HALT, 88253dc75aSTaniya Das .clkr = { 89253dc75aSTaniya Das .enable_reg = 0x9ec, 90253dc75aSTaniya Das .enable_mask = BIT(0), 91253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 92253dc75aSTaniya Das .name = "video_cc_vcodec0_axi_clk", 93253dc75aSTaniya Das .ops = &clk_branch2_ops, 94253dc75aSTaniya Das }, 95253dc75aSTaniya Das }, 96253dc75aSTaniya Das }; 97253dc75aSTaniya Das 98253dc75aSTaniya Das static struct clk_branch video_cc_vcodec0_core_clk = { 99253dc75aSTaniya Das .halt_reg = 0x890, 100253dc75aSTaniya Das .halt_check = BRANCH_HALT, 101253dc75aSTaniya Das .clkr = { 102253dc75aSTaniya Das .enable_reg = 0x890, 103253dc75aSTaniya Das .enable_mask = BIT(0), 104253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 105253dc75aSTaniya Das .name = "video_cc_vcodec0_core_clk", 106253dc75aSTaniya Das .parent_data = &(const struct clk_parent_data){ 107253dc75aSTaniya Das .hw = &video_cc_venus_clk_src.clkr.hw, 108253dc75aSTaniya Das }, 109253dc75aSTaniya Das .num_parents = 1, 110253dc75aSTaniya Das .flags = CLK_SET_RATE_PARENT, 111253dc75aSTaniya Das .ops = &clk_branch2_ops, 112253dc75aSTaniya Das }, 113253dc75aSTaniya Das }, 114253dc75aSTaniya Das }; 115253dc75aSTaniya Das 116253dc75aSTaniya Das static struct clk_branch video_cc_venus_ahb_clk = { 117253dc75aSTaniya Das .halt_reg = 0xa4c, 118253dc75aSTaniya Das .halt_check = BRANCH_HALT, 119253dc75aSTaniya Das .clkr = { 120253dc75aSTaniya Das .enable_reg = 0xa4c, 121253dc75aSTaniya Das .enable_mask = BIT(0), 122253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 123253dc75aSTaniya Das .name = "video_cc_venus_ahb_clk", 124253dc75aSTaniya Das .ops = &clk_branch2_ops, 125253dc75aSTaniya Das }, 126253dc75aSTaniya Das }, 127253dc75aSTaniya Das }; 128253dc75aSTaniya Das 129253dc75aSTaniya Das static struct clk_branch video_cc_venus_ctl_axi_clk = { 130253dc75aSTaniya Das .halt_reg = 0x9cc, 131253dc75aSTaniya Das .halt_check = BRANCH_HALT, 132253dc75aSTaniya Das .clkr = { 133253dc75aSTaniya Das .enable_reg = 0x9cc, 134253dc75aSTaniya Das .enable_mask = BIT(0), 135253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 136253dc75aSTaniya Das .name = "video_cc_venus_ctl_axi_clk", 137253dc75aSTaniya Das .ops = &clk_branch2_ops, 138253dc75aSTaniya Das }, 139253dc75aSTaniya Das }, 140253dc75aSTaniya Das }; 141253dc75aSTaniya Das 142253dc75aSTaniya Das static struct clk_branch video_cc_venus_ctl_core_clk = { 143253dc75aSTaniya Das .halt_reg = 0x850, 144253dc75aSTaniya Das .halt_check = BRANCH_HALT, 145253dc75aSTaniya Das .clkr = { 146253dc75aSTaniya Das .enable_reg = 0x850, 147253dc75aSTaniya Das .enable_mask = BIT(0), 148253dc75aSTaniya Das .hw.init = &(struct clk_init_data){ 149253dc75aSTaniya Das .name = "video_cc_venus_ctl_core_clk", 150253dc75aSTaniya Das .parent_data = &(const struct clk_parent_data){ 151253dc75aSTaniya Das .hw = &video_cc_venus_clk_src.clkr.hw, 152253dc75aSTaniya Das }, 153253dc75aSTaniya Das .num_parents = 1, 154253dc75aSTaniya Das .flags = CLK_SET_RATE_PARENT, 155253dc75aSTaniya Das .ops = &clk_branch2_ops, 156253dc75aSTaniya Das }, 157253dc75aSTaniya Das }, 158253dc75aSTaniya Das }; 159253dc75aSTaniya Das 160253dc75aSTaniya Das static struct gdsc venus_gdsc = { 161253dc75aSTaniya Das .gdscr = 0x814, 162253dc75aSTaniya Das .pd = { 163253dc75aSTaniya Das .name = "venus_gdsc", 164253dc75aSTaniya Das }, 165253dc75aSTaniya Das .pwrsts = PWRSTS_OFF_ON, 166253dc75aSTaniya Das }; 167253dc75aSTaniya Das 168253dc75aSTaniya Das static struct gdsc vcodec0_gdsc = { 169253dc75aSTaniya Das .gdscr = 0x874, 170253dc75aSTaniya Das .pd = { 171253dc75aSTaniya Das .name = "vcodec0_gdsc", 172253dc75aSTaniya Das }, 173253dc75aSTaniya Das .flags = HW_CTRL, 174253dc75aSTaniya Das .pwrsts = PWRSTS_OFF_ON, 175253dc75aSTaniya Das }; 176253dc75aSTaniya Das 177253dc75aSTaniya Das static struct clk_regmap *video_cc_sc7180_clocks[] = { 178253dc75aSTaniya Das [VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr, 179253dc75aSTaniya Das [VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr, 180253dc75aSTaniya Das [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr, 181253dc75aSTaniya Das [VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr, 182253dc75aSTaniya Das [VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr, 183253dc75aSTaniya Das [VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr, 184253dc75aSTaniya Das [VIDEO_PLL0] = &video_pll0.clkr, 185253dc75aSTaniya Das }; 186253dc75aSTaniya Das 187253dc75aSTaniya Das static struct gdsc *video_cc_sc7180_gdscs[] = { 188253dc75aSTaniya Das [VENUS_GDSC] = &venus_gdsc, 189253dc75aSTaniya Das [VCODEC0_GDSC] = &vcodec0_gdsc, 190253dc75aSTaniya Das }; 191253dc75aSTaniya Das 192253dc75aSTaniya Das static const struct regmap_config video_cc_sc7180_regmap_config = { 193253dc75aSTaniya Das .reg_bits = 32, 194253dc75aSTaniya Das .reg_stride = 4, 195253dc75aSTaniya Das .val_bits = 32, 196253dc75aSTaniya Das .max_register = 0xb94, 197253dc75aSTaniya Das .fast_io = true, 198253dc75aSTaniya Das }; 199253dc75aSTaniya Das 200253dc75aSTaniya Das static const struct qcom_cc_desc video_cc_sc7180_desc = { 201253dc75aSTaniya Das .config = &video_cc_sc7180_regmap_config, 202253dc75aSTaniya Das .clks = video_cc_sc7180_clocks, 203253dc75aSTaniya Das .num_clks = ARRAY_SIZE(video_cc_sc7180_clocks), 204253dc75aSTaniya Das .gdscs = video_cc_sc7180_gdscs, 205253dc75aSTaniya Das .num_gdscs = ARRAY_SIZE(video_cc_sc7180_gdscs), 206253dc75aSTaniya Das }; 207253dc75aSTaniya Das 208253dc75aSTaniya Das static const struct of_device_id video_cc_sc7180_match_table[] = { 209253dc75aSTaniya Das { .compatible = "qcom,sc7180-videocc" }, 210253dc75aSTaniya Das { } 211253dc75aSTaniya Das }; 212253dc75aSTaniya Das MODULE_DEVICE_TABLE(of, video_cc_sc7180_match_table); 213253dc75aSTaniya Das 214253dc75aSTaniya Das static int video_cc_sc7180_probe(struct platform_device *pdev) 215253dc75aSTaniya Das { 216253dc75aSTaniya Das struct regmap *regmap; 217253dc75aSTaniya Das struct alpha_pll_config video_pll0_config = {}; 218253dc75aSTaniya Das 219253dc75aSTaniya Das regmap = qcom_cc_map(pdev, &video_cc_sc7180_desc); 220253dc75aSTaniya Das if (IS_ERR(regmap)) 221253dc75aSTaniya Das return PTR_ERR(regmap); 222253dc75aSTaniya Das 223253dc75aSTaniya Das video_pll0_config.l = 0x1f; 224253dc75aSTaniya Das video_pll0_config.alpha = 0x4000; 225253dc75aSTaniya Das video_pll0_config.user_ctl_val = 0x00000001; 226253dc75aSTaniya Das video_pll0_config.user_ctl_hi_val = 0x00004805; 227253dc75aSTaniya Das 228253dc75aSTaniya Das clk_fabia_pll_configure(&video_pll0, regmap, &video_pll0_config); 229253dc75aSTaniya Das 230253dc75aSTaniya Das /* Keep VIDEO_CC_XO_CLK ALWAYS-ON */ 231253dc75aSTaniya Das regmap_update_bits(regmap, 0x984, 0x1, 0x1); 232253dc75aSTaniya Das 233253dc75aSTaniya Das return qcom_cc_really_probe(pdev, &video_cc_sc7180_desc, regmap); 234253dc75aSTaniya Das } 235253dc75aSTaniya Das 236253dc75aSTaniya Das static struct platform_driver video_cc_sc7180_driver = { 237253dc75aSTaniya Das .probe = video_cc_sc7180_probe, 238253dc75aSTaniya Das .driver = { 239253dc75aSTaniya Das .name = "sc7180-videocc", 240253dc75aSTaniya Das .of_match_table = video_cc_sc7180_match_table, 241253dc75aSTaniya Das }, 242253dc75aSTaniya Das }; 243253dc75aSTaniya Das 244253dc75aSTaniya Das static int __init video_cc_sc7180_init(void) 245253dc75aSTaniya Das { 246253dc75aSTaniya Das return platform_driver_register(&video_cc_sc7180_driver); 247253dc75aSTaniya Das } 248253dc75aSTaniya Das subsys_initcall(video_cc_sc7180_init); 249253dc75aSTaniya Das 250253dc75aSTaniya Das static void __exit video_cc_sc7180_exit(void) 251253dc75aSTaniya Das { 252253dc75aSTaniya Das platform_driver_unregister(&video_cc_sc7180_driver); 253253dc75aSTaniya Das } 254253dc75aSTaniya Das module_exit(video_cc_sc7180_exit); 255253dc75aSTaniya Das 256253dc75aSTaniya Das MODULE_LICENSE("GPL v2"); 257253dc75aSTaniya Das MODULE_DESCRIPTION("QTI VIDEOCC SC7180 Driver"); 258