videocc-sc7180.c (6273B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2019, 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-sc7180.h> 12 13#include "clk-alpha-pll.h" 14#include "clk-branch.h" 15#include "clk-rcg.h" 16#include "clk-regmap.h" 17#include "common.h" 18#include "gdsc.h" 19 20enum { 21 P_BI_TCXO, 22 P_VIDEO_PLL0_OUT_MAIN, 23}; 24 25static const struct pll_vco fabia_vco[] = { 26 { 249600000, 2000000000, 0 }, 27}; 28 29static struct clk_alpha_pll video_pll0 = { 30 .offset = 0x42c, 31 .vco_table = fabia_vco, 32 .num_vco = ARRAY_SIZE(fabia_vco), 33 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], 34 .clkr = { 35 .hw.init = &(struct clk_init_data){ 36 .name = "video_pll0", 37 .parent_data = &(const struct clk_parent_data){ 38 .fw_name = "bi_tcxo", 39 }, 40 .num_parents = 1, 41 .ops = &clk_alpha_pll_fabia_ops, 42 }, 43 }, 44}; 45 46static const struct parent_map video_cc_parent_map_1[] = { 47 { P_BI_TCXO, 0 }, 48 { P_VIDEO_PLL0_OUT_MAIN, 1 }, 49}; 50 51static const struct clk_parent_data video_cc_parent_data_1[] = { 52 { .fw_name = "bi_tcxo" }, 53 { .hw = &video_pll0.clkr.hw }, 54}; 55 56static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = { 57 F(19200000, P_BI_TCXO, 1, 0, 0), 58 F(150000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0), 59 F(270000000, P_VIDEO_PLL0_OUT_MAIN, 2.5, 0, 0), 60 F(340000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 61 F(434000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 62 F(500000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), 63 { } 64}; 65 66static struct clk_rcg2 video_cc_venus_clk_src = { 67 .cmd_rcgr = 0x7f0, 68 .mnd_width = 0, 69 .hid_width = 5, 70 .parent_map = video_cc_parent_map_1, 71 .freq_tbl = ftbl_video_cc_venus_clk_src, 72 .clkr.hw.init = &(struct clk_init_data){ 73 .name = "video_cc_venus_clk_src", 74 .parent_data = video_cc_parent_data_1, 75 .num_parents = ARRAY_SIZE(video_cc_parent_data_1), 76 .flags = CLK_SET_RATE_PARENT, 77 .ops = &clk_rcg2_shared_ops, 78 }, 79}; 80 81static struct clk_branch video_cc_vcodec0_axi_clk = { 82 .halt_reg = 0x9ec, 83 .halt_check = BRANCH_HALT, 84 .clkr = { 85 .enable_reg = 0x9ec, 86 .enable_mask = BIT(0), 87 .hw.init = &(struct clk_init_data){ 88 .name = "video_cc_vcodec0_axi_clk", 89 .ops = &clk_branch2_ops, 90 }, 91 }, 92}; 93 94static struct clk_branch video_cc_vcodec0_core_clk = { 95 .halt_reg = 0x890, 96 .halt_check = BRANCH_HALT_VOTED, 97 .clkr = { 98 .enable_reg = 0x890, 99 .enable_mask = BIT(0), 100 .hw.init = &(struct clk_init_data){ 101 .name = "video_cc_vcodec0_core_clk", 102 .parent_hws = (const struct clk_hw*[]){ 103 &video_cc_venus_clk_src.clkr.hw, 104 }, 105 .num_parents = 1, 106 .flags = CLK_SET_RATE_PARENT, 107 .ops = &clk_branch2_ops, 108 }, 109 }, 110}; 111 112static struct clk_branch video_cc_venus_ahb_clk = { 113 .halt_reg = 0xa4c, 114 .halt_check = BRANCH_HALT, 115 .clkr = { 116 .enable_reg = 0xa4c, 117 .enable_mask = BIT(0), 118 .hw.init = &(struct clk_init_data){ 119 .name = "video_cc_venus_ahb_clk", 120 .ops = &clk_branch2_ops, 121 }, 122 }, 123}; 124 125static struct clk_branch video_cc_venus_ctl_axi_clk = { 126 .halt_reg = 0x9cc, 127 .halt_check = BRANCH_HALT, 128 .clkr = { 129 .enable_reg = 0x9cc, 130 .enable_mask = BIT(0), 131 .hw.init = &(struct clk_init_data){ 132 .name = "video_cc_venus_ctl_axi_clk", 133 .ops = &clk_branch2_ops, 134 }, 135 }, 136}; 137 138static struct clk_branch video_cc_venus_ctl_core_clk = { 139 .halt_reg = 0x850, 140 .halt_check = BRANCH_HALT, 141 .clkr = { 142 .enable_reg = 0x850, 143 .enable_mask = BIT(0), 144 .hw.init = &(struct clk_init_data){ 145 .name = "video_cc_venus_ctl_core_clk", 146 .parent_hws = (const struct clk_hw*[]){ 147 &video_cc_venus_clk_src.clkr.hw, 148 }, 149 .num_parents = 1, 150 .flags = CLK_SET_RATE_PARENT, 151 .ops = &clk_branch2_ops, 152 }, 153 }, 154}; 155 156static struct gdsc venus_gdsc = { 157 .gdscr = 0x814, 158 .pd = { 159 .name = "venus_gdsc", 160 }, 161 .pwrsts = PWRSTS_OFF_ON, 162}; 163 164static struct gdsc vcodec0_gdsc = { 165 .gdscr = 0x874, 166 .pd = { 167 .name = "vcodec0_gdsc", 168 }, 169 .flags = HW_CTRL, 170 .pwrsts = PWRSTS_OFF_ON, 171}; 172 173static struct clk_regmap *video_cc_sc7180_clocks[] = { 174 [VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr, 175 [VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr, 176 [VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr, 177 [VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr, 178 [VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr, 179 [VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr, 180 [VIDEO_PLL0] = &video_pll0.clkr, 181}; 182 183static struct gdsc *video_cc_sc7180_gdscs[] = { 184 [VENUS_GDSC] = &venus_gdsc, 185 [VCODEC0_GDSC] = &vcodec0_gdsc, 186}; 187 188static const struct regmap_config video_cc_sc7180_regmap_config = { 189 .reg_bits = 32, 190 .reg_stride = 4, 191 .val_bits = 32, 192 .max_register = 0xb94, 193 .fast_io = true, 194}; 195 196static const struct qcom_cc_desc video_cc_sc7180_desc = { 197 .config = &video_cc_sc7180_regmap_config, 198 .clks = video_cc_sc7180_clocks, 199 .num_clks = ARRAY_SIZE(video_cc_sc7180_clocks), 200 .gdscs = video_cc_sc7180_gdscs, 201 .num_gdscs = ARRAY_SIZE(video_cc_sc7180_gdscs), 202}; 203 204static const struct of_device_id video_cc_sc7180_match_table[] = { 205 { .compatible = "qcom,sc7180-videocc" }, 206 { } 207}; 208MODULE_DEVICE_TABLE(of, video_cc_sc7180_match_table); 209 210static int video_cc_sc7180_probe(struct platform_device *pdev) 211{ 212 struct regmap *regmap; 213 struct alpha_pll_config video_pll0_config = {}; 214 215 regmap = qcom_cc_map(pdev, &video_cc_sc7180_desc); 216 if (IS_ERR(regmap)) 217 return PTR_ERR(regmap); 218 219 video_pll0_config.l = 0x1f; 220 video_pll0_config.alpha = 0x4000; 221 video_pll0_config.user_ctl_val = 0x00000001; 222 video_pll0_config.user_ctl_hi_val = 0x00004805; 223 224 clk_fabia_pll_configure(&video_pll0, regmap, &video_pll0_config); 225 226 /* Keep VIDEO_CC_XO_CLK ALWAYS-ON */ 227 regmap_update_bits(regmap, 0x984, 0x1, 0x1); 228 229 return qcom_cc_really_probe(pdev, &video_cc_sc7180_desc, regmap); 230} 231 232static struct platform_driver video_cc_sc7180_driver = { 233 .probe = video_cc_sc7180_probe, 234 .driver = { 235 .name = "sc7180-videocc", 236 .of_match_table = video_cc_sc7180_match_table, 237 }, 238}; 239 240static int __init video_cc_sc7180_init(void) 241{ 242 return platform_driver_register(&video_cc_sc7180_driver); 243} 244subsys_initcall(video_cc_sc7180_init); 245 246static void __exit video_cc_sc7180_exit(void) 247{ 248 platform_driver_unregister(&video_cc_sc7180_driver); 249} 250module_exit(video_cc_sc7180_exit); 251 252MODULE_LICENSE("GPL v2"); 253MODULE_DESCRIPTION("QTI VIDEOCC SC7180 Driver");