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) 2023, Linaro Limited 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/mod_devicetable.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 14 #include <dt-bindings/clock/qcom,sm8650-tcsr.h> 15 16 #include "clk-branch.h" 17 #include "clk-regmap.h" 18 #include "common.h" 19 #include "reset.h" 20 21 enum { 22 DT_BI_TCXO_PAD, 23 }; 24 25 static struct clk_branch tcsr_pcie_0_clkref_en = { 26 .halt_reg = 0x31100, 27 .halt_check = BRANCH_HALT_DELAY, 28 .clkr = { 29 .enable_reg = 0x31100, 30 .enable_mask = BIT(0), 31 .hw.init = &(struct clk_init_data){ 32 .name = "tcsr_pcie_0_clkref_en", 33 .parent_data = &(const struct clk_parent_data){ 34 .index = DT_BI_TCXO_PAD, 35 }, 36 .num_parents = 1, 37 .ops = &clk_branch2_ops, 38 }, 39 }, 40 }; 41 42 static struct clk_branch tcsr_pcie_1_clkref_en = { 43 .halt_reg = 0x31114, 44 .halt_check = BRANCH_HALT_DELAY, 45 .clkr = { 46 .enable_reg = 0x31114, 47 .enable_mask = BIT(0), 48 .hw.init = &(struct clk_init_data){ 49 .name = "tcsr_pcie_1_clkref_en", 50 .parent_data = &(const struct clk_parent_data){ 51 .index = DT_BI_TCXO_PAD, 52 }, 53 .num_parents = 1, 54 .ops = &clk_branch2_ops, 55 }, 56 }, 57 }; 58 59 static struct clk_branch tcsr_ufs_clkref_en = { 60 .halt_reg = 0x31110, 61 .halt_check = BRANCH_HALT_DELAY, 62 .clkr = { 63 .enable_reg = 0x31110, 64 .enable_mask = BIT(0), 65 .hw.init = &(struct clk_init_data){ 66 .name = "tcsr_ufs_clkref_en", 67 .parent_data = &(const struct clk_parent_data){ 68 .index = DT_BI_TCXO_PAD, 69 }, 70 .num_parents = 1, 71 .ops = &clk_branch2_ops, 72 }, 73 }, 74 }; 75 76 static struct clk_branch tcsr_ufs_pad_clkref_en = { 77 .halt_reg = 0x31104, 78 .halt_check = BRANCH_HALT_DELAY, 79 .clkr = { 80 .enable_reg = 0x31104, 81 .enable_mask = BIT(0), 82 .hw.init = &(struct clk_init_data){ 83 .name = "tcsr_ufs_pad_clkref_en", 84 .parent_data = &(const struct clk_parent_data){ 85 .index = DT_BI_TCXO_PAD, 86 }, 87 .num_parents = 1, 88 .ops = &clk_branch2_ops, 89 }, 90 }, 91 }; 92 93 static struct clk_branch tcsr_usb2_clkref_en = { 94 .halt_reg = 0x31118, 95 .halt_check = BRANCH_HALT_DELAY, 96 .clkr = { 97 .enable_reg = 0x31118, 98 .enable_mask = BIT(0), 99 .hw.init = &(struct clk_init_data){ 100 .name = "tcsr_usb2_clkref_en", 101 .parent_data = &(const struct clk_parent_data){ 102 .index = DT_BI_TCXO_PAD, 103 }, 104 .num_parents = 1, 105 .ops = &clk_branch2_ops, 106 }, 107 }, 108 }; 109 110 static struct clk_branch tcsr_usb3_clkref_en = { 111 .halt_reg = 0x31108, 112 .halt_check = BRANCH_HALT_DELAY, 113 .clkr = { 114 .enable_reg = 0x31108, 115 .enable_mask = BIT(0), 116 .hw.init = &(struct clk_init_data){ 117 .name = "tcsr_usb3_clkref_en", 118 .parent_data = &(const struct clk_parent_data){ 119 .index = DT_BI_TCXO_PAD, 120 }, 121 .num_parents = 1, 122 .ops = &clk_branch2_ops, 123 }, 124 }, 125 }; 126 127 static struct clk_regmap *tcsr_cc_sm8650_clocks[] = { 128 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 129 [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 130 [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 131 [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, 132 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 133 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 134 }; 135 136 static const struct regmap_config tcsr_cc_sm8650_regmap_config = { 137 .reg_bits = 32, 138 .reg_stride = 4, 139 .val_bits = 32, 140 .max_register = 0x3b000, 141 .fast_io = true, 142 }; 143 144 static const struct qcom_cc_desc tcsr_cc_sm8650_desc = { 145 .config = &tcsr_cc_sm8650_regmap_config, 146 .clks = tcsr_cc_sm8650_clocks, 147 .num_clks = ARRAY_SIZE(tcsr_cc_sm8650_clocks), 148 }; 149 150 static const struct of_device_id tcsr_cc_sm8650_match_table[] = { 151 { .compatible = "qcom,sm8650-tcsr" }, 152 { } 153 }; 154 MODULE_DEVICE_TABLE(of, tcsr_cc_sm8650_match_table); 155 156 static int tcsr_cc_sm8650_probe(struct platform_device *pdev) 157 { 158 return qcom_cc_probe(pdev, &tcsr_cc_sm8650_desc); 159 } 160 161 static struct platform_driver tcsr_cc_sm8650_driver = { 162 .probe = tcsr_cc_sm8650_probe, 163 .driver = { 164 .name = "tcsr_cc-sm8650", 165 .of_match_table = tcsr_cc_sm8650_match_table, 166 }, 167 }; 168 169 static int __init tcsr_cc_sm8650_init(void) 170 { 171 return platform_driver_register(&tcsr_cc_sm8650_driver); 172 } 173 subsys_initcall(tcsr_cc_sm8650_init); 174 175 static void __exit tcsr_cc_sm8650_exit(void) 176 { 177 platform_driver_unregister(&tcsr_cc_sm8650_driver); 178 } 179 module_exit(tcsr_cc_sm8650_exit); 180 181 MODULE_DESCRIPTION("QTI TCSRCC SM8650 Driver"); 182 MODULE_LICENSE("GPL"); 183