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, desc: &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 | |