Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: qcom: Add TCSR clock driver for Glymur SoC

Add a clock driver for the TCSR clock controller found on Glymur SoC,
which provides refclks for PCIE, USB, and UFS subsystems.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250825-glymur-clock-controller-v5-v5-3-01b8c8681bcd@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Taniya Das and committed by
Bjorn Andersson
2c1d6ce4 ae5b8478

+322
+8
drivers/clk/qcom/Kconfig
··· 29 29 Say Y if you want to support display devices and functionality such as 30 30 splash screen. 31 31 32 + config CLK_GLYMUR_TCSRCC 33 + tristate "GLYMUR TCSR Clock Controller" 34 + depends on ARM64 || COMPILE_TEST 35 + select QCOM_GDSC 36 + help 37 + Support for the TCSR clock controller on GLYMUR devices. 38 + Say Y if you want to use peripheral devices such as USB/PCIe/EDP. 39 + 32 40 config CLK_X1E80100_CAMCC 33 41 tristate "X1E80100 Camera Clock Controller" 34 42 depends on ARM64 || COMPILE_TEST
+1
drivers/clk/qcom/Makefile
··· 22 22 obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o 23 23 obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o 24 24 obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o 25 + obj-$(CONFIG_CLK_GLYMUR_TCSRCC) += tcsrcc-glymur.o 25 26 obj-$(CONFIG_CLK_X1E80100_CAMCC) += camcc-x1e80100.o 26 27 obj-$(CONFIG_CLK_X1E80100_DISPCC) += dispcc-x1e80100.o 27 28 obj-$(CONFIG_CLK_X1E80100_GCC) += gcc-x1e80100.o
+313
drivers/clk/qcom/tcsrcc-glymur.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2025, Qualcomm Technologies, Inc. and/or its subsidiaries. 4 + */ 5 + 6 + #include <linux/clk-provider.h> 7 + #include <linux/mod_devicetable.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/platform_device.h> 11 + #include <linux/regmap.h> 12 + 13 + #include <dt-bindings/clock/qcom,glymur-tcsr.h> 14 + 15 + #include "clk-alpha-pll.h" 16 + #include "clk-branch.h" 17 + #include "clk-pll.h" 18 + #include "clk-rcg.h" 19 + #include "clk-regmap.h" 20 + #include "clk-regmap-divider.h" 21 + #include "clk-regmap-mux.h" 22 + #include "common.h" 23 + #include "gdsc.h" 24 + #include "reset.h" 25 + 26 + enum { 27 + DT_BI_TCXO_PAD, 28 + }; 29 + 30 + static struct clk_branch tcsr_edp_clkref_en = { 31 + .halt_reg = 0x1c, 32 + .halt_check = BRANCH_HALT_DELAY, 33 + .clkr = { 34 + .enable_reg = 0x1c, 35 + .enable_mask = BIT(0), 36 + .hw.init = &(const struct clk_init_data) { 37 + .name = "tcsr_edp_clkref_en", 38 + .parent_data = &(const struct clk_parent_data){ 39 + .index = DT_BI_TCXO_PAD, 40 + }, 41 + .num_parents = 1, 42 + .ops = &clk_branch2_ops, 43 + }, 44 + }, 45 + }; 46 + 47 + static struct clk_branch tcsr_pcie_1_clkref_en = { 48 + .halt_reg = 0x4, 49 + .halt_check = BRANCH_HALT_DELAY, 50 + .clkr = { 51 + .enable_reg = 0x4, 52 + .enable_mask = BIT(0), 53 + .hw.init = &(const struct clk_init_data) { 54 + .name = "tcsr_pcie_1_clkref_en", 55 + .parent_data = &(const struct clk_parent_data){ 56 + .index = DT_BI_TCXO_PAD, 57 + }, 58 + .num_parents = 1, 59 + .ops = &clk_branch2_ops, 60 + }, 61 + }, 62 + }; 63 + 64 + static struct clk_branch tcsr_pcie_2_clkref_en = { 65 + .halt_reg = 0x8, 66 + .halt_check = BRANCH_HALT_DELAY, 67 + .clkr = { 68 + .enable_reg = 0x8, 69 + .enable_mask = BIT(0), 70 + .hw.init = &(const struct clk_init_data) { 71 + .name = "tcsr_pcie_2_clkref_en", 72 + .parent_data = &(const struct clk_parent_data){ 73 + .index = DT_BI_TCXO_PAD, 74 + }, 75 + .num_parents = 1, 76 + .ops = &clk_branch2_ops, 77 + }, 78 + }, 79 + }; 80 + 81 + static struct clk_branch tcsr_pcie_3_clkref_en = { 82 + .halt_reg = 0x10, 83 + .halt_check = BRANCH_HALT_DELAY, 84 + .clkr = { 85 + .enable_reg = 0x10, 86 + .enable_mask = BIT(0), 87 + .hw.init = &(const struct clk_init_data) { 88 + .name = "tcsr_pcie_3_clkref_en", 89 + .parent_data = &(const struct clk_parent_data){ 90 + .index = DT_BI_TCXO_PAD, 91 + }, 92 + .num_parents = 1, 93 + .ops = &clk_branch2_ops, 94 + }, 95 + }, 96 + }; 97 + 98 + static struct clk_branch tcsr_pcie_4_clkref_en = { 99 + .halt_reg = 0x14, 100 + .halt_check = BRANCH_HALT_DELAY, 101 + .clkr = { 102 + .enable_reg = 0x14, 103 + .enable_mask = BIT(0), 104 + .hw.init = &(const struct clk_init_data) { 105 + .name = "tcsr_pcie_4_clkref_en", 106 + .parent_data = &(const struct clk_parent_data){ 107 + .index = DT_BI_TCXO_PAD, 108 + }, 109 + .num_parents = 1, 110 + .ops = &clk_branch2_ops, 111 + }, 112 + }, 113 + }; 114 + 115 + static struct clk_branch tcsr_usb2_1_clkref_en = { 116 + .halt_reg = 0x28, 117 + .halt_check = BRANCH_HALT_DELAY, 118 + .clkr = { 119 + .enable_reg = 0x28, 120 + .enable_mask = BIT(0), 121 + .hw.init = &(const struct clk_init_data) { 122 + .name = "tcsr_usb2_1_clkref_en", 123 + .parent_data = &(const struct clk_parent_data){ 124 + .index = DT_BI_TCXO_PAD, 125 + }, 126 + .num_parents = 1, 127 + .ops = &clk_branch2_ops, 128 + }, 129 + }, 130 + }; 131 + 132 + static struct clk_branch tcsr_usb2_2_clkref_en = { 133 + .halt_reg = 0x2c, 134 + .halt_check = BRANCH_HALT_DELAY, 135 + .clkr = { 136 + .enable_reg = 0x2c, 137 + .enable_mask = BIT(0), 138 + .hw.init = &(const struct clk_init_data) { 139 + .name = "tcsr_usb2_2_clkref_en", 140 + .parent_data = &(const struct clk_parent_data){ 141 + .index = DT_BI_TCXO_PAD, 142 + }, 143 + .num_parents = 1, 144 + .ops = &clk_branch2_ops, 145 + }, 146 + }, 147 + }; 148 + 149 + static struct clk_branch tcsr_usb2_3_clkref_en = { 150 + .halt_reg = 0x30, 151 + .halt_check = BRANCH_HALT_DELAY, 152 + .clkr = { 153 + .enable_reg = 0x30, 154 + .enable_mask = BIT(0), 155 + .hw.init = &(const struct clk_init_data) { 156 + .name = "tcsr_usb2_3_clkref_en", 157 + .parent_data = &(const struct clk_parent_data){ 158 + .index = DT_BI_TCXO_PAD, 159 + }, 160 + .num_parents = 1, 161 + .ops = &clk_branch2_ops, 162 + }, 163 + }, 164 + }; 165 + 166 + static struct clk_branch tcsr_usb2_4_clkref_en = { 167 + .halt_reg = 0x44, 168 + .halt_check = BRANCH_HALT_DELAY, 169 + .clkr = { 170 + .enable_reg = 0x44, 171 + .enable_mask = BIT(0), 172 + .hw.init = &(const struct clk_init_data) { 173 + .name = "tcsr_usb2_4_clkref_en", 174 + .parent_data = &(const struct clk_parent_data){ 175 + .index = DT_BI_TCXO_PAD, 176 + }, 177 + .num_parents = 1, 178 + .ops = &clk_branch2_ops, 179 + }, 180 + }, 181 + }; 182 + 183 + static struct clk_branch tcsr_usb3_0_clkref_en = { 184 + .halt_reg = 0x20, 185 + .halt_check = BRANCH_HALT_DELAY, 186 + .clkr = { 187 + .enable_reg = 0x20, 188 + .enable_mask = BIT(0), 189 + .hw.init = &(const struct clk_init_data) { 190 + .name = "tcsr_usb3_0_clkref_en", 191 + .parent_data = &(const struct clk_parent_data){ 192 + .index = DT_BI_TCXO_PAD, 193 + }, 194 + .num_parents = 1, 195 + .ops = &clk_branch2_ops, 196 + }, 197 + }, 198 + }; 199 + 200 + static struct clk_branch tcsr_usb3_1_clkref_en = { 201 + .halt_reg = 0x24, 202 + .halt_check = BRANCH_HALT_DELAY, 203 + .clkr = { 204 + .enable_reg = 0x24, 205 + .enable_mask = BIT(0), 206 + .hw.init = &(const struct clk_init_data) { 207 + .name = "tcsr_usb3_1_clkref_en", 208 + .parent_data = &(const struct clk_parent_data){ 209 + .index = DT_BI_TCXO_PAD, 210 + }, 211 + .num_parents = 1, 212 + .ops = &clk_branch2_ops, 213 + }, 214 + }, 215 + }; 216 + 217 + static struct clk_branch tcsr_usb4_1_clkref_en = { 218 + .halt_reg = 0x0, 219 + .halt_check = BRANCH_HALT_DELAY, 220 + .clkr = { 221 + .enable_reg = 0x0, 222 + .enable_mask = BIT(0), 223 + .hw.init = &(const struct clk_init_data) { 224 + .name = "tcsr_usb4_1_clkref_en", 225 + .parent_data = &(const struct clk_parent_data){ 226 + .index = DT_BI_TCXO_PAD, 227 + }, 228 + .num_parents = 1, 229 + .ops = &clk_branch2_ops, 230 + }, 231 + }, 232 + }; 233 + 234 + static struct clk_branch tcsr_usb4_2_clkref_en = { 235 + .halt_reg = 0x18, 236 + .halt_check = BRANCH_HALT_DELAY, 237 + .clkr = { 238 + .enable_reg = 0x18, 239 + .enable_mask = BIT(0), 240 + .hw.init = &(const struct clk_init_data) { 241 + .name = "tcsr_usb4_2_clkref_en", 242 + .parent_data = &(const struct clk_parent_data){ 243 + .index = DT_BI_TCXO_PAD, 244 + }, 245 + .num_parents = 1, 246 + .ops = &clk_branch2_ops, 247 + }, 248 + }, 249 + }; 250 + 251 + static struct clk_regmap *tcsr_cc_glymur_clocks[] = { 252 + [TCSR_EDP_CLKREF_EN] = &tcsr_edp_clkref_en.clkr, 253 + [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 254 + [TCSR_PCIE_2_CLKREF_EN] = &tcsr_pcie_2_clkref_en.clkr, 255 + [TCSR_PCIE_3_CLKREF_EN] = &tcsr_pcie_3_clkref_en.clkr, 256 + [TCSR_PCIE_4_CLKREF_EN] = &tcsr_pcie_4_clkref_en.clkr, 257 + [TCSR_USB2_1_CLKREF_EN] = &tcsr_usb2_1_clkref_en.clkr, 258 + [TCSR_USB2_2_CLKREF_EN] = &tcsr_usb2_2_clkref_en.clkr, 259 + [TCSR_USB2_3_CLKREF_EN] = &tcsr_usb2_3_clkref_en.clkr, 260 + [TCSR_USB2_4_CLKREF_EN] = &tcsr_usb2_4_clkref_en.clkr, 261 + [TCSR_USB3_0_CLKREF_EN] = &tcsr_usb3_0_clkref_en.clkr, 262 + [TCSR_USB3_1_CLKREF_EN] = &tcsr_usb3_1_clkref_en.clkr, 263 + [TCSR_USB4_1_CLKREF_EN] = &tcsr_usb4_1_clkref_en.clkr, 264 + [TCSR_USB4_2_CLKREF_EN] = &tcsr_usb4_2_clkref_en.clkr, 265 + }; 266 + 267 + static const struct regmap_config tcsr_cc_glymur_regmap_config = { 268 + .reg_bits = 32, 269 + .reg_stride = 4, 270 + .val_bits = 32, 271 + .max_register = 0x44, 272 + .fast_io = true, 273 + }; 274 + 275 + static const struct qcom_cc_desc tcsr_cc_glymur_desc = { 276 + .config = &tcsr_cc_glymur_regmap_config, 277 + .clks = tcsr_cc_glymur_clocks, 278 + .num_clks = ARRAY_SIZE(tcsr_cc_glymur_clocks), 279 + }; 280 + 281 + static const struct of_device_id tcsr_cc_glymur_match_table[] = { 282 + { .compatible = "qcom,glymur-tcsr" }, 283 + { } 284 + }; 285 + MODULE_DEVICE_TABLE(of, tcsr_cc_glymur_match_table); 286 + 287 + static int tcsr_cc_glymur_probe(struct platform_device *pdev) 288 + { 289 + return qcom_cc_probe(pdev, &tcsr_cc_glymur_desc); 290 + } 291 + 292 + static struct platform_driver tcsr_cc_glymur_driver = { 293 + .probe = tcsr_cc_glymur_probe, 294 + .driver = { 295 + .name = "tcsrcc-glymur", 296 + .of_match_table = tcsr_cc_glymur_match_table, 297 + }, 298 + }; 299 + 300 + static int __init tcsr_cc_glymur_init(void) 301 + { 302 + return platform_driver_register(&tcsr_cc_glymur_driver); 303 + } 304 + subsys_initcall(tcsr_cc_glymur_init); 305 + 306 + static void __exit tcsr_cc_glymur_exit(void) 307 + { 308 + platform_driver_unregister(&tcsr_cc_glymur_driver); 309 + } 310 + module_exit(tcsr_cc_glymur_exit); 311 + 312 + MODULE_DESCRIPTION("QTI TCSRCC GLYMUR Driver"); 313 + MODULE_LICENSE("GPL");