1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. 5 * Copyright (c) 2022, Linaro Limited 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/module.h> 10 #include <linux/of_device.h> 11 #include <linux/regmap.h> 12 13 #include <dt-bindings/clock/qcom,sm8550-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 "reset.h" 24 25 enum { 26 DT_BI_TCXO_PAD, 27 }; 28 29 static struct clk_branch tcsr_pcie_0_clkref_en = { 30 .halt_reg = 0x15100, 31 .halt_check = BRANCH_HALT_SKIP, 32 .clkr = { 33 .enable_reg = 0x15100, 34 .enable_mask = BIT(0), 35 .hw.init = &(struct clk_init_data){ 36 .name = "tcsr_pcie_0_clkref_en", 37 .parent_data = &(const struct clk_parent_data){ 38 .index = DT_BI_TCXO_PAD, 39 }, 40 .num_parents = 1, 41 .ops = &clk_branch2_ops, 42 }, 43 }, 44 }; 45 46 static struct clk_branch tcsr_pcie_1_clkref_en = { 47 .halt_reg = 0x15114, 48 .halt_check = BRANCH_HALT_SKIP, 49 .clkr = { 50 .enable_reg = 0x15114, 51 .enable_mask = BIT(0), 52 .hw.init = &(struct clk_init_data){ 53 .name = "tcsr_pcie_1_clkref_en", 54 .parent_data = &(const struct clk_parent_data){ 55 .index = DT_BI_TCXO_PAD, 56 }, 57 .num_parents = 1, 58 .ops = &clk_branch2_ops, 59 }, 60 }, 61 }; 62 63 static struct clk_branch tcsr_ufs_clkref_en = { 64 .halt_reg = 0x15110, 65 .halt_check = BRANCH_HALT_SKIP, 66 .clkr = { 67 .enable_reg = 0x15110, 68 .enable_mask = BIT(0), 69 .hw.init = &(struct clk_init_data){ 70 .name = "tcsr_ufs_clkref_en", 71 .parent_data = &(const struct clk_parent_data){ 72 .index = DT_BI_TCXO_PAD, 73 }, 74 .num_parents = 1, 75 .ops = &clk_branch2_ops, 76 }, 77 }, 78 }; 79 80 static struct clk_branch tcsr_ufs_pad_clkref_en = { 81 .halt_reg = 0x15104, 82 .halt_check = BRANCH_HALT_SKIP, 83 .clkr = { 84 .enable_reg = 0x15104, 85 .enable_mask = BIT(0), 86 .hw.init = &(struct clk_init_data){ 87 .name = "tcsr_ufs_pad_clkref_en", 88 .parent_data = &(const struct clk_parent_data){ 89 .index = DT_BI_TCXO_PAD, 90 }, 91 .num_parents = 1, 92 .ops = &clk_branch2_ops, 93 }, 94 }, 95 }; 96 97 static struct clk_branch tcsr_usb2_clkref_en = { 98 .halt_reg = 0x15118, 99 .halt_check = BRANCH_HALT_SKIP, 100 .clkr = { 101 .enable_reg = 0x15118, 102 .enable_mask = BIT(0), 103 .hw.init = &(struct clk_init_data){ 104 .name = "tcsr_usb2_clkref_en", 105 .parent_data = &(const struct clk_parent_data){ 106 .index = DT_BI_TCXO_PAD, 107 }, 108 .num_parents = 1, 109 .ops = &clk_branch2_ops, 110 }, 111 }, 112 }; 113 114 static struct clk_branch tcsr_usb3_clkref_en = { 115 .halt_reg = 0x15108, 116 .halt_check = BRANCH_HALT_SKIP, 117 .clkr = { 118 .enable_reg = 0x15108, 119 .enable_mask = BIT(0), 120 .hw.init = &(struct clk_init_data){ 121 .name = "tcsr_usb3_clkref_en", 122 .parent_data = &(const struct clk_parent_data){ 123 .index = DT_BI_TCXO_PAD, 124 }, 125 .num_parents = 1, 126 .ops = &clk_branch2_ops, 127 }, 128 }, 129 }; 130 131 static struct clk_regmap *tcsr_cc_sm8550_clocks[] = { 132 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 133 [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 134 [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 135 [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, 136 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 137 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 138 }; 139 140 static const struct regmap_config tcsr_cc_sm8550_regmap_config = { 141 .reg_bits = 32, 142 .reg_stride = 4, 143 .val_bits = 32, 144 .max_register = 0x2f000, 145 .fast_io = true, 146 }; 147 148 static const struct qcom_cc_desc tcsr_cc_sm8550_desc = { 149 .config = &tcsr_cc_sm8550_regmap_config, 150 .clks = tcsr_cc_sm8550_clocks, 151 .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks), 152 }; 153 154 static const struct of_device_id tcsr_cc_sm8550_match_table[] = { 155 { .compatible = "qcom,sm8550-tcsr" }, 156 { } 157 }; 158 MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table); 159 160 static int tcsr_cc_sm8550_probe(struct platform_device *pdev) 161 { 162 struct regmap *regmap; 163 164 regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc); 165 if (IS_ERR(regmap)) 166 return PTR_ERR(regmap); 167 168 return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap); 169 } 170 171 static struct platform_driver tcsr_cc_sm8550_driver = { 172 .probe = tcsr_cc_sm8550_probe, 173 .driver = { 174 .name = "tcsr_cc-sm8550", 175 .of_match_table = tcsr_cc_sm8550_match_table, 176 }, 177 }; 178 179 static int __init tcsr_cc_sm8550_init(void) 180 { 181 return platform_driver_register(&tcsr_cc_sm8550_driver); 182 } 183 subsys_initcall(tcsr_cc_sm8550_init); 184 185 static void __exit tcsr_cc_sm8550_exit(void) 186 { 187 platform_driver_unregister(&tcsr_cc_sm8550_driver); 188 } 189 module_exit(tcsr_cc_sm8550_exit); 190 191 MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver"); 192 MODULE_LICENSE("GPL"); 193