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
tcsr_cc_sm8550_probe(struct platform_device * pdev)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
tcsr_cc_sm8550_init(void)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
tcsr_cc_sm8550_exit(void)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