1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
6 #include <linux/clk-provider.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
11 #include <linux/of_device.h>
12 #include <linux/platform_device.h>
13 #include <soc/qcom/cmd-db.h>
14 #include <soc/qcom/rpmh.h>
15 #include <soc/qcom/tcs.h>
17 #include <dt-bindings/clock/qcom,rpmh.h>
19 #define CLK_RPMH_ARC_EN_OFFSET 0
20 #define CLK_RPMH_VRM_EN_OFFSET 4
23 * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager(BCM)
24 * @unit: divisor used to convert Hz value to an RPMh msg
25 * @width: multiplier used to convert Hz value to an RPMh msg
26 * @vcd: virtual clock domain that this bcm belongs to
27 * @reserved: reserved to pad the struct
37 * struct clk_rpmh - individual rpmh clock data structure
38 * @hw: handle between common and hardware-specific interfaces
39 * @res_name: resource name for the rpmh clock
40 * @div: clock divider to compute the clock rate
41 * @res_addr: base address of the rpmh resource within the RPMh
42 * @res_on_val: rpmh clock enable value
43 * @state: rpmh clock requested state
44 * @aggr_state: rpmh clock aggregated state
45 * @last_sent_aggr_state: rpmh clock last aggr state sent to RPMh
46 * @valid_state_mask: mask to determine the state of the rpmh clock
47 * @unit: divisor to convert rate to rpmh msg in magnitudes of Khz
48 * @dev: device to which it is attached
49 * @peer: pointer to the clock rpmh sibling
59 u32 last_sent_aggr_state
;
63 struct clk_rpmh
*peer
;
66 struct clk_rpmh_desc
{
71 static DEFINE_MUTEX(rpmh_clk_lock
);
73 #define __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
74 _res_en_offset, _res_on, _div) \
75 static struct clk_rpmh _platform##_##_name_active; \
76 static struct clk_rpmh _platform##_##_name = { \
77 .res_name = _res_name, \
78 .res_addr = _res_en_offset, \
79 .res_on_val = _res_on, \
81 .peer = &_platform##_##_name_active, \
82 .valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
83 BIT(RPMH_ACTIVE_ONLY_STATE) | \
84 BIT(RPMH_SLEEP_STATE)), \
85 .hw.init = &(struct clk_init_data){ \
86 .ops = &clk_rpmh_ops, \
88 .parent_data = &(const struct clk_parent_data){ \
95 static struct clk_rpmh _platform##_##_name_active = { \
96 .res_name = _res_name, \
97 .res_addr = _res_en_offset, \
98 .res_on_val = _res_on, \
100 .peer = &_platform##_##_name, \
101 .valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
102 BIT(RPMH_ACTIVE_ONLY_STATE)), \
103 .hw.init = &(struct clk_init_data){ \
104 .ops = &clk_rpmh_ops, \
105 .name = #_name_active, \
106 .parent_data = &(const struct clk_parent_data){ \
108 .name = "xo_board", \
114 #define DEFINE_CLK_RPMH_ARC(_platform, _name, _name_active, _res_name, \
116 __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
117 CLK_RPMH_ARC_EN_OFFSET, _res_on, _div)
119 #define DEFINE_CLK_RPMH_VRM(_platform, _name, _name_active, _res_name, \
121 __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
122 CLK_RPMH_VRM_EN_OFFSET, 1, _div)
124 #define DEFINE_CLK_RPMH_BCM(_platform, _name, _res_name) \
125 static struct clk_rpmh _platform##_##_name = { \
126 .res_name = _res_name, \
127 .valid_state_mask = BIT(RPMH_ACTIVE_ONLY_STATE), \
129 .hw.init = &(struct clk_init_data){ \
130 .ops = &clk_rpmh_bcm_ops, \
135 static inline struct clk_rpmh
*to_clk_rpmh(struct clk_hw
*_hw
)
137 return container_of(_hw
, struct clk_rpmh
, hw
);
140 static inline bool has_state_changed(struct clk_rpmh
*c
, u32 state
)
142 return (c
->last_sent_aggr_state
& BIT(state
))
143 != (c
->aggr_state
& BIT(state
));
146 static int clk_rpmh_send(struct clk_rpmh
*c
, enum rpmh_state state
,
147 struct tcs_cmd
*cmd
, bool wait
)
150 return rpmh_write(c
->dev
, state
, cmd
, 1);
152 return rpmh_write_async(c
->dev
, state
, cmd
, 1);
155 static int clk_rpmh_send_aggregate_command(struct clk_rpmh
*c
)
157 struct tcs_cmd cmd
= { 0 };
158 u32 cmd_state
, on_val
;
159 enum rpmh_state state
= RPMH_SLEEP_STATE
;
163 cmd
.addr
= c
->res_addr
;
164 cmd_state
= c
->aggr_state
;
165 on_val
= c
->res_on_val
;
167 for (; state
<= RPMH_ACTIVE_ONLY_STATE
; state
++) {
168 if (has_state_changed(c
, state
)) {
169 if (cmd_state
& BIT(state
))
172 wait
= cmd_state
&& state
== RPMH_ACTIVE_ONLY_STATE
;
173 ret
= clk_rpmh_send(c
, state
, &cmd
, wait
);
175 dev_err(c
->dev
, "set %s state of %s failed: (%d)\n",
177 state
== RPMH_WAKE_ONLY_STATE
?
178 "wake" : "active", c
->res_name
, ret
);
184 c
->last_sent_aggr_state
= c
->aggr_state
;
185 c
->peer
->last_sent_aggr_state
= c
->last_sent_aggr_state
;
191 * Update state and aggregate state values based on enable value.
193 static int clk_rpmh_aggregate_state_send_command(struct clk_rpmh
*c
,
198 /* Nothing required to be done if already off or on */
199 if (enable
== c
->state
)
202 c
->state
= enable
? c
->valid_state_mask
: 0;
203 c
->aggr_state
= c
->state
| c
->peer
->state
;
204 c
->peer
->aggr_state
= c
->aggr_state
;
206 ret
= clk_rpmh_send_aggregate_command(c
);
213 c
->state
= c
->valid_state_mask
;
215 WARN(1, "clk: %s failed to %s\n", c
->res_name
,
216 enable
? "enable" : "disable");
220 static int clk_rpmh_prepare(struct clk_hw
*hw
)
222 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
225 mutex_lock(&rpmh_clk_lock
);
226 ret
= clk_rpmh_aggregate_state_send_command(c
, true);
227 mutex_unlock(&rpmh_clk_lock
);
232 static void clk_rpmh_unprepare(struct clk_hw
*hw
)
234 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
236 mutex_lock(&rpmh_clk_lock
);
237 clk_rpmh_aggregate_state_send_command(c
, false);
238 mutex_unlock(&rpmh_clk_lock
);
241 static unsigned long clk_rpmh_recalc_rate(struct clk_hw
*hw
,
244 struct clk_rpmh
*r
= to_clk_rpmh(hw
);
247 * RPMh clocks have a fixed rate. Return static rate.
249 return prate
/ r
->div
;
252 static const struct clk_ops clk_rpmh_ops
= {
253 .prepare
= clk_rpmh_prepare
,
254 .unprepare
= clk_rpmh_unprepare
,
255 .recalc_rate
= clk_rpmh_recalc_rate
,
258 static int clk_rpmh_bcm_send_cmd(struct clk_rpmh
*c
, bool enable
)
260 struct tcs_cmd cmd
= { 0 };
264 mutex_lock(&rpmh_clk_lock
);
268 cmd_state
= c
->aggr_state
;
273 if (c
->last_sent_aggr_state
!= cmd_state
) {
274 cmd
.addr
= c
->res_addr
;
275 cmd
.data
= BCM_TCS_CMD(1, enable
, 0, cmd_state
);
277 ret
= clk_rpmh_send(c
, RPMH_ACTIVE_ONLY_STATE
, &cmd
, enable
);
279 dev_err(c
->dev
, "set active state of %s failed: (%d)\n",
282 c
->last_sent_aggr_state
= cmd_state
;
286 mutex_unlock(&rpmh_clk_lock
);
291 static int clk_rpmh_bcm_prepare(struct clk_hw
*hw
)
293 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
295 return clk_rpmh_bcm_send_cmd(c
, true);
298 static void clk_rpmh_bcm_unprepare(struct clk_hw
*hw
)
300 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
302 clk_rpmh_bcm_send_cmd(c
, false);
305 static int clk_rpmh_bcm_set_rate(struct clk_hw
*hw
, unsigned long rate
,
306 unsigned long parent_rate
)
308 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
310 c
->aggr_state
= rate
/ c
->unit
;
312 * Since any non-zero value sent to hw would result in enabling the
313 * clock, only send the value if the clock has already been prepared.
315 if (clk_hw_is_prepared(hw
))
316 clk_rpmh_bcm_send_cmd(c
, true);
321 static long clk_rpmh_round_rate(struct clk_hw
*hw
, unsigned long rate
,
322 unsigned long *parent_rate
)
327 static unsigned long clk_rpmh_bcm_recalc_rate(struct clk_hw
*hw
,
330 struct clk_rpmh
*c
= to_clk_rpmh(hw
);
332 return c
->aggr_state
* c
->unit
;
335 static const struct clk_ops clk_rpmh_bcm_ops
= {
336 .prepare
= clk_rpmh_bcm_prepare
,
337 .unprepare
= clk_rpmh_bcm_unprepare
,
338 .set_rate
= clk_rpmh_bcm_set_rate
,
339 .round_rate
= clk_rpmh_round_rate
,
340 .recalc_rate
= clk_rpmh_bcm_recalc_rate
,
343 /* Resource name must match resource id present in cmd-db */
344 DEFINE_CLK_RPMH_ARC(sdm845
, bi_tcxo
, bi_tcxo_ao
, "xo.lvl", 0x3, 2);
345 DEFINE_CLK_RPMH_VRM(sdm845
, ln_bb_clk2
, ln_bb_clk2_ao
, "lnbclka2", 2);
346 DEFINE_CLK_RPMH_VRM(sdm845
, ln_bb_clk3
, ln_bb_clk3_ao
, "lnbclka3", 2);
347 DEFINE_CLK_RPMH_VRM(sdm845
, rf_clk1
, rf_clk1_ao
, "rfclka1", 1);
348 DEFINE_CLK_RPMH_VRM(sdm845
, rf_clk2
, rf_clk2_ao
, "rfclka2", 1);
349 DEFINE_CLK_RPMH_VRM(sdm845
, rf_clk3
, rf_clk3_ao
, "rfclka3", 1);
350 DEFINE_CLK_RPMH_VRM(sm8150
, rf_clk3
, rf_clk3_ao
, "rfclka3", 1);
351 DEFINE_CLK_RPMH_BCM(sdm845
, ipa
, "IP0");
352 DEFINE_CLK_RPMH_BCM(sdm845
, ce
, "CE0");
354 static struct clk_hw
*sdm845_rpmh_clocks
[] = {
355 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
356 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
357 [RPMH_LN_BB_CLK2
] = &sdm845_ln_bb_clk2
.hw
,
358 [RPMH_LN_BB_CLK2_A
] = &sdm845_ln_bb_clk2_ao
.hw
,
359 [RPMH_LN_BB_CLK3
] = &sdm845_ln_bb_clk3
.hw
,
360 [RPMH_LN_BB_CLK3_A
] = &sdm845_ln_bb_clk3_ao
.hw
,
361 [RPMH_RF_CLK1
] = &sdm845_rf_clk1
.hw
,
362 [RPMH_RF_CLK1_A
] = &sdm845_rf_clk1_ao
.hw
,
363 [RPMH_RF_CLK2
] = &sdm845_rf_clk2
.hw
,
364 [RPMH_RF_CLK2_A
] = &sdm845_rf_clk2_ao
.hw
,
365 [RPMH_RF_CLK3
] = &sdm845_rf_clk3
.hw
,
366 [RPMH_RF_CLK3_A
] = &sdm845_rf_clk3_ao
.hw
,
367 [RPMH_IPA_CLK
] = &sdm845_ipa
.hw
,
368 [RPMH_CE_CLK
] = &sdm845_ce
.hw
,
371 static const struct clk_rpmh_desc clk_rpmh_sdm845
= {
372 .clks
= sdm845_rpmh_clocks
,
373 .num_clks
= ARRAY_SIZE(sdm845_rpmh_clocks
),
376 DEFINE_CLK_RPMH_VRM(sdx55
, rf_clk1
, rf_clk1_ao
, "rfclkd1", 1);
377 DEFINE_CLK_RPMH_VRM(sdx55
, rf_clk2
, rf_clk2_ao
, "rfclkd2", 1);
378 DEFINE_CLK_RPMH_BCM(sdx55
, qpic_clk
, "QP0");
380 static struct clk_hw
*sdx55_rpmh_clocks
[] = {
381 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
382 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
383 [RPMH_RF_CLK1
] = &sdx55_rf_clk1
.hw
,
384 [RPMH_RF_CLK1_A
] = &sdx55_rf_clk1_ao
.hw
,
385 [RPMH_RF_CLK2
] = &sdx55_rf_clk2
.hw
,
386 [RPMH_RF_CLK2_A
] = &sdx55_rf_clk2_ao
.hw
,
387 [RPMH_QPIC_CLK
] = &sdx55_qpic_clk
.hw
,
390 static const struct clk_rpmh_desc clk_rpmh_sdx55
= {
391 .clks
= sdx55_rpmh_clocks
,
392 .num_clks
= ARRAY_SIZE(sdx55_rpmh_clocks
),
395 static struct clk_hw
*sm8150_rpmh_clocks
[] = {
396 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
397 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
398 [RPMH_LN_BB_CLK2
] = &sdm845_ln_bb_clk2
.hw
,
399 [RPMH_LN_BB_CLK2_A
] = &sdm845_ln_bb_clk2_ao
.hw
,
400 [RPMH_LN_BB_CLK3
] = &sdm845_ln_bb_clk3
.hw
,
401 [RPMH_LN_BB_CLK3_A
] = &sdm845_ln_bb_clk3_ao
.hw
,
402 [RPMH_RF_CLK1
] = &sdm845_rf_clk1
.hw
,
403 [RPMH_RF_CLK1_A
] = &sdm845_rf_clk1_ao
.hw
,
404 [RPMH_RF_CLK2
] = &sdm845_rf_clk2
.hw
,
405 [RPMH_RF_CLK2_A
] = &sdm845_rf_clk2_ao
.hw
,
406 [RPMH_RF_CLK3
] = &sdm845_rf_clk3
.hw
,
407 [RPMH_RF_CLK3_A
] = &sdm845_rf_clk3_ao
.hw
,
410 static const struct clk_rpmh_desc clk_rpmh_sm8150
= {
411 .clks
= sm8150_rpmh_clocks
,
412 .num_clks
= ARRAY_SIZE(sm8150_rpmh_clocks
),
415 static struct clk_hw
*sc7180_rpmh_clocks
[] = {
416 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
417 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
418 [RPMH_LN_BB_CLK2
] = &sdm845_ln_bb_clk2
.hw
,
419 [RPMH_LN_BB_CLK2_A
] = &sdm845_ln_bb_clk2_ao
.hw
,
420 [RPMH_LN_BB_CLK3
] = &sdm845_ln_bb_clk3
.hw
,
421 [RPMH_LN_BB_CLK3_A
] = &sdm845_ln_bb_clk3_ao
.hw
,
422 [RPMH_RF_CLK1
] = &sdm845_rf_clk1
.hw
,
423 [RPMH_RF_CLK1_A
] = &sdm845_rf_clk1_ao
.hw
,
424 [RPMH_RF_CLK2
] = &sdm845_rf_clk2
.hw
,
425 [RPMH_RF_CLK2_A
] = &sdm845_rf_clk2_ao
.hw
,
426 [RPMH_IPA_CLK
] = &sdm845_ipa
.hw
,
429 static const struct clk_rpmh_desc clk_rpmh_sc7180
= {
430 .clks
= sc7180_rpmh_clocks
,
431 .num_clks
= ARRAY_SIZE(sc7180_rpmh_clocks
),
434 DEFINE_CLK_RPMH_VRM(sm8250
, ln_bb_clk1
, ln_bb_clk1_ao
, "lnbclka1", 2);
436 static struct clk_hw
*sm8250_rpmh_clocks
[] = {
437 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
438 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
439 [RPMH_LN_BB_CLK1
] = &sm8250_ln_bb_clk1
.hw
,
440 [RPMH_LN_BB_CLK1_A
] = &sm8250_ln_bb_clk1_ao
.hw
,
441 [RPMH_LN_BB_CLK2
] = &sdm845_ln_bb_clk2
.hw
,
442 [RPMH_LN_BB_CLK2_A
] = &sdm845_ln_bb_clk2_ao
.hw
,
443 [RPMH_LN_BB_CLK3
] = &sdm845_ln_bb_clk3
.hw
,
444 [RPMH_LN_BB_CLK3_A
] = &sdm845_ln_bb_clk3_ao
.hw
,
445 [RPMH_RF_CLK1
] = &sdm845_rf_clk1
.hw
,
446 [RPMH_RF_CLK1_A
] = &sdm845_rf_clk1_ao
.hw
,
447 [RPMH_RF_CLK3
] = &sdm845_rf_clk3
.hw
,
448 [RPMH_RF_CLK3_A
] = &sdm845_rf_clk3_ao
.hw
,
451 static const struct clk_rpmh_desc clk_rpmh_sm8250
= {
452 .clks
= sm8250_rpmh_clocks
,
453 .num_clks
= ARRAY_SIZE(sm8250_rpmh_clocks
),
456 DEFINE_CLK_RPMH_VRM(sm8350
, div_clk1
, div_clk1_ao
, "divclka1", 2);
457 DEFINE_CLK_RPMH_VRM(sm8350
, rf_clk4
, rf_clk4_ao
, "rfclka4", 1);
458 DEFINE_CLK_RPMH_VRM(sm8350
, rf_clk5
, rf_clk5_ao
, "rfclka5", 1);
459 DEFINE_CLK_RPMH_BCM(sm8350
, pka
, "PKA0");
460 DEFINE_CLK_RPMH_BCM(sm8350
, hwkm
, "HK0");
462 static struct clk_hw
*sm8350_rpmh_clocks
[] = {
463 [RPMH_CXO_CLK
] = &sdm845_bi_tcxo
.hw
,
464 [RPMH_CXO_CLK_A
] = &sdm845_bi_tcxo_ao
.hw
,
465 [RPMH_DIV_CLK1
] = &sm8350_div_clk1
.hw
,
466 [RPMH_DIV_CLK1_A
] = &sm8350_div_clk1_ao
.hw
,
467 [RPMH_LN_BB_CLK1
] = &sm8250_ln_bb_clk1
.hw
,
468 [RPMH_LN_BB_CLK1_A
] = &sm8250_ln_bb_clk1_ao
.hw
,
469 [RPMH_LN_BB_CLK2
] = &sdm845_ln_bb_clk2
.hw
,
470 [RPMH_LN_BB_CLK2_A
] = &sdm845_ln_bb_clk2_ao
.hw
,
471 [RPMH_RF_CLK1
] = &sdm845_rf_clk1
.hw
,
472 [RPMH_RF_CLK1_A
] = &sdm845_rf_clk1_ao
.hw
,
473 [RPMH_RF_CLK3
] = &sdm845_rf_clk3
.hw
,
474 [RPMH_RF_CLK3_A
] = &sdm845_rf_clk3_ao
.hw
,
475 [RPMH_RF_CLK4
] = &sm8350_rf_clk4
.hw
,
476 [RPMH_RF_CLK4_A
] = &sm8350_rf_clk4_ao
.hw
,
477 [RPMH_RF_CLK5
] = &sm8350_rf_clk5
.hw
,
478 [RPMH_RF_CLK5_A
] = &sm8350_rf_clk5_ao
.hw
,
479 [RPMH_IPA_CLK
] = &sdm845_ipa
.hw
,
480 [RPMH_PKA_CLK
] = &sm8350_pka
.hw
,
481 [RPMH_HWKM_CLK
] = &sm8350_hwkm
.hw
,
484 static const struct clk_rpmh_desc clk_rpmh_sm8350
= {
485 .clks
= sm8350_rpmh_clocks
,
486 .num_clks
= ARRAY_SIZE(sm8350_rpmh_clocks
),
489 static struct clk_hw
*of_clk_rpmh_hw_get(struct of_phandle_args
*clkspec
,
492 struct clk_rpmh_desc
*rpmh
= data
;
493 unsigned int idx
= clkspec
->args
[0];
495 if (idx
>= rpmh
->num_clks
) {
496 pr_err("%s: invalid index %u\n", __func__
, idx
);
497 return ERR_PTR(-EINVAL
);
500 return rpmh
->clks
[idx
];
503 static int clk_rpmh_probe(struct platform_device
*pdev
)
505 struct clk_hw
**hw_clks
;
506 struct clk_rpmh
*rpmh_clk
;
507 const struct clk_rpmh_desc
*desc
;
510 desc
= of_device_get_match_data(&pdev
->dev
);
514 hw_clks
= desc
->clks
;
516 for (i
= 0; i
< desc
->num_clks
; i
++) {
520 const struct bcm_db
*data
;
525 name
= hw_clks
[i
]->init
->name
;
527 rpmh_clk
= to_clk_rpmh(hw_clks
[i
]);
528 res_addr
= cmd_db_read_addr(rpmh_clk
->res_name
);
530 dev_err(&pdev
->dev
, "missing RPMh resource address for %s\n",
535 data
= cmd_db_read_aux_data(rpmh_clk
->res_name
, &aux_data_len
);
539 "error reading RPMh aux data for %s (%d)\n",
540 rpmh_clk
->res_name
, ret
);
544 /* Convert unit from Khz to Hz */
545 if (aux_data_len
== sizeof(*data
))
546 rpmh_clk
->unit
= le32_to_cpu(data
->unit
) * 1000ULL;
548 rpmh_clk
->res_addr
+= res_addr
;
549 rpmh_clk
->dev
= &pdev
->dev
;
551 ret
= devm_clk_hw_register(&pdev
->dev
, hw_clks
[i
]);
553 dev_err(&pdev
->dev
, "failed to register %s\n", name
);
558 /* typecast to silence compiler warning */
559 ret
= devm_of_clk_add_hw_provider(&pdev
->dev
, of_clk_rpmh_hw_get
,
562 dev_err(&pdev
->dev
, "Failed to add clock provider\n");
566 dev_dbg(&pdev
->dev
, "Registered RPMh clocks\n");
571 static const struct of_device_id clk_rpmh_match_table
[] = {
572 { .compatible
= "qcom,sc7180-rpmh-clk", .data
= &clk_rpmh_sc7180
},
573 { .compatible
= "qcom,sdm845-rpmh-clk", .data
= &clk_rpmh_sdm845
},
574 { .compatible
= "qcom,sdx55-rpmh-clk", .data
= &clk_rpmh_sdx55
},
575 { .compatible
= "qcom,sm8150-rpmh-clk", .data
= &clk_rpmh_sm8150
},
576 { .compatible
= "qcom,sm8250-rpmh-clk", .data
= &clk_rpmh_sm8250
},
577 { .compatible
= "qcom,sm8350-rpmh-clk", .data
= &clk_rpmh_sm8350
},
580 MODULE_DEVICE_TABLE(of
, clk_rpmh_match_table
);
582 static struct platform_driver clk_rpmh_driver
= {
583 .probe
= clk_rpmh_probe
,
586 .of_match_table
= clk_rpmh_match_table
,
590 static int __init
clk_rpmh_init(void)
592 return platform_driver_register(&clk_rpmh_driver
);
594 core_initcall(clk_rpmh_init
);
596 static void __exit
clk_rpmh_exit(void)
598 platform_driver_unregister(&clk_rpmh_driver
);
600 module_exit(clk_rpmh_exit
);
602 MODULE_DESCRIPTION("QCOM RPMh Clock Driver");
603 MODULE_LICENSE("GPL v2");