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