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_sm8550_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_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 136 [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, 137 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 138 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 139 }; 140 141 static const struct regmap_config tcsr_cc_sm8550_regmap_config = { 142 .reg_bits = 32, 143 .reg_stride = 4, 144 .val_bits = 32, 145 .max_register = 0x2f000, 146 .fast_io = true, 147 }; 148 149 static const struct qcom_cc_desc tcsr_cc_sm8550_desc = { 150 .config = &tcsr_cc_sm8550_regmap_config, 151 .clks = tcsr_cc_sm8550_clocks, 152 .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks), 153 }; 154 155 static const struct of_device_id tcsr_cc_sm8550_match_table[] = { 156 { .compatible = "qcom,sm8550-tcsr" }, 157 { } 158 }; 159 MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table); 160 161 static int tcsr_cc_sm8550_probe(struct platform_device *pdev) 162 { 163 struct regmap *regmap; 164 165 regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc); 166 if (IS_ERR(regmap)) 167 return PTR_ERR(regmap); 168 169 return qcom_cc_really_probe(&pdev->dev, &tcsr_cc_sm8550_desc, regmap); 170 } 171 172 static struct platform_driver tcsr_cc_sm8550_driver = { 173 .probe = tcsr_cc_sm8550_probe, 174 .driver = { 175 .name = "tcsr_cc-sm8550", 176 .of_match_table = tcsr_cc_sm8550_match_table, 177 }, 178 }; 179 180 static int __init tcsr_cc_sm8550_init(void) 181 { 182 return platform_driver_register(&tcsr_cc_sm8550_driver); 183 } 184 subsys_initcall(tcsr_cc_sm8550_init); 185 186 static void __exit tcsr_cc_sm8550_exit(void) 187 { 188 platform_driver_unregister(&tcsr_cc_sm8550_driver); 189 } 190 module_exit(tcsr_cc_sm8550_exit); 191 192 MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver"); 193 MODULE_LICENSE("GPL"); 194