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.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 14 #include <dt-bindings/clock/qcom,sm8550-tcsr.h> 15 16 #include "clk-alpha-pll.h" 17 #include "clk-branch.h" 18 #include "clk-pll.h" 19 #include "clk-rcg.h" 20 #include "clk-regmap.h" 21 #include "clk-regmap-divider.h" 22 #include "clk-regmap-mux.h" 23 #include "common.h" 24 #include "reset.h" 25 26 enum { 27 DT_BI_TCXO_PAD, 28 }; 29 30 static struct clk_branch tcsr_pcie_0_clkref_en = { 31 .halt_reg = 0x15100, 32 .halt_check = BRANCH_HALT_SKIP, 33 .clkr = { 34 .enable_reg = 0x15100, 35 .enable_mask = BIT(0), 36 .hw.init = &(struct clk_init_data){ 37 .name = "tcsr_pcie_0_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 = 0x15114, 49 .halt_check = BRANCH_HALT_SKIP, 50 .clkr = { 51 .enable_reg = 0x15114, 52 .enable_mask = BIT(0), 53 .hw.init = &(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_ufs_clkref_en = { 65 .halt_reg = 0x15110, 66 .halt_check = BRANCH_HALT_SKIP, 67 .clkr = { 68 .enable_reg = 0x15110, 69 .enable_mask = BIT(0), 70 .hw.init = &(struct clk_init_data){ 71 .name = "tcsr_ufs_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_ufs_pad_clkref_en = { 82 .halt_reg = 0x15104, 83 .halt_check = BRANCH_HALT_SKIP, 84 .clkr = { 85 .enable_reg = 0x15104, 86 .enable_mask = BIT(0), 87 .hw.init = &(struct clk_init_data){ 88 .name = "tcsr_ufs_pad_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_usb2_clkref_en = { 99 .halt_reg = 0x15118, 100 .halt_check = BRANCH_HALT_SKIP, 101 .clkr = { 102 .enable_reg = 0x15118, 103 .enable_mask = BIT(0), 104 .hw.init = &(struct clk_init_data){ 105 .name = "tcsr_usb2_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_usb3_clkref_en = { 116 .halt_reg = 0x15108, 117 .halt_check = BRANCH_HALT_SKIP, 118 .clkr = { 119 .enable_reg = 0x15108, 120 .enable_mask = BIT(0), 121 .hw.init = &(struct clk_init_data){ 122 .name = "tcsr_usb3_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_regmap *tcsr_cc_sar2130p_clocks[] = { 133 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 134 [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 135 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 136 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 137 }; 138 139 static struct clk_regmap *tcsr_cc_sm8550_clocks[] = { 140 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 141 [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 142 [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 143 [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, 144 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 145 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 146 }; 147 148 static const struct regmap_config tcsr_cc_sm8550_regmap_config = { 149 .reg_bits = 32, 150 .reg_stride = 4, 151 .val_bits = 32, 152 .max_register = 0x2f000, 153 .fast_io = true, 154 }; 155 156 static const struct qcom_cc_desc tcsr_cc_sar2130p_desc = { 157 .config = &tcsr_cc_sm8550_regmap_config, 158 .clks = tcsr_cc_sar2130p_clocks, 159 .num_clks = ARRAY_SIZE(tcsr_cc_sar2130p_clocks), 160 }; 161 162 static const struct qcom_cc_desc tcsr_cc_sm8550_desc = { 163 .config = &tcsr_cc_sm8550_regmap_config, 164 .clks = tcsr_cc_sm8550_clocks, 165 .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks), 166 }; 167 168 static const struct of_device_id tcsr_cc_sm8550_match_table[] = { 169 { .compatible = "qcom,sar2130p-tcsr", .data = &tcsr_cc_sar2130p_desc }, 170 { .compatible = "qcom,sm8550-tcsr", .data = &tcsr_cc_sm8550_desc }, 171 { } 172 }; 173 MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table); 174 175 static int tcsr_cc_sm8550_probe(struct platform_device *pdev) 176 { 177 struct regmap *regmap; 178 179 regmap = qcom_cc_map(pdev, of_device_get_match_data(&pdev->dev)); 180 if (IS_ERR(regmap)) 181 return PTR_ERR(regmap); 182 183 return qcom_cc_really_probe(&pdev->dev, &tcsr_cc_sm8550_desc, regmap); 184 } 185 186 static struct platform_driver tcsr_cc_sm8550_driver = { 187 .probe = tcsr_cc_sm8550_probe, 188 .driver = { 189 .name = "tcsr_cc-sm8550", 190 .of_match_table = tcsr_cc_sm8550_match_table, 191 }, 192 }; 193 194 static int __init tcsr_cc_sm8550_init(void) 195 { 196 return platform_driver_register(&tcsr_cc_sm8550_driver); 197 } 198 subsys_initcall(tcsr_cc_sm8550_init); 199 200 static void __exit tcsr_cc_sm8550_exit(void) 201 { 202 platform_driver_unregister(&tcsr_cc_sm8550_driver); 203 } 204 module_exit(tcsr_cc_sm8550_exit); 205 206 MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver"); 207 MODULE_LICENSE("GPL"); 208