forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/clk/rockchip/clk.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (c) 2014 MundoReader S.L.
34 * Author: Heiko Stuebner <heiko@sntech.de>
....@@ -11,21 +12,12 @@
1112 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
1213 * Copyright (c) 2013 Linaro Ltd.
1314 * Author: Thomas Abraham <thomas.ab@samsung.com>
14
- *
15
- * This program is free software; you can redistribute it and/or modify
16
- * it under the terms of the GNU General Public License as published by
17
- * the Free Software Foundation; either version 2 of the License, or
18
- * (at your option) any later version.
19
- *
20
- * This program is distributed in the hope that it will be useful,
21
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
- * GNU General Public License for more details.
2415 */
2516
2617 #include <linux/slab.h>
2718 #include <linux/clk.h>
2819 #include <linux/clk-provider.h>
20
+#include <linux/io.h>
2921 #include <linux/mfd/syscon.h>
3022 #include <linux/regmap.h>
3123 #include <linux/reboot.h>
....@@ -52,7 +44,7 @@
5244 u8 gate_shift, u8 gate_flags, unsigned long flags,
5345 spinlock_t *lock)
5446 {
55
- struct clk *clk;
47
+ struct clk_hw *hw;
5648 struct clk_mux *mux = NULL;
5749 struct clk_gate *gate = NULL;
5850 struct clk_divider *div = NULL;
....@@ -110,20 +102,18 @@
110102 : &clk_divider_ops;
111103 }
112104
113
- clk = clk_register_composite(NULL, name, parent_names, num_parents,
114
- mux ? &mux->hw : NULL, mux_ops,
115
- div ? &div->hw : NULL, div_ops,
116
- gate ? &gate->hw : NULL, gate_ops,
117
- flags);
118
-
119
- if (IS_ERR(clk)) {
120
- ret = PTR_ERR(clk);
121
- goto err_composite;
105
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
106
+ mux ? &mux->hw : NULL, mux_ops,
107
+ div ? &div->hw : NULL, div_ops,
108
+ gate ? &gate->hw : NULL, gate_ops,
109
+ flags);
110
+ if (IS_ERR(hw)) {
111
+ kfree(div);
112
+ kfree(gate);
113
+ return ERR_CAST(hw);
122114 }
123115
124
- return clk;
125
-err_composite:
126
- kfree(div);
116
+ return hw->clk;
127117 err_div:
128118 kfree(gate);
129119 err_gate:
....@@ -194,22 +184,15 @@
194184 unsigned long p_rate, p_parent_rate;
195185 struct clk_hw *p_parent;
196186 unsigned long scale;
197
- u32 div;
198187
199188 p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
200
- if (((rate * 20 > p_rate) && (p_rate % rate != 0)) ||
201
- (fd->max_prate && fd->max_prate < p_rate)) {
189
+ if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
202190 p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
203191 if (!p_parent) {
204192 *parent_rate = p_rate;
205193 } else {
206194 p_parent_rate = clk_hw_get_rate(p_parent);
207195 *parent_rate = p_parent_rate;
208
- if (fd->max_prate && p_parent_rate > fd->max_prate) {
209
- div = DIV_ROUND_UP(p_parent_rate,
210
- fd->max_prate);
211
- *parent_rate = p_parent_rate / div;
212
- }
213196 }
214197
215198 if (*parent_rate < rate * 20) {
....@@ -253,10 +236,10 @@
253236 void __iomem *base, int muxdiv_offset, u8 div_flags,
254237 int gate_offset, u8 gate_shift, u8 gate_flags,
255238 unsigned long flags, struct rockchip_clk_branch *child,
256
- unsigned long max_prate, spinlock_t *lock)
239
+ spinlock_t *lock)
257240 {
241
+ struct clk_hw *hw;
258242 struct rockchip_clk_frac *frac;
259
- struct clk *clk;
260243 struct clk_gate *gate = NULL;
261244 struct clk_fractional_divider *div = NULL;
262245 const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
....@@ -294,22 +277,21 @@
294277 div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
295278 div->lock = lock;
296279 div->approximation = rockchip_fractional_approximation;
297
- div->max_prate = max_prate;
298280 div_ops = &clk_fractional_divider_ops;
299281
300
- clk = clk_register_composite(NULL, name, parent_names, num_parents,
301
- NULL, NULL,
302
- &div->hw, div_ops,
303
- gate ? &gate->hw : NULL, gate_ops,
304
- flags | CLK_SET_RATE_UNGATE);
305
- if (IS_ERR(clk)) {
282
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
283
+ NULL, NULL,
284
+ &div->hw, div_ops,
285
+ gate ? &gate->hw : NULL, gate_ops,
286
+ flags | CLK_SET_RATE_UNGATE);
287
+ if (IS_ERR(hw)) {
306288 kfree(frac);
307
- return clk;
289
+ return ERR_CAST(hw);
308290 }
309291
310292 if (child) {
311293 struct clk_mux *frac_mux = &frac->mux;
312
- struct clk_init_data init = {};
294
+ struct clk_init_data init;
313295 struct clk *mux_clk;
314296 int ret;
315297
....@@ -336,7 +318,7 @@
336318 mux_clk = clk_register(NULL, &frac_mux->hw);
337319 if (IS_ERR(mux_clk)) {
338320 kfree(frac);
339
- return clk;
321
+ return mux_clk;
340322 }
341323
342324 rockchip_clk_add_lookup(ctx, mux_clk, child->id);
....@@ -345,7 +327,7 @@
345327 if (frac->mux_frac_idx >= 0) {
346328 pr_debug("%s: found fractional parent in mux at pos %d\n",
347329 __func__, frac->mux_frac_idx);
348
- ret = clk_notifier_register(clk, &frac->clk_nb);
330
+ ret = clk_notifier_register(hw->clk, &frac->clk_nb);
349331 if (ret)
350332 pr_err("%s: failed to register clock notifier for %s\n",
351333 __func__, name);
....@@ -355,7 +337,7 @@
355337 }
356338 }
357339
358
- return clk;
340
+ return hw->clk;
359341 }
360342
361343 static struct clk *rockchip_clk_register_factor_branch(const char *name,
....@@ -364,7 +346,7 @@
364346 int gate_offset, u8 gate_shift, u8 gate_flags,
365347 unsigned long flags, spinlock_t *lock)
366348 {
367
- struct clk *clk;
349
+ struct clk_hw *hw;
368350 struct clk_gate *gate = NULL;
369351 struct clk_fixed_factor *fix = NULL;
370352
....@@ -393,75 +375,22 @@
393375 fix->mult = mult;
394376 fix->div = div;
395377
396
- clk = clk_register_composite(NULL, name, parent_names, num_parents,
397
- NULL, NULL,
398
- &fix->hw, &clk_fixed_factor_ops,
399
- &gate->hw, &clk_gate_ops, flags);
400
- if (IS_ERR(clk)) {
378
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
379
+ NULL, NULL,
380
+ &fix->hw, &clk_fixed_factor_ops,
381
+ &gate->hw, &clk_gate_ops, flags);
382
+ if (IS_ERR(hw)) {
401383 kfree(fix);
402384 kfree(gate);
385
+ return ERR_CAST(hw);
403386 }
404387
405
- return clk;
388
+ return hw->clk;
406389 }
407390
408
-static struct clk *rockchip_clk_register_composite_brother_branch(
409
- struct rockchip_clk_provider *ctx, const char *name,
410
- const char *const *parent_names, u8 num_parents,
411
- void __iomem *base, int muxdiv_offset, u8 mux_shift,
412
- u8 mux_width, u8 mux_flags, u32 *mux_table,
413
- int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
414
- struct clk_div_table *div_table, int gate_offset,
415
- u8 gate_shift, u8 gate_flags, unsigned long flags,
416
- struct rockchip_clk_branch *brother, spinlock_t *lock)
417
-{
418
- struct clk *clk, *brother_clk;
419
- struct clk_composite *composite, *brother_composite;
420
- struct clk_hw *hw, *brother_hw;
421
-
422
- if (brother && brother->branch_type != branch_half_divider) {
423
- pr_err("%s: composite brother for %s can only be a halfdiv\n",
424
- __func__, name);
425
- return ERR_PTR(-EINVAL);
426
- }
427
-
428
- clk = rockchip_clk_register_branch(name, parent_names, num_parents,
429
- base, muxdiv_offset, mux_shift,
430
- mux_width, mux_flags, mux_table,
431
- div_offset, div_shift, div_width,
432
- div_flags, div_table,
433
- gate_offset, gate_shift, gate_flags,
434
- flags, lock);
435
- if (IS_ERR(clk))
436
- return clk;
437
-
438
- brother_clk = rockchip_clk_register_halfdiv(brother->name,
439
- brother->parent_names, brother->num_parents,
440
- base, brother->muxdiv_offset,
441
- brother->mux_shift, brother->mux_width,
442
- brother->mux_flags, brother->div_offset,
443
- brother->div_shift, brother->div_width,
444
- brother->div_flags, brother->gate_offset,
445
- brother->gate_shift, brother->gate_flags,
446
- flags, lock);
447
- if (IS_ERR(brother_clk))
448
- return brother_clk;
449
- rockchip_clk_add_lookup(ctx, brother_clk, brother->id);
450
-
451
- hw = __clk_get_hw(clk);
452
- brother_hw = __clk_get_hw(brother_clk);
453
- if (hw && brother_hw) {
454
- composite = to_clk_composite(hw);
455
- brother_composite = to_clk_composite(brother_hw);
456
- composite->brother_hw = brother_hw;
457
- brother_composite->brother_hw = hw;
458
- }
459
-
460
- return clk;
461
-}
462
-
463
-struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
464
- void __iomem *base, unsigned long nr_clks)
391
+struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
392
+ void __iomem *base,
393
+ unsigned long nr_clks)
465394 {
466395 struct rockchip_clk_provider *ctx;
467396 struct clk **clk_table;
....@@ -495,14 +424,16 @@
495424 kfree(ctx);
496425 return ERR_PTR(-ENOMEM);
497426 }
427
+EXPORT_SYMBOL_GPL(rockchip_clk_init);
498428
499
-void __init rockchip_clk_of_add_provider(struct device_node *np,
500
- struct rockchip_clk_provider *ctx)
429
+void rockchip_clk_of_add_provider(struct device_node *np,
430
+ struct rockchip_clk_provider *ctx)
501431 {
502432 if (of_clk_add_provider(np, of_clk_src_onecell_get,
503433 &ctx->clk_data))
504434 pr_err("%s: could not register clk provider\n", __func__);
505435 }
436
+EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider);
506437
507438 void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
508439 struct clk *clk, unsigned int id)
....@@ -510,8 +441,9 @@
510441 if (ctx->clk_data.clks && id)
511442 ctx->clk_data.clks[id] = clk;
512443 }
444
+EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup);
513445
514
-void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
446
+void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
515447 struct rockchip_pll_clock *list,
516448 unsigned int nr_pll, int grf_lock_offset)
517449 {
....@@ -534,11 +466,11 @@
534466 rockchip_clk_add_lookup(ctx, clk, list->id);
535467 }
536468 }
469
+EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
537470
538
-void __init rockchip_clk_register_branches(
539
- struct rockchip_clk_provider *ctx,
540
- struct rockchip_clk_branch *list,
541
- unsigned int nr_clk)
471
+void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
472
+ struct rockchip_clk_branch *list,
473
+ unsigned int nr_clk)
542474 {
543475 struct clk *clk = NULL;
544476 unsigned int idx;
....@@ -604,7 +536,7 @@
604536 list->div_flags,
605537 list->gate_offset, list->gate_shift,
606538 list->gate_flags, flags, list->child,
607
- list->max_prate, &ctx->lock);
539
+ &ctx->lock);
608540 break;
609541 case branch_half_divider:
610542 clk = rockchip_clk_register_halfdiv(list->name,
....@@ -618,8 +550,15 @@
618550 flags, &ctx->lock);
619551 break;
620552 case branch_gate:
621
- if (!(list->gate_flags & CLK_GATE_NO_SET_RATE))
622
- flags |= CLK_SET_RATE_PARENT;
553
+ flags |= CLK_SET_RATE_PARENT;
554
+
555
+ clk = clk_register_gate(NULL, list->name,
556
+ list->parent_names[0], flags,
557
+ ctx->reg_base + list->gate_offset,
558
+ list->gate_shift, list->gate_flags, &ctx->lock);
559
+ break;
560
+ case branch_gate_no_set_rate:
561
+ flags &= ~CLK_SET_RATE_PARENT;
623562
624563 clk = clk_register_gate(NULL, list->name,
625564 list->parent_names[0], flags,
....@@ -637,19 +576,6 @@
637576 list->div_flags, list->div_table,
638577 list->gate_offset, list->gate_shift,
639578 list->gate_flags, flags, &ctx->lock);
640
- break;
641
- case branch_composite_brother:
642
- clk = rockchip_clk_register_composite_brother_branch(
643
- ctx, list->name, list->parent_names,
644
- list->num_parents, ctx->reg_base,
645
- list->muxdiv_offset, list->mux_shift,
646
- list->mux_width, list->mux_flags,
647
- list->mux_table, list->div_offset,
648
- list->div_shift, list->div_width,
649
- list->div_flags, list->div_table,
650
- list->gate_offset, list->gate_shift,
651
- list->gate_flags, flags, list->child,
652
- &ctx->lock);
653579 break;
654580 case branch_mmc:
655581 clk = rockchip_clk_register_mmc(
....@@ -685,18 +611,6 @@
685611 list->div_width, list->div_flags,
686612 ctx->reg_base);
687613 break;
688
- case branch_dclk_divider:
689
-#ifdef CONFIG_ROCKCHIP_DCLK_DIV
690
- clk = rockchip_clk_register_dclk_branch(list->name,
691
- list->parent_names, list->num_parents,
692
- ctx->reg_base, list->muxdiv_offset, list->mux_shift,
693
- list->mux_width, list->mux_flags,
694
- list->div_offset, list->div_shift, list->div_width,
695
- list->div_flags, list->div_table,
696
- list->gate_offset, list->gate_shift,
697
- list->gate_flags, flags, list->max_prate, &ctx->lock);
698
-#endif
699
- break;
700614 }
701615
702616 /* none of the cases above matched */
....@@ -715,18 +629,21 @@
715629 rockchip_clk_add_lookup(ctx, clk, list->id);
716630 }
717631 }
632
+EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
718633
719
-void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
720
- unsigned int lookup_id,
721
- const char *name, const char *const *parent_names,
722
- u8 num_parents,
723
- const struct rockchip_cpuclk_reg_data *reg_data,
724
- const struct rockchip_cpuclk_rate_table *rates,
725
- int nrates)
634
+void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
635
+ unsigned int lookup_id,
636
+ const char *name,
637
+ u8 num_parents,
638
+ struct clk *parent, struct clk *alt_parent,
639
+ const struct rockchip_cpuclk_reg_data *reg_data,
640
+ const struct rockchip_cpuclk_rate_table *rates,
641
+ int nrates)
726642 {
727643 struct clk *clk;
728644
729
- clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
645
+ clk = rockchip_clk_register_cpuclk(name, num_parents,
646
+ parent, alt_parent,
730647 reg_data, rates, nrates,
731648 ctx->reg_base, &ctx->lock);
732649 if (IS_ERR(clk)) {
....@@ -737,20 +654,31 @@
737654
738655 rockchip_clk_add_lookup(ctx, clk, lookup_id);
739656 }
657
+EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk);
740658
741
-void __init rockchip_clk_protect_critical(const char *const clocks[],
742
- int nclocks)
659
+void rockchip_clk_register_armclk_v2(struct rockchip_clk_provider *ctx,
660
+ struct rockchip_clk_branch *list,
661
+ const struct rockchip_cpuclk_rate_table *rates,
662
+ int nrates)
743663 {
744
- int i;
664
+ struct clk *clk;
745665
746
- /* Protect the clocks that needs to stay on */
747
- for (i = 0; i < nclocks; i++) {
748
- struct clk *clk = __clk_lookup(clocks[i]);
749
-
750
- if (clk)
751
- clk_prepare_enable(clk);
666
+ clk = rockchip_clk_register_cpuclk_v2(list->name, list->parent_names,
667
+ list->num_parents, ctx->reg_base,
668
+ list->muxdiv_offset, list->mux_shift,
669
+ list->mux_width, list->mux_flags,
670
+ list->div_offset, list->div_shift,
671
+ list->div_width, list->div_flags,
672
+ list->flags, &ctx->lock, rates, nrates);
673
+ if (IS_ERR(clk)) {
674
+ pr_err("%s: failed to register clock %s: %ld\n",
675
+ __func__, list->name, PTR_ERR(clk));
676
+ return;
752677 }
678
+
679
+ rockchip_clk_add_lookup(ctx, clk, list->id);
753680 }
681
+EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk_v2);
754682
755683 void (*rk_dump_cru)(void);
756684 EXPORT_SYMBOL(rk_dump_cru);
....@@ -785,10 +713,10 @@
785713 .priority = 128,
786714 };
787715
788
-void __init
716
+void
789717 rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
790
- unsigned int reg,
791
- void (*cb)(void))
718
+ unsigned int reg,
719
+ void (*cb)(void))
792720 {
793721 int ret;
794722
....@@ -802,3 +730,57 @@
802730 atomic_notifier_chain_register(&panic_notifier_list,
803731 &rk_clk_panic_block);
804732 }
733
+EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier);
734
+
735
+#ifdef MODULE
736
+static struct clk **protect_clocks;
737
+static unsigned int protect_nclocks;
738
+
739
+int rockchip_clk_protect(struct rockchip_clk_provider *ctx,
740
+ unsigned int *clocks, unsigned int nclocks)
741
+{
742
+ struct clk *clk = NULL;
743
+ int i = 0;
744
+
745
+ if (protect_clocks || !ctx || !clocks || !ctx->clk_data.clks)
746
+ return 0;
747
+
748
+ protect_clocks = kcalloc(nclocks, sizeof(void *), GFP_KERNEL);
749
+ if (!protect_clocks)
750
+ return -ENOMEM;
751
+
752
+ for (i = 0; i < nclocks; i++) {
753
+ if (clocks[i] >= ctx->clk_data.clk_num) {
754
+ pr_err("%s: invalid clock id %u\n", __func__, clocks[i]);
755
+ continue;
756
+ }
757
+ clk = ctx->clk_data.clks[clocks[i]];
758
+ if (clk) {
759
+ clk_prepare_enable(clk);
760
+ protect_clocks[i] = clk;
761
+ }
762
+ }
763
+ protect_nclocks = nclocks;
764
+
765
+ return 0;
766
+}
767
+EXPORT_SYMBOL_GPL(rockchip_clk_protect);
768
+
769
+void rockchip_clk_unprotect(void)
770
+{
771
+ int i = 0;
772
+
773
+ if (!protect_clocks || !protect_nclocks)
774
+ return;
775
+
776
+ for (i = 0; i < protect_nclocks; i++) {
777
+ if (protect_clocks[i])
778
+ clk_disable_unprepare(protect_clocks[i]);
779
+ }
780
+ protect_nclocks = 0;
781
+ kfree(protect_clocks);
782
+ protect_clocks = NULL;
783
+
784
+}
785
+EXPORT_SYMBOL_GPL(rockchip_clk_unprotect);
786
+#endif /* MODULE */