]>
Commit | Line | Data |
---|---|---|
9c92ab61 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
00f64b58 GD |
2 | /* |
3 | * Copyright (c) 2016, Linaro Limited | |
4 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. | |
00f64b58 GD |
5 | */ |
6 | ||
7 | #include <linux/clk-provider.h> | |
8 | #include <linux/err.h> | |
9 | #include <linux/export.h> | |
10 | #include <linux/init.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/mutex.h> | |
14 | #include <linux/of.h> | |
15 | #include <linux/of_device.h> | |
16 | #include <linux/platform_device.h> | |
17 | #include <linux/soc/qcom/smd-rpm.h> | |
18 | ||
19 | #include <dt-bindings/clock/qcom,rpmcc.h> | |
20 | #include <dt-bindings/mfd/qcom-rpm.h> | |
21 | ||
22 | #define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773 | |
23 | #define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370 | |
24 | #define QCOM_RPM_SMD_KEY_RATE 0x007a484b | |
25 | #define QCOM_RPM_SMD_KEY_ENABLE 0x62616e45 | |
26 | #define QCOM_RPM_SMD_KEY_STATE 0x54415453 | |
27 | #define QCOM_RPM_SCALING_ENABLE_ID 0x2 | |
28 | ||
29 | #define __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, stat_id, \ | |
30 | key) \ | |
31 | static struct clk_smd_rpm _platform##_##_active; \ | |
32 | static struct clk_smd_rpm _platform##_##_name = { \ | |
33 | .rpm_res_type = (type), \ | |
34 | .rpm_clk_id = (r_id), \ | |
35 | .rpm_status_id = (stat_id), \ | |
36 | .rpm_key = (key), \ | |
37 | .peer = &_platform##_##_active, \ | |
38 | .rate = INT_MAX, \ | |
39 | .hw.init = &(struct clk_init_data){ \ | |
40 | .ops = &clk_smd_rpm_ops, \ | |
41 | .name = #_name, \ | |
42 | .parent_names = (const char *[]){ "xo_board" }, \ | |
43 | .num_parents = 1, \ | |
44 | }, \ | |
45 | }; \ | |
46 | static struct clk_smd_rpm _platform##_##_active = { \ | |
47 | .rpm_res_type = (type), \ | |
48 | .rpm_clk_id = (r_id), \ | |
49 | .rpm_status_id = (stat_id), \ | |
50 | .active_only = true, \ | |
51 | .rpm_key = (key), \ | |
52 | .peer = &_platform##_##_name, \ | |
53 | .rate = INT_MAX, \ | |
54 | .hw.init = &(struct clk_init_data){ \ | |
55 | .ops = &clk_smd_rpm_ops, \ | |
56 | .name = #_active, \ | |
57 | .parent_names = (const char *[]){ "xo_board" }, \ | |
58 | .num_parents = 1, \ | |
59 | }, \ | |
60 | } | |
61 | ||
62 | #define __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, \ | |
63 | stat_id, r, key) \ | |
64 | static struct clk_smd_rpm _platform##_##_active; \ | |
65 | static struct clk_smd_rpm _platform##_##_name = { \ | |
66 | .rpm_res_type = (type), \ | |
67 | .rpm_clk_id = (r_id), \ | |
68 | .rpm_status_id = (stat_id), \ | |
69 | .rpm_key = (key), \ | |
70 | .branch = true, \ | |
71 | .peer = &_platform##_##_active, \ | |
72 | .rate = (r), \ | |
73 | .hw.init = &(struct clk_init_data){ \ | |
74 | .ops = &clk_smd_rpm_branch_ops, \ | |
75 | .name = #_name, \ | |
76 | .parent_names = (const char *[]){ "xo_board" }, \ | |
77 | .num_parents = 1, \ | |
78 | }, \ | |
79 | }; \ | |
80 | static struct clk_smd_rpm _platform##_##_active = { \ | |
81 | .rpm_res_type = (type), \ | |
82 | .rpm_clk_id = (r_id), \ | |
83 | .rpm_status_id = (stat_id), \ | |
84 | .active_only = true, \ | |
85 | .rpm_key = (key), \ | |
86 | .branch = true, \ | |
87 | .peer = &_platform##_##_name, \ | |
88 | .rate = (r), \ | |
89 | .hw.init = &(struct clk_init_data){ \ | |
90 | .ops = &clk_smd_rpm_branch_ops, \ | |
91 | .name = #_active, \ | |
92 | .parent_names = (const char *[]){ "xo_board" }, \ | |
93 | .num_parents = 1, \ | |
94 | }, \ | |
95 | } | |
96 | ||
97 | #define DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id) \ | |
98 | __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \ | |
99 | 0, QCOM_RPM_SMD_KEY_RATE) | |
100 | ||
101 | #define DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, r) \ | |
102 | __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, \ | |
103 | r_id, 0, r, QCOM_RPM_SMD_KEY_ENABLE) | |
104 | ||
105 | #define DEFINE_CLK_SMD_RPM_QDSS(_platform, _name, _active, type, r_id) \ | |
106 | __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, \ | |
107 | 0, QCOM_RPM_SMD_KEY_STATE) | |
108 | ||
109 | #define DEFINE_CLK_SMD_RPM_XO_BUFFER(_platform, _name, _active, r_id) \ | |
110 | __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \ | |
111 | QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \ | |
112 | QCOM_RPM_KEY_SOFTWARE_ENABLE) | |
113 | ||
114 | #define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_platform, _name, _active, r_id) \ | |
115 | __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, \ | |
116 | QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000, \ | |
117 | QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY) | |
118 | ||
119 | #define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw) | |
120 | ||
121 | struct clk_smd_rpm { | |
122 | const int rpm_res_type; | |
123 | const int rpm_key; | |
124 | const int rpm_clk_id; | |
125 | const int rpm_status_id; | |
126 | const bool active_only; | |
127 | bool enabled; | |
128 | bool branch; | |
129 | struct clk_smd_rpm *peer; | |
130 | struct clk_hw hw; | |
131 | unsigned long rate; | |
132 | struct qcom_smd_rpm *rpm; | |
133 | }; | |
134 | ||
135 | struct clk_smd_rpm_req { | |
136 | __le32 key; | |
137 | __le32 nbytes; | |
138 | __le32 value; | |
139 | }; | |
140 | ||
141 | struct rpm_cc { | |
142 | struct qcom_rpm *rpm; | |
81b7667a GD |
143 | struct clk_smd_rpm **clks; |
144 | size_t num_clks; | |
00f64b58 GD |
145 | }; |
146 | ||
147 | struct rpm_smd_clk_desc { | |
148 | struct clk_smd_rpm **clks; | |
149 | size_t num_clks; | |
150 | }; | |
151 | ||
152 | static DEFINE_MUTEX(rpm_smd_clk_lock); | |
153 | ||
154 | static int clk_smd_rpm_handoff(struct clk_smd_rpm *r) | |
155 | { | |
156 | int ret; | |
157 | struct clk_smd_rpm_req req = { | |
158 | .key = cpu_to_le32(r->rpm_key), | |
159 | .nbytes = cpu_to_le32(sizeof(u32)), | |
46a7253d | 160 | .value = cpu_to_le32(r->branch ? 1 : INT_MAX), |
00f64b58 GD |
161 | }; |
162 | ||
163 | ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, | |
164 | r->rpm_res_type, r->rpm_clk_id, &req, | |
165 | sizeof(req)); | |
166 | if (ret) | |
167 | return ret; | |
168 | ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, | |
169 | r->rpm_res_type, r->rpm_clk_id, &req, | |
170 | sizeof(req)); | |
171 | if (ret) | |
172 | return ret; | |
173 | ||
174 | return 0; | |
175 | } | |
176 | ||
177 | static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r, | |
178 | unsigned long rate) | |
179 | { | |
180 | struct clk_smd_rpm_req req = { | |
181 | .key = cpu_to_le32(r->rpm_key), | |
182 | .nbytes = cpu_to_le32(sizeof(u32)), | |
183 | .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ | |
184 | }; | |
185 | ||
186 | return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, | |
187 | r->rpm_res_type, r->rpm_clk_id, &req, | |
188 | sizeof(req)); | |
189 | } | |
190 | ||
191 | static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r, | |
192 | unsigned long rate) | |
193 | { | |
194 | struct clk_smd_rpm_req req = { | |
195 | .key = cpu_to_le32(r->rpm_key), | |
196 | .nbytes = cpu_to_le32(sizeof(u32)), | |
197 | .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ | |
198 | }; | |
199 | ||
200 | return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, | |
201 | r->rpm_res_type, r->rpm_clk_id, &req, | |
202 | sizeof(req)); | |
203 | } | |
204 | ||
205 | static void to_active_sleep(struct clk_smd_rpm *r, unsigned long rate, | |
206 | unsigned long *active, unsigned long *sleep) | |
207 | { | |
208 | *active = rate; | |
209 | ||
210 | /* | |
211 | * Active-only clocks don't care what the rate is during sleep. So, | |
212 | * they vote for zero. | |
213 | */ | |
214 | if (r->active_only) | |
215 | *sleep = 0; | |
216 | else | |
217 | *sleep = *active; | |
218 | } | |
219 | ||
220 | static int clk_smd_rpm_prepare(struct clk_hw *hw) | |
221 | { | |
222 | struct clk_smd_rpm *r = to_clk_smd_rpm(hw); | |
223 | struct clk_smd_rpm *peer = r->peer; | |
224 | unsigned long this_rate = 0, this_sleep_rate = 0; | |
225 | unsigned long peer_rate = 0, peer_sleep_rate = 0; | |
226 | unsigned long active_rate, sleep_rate; | |
227 | int ret = 0; | |
228 | ||
229 | mutex_lock(&rpm_smd_clk_lock); | |
230 | ||
231 | /* Don't send requests to the RPM if the rate has not been set. */ | |
232 | if (!r->rate) | |
233 | goto out; | |
234 | ||
235 | to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate); | |
236 | ||
237 | /* Take peer clock's rate into account only if it's enabled. */ | |
238 | if (peer->enabled) | |
239 | to_active_sleep(peer, peer->rate, | |
240 | &peer_rate, &peer_sleep_rate); | |
241 | ||
242 | active_rate = max(this_rate, peer_rate); | |
243 | ||
244 | if (r->branch) | |
245 | active_rate = !!active_rate; | |
246 | ||
247 | ret = clk_smd_rpm_set_rate_active(r, active_rate); | |
248 | if (ret) | |
249 | goto out; | |
250 | ||
251 | sleep_rate = max(this_sleep_rate, peer_sleep_rate); | |
252 | if (r->branch) | |
253 | sleep_rate = !!sleep_rate; | |
254 | ||
255 | ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate); | |
256 | if (ret) | |
257 | /* Undo the active set vote and restore it */ | |
258 | ret = clk_smd_rpm_set_rate_active(r, peer_rate); | |
259 | ||
260 | out: | |
261 | if (!ret) | |
262 | r->enabled = true; | |
263 | ||
264 | mutex_unlock(&rpm_smd_clk_lock); | |
265 | ||
266 | return ret; | |
267 | } | |
268 | ||
269 | static void clk_smd_rpm_unprepare(struct clk_hw *hw) | |
270 | { | |
271 | struct clk_smd_rpm *r = to_clk_smd_rpm(hw); | |
272 | struct clk_smd_rpm *peer = r->peer; | |
273 | unsigned long peer_rate = 0, peer_sleep_rate = 0; | |
274 | unsigned long active_rate, sleep_rate; | |
275 | int ret; | |
276 | ||
277 | mutex_lock(&rpm_smd_clk_lock); | |
278 | ||
279 | if (!r->rate) | |
280 | goto out; | |
281 | ||
282 | /* Take peer clock's rate into account only if it's enabled. */ | |
283 | if (peer->enabled) | |
284 | to_active_sleep(peer, peer->rate, &peer_rate, | |
285 | &peer_sleep_rate); | |
286 | ||
287 | active_rate = r->branch ? !!peer_rate : peer_rate; | |
288 | ret = clk_smd_rpm_set_rate_active(r, active_rate); | |
289 | if (ret) | |
290 | goto out; | |
291 | ||
292 | sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate; | |
293 | ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate); | |
294 | if (ret) | |
295 | goto out; | |
296 | ||
297 | r->enabled = false; | |
298 | ||
299 | out: | |
300 | mutex_unlock(&rpm_smd_clk_lock); | |
301 | } | |
302 | ||
303 | static int clk_smd_rpm_set_rate(struct clk_hw *hw, unsigned long rate, | |
304 | unsigned long parent_rate) | |
305 | { | |
306 | struct clk_smd_rpm *r = to_clk_smd_rpm(hw); | |
307 | struct clk_smd_rpm *peer = r->peer; | |
308 | unsigned long active_rate, sleep_rate; | |
309 | unsigned long this_rate = 0, this_sleep_rate = 0; | |
310 | unsigned long peer_rate = 0, peer_sleep_rate = 0; | |
311 | int ret = 0; | |
312 | ||
313 | mutex_lock(&rpm_smd_clk_lock); | |
314 | ||
315 | if (!r->enabled) | |
316 | goto out; | |
317 | ||
318 | to_active_sleep(r, rate, &this_rate, &this_sleep_rate); | |
319 | ||
320 | /* Take peer clock's rate into account only if it's enabled. */ | |
321 | if (peer->enabled) | |
322 | to_active_sleep(peer, peer->rate, | |
323 | &peer_rate, &peer_sleep_rate); | |
324 | ||
325 | active_rate = max(this_rate, peer_rate); | |
326 | ret = clk_smd_rpm_set_rate_active(r, active_rate); | |
327 | if (ret) | |
328 | goto out; | |
329 | ||
330 | sleep_rate = max(this_sleep_rate, peer_sleep_rate); | |
331 | ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate); | |
332 | if (ret) | |
333 | goto out; | |
334 | ||
335 | r->rate = rate; | |
336 | ||
337 | out: | |
338 | mutex_unlock(&rpm_smd_clk_lock); | |
339 | ||
340 | return ret; | |
341 | } | |
342 | ||
343 | static long clk_smd_rpm_round_rate(struct clk_hw *hw, unsigned long rate, | |
344 | unsigned long *parent_rate) | |
345 | { | |
346 | /* | |
347 | * RPM handles rate rounding and we don't have a way to | |
348 | * know what the rate will be, so just return whatever | |
349 | * rate is requested. | |
350 | */ | |
351 | return rate; | |
352 | } | |
353 | ||
354 | static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw, | |
355 | unsigned long parent_rate) | |
356 | { | |
357 | struct clk_smd_rpm *r = to_clk_smd_rpm(hw); | |
358 | ||
359 | /* | |
360 | * RPM handles rate rounding and we don't have a way to | |
361 | * know what the rate will be, so just return whatever | |
362 | * rate was set. | |
363 | */ | |
364 | return r->rate; | |
365 | } | |
366 | ||
367 | static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) | |
368 | { | |
369 | int ret; | |
370 | struct clk_smd_rpm_req req = { | |
371 | .key = cpu_to_le32(QCOM_RPM_SMD_KEY_ENABLE), | |
372 | .nbytes = cpu_to_le32(sizeof(u32)), | |
373 | .value = cpu_to_le32(1), | |
374 | }; | |
375 | ||
376 | ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE, | |
377 | QCOM_SMD_RPM_MISC_CLK, | |
378 | QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); | |
379 | if (ret) { | |
380 | pr_err("RPM clock scaling (sleep set) not enabled!\n"); | |
381 | return ret; | |
382 | } | |
383 | ||
384 | ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE, | |
385 | QCOM_SMD_RPM_MISC_CLK, | |
386 | QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); | |
387 | if (ret) { | |
388 | pr_err("RPM clock scaling (active set) not enabled!\n"); | |
389 | return ret; | |
390 | } | |
391 | ||
392 | pr_debug("%s: RPM clock scaling is enabled\n", __func__); | |
393 | return 0; | |
394 | } | |
395 | ||
396 | static const struct clk_ops clk_smd_rpm_ops = { | |
397 | .prepare = clk_smd_rpm_prepare, | |
398 | .unprepare = clk_smd_rpm_unprepare, | |
399 | .set_rate = clk_smd_rpm_set_rate, | |
400 | .round_rate = clk_smd_rpm_round_rate, | |
401 | .recalc_rate = clk_smd_rpm_recalc_rate, | |
402 | }; | |
403 | ||
404 | static const struct clk_ops clk_smd_rpm_branch_ops = { | |
405 | .prepare = clk_smd_rpm_prepare, | |
406 | .unprepare = clk_smd_rpm_unprepare, | |
00f64b58 GD |
407 | }; |
408 | ||
409 | /* msm8916 */ | |
410 | DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); | |
411 | DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); | |
412 | DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); | |
413 | DEFINE_CLK_SMD_RPM_QDSS(msm8916, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); | |
414 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk1, bb_clk1_a, 1); | |
415 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk2, bb_clk2_a, 2); | |
416 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk1, rf_clk1_a, 4); | |
417 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk2, rf_clk2_a, 5); | |
418 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk1_pin, bb_clk1_a_pin, 1); | |
419 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk2_pin, bb_clk2_a_pin, 2); | |
420 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk1_pin, rf_clk1_a_pin, 4); | |
421 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk2_pin, rf_clk2_a_pin, 5); | |
422 | ||
423 | static struct clk_smd_rpm *msm8916_clks[] = { | |
424 | [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, | |
425 | [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, | |
426 | [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, | |
427 | [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, | |
428 | [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, | |
429 | [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, | |
430 | [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, | |
431 | [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, | |
432 | [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, | |
433 | [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, | |
434 | [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, | |
435 | [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, | |
436 | [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, | |
437 | [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, | |
438 | [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, | |
439 | [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, | |
440 | [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, | |
441 | [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, | |
442 | [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, | |
443 | [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, | |
444 | [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, | |
445 | [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, | |
446 | [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, | |
447 | [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, | |
448 | }; | |
449 | ||
450 | static const struct rpm_smd_clk_desc rpm_clk_msm8916 = { | |
451 | .clks = msm8916_clks, | |
452 | .num_clks = ARRAY_SIZE(msm8916_clks), | |
453 | }; | |
454 | ||
685dc94b BA |
455 | /* msm8974 */ |
456 | DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); | |
457 | DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); | |
458 | DEFINE_CLK_SMD_RPM(msm8974, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); | |
459 | DEFINE_CLK_SMD_RPM(msm8974, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, QCOM_SMD_RPM_BUS_CLK, 3); | |
460 | DEFINE_CLK_SMD_RPM(msm8974, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); | |
461 | DEFINE_CLK_SMD_RPM(msm8974, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); | |
462 | DEFINE_CLK_SMD_RPM(msm8974, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); | |
463 | DEFINE_CLK_SMD_RPM_QDSS(msm8974, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); | |
464 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d0, cxo_d0_a, 1); | |
465 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d1, cxo_d1_a, 2); | |
466 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_a0, cxo_a0_a, 4); | |
467 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_a1, cxo_a1_a, 5); | |
468 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_a2, cxo_a2_a, 6); | |
469 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, diff_clk, diff_a_clk, 7); | |
470 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, div_clk1, div_a_clk1, 11); | |
471 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, div_clk2, div_a_clk2, 12); | |
472 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_d0_pin, cxo_d0_a_pin, 1); | |
473 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_d1_pin, cxo_d1_a_pin, 2); | |
474 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a0_pin, cxo_a0_a_pin, 4); | |
475 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a1_pin, cxo_a1_a_pin, 5); | |
476 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a2_pin, cxo_a2_a_pin, 6); | |
477 | ||
478 | static struct clk_smd_rpm *msm8974_clks[] = { | |
479 | [RPM_SMD_PNOC_CLK] = &msm8974_pnoc_clk, | |
480 | [RPM_SMD_PNOC_A_CLK] = &msm8974_pnoc_a_clk, | |
481 | [RPM_SMD_SNOC_CLK] = &msm8974_snoc_clk, | |
482 | [RPM_SMD_SNOC_A_CLK] = &msm8974_snoc_a_clk, | |
483 | [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, | |
484 | [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, | |
485 | [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, | |
486 | [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, | |
487 | [RPM_SMD_BIMC_CLK] = &msm8974_bimc_clk, | |
488 | [RPM_SMD_BIMC_A_CLK] = &msm8974_bimc_a_clk, | |
489 | [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, | |
490 | [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, | |
491 | [RPM_SMD_QDSS_CLK] = &msm8974_qdss_clk, | |
492 | [RPM_SMD_QDSS_A_CLK] = &msm8974_qdss_a_clk, | |
493 | [RPM_SMD_CXO_D0] = &msm8974_cxo_d0, | |
494 | [RPM_SMD_CXO_D0_A] = &msm8974_cxo_d0_a, | |
495 | [RPM_SMD_CXO_D1] = &msm8974_cxo_d1, | |
496 | [RPM_SMD_CXO_D1_A] = &msm8974_cxo_d1_a, | |
497 | [RPM_SMD_CXO_A0] = &msm8974_cxo_a0, | |
498 | [RPM_SMD_CXO_A0_A] = &msm8974_cxo_a0_a, | |
499 | [RPM_SMD_CXO_A1] = &msm8974_cxo_a1, | |
500 | [RPM_SMD_CXO_A1_A] = &msm8974_cxo_a1_a, | |
501 | [RPM_SMD_CXO_A2] = &msm8974_cxo_a2, | |
502 | [RPM_SMD_CXO_A2_A] = &msm8974_cxo_a2_a, | |
503 | [RPM_SMD_DIFF_CLK] = &msm8974_diff_clk, | |
504 | [RPM_SMD_DIFF_A_CLK] = &msm8974_diff_a_clk, | |
505 | [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, | |
506 | [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, | |
507 | [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, | |
508 | [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, | |
509 | [RPM_SMD_CXO_D0_PIN] = &msm8974_cxo_d0_pin, | |
510 | [RPM_SMD_CXO_D0_A_PIN] = &msm8974_cxo_d0_a_pin, | |
511 | [RPM_SMD_CXO_D1_PIN] = &msm8974_cxo_d1_pin, | |
512 | [RPM_SMD_CXO_D1_A_PIN] = &msm8974_cxo_d1_a_pin, | |
513 | [RPM_SMD_CXO_A0_PIN] = &msm8974_cxo_a0_pin, | |
514 | [RPM_SMD_CXO_A0_A_PIN] = &msm8974_cxo_a0_a_pin, | |
515 | [RPM_SMD_CXO_A1_PIN] = &msm8974_cxo_a1_pin, | |
516 | [RPM_SMD_CXO_A1_A_PIN] = &msm8974_cxo_a1_a_pin, | |
517 | [RPM_SMD_CXO_A2_PIN] = &msm8974_cxo_a2_pin, | |
518 | [RPM_SMD_CXO_A2_A_PIN] = &msm8974_cxo_a2_a_pin, | |
519 | }; | |
520 | ||
521 | static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { | |
522 | .clks = msm8974_clks, | |
523 | .num_clks = ARRAY_SIZE(msm8974_clks), | |
524 | }; | |
7066fdd0 RN |
525 | |
526 | /* msm8996 */ | |
527 | DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); | |
528 | DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); | |
529 | DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); | |
530 | DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); | |
531 | DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, | |
532 | QCOM_SMD_RPM_MMAXI_CLK, 0); | |
533 | DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); | |
534 | DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); | |
535 | DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk, | |
536 | QCOM_SMD_RPM_AGGR_CLK, 1, 1000); | |
537 | DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk, | |
538 | QCOM_SMD_RPM_AGGR_CLK, 2, 1000); | |
539 | DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk, | |
540 | QCOM_SMD_RPM_MISC_CLK, 1); | |
541 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1); | |
542 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2); | |
543 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4); | |
544 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5); | |
545 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8); | |
546 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb); | |
547 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc); | |
548 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd); | |
549 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1); | |
550 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2); | |
551 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4); | |
552 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5); | |
553 | ||
554 | static struct clk_smd_rpm *msm8996_clks[] = { | |
555 | [RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk, | |
556 | [RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk, | |
557 | [RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk, | |
558 | [RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk, | |
559 | [RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk, | |
560 | [RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk, | |
561 | [RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk, | |
562 | [RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk, | |
563 | [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, | |
564 | [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, | |
565 | [RPM_SMD_IPA_CLK] = &msm8996_ipa_clk, | |
566 | [RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk, | |
567 | [RPM_SMD_CE1_CLK] = &msm8996_ce1_clk, | |
568 | [RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk, | |
569 | [RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk, | |
570 | [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk, | |
571 | [RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk, | |
572 | [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk, | |
573 | [RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk, | |
574 | [RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk, | |
575 | [RPM_SMD_BB_CLK1] = &msm8996_bb_clk1, | |
576 | [RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a, | |
577 | [RPM_SMD_BB_CLK2] = &msm8996_bb_clk2, | |
578 | [RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a, | |
579 | [RPM_SMD_RF_CLK1] = &msm8996_rf_clk1, | |
580 | [RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a, | |
581 | [RPM_SMD_RF_CLK2] = &msm8996_rf_clk2, | |
582 | [RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a, | |
583 | [RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk, | |
584 | [RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk, | |
585 | [RPM_SMD_DIV_CLK1] = &msm8996_div_clk1, | |
586 | [RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a, | |
587 | [RPM_SMD_DIV_CLK2] = &msm8996_div_clk2, | |
588 | [RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a, | |
589 | [RPM_SMD_DIV_CLK3] = &msm8996_div_clk3, | |
590 | [RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a, | |
591 | [RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin, | |
592 | [RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin, | |
593 | [RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin, | |
594 | [RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin, | |
595 | [RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin, | |
596 | [RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin, | |
597 | [RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin, | |
598 | [RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin, | |
599 | }; | |
600 | ||
601 | static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { | |
602 | .clks = msm8996_clks, | |
603 | .num_clks = ARRAY_SIZE(msm8996_clks), | |
604 | }; | |
605 | ||
eaeee28d TD |
606 | /* QCS404 */ |
607 | DEFINE_CLK_SMD_RPM_QDSS(qcs404, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); | |
608 | ||
609 | DEFINE_CLK_SMD_RPM(qcs404, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); | |
610 | DEFINE_CLK_SMD_RPM(qcs404, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); | |
611 | ||
612 | DEFINE_CLK_SMD_RPM(qcs404, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); | |
613 | DEFINE_CLK_SMD_RPM(qcs404, bimc_gpu_clk, bimc_gpu_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); | |
614 | ||
615 | DEFINE_CLK_SMD_RPM(qcs404, qpic_clk, qpic_a_clk, QCOM_SMD_RPM_QPIC_CLK, 0); | |
616 | DEFINE_CLK_SMD_RPM(qcs404, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); | |
617 | ||
618 | DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, rf_clk1, rf_clk1_a, 4); | |
619 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, rf_clk1_pin, rf_clk1_a_pin, 4); | |
620 | ||
621 | DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, ln_bb_clk, ln_bb_a_clk, 8); | |
622 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); | |
623 | ||
624 | static struct clk_smd_rpm *qcs404_clks[] = { | |
625 | [RPM_SMD_QDSS_CLK] = &qcs404_qdss_clk, | |
626 | [RPM_SMD_QDSS_A_CLK] = &qcs404_qdss_a_clk, | |
627 | [RPM_SMD_PNOC_CLK] = &qcs404_pnoc_clk, | |
628 | [RPM_SMD_PNOC_A_CLK] = &qcs404_pnoc_a_clk, | |
629 | [RPM_SMD_SNOC_CLK] = &qcs404_snoc_clk, | |
630 | [RPM_SMD_SNOC_A_CLK] = &qcs404_snoc_a_clk, | |
631 | [RPM_SMD_BIMC_CLK] = &qcs404_bimc_clk, | |
632 | [RPM_SMD_BIMC_A_CLK] = &qcs404_bimc_a_clk, | |
633 | [RPM_SMD_BIMC_GPU_CLK] = &qcs404_bimc_gpu_clk, | |
634 | [RPM_SMD_BIMC_GPU_A_CLK] = &qcs404_bimc_gpu_a_clk, | |
635 | [RPM_SMD_QPIC_CLK] = &qcs404_qpic_clk, | |
636 | [RPM_SMD_QPIC_CLK_A] = &qcs404_qpic_a_clk, | |
637 | [RPM_SMD_CE1_CLK] = &qcs404_ce1_clk, | |
638 | [RPM_SMD_CE1_A_CLK] = &qcs404_ce1_a_clk, | |
639 | [RPM_SMD_RF_CLK1] = &qcs404_rf_clk1, | |
640 | [RPM_SMD_RF_CLK1_A] = &qcs404_rf_clk1_a, | |
641 | [RPM_SMD_LN_BB_CLK] = &qcs404_ln_bb_clk, | |
642 | [RPM_SMD_LN_BB_A_CLK] = &qcs404_ln_bb_a_clk, | |
643 | }; | |
644 | ||
645 | static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { | |
646 | .clks = qcs404_clks, | |
647 | .num_clks = ARRAY_SIZE(qcs404_clks), | |
648 | }; | |
649 | ||
6131dc81 JH |
650 | /* msm8998 */ |
651 | DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); | |
652 | DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); | |
653 | DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); | |
654 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, div_clk1, div_clk1_a, 0xb); | |
655 | DEFINE_CLK_SMD_RPM(msm8998, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); | |
656 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk1, ln_bb_clk1_a, 1); | |
657 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk2, ln_bb_clk2_a, 2); | |
658 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, | |
659 | 3); | |
660 | DEFINE_CLK_SMD_RPM(msm8998, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, | |
661 | QCOM_SMD_RPM_MMAXI_CLK, 0); | |
662 | DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk, | |
663 | QCOM_SMD_RPM_AGGR_CLK, 1); | |
664 | DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk, | |
665 | QCOM_SMD_RPM_AGGR_CLK, 2); | |
666 | DEFINE_CLK_SMD_RPM_QDSS(msm8998, qdss_clk, qdss_a_clk, | |
667 | QCOM_SMD_RPM_MISC_CLK, 1); | |
668 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk1, rf_clk1_a, 4); | |
669 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk2_pin, rf_clk2_a_pin, 5); | |
670 | DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6); | |
671 | DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6); | |
672 | static struct clk_smd_rpm *msm8998_clks[] = { | |
673 | [RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk, | |
674 | [RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk, | |
675 | [RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk, | |
676 | [RPM_SMD_CNOC_A_CLK] = &msm8998_cnoc_a_clk, | |
677 | [RPM_SMD_CE1_CLK] = &msm8998_ce1_clk, | |
678 | [RPM_SMD_CE1_A_CLK] = &msm8998_ce1_a_clk, | |
679 | [RPM_SMD_DIV_CLK1] = &msm8998_div_clk1, | |
680 | [RPM_SMD_DIV_A_CLK1] = &msm8998_div_clk1_a, | |
681 | [RPM_SMD_IPA_CLK] = &msm8998_ipa_clk, | |
682 | [RPM_SMD_IPA_A_CLK] = &msm8998_ipa_a_clk, | |
683 | [RPM_SMD_LN_BB_CLK1] = &msm8998_ln_bb_clk1, | |
684 | [RPM_SMD_LN_BB_CLK1_A] = &msm8998_ln_bb_clk1_a, | |
685 | [RPM_SMD_LN_BB_CLK2] = &msm8998_ln_bb_clk2, | |
686 | [RPM_SMD_LN_BB_CLK2_A] = &msm8998_ln_bb_clk2_a, | |
687 | [RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin, | |
688 | [RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin, | |
689 | [RPM_SMD_MMAXI_CLK] = &msm8998_mmssnoc_axi_rpm_clk, | |
690 | [RPM_SMD_MMAXI_A_CLK] = &msm8998_mmssnoc_axi_rpm_a_clk, | |
691 | [RPM_SMD_AGGR1_NOC_CLK] = &msm8998_aggre1_noc_clk, | |
692 | [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8998_aggre1_noc_a_clk, | |
693 | [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk, | |
694 | [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk, | |
695 | [RPM_SMD_QDSS_CLK] = &msm8998_qdss_clk, | |
696 | [RPM_SMD_QDSS_A_CLK] = &msm8998_qdss_a_clk, | |
697 | [RPM_SMD_RF_CLK1] = &msm8998_rf_clk1, | |
698 | [RPM_SMD_RF_CLK1_A] = &msm8998_rf_clk1_a, | |
699 | [RPM_SMD_RF_CLK2_PIN] = &msm8998_rf_clk2_pin, | |
700 | [RPM_SMD_RF_CLK2_A_PIN] = &msm8998_rf_clk2_a_pin, | |
701 | [RPM_SMD_RF_CLK3] = &msm8998_rf_clk3, | |
702 | [RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a, | |
703 | [RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin, | |
704 | [RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin, | |
705 | }; | |
706 | ||
707 | static const struct rpm_smd_clk_desc rpm_clk_msm8998 = { | |
708 | .clks = msm8998_clks, | |
709 | .num_clks = ARRAY_SIZE(msm8998_clks), | |
710 | }; | |
711 | ||
00f64b58 GD |
712 | static const struct of_device_id rpm_smd_clk_match_table[] = { |
713 | { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, | |
685dc94b | 714 | { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, |
7066fdd0 | 715 | { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, |
6131dc81 | 716 | { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 }, |
eaeee28d | 717 | { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, |
00f64b58 GD |
718 | { } |
719 | }; | |
720 | MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); | |
721 | ||
81b7667a GD |
722 | static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec, |
723 | void *data) | |
724 | { | |
725 | struct rpm_cc *rcc = data; | |
726 | unsigned int idx = clkspec->args[0]; | |
727 | ||
728 | if (idx >= rcc->num_clks) { | |
729 | pr_err("%s: invalid index %u\n", __func__, idx); | |
730 | return ERR_PTR(-EINVAL); | |
731 | } | |
732 | ||
733 | return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT); | |
734 | } | |
735 | ||
00f64b58 GD |
736 | static int rpm_smd_clk_probe(struct platform_device *pdev) |
737 | { | |
00f64b58 | 738 | struct rpm_cc *rcc; |
00f64b58 GD |
739 | int ret; |
740 | size_t num_clks, i; | |
741 | struct qcom_smd_rpm *rpm; | |
742 | struct clk_smd_rpm **rpm_smd_clks; | |
743 | const struct rpm_smd_clk_desc *desc; | |
744 | ||
745 | rpm = dev_get_drvdata(pdev->dev.parent); | |
746 | if (!rpm) { | |
747 | dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); | |
748 | return -ENODEV; | |
749 | } | |
750 | ||
751 | desc = of_device_get_match_data(&pdev->dev); | |
752 | if (!desc) | |
753 | return -EINVAL; | |
754 | ||
755 | rpm_smd_clks = desc->clks; | |
756 | num_clks = desc->num_clks; | |
757 | ||
81b7667a | 758 | rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL); |
00f64b58 GD |
759 | if (!rcc) |
760 | return -ENOMEM; | |
761 | ||
81b7667a GD |
762 | rcc->clks = rpm_smd_clks; |
763 | rcc->num_clks = num_clks; | |
00f64b58 GD |
764 | |
765 | for (i = 0; i < num_clks; i++) { | |
766 | if (!rpm_smd_clks[i]) | |
767 | continue; | |
768 | ||
769 | rpm_smd_clks[i]->rpm = rpm; | |
770 | ||
771 | ret = clk_smd_rpm_handoff(rpm_smd_clks[i]); | |
772 | if (ret) | |
773 | goto err; | |
774 | } | |
775 | ||
776 | ret = clk_smd_rpm_enable_scaling(rpm); | |
777 | if (ret) | |
778 | goto err; | |
779 | ||
780 | for (i = 0; i < num_clks; i++) { | |
81b7667a | 781 | if (!rpm_smd_clks[i]) |
00f64b58 | 782 | continue; |
00f64b58 GD |
783 | |
784 | ret = devm_clk_hw_register(&pdev->dev, &rpm_smd_clks[i]->hw); | |
785 | if (ret) | |
786 | goto err; | |
787 | } | |
788 | ||
91927ff6 | 789 | ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get, |
81b7667a | 790 | rcc); |
00f64b58 GD |
791 | if (ret) |
792 | goto err; | |
793 | ||
794 | return 0; | |
795 | err: | |
796 | dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret); | |
797 | return ret; | |
798 | } | |
799 | ||
00f64b58 GD |
800 | static struct platform_driver rpm_smd_clk_driver = { |
801 | .driver = { | |
802 | .name = "qcom-clk-smd-rpm", | |
803 | .of_match_table = rpm_smd_clk_match_table, | |
804 | }, | |
805 | .probe = rpm_smd_clk_probe, | |
00f64b58 GD |
806 | }; |
807 | ||
808 | static int __init rpm_smd_clk_init(void) | |
809 | { | |
810 | return platform_driver_register(&rpm_smd_clk_driver); | |
811 | } | |
812 | core_initcall(rpm_smd_clk_init); | |
813 | ||
814 | static void __exit rpm_smd_clk_exit(void) | |
815 | { | |
816 | platform_driver_unregister(&rpm_smd_clk_driver); | |
817 | } | |
818 | module_exit(rpm_smd_clk_exit); | |
819 | ||
820 | MODULE_DESCRIPTION("Qualcomm RPM over SMD Clock Controller Driver"); | |
821 | MODULE_LICENSE("GPL v2"); | |
822 | MODULE_ALIAS("platform:qcom-clk-smd-rpm"); |