diff options
author | Xing Zheng <zhengxing@rock-chips.com> | 2016-03-08 21:37:04 -0500 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2016-03-27 07:03:34 -0400 |
commit | ef1d9feeccc094f59b72bb11fe14ec886eb574d3 (patch) | |
tree | aa1b6e1c3588d53459f206e92e4ad2fb4629f28c | |
parent | 268aebaa2410152bf91ea1ede6b284ff8138822d (diff) |
clk: rockchip: Add support for multiple clock providers
There are need to support Multi-CRUs probability in future, but
it is not supported on the current Rockchip Clock Framework.
Therefore, this patch add support a provider as the parameter
handler when we call the clock register functions for per CRU.
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 30 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3036.c | 17 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3188.c | 44 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3228.c | 17 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3288.c | 19 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3368.c | 21 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.c | 148 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.h | 51 |
8 files changed, 229 insertions, 118 deletions
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 5de797e34d54..27be66a2a358 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -46,6 +46,8 @@ struct rockchip_clk_pll { | |||
46 | const struct rockchip_pll_rate_table *rate_table; | 46 | const struct rockchip_pll_rate_table *rate_table; |
47 | unsigned int rate_count; | 47 | unsigned int rate_count; |
48 | spinlock_t *lock; | 48 | spinlock_t *lock; |
49 | |||
50 | struct rockchip_clk_provider *ctx; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) | 53 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) |
@@ -90,7 +92,7 @@ static long rockchip_pll_round_rate(struct clk_hw *hw, | |||
90 | */ | 92 | */ |
91 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) | 93 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) |
92 | { | 94 | { |
93 | struct regmap *grf = rockchip_clk_get_grf(); | 95 | struct regmap *grf = rockchip_clk_get_grf(pll->ctx); |
94 | unsigned int val; | 96 | unsigned int val; |
95 | int delay = 24000000, ret; | 97 | int delay = 24000000, ret; |
96 | 98 | ||
@@ -251,7 +253,7 @@ static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
251 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | 253 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
252 | const struct rockchip_pll_rate_table *rate; | 254 | const struct rockchip_pll_rate_table *rate; |
253 | unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate); | 255 | unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate); |
254 | struct regmap *grf = rockchip_clk_get_grf(); | 256 | struct regmap *grf = rockchip_clk_get_grf(pll->ctx); |
255 | 257 | ||
256 | if (IS_ERR(grf)) { | 258 | if (IS_ERR(grf)) { |
257 | pr_debug("%s: grf regmap not available, aborting rate change\n", | 259 | pr_debug("%s: grf regmap not available, aborting rate change\n", |
@@ -490,7 +492,7 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
490 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | 492 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
491 | const struct rockchip_pll_rate_table *rate; | 493 | const struct rockchip_pll_rate_table *rate; |
492 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); | 494 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); |
493 | struct regmap *grf = rockchip_clk_get_grf(); | 495 | struct regmap *grf = rockchip_clk_get_grf(pll->ctx); |
494 | 496 | ||
495 | if (IS_ERR(grf)) { | 497 | if (IS_ERR(grf)) { |
496 | pr_debug("%s: grf regmap not available, aborting rate change\n", | 498 | pr_debug("%s: grf regmap not available, aborting rate change\n", |
@@ -563,7 +565,7 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw) | |||
563 | rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); | 565 | rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); |
564 | if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf | 566 | if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf |
565 | || rate->nb != cur.nb) { | 567 | || rate->nb != cur.nb) { |
566 | struct regmap *grf = rockchip_clk_get_grf(); | 568 | struct regmap *grf = rockchip_clk_get_grf(pll->ctx); |
567 | 569 | ||
568 | if (IS_ERR(grf)) | 570 | if (IS_ERR(grf)) |
569 | return; | 571 | return; |
@@ -595,12 +597,13 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { | |||
595 | * Common registering of pll clocks | 597 | * Common registering of pll clocks |
596 | */ | 598 | */ |
597 | 599 | ||
598 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | 600 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
601 | enum rockchip_pll_type pll_type, | ||
599 | const char *name, const char *const *parent_names, | 602 | const char *name, const char *const *parent_names, |
600 | u8 num_parents, void __iomem *base, int con_offset, | 603 | u8 num_parents, int con_offset, int grf_lock_offset, |
601 | int grf_lock_offset, int lock_shift, int mode_offset, | 604 | int lock_shift, int mode_offset, int mode_shift, |
602 | int mode_shift, struct rockchip_pll_rate_table *rate_table, | 605 | struct rockchip_pll_rate_table *rate_table, |
603 | u8 clk_pll_flags, spinlock_t *lock) | 606 | u8 clk_pll_flags) |
604 | { | 607 | { |
605 | const char *pll_parents[3]; | 608 | const char *pll_parents[3]; |
606 | struct clk_init_data init; | 609 | struct clk_init_data init; |
@@ -624,11 +627,11 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
624 | /* create the mux on top of the real pll */ | 627 | /* create the mux on top of the real pll */ |
625 | pll->pll_mux_ops = &clk_mux_ops; | 628 | pll->pll_mux_ops = &clk_mux_ops; |
626 | pll_mux = &pll->pll_mux; | 629 | pll_mux = &pll->pll_mux; |
627 | pll_mux->reg = base + mode_offset; | 630 | pll_mux->reg = ctx->reg_base + mode_offset; |
628 | pll_mux->shift = mode_shift; | 631 | pll_mux->shift = mode_shift; |
629 | pll_mux->mask = PLL_MODE_MASK; | 632 | pll_mux->mask = PLL_MODE_MASK; |
630 | pll_mux->flags = 0; | 633 | pll_mux->flags = 0; |
631 | pll_mux->lock = lock; | 634 | pll_mux->lock = &ctx->lock; |
632 | pll_mux->hw.init = &init; | 635 | pll_mux->hw.init = &init; |
633 | 636 | ||
634 | if (pll_type == pll_rk3036 || pll_type == pll_rk3066) | 637 | if (pll_type == pll_rk3036 || pll_type == pll_rk3066) |
@@ -695,11 +698,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
695 | 698 | ||
696 | pll->hw.init = &init; | 699 | pll->hw.init = &init; |
697 | pll->type = pll_type; | 700 | pll->type = pll_type; |
698 | pll->reg_base = base + con_offset; | 701 | pll->reg_base = ctx->reg_base + con_offset; |
699 | pll->lock_offset = grf_lock_offset; | 702 | pll->lock_offset = grf_lock_offset; |
700 | pll->lock_shift = lock_shift; | 703 | pll->lock_shift = lock_shift; |
701 | pll->flags = clk_pll_flags; | 704 | pll->flags = clk_pll_flags; |
702 | pll->lock = lock; | 705 | pll->lock = &ctx->lock; |
706 | pll->ctx = ctx; | ||
703 | 707 | ||
704 | pll_clk = clk_register(NULL, &pll->hw); | 708 | pll_clk = clk_register(NULL, &pll->hw); |
705 | if (IS_ERR(pll_clk)) { | 709 | if (IS_ERR(pll_clk)) { |
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index f9cbba0eac36..c7c8260e1c66 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c | |||
@@ -440,6 +440,7 @@ static const char *const rk3036_critical_clocks[] __initconst = { | |||
440 | 440 | ||
441 | static void __init rk3036_clk_init(struct device_node *np) | 441 | static void __init rk3036_clk_init(struct device_node *np) |
442 | { | 442 | { |
443 | struct rockchip_clk_provider *ctx; | ||
443 | void __iomem *reg_base; | 444 | void __iomem *reg_base; |
444 | struct clk *clk; | 445 | struct clk *clk; |
445 | 446 | ||
@@ -449,22 +450,26 @@ static void __init rk3036_clk_init(struct device_node *np) | |||
449 | return; | 450 | return; |
450 | } | 451 | } |
451 | 452 | ||
452 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 453 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
454 | if (IS_ERR(ctx)) { | ||
455 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
456 | return; | ||
457 | } | ||
453 | 458 | ||
454 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); | 459 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); |
455 | if (IS_ERR(clk)) | 460 | if (IS_ERR(clk)) |
456 | pr_warn("%s: could not register clock usb480m: %ld\n", | 461 | pr_warn("%s: could not register clock usb480m: %ld\n", |
457 | __func__, PTR_ERR(clk)); | 462 | __func__, PTR_ERR(clk)); |
458 | 463 | ||
459 | rockchip_clk_register_plls(rk3036_pll_clks, | 464 | rockchip_clk_register_plls(ctx, rk3036_pll_clks, |
460 | ARRAY_SIZE(rk3036_pll_clks), | 465 | ARRAY_SIZE(rk3036_pll_clks), |
461 | RK3036_GRF_SOC_STATUS0); | 466 | RK3036_GRF_SOC_STATUS0); |
462 | rockchip_clk_register_branches(rk3036_clk_branches, | 467 | rockchip_clk_register_branches(ctx, rk3036_clk_branches, |
463 | ARRAY_SIZE(rk3036_clk_branches)); | 468 | ARRAY_SIZE(rk3036_clk_branches)); |
464 | rockchip_clk_protect_critical(rk3036_critical_clocks, | 469 | rockchip_clk_protect_critical(rk3036_critical_clocks, |
465 | ARRAY_SIZE(rk3036_critical_clocks)); | 470 | ARRAY_SIZE(rk3036_critical_clocks)); |
466 | 471 | ||
467 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 472 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
468 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 473 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
469 | &rk3036_cpuclk_data, rk3036_cpuclk_rates, | 474 | &rk3036_cpuclk_data, rk3036_cpuclk_rates, |
470 | ARRAY_SIZE(rk3036_cpuclk_rates)); | 475 | ARRAY_SIZE(rk3036_cpuclk_rates)); |
@@ -472,6 +477,8 @@ static void __init rk3036_clk_init(struct device_node *np) | |||
472 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 477 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
473 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 478 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
474 | 479 | ||
475 | rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); | 480 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
481 | |||
482 | rockchip_clk_of_add_provider(np, ctx); | ||
476 | } | 483 | } |
477 | CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); | 484 | CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c index e832403a0f9f..0fcce2295b37 100644 --- a/drivers/clk/rockchip/clk-rk3188.c +++ b/drivers/clk/rockchip/clk-rk3188.c | |||
@@ -759,57 +759,74 @@ static const char *const rk3188_critical_clocks[] __initconst = { | |||
759 | "hclk_cpubus" | 759 | "hclk_cpubus" |
760 | }; | 760 | }; |
761 | 761 | ||
762 | static void __init rk3188_common_clk_init(struct device_node *np) | 762 | static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np) |
763 | { | 763 | { |
764 | struct rockchip_clk_provider *ctx; | ||
764 | void __iomem *reg_base; | 765 | void __iomem *reg_base; |
765 | 766 | ||
766 | reg_base = of_iomap(np, 0); | 767 | reg_base = of_iomap(np, 0); |
767 | if (!reg_base) { | 768 | if (!reg_base) { |
768 | pr_err("%s: could not map cru region\n", __func__); | 769 | pr_err("%s: could not map cru region\n", __func__); |
769 | return; | 770 | return ERR_PTR(-ENOMEM); |
770 | } | 771 | } |
771 | 772 | ||
772 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 773 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
774 | if (IS_ERR(ctx)) { | ||
775 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
776 | return ERR_PTR(-ENOMEM); | ||
777 | } | ||
773 | 778 | ||
774 | rockchip_clk_register_branches(common_clk_branches, | 779 | rockchip_clk_register_branches(ctx, common_clk_branches, |
775 | ARRAY_SIZE(common_clk_branches)); | 780 | ARRAY_SIZE(common_clk_branches)); |
776 | 781 | ||
777 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 782 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
778 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 783 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
779 | 784 | ||
780 | rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL); | 785 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
786 | |||
787 | return ctx; | ||
781 | } | 788 | } |
782 | 789 | ||
783 | static void __init rk3066a_clk_init(struct device_node *np) | 790 | static void __init rk3066a_clk_init(struct device_node *np) |
784 | { | 791 | { |
785 | rk3188_common_clk_init(np); | 792 | struct rockchip_clk_provider *ctx; |
786 | rockchip_clk_register_plls(rk3066_pll_clks, | 793 | |
794 | ctx = rk3188_common_clk_init(np); | ||
795 | if (IS_ERR(ctx)) | ||
796 | return; | ||
797 | |||
798 | rockchip_clk_register_plls(ctx, rk3066_pll_clks, | ||
787 | ARRAY_SIZE(rk3066_pll_clks), | 799 | ARRAY_SIZE(rk3066_pll_clks), |
788 | RK3066_GRF_SOC_STATUS); | 800 | RK3066_GRF_SOC_STATUS); |
789 | rockchip_clk_register_branches(rk3066a_clk_branches, | 801 | rockchip_clk_register_branches(ctx, rk3066a_clk_branches, |
790 | ARRAY_SIZE(rk3066a_clk_branches)); | 802 | ARRAY_SIZE(rk3066a_clk_branches)); |
791 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 803 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
792 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 804 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
793 | &rk3066_cpuclk_data, rk3066_cpuclk_rates, | 805 | &rk3066_cpuclk_data, rk3066_cpuclk_rates, |
794 | ARRAY_SIZE(rk3066_cpuclk_rates)); | 806 | ARRAY_SIZE(rk3066_cpuclk_rates)); |
795 | rockchip_clk_protect_critical(rk3188_critical_clocks, | 807 | rockchip_clk_protect_critical(rk3188_critical_clocks, |
796 | ARRAY_SIZE(rk3188_critical_clocks)); | 808 | ARRAY_SIZE(rk3188_critical_clocks)); |
809 | rockchip_clk_of_add_provider(np, ctx); | ||
797 | } | 810 | } |
798 | CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); | 811 | CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); |
799 | 812 | ||
800 | static void __init rk3188a_clk_init(struct device_node *np) | 813 | static void __init rk3188a_clk_init(struct device_node *np) |
801 | { | 814 | { |
815 | struct rockchip_clk_provider *ctx; | ||
802 | struct clk *clk1, *clk2; | 816 | struct clk *clk1, *clk2; |
803 | unsigned long rate; | 817 | unsigned long rate; |
804 | int ret; | 818 | int ret; |
805 | 819 | ||
806 | rk3188_common_clk_init(np); | 820 | ctx = rk3188_common_clk_init(np); |
807 | rockchip_clk_register_plls(rk3188_pll_clks, | 821 | if (IS_ERR(ctx)) |
822 | return; | ||
823 | |||
824 | rockchip_clk_register_plls(ctx, rk3188_pll_clks, | ||
808 | ARRAY_SIZE(rk3188_pll_clks), | 825 | ARRAY_SIZE(rk3188_pll_clks), |
809 | RK3188_GRF_SOC_STATUS); | 826 | RK3188_GRF_SOC_STATUS); |
810 | rockchip_clk_register_branches(rk3188_clk_branches, | 827 | rockchip_clk_register_branches(ctx, rk3188_clk_branches, |
811 | ARRAY_SIZE(rk3188_clk_branches)); | 828 | ARRAY_SIZE(rk3188_clk_branches)); |
812 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 829 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
813 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 830 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
814 | &rk3188_cpuclk_data, rk3188_cpuclk_rates, | 831 | &rk3188_cpuclk_data, rk3188_cpuclk_rates, |
815 | ARRAY_SIZE(rk3188_cpuclk_rates)); | 832 | ARRAY_SIZE(rk3188_cpuclk_rates)); |
@@ -833,6 +850,7 @@ static void __init rk3188a_clk_init(struct device_node *np) | |||
833 | 850 | ||
834 | rockchip_clk_protect_critical(rk3188_critical_clocks, | 851 | rockchip_clk_protect_critical(rk3188_critical_clocks, |
835 | ARRAY_SIZE(rk3188_critical_clocks)); | 852 | ARRAY_SIZE(rk3188_critical_clocks)); |
853 | rockchip_clk_of_add_provider(np, ctx); | ||
836 | } | 854 | } |
837 | CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); | 855 | CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); |
838 | 856 | ||
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c index 4b4137e85125..c112b2f95224 100644 --- a/drivers/clk/rockchip/clk-rk3228.c +++ b/drivers/clk/rockchip/clk-rk3228.c | |||
@@ -628,6 +628,7 @@ static const char *const rk3228_critical_clocks[] __initconst = { | |||
628 | 628 | ||
629 | static void __init rk3228_clk_init(struct device_node *np) | 629 | static void __init rk3228_clk_init(struct device_node *np) |
630 | { | 630 | { |
631 | struct rockchip_clk_provider *ctx; | ||
631 | void __iomem *reg_base; | 632 | void __iomem *reg_base; |
632 | 633 | ||
633 | reg_base = of_iomap(np, 0); | 634 | reg_base = of_iomap(np, 0); |
@@ -636,17 +637,21 @@ static void __init rk3228_clk_init(struct device_node *np) | |||
636 | return; | 637 | return; |
637 | } | 638 | } |
638 | 639 | ||
639 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 640 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
641 | if (IS_ERR(ctx)) { | ||
642 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
643 | return; | ||
644 | } | ||
640 | 645 | ||
641 | rockchip_clk_register_plls(rk3228_pll_clks, | 646 | rockchip_clk_register_plls(ctx, rk3228_pll_clks, |
642 | ARRAY_SIZE(rk3228_pll_clks), | 647 | ARRAY_SIZE(rk3228_pll_clks), |
643 | RK3228_GRF_SOC_STATUS0); | 648 | RK3228_GRF_SOC_STATUS0); |
644 | rockchip_clk_register_branches(rk3228_clk_branches, | 649 | rockchip_clk_register_branches(ctx, rk3228_clk_branches, |
645 | ARRAY_SIZE(rk3228_clk_branches)); | 650 | ARRAY_SIZE(rk3228_clk_branches)); |
646 | rockchip_clk_protect_critical(rk3228_critical_clocks, | 651 | rockchip_clk_protect_critical(rk3228_critical_clocks, |
647 | ARRAY_SIZE(rk3228_critical_clocks)); | 652 | ARRAY_SIZE(rk3228_critical_clocks)); |
648 | 653 | ||
649 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 654 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
650 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 655 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
651 | &rk3228_cpuclk_data, rk3228_cpuclk_rates, | 656 | &rk3228_cpuclk_data, rk3228_cpuclk_rates, |
652 | ARRAY_SIZE(rk3228_cpuclk_rates)); | 657 | ARRAY_SIZE(rk3228_cpuclk_rates)); |
@@ -654,6 +659,8 @@ static void __init rk3228_clk_init(struct device_node *np) | |||
654 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | 659 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), |
655 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 660 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
656 | 661 | ||
657 | rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL); | 662 | rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL); |
663 | |||
664 | rockchip_clk_of_add_provider(np, ctx); | ||
658 | } | 665 | } |
659 | CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); | 666 | CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 00faf3f9b179..d1031d1149ce 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c | |||
@@ -881,6 +881,7 @@ static struct syscore_ops rk3288_clk_syscore_ops = { | |||
881 | 881 | ||
882 | static void __init rk3288_clk_init(struct device_node *np) | 882 | static void __init rk3288_clk_init(struct device_node *np) |
883 | { | 883 | { |
884 | struct rockchip_clk_provider *ctx; | ||
884 | struct clk *clk; | 885 | struct clk *clk; |
885 | 886 | ||
886 | rk3288_cru_base = of_iomap(np, 0); | 887 | rk3288_cru_base = of_iomap(np, 0); |
@@ -889,7 +890,11 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
889 | return; | 890 | return; |
890 | } | 891 | } |
891 | 892 | ||
892 | rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); | 893 | ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS); |
894 | if (IS_ERR(ctx)) { | ||
895 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
896 | return; | ||
897 | } | ||
893 | 898 | ||
894 | /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ | 899 | /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */ |
895 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); | 900 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); |
@@ -897,17 +902,17 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
897 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", | 902 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", |
898 | __func__, PTR_ERR(clk)); | 903 | __func__, PTR_ERR(clk)); |
899 | else | 904 | else |
900 | rockchip_clk_add_lookup(clk, PCLK_WDT); | 905 | rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); |
901 | 906 | ||
902 | rockchip_clk_register_plls(rk3288_pll_clks, | 907 | rockchip_clk_register_plls(ctx, rk3288_pll_clks, |
903 | ARRAY_SIZE(rk3288_pll_clks), | 908 | ARRAY_SIZE(rk3288_pll_clks), |
904 | RK3288_GRF_SOC_STATUS1); | 909 | RK3288_GRF_SOC_STATUS1); |
905 | rockchip_clk_register_branches(rk3288_clk_branches, | 910 | rockchip_clk_register_branches(ctx, rk3288_clk_branches, |
906 | ARRAY_SIZE(rk3288_clk_branches)); | 911 | ARRAY_SIZE(rk3288_clk_branches)); |
907 | rockchip_clk_protect_critical(rk3288_critical_clocks, | 912 | rockchip_clk_protect_critical(rk3288_critical_clocks, |
908 | ARRAY_SIZE(rk3288_critical_clocks)); | 913 | ARRAY_SIZE(rk3288_critical_clocks)); |
909 | 914 | ||
910 | rockchip_clk_register_armclk(ARMCLK, "armclk", | 915 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
911 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), | 916 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
912 | &rk3288_cpuclk_data, rk3288_cpuclk_rates, | 917 | &rk3288_cpuclk_data, rk3288_cpuclk_rates, |
913 | ARRAY_SIZE(rk3288_cpuclk_rates)); | 918 | ARRAY_SIZE(rk3288_cpuclk_rates)); |
@@ -916,8 +921,10 @@ static void __init rk3288_clk_init(struct device_node *np) | |||
916 | rk3288_cru_base + RK3288_SOFTRST_CON(0), | 921 | rk3288_cru_base + RK3288_SOFTRST_CON(0), |
917 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 922 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
918 | 923 | ||
919 | rockchip_register_restart_notifier(RK3288_GLB_SRST_FST, | 924 | rockchip_register_restart_notifier(ctx, RK3288_GLB_SRST_FST, |
920 | rk3288_clk_shutdown); | 925 | rk3288_clk_shutdown); |
921 | register_syscore_ops(&rk3288_clk_syscore_ops); | 926 | register_syscore_ops(&rk3288_clk_syscore_ops); |
927 | |||
928 | rockchip_clk_of_add_provider(np, ctx); | ||
922 | } | 929 | } |
923 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); | 930 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); |
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index c26ff4a36dcd..3121414cfd63 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c | |||
@@ -862,6 +862,7 @@ static const char *const rk3368_critical_clocks[] __initconst = { | |||
862 | 862 | ||
863 | static void __init rk3368_clk_init(struct device_node *np) | 863 | static void __init rk3368_clk_init(struct device_node *np) |
864 | { | 864 | { |
865 | struct rockchip_clk_provider *ctx; | ||
865 | void __iomem *reg_base; | 866 | void __iomem *reg_base; |
866 | struct clk *clk; | 867 | struct clk *clk; |
867 | 868 | ||
@@ -871,7 +872,11 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
871 | return; | 872 | return; |
872 | } | 873 | } |
873 | 874 | ||
874 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | 875 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
876 | if (IS_ERR(ctx)) { | ||
877 | pr_err("%s: rockchip clk init failed\n", __func__); | ||
878 | return; | ||
879 | } | ||
875 | 880 | ||
876 | /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ | 881 | /* Watchdog pclk is controlled by sgrf_soc_con3[7]. */ |
877 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); | 882 | clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1); |
@@ -879,22 +884,22 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
879 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", | 884 | pr_warn("%s: could not register clock pclk_wdt: %ld\n", |
880 | __func__, PTR_ERR(clk)); | 885 | __func__, PTR_ERR(clk)); |
881 | else | 886 | else |
882 | rockchip_clk_add_lookup(clk, PCLK_WDT); | 887 | rockchip_clk_add_lookup(ctx, clk, PCLK_WDT); |
883 | 888 | ||
884 | rockchip_clk_register_plls(rk3368_pll_clks, | 889 | rockchip_clk_register_plls(ctx, rk3368_pll_clks, |
885 | ARRAY_SIZE(rk3368_pll_clks), | 890 | ARRAY_SIZE(rk3368_pll_clks), |
886 | RK3368_GRF_SOC_STATUS0); | 891 | RK3368_GRF_SOC_STATUS0); |
887 | rockchip_clk_register_branches(rk3368_clk_branches, | 892 | rockchip_clk_register_branches(ctx, rk3368_clk_branches, |
888 | ARRAY_SIZE(rk3368_clk_branches)); | 893 | ARRAY_SIZE(rk3368_clk_branches)); |
889 | rockchip_clk_protect_critical(rk3368_critical_clocks, | 894 | rockchip_clk_protect_critical(rk3368_critical_clocks, |
890 | ARRAY_SIZE(rk3368_critical_clocks)); | 895 | ARRAY_SIZE(rk3368_critical_clocks)); |
891 | 896 | ||
892 | rockchip_clk_register_armclk(ARMCLKB, "armclkb", | 897 | rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb", |
893 | mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), | 898 | mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p), |
894 | &rk3368_cpuclkb_data, rk3368_cpuclkb_rates, | 899 | &rk3368_cpuclkb_data, rk3368_cpuclkb_rates, |
895 | ARRAY_SIZE(rk3368_cpuclkb_rates)); | 900 | ARRAY_SIZE(rk3368_cpuclkb_rates)); |
896 | 901 | ||
897 | rockchip_clk_register_armclk(ARMCLKL, "armclkl", | 902 | rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl", |
898 | mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), | 903 | mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p), |
899 | &rk3368_cpuclkl_data, rk3368_cpuclkl_rates, | 904 | &rk3368_cpuclkl_data, rk3368_cpuclkl_rates, |
900 | ARRAY_SIZE(rk3368_cpuclkl_rates)); | 905 | ARRAY_SIZE(rk3368_cpuclkl_rates)); |
@@ -902,6 +907,8 @@ static void __init rk3368_clk_init(struct device_node *np) | |||
902 | rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), | 907 | rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0), |
903 | ROCKCHIP_SOFTRST_HIWORD_MASK); | 908 | ROCKCHIP_SOFTRST_HIWORD_MASK); |
904 | 909 | ||
905 | rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL); | 910 | rockchip_register_restart_notifier(ctx, RK3368_GLB_SRST_FST, NULL); |
911 | |||
912 | rockchip_clk_of_add_provider(np, ctx); | ||
906 | } | 913 | } |
907 | CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); | 914 | CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init); |
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index ec06350c78c4..5618a8761dee 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c | |||
@@ -2,6 +2,9 @@ | |||
2 | * Copyright (c) 2014 MundoReader S.L. | 2 | * Copyright (c) 2014 MundoReader S.L. |
3 | * Author: Heiko Stuebner <heiko@sntech.de> | 3 | * Author: Heiko Stuebner <heiko@sntech.de> |
4 | * | 4 | * |
5 | * Copyright (c) 2016 Rockchip Electronics Co. Ltd. | ||
6 | * Author: Xing Zheng <zhengxing@rock-chips.com> | ||
7 | * | ||
5 | * based on | 8 | * based on |
6 | * | 9 | * |
7 | * samsung/clk.c | 10 | * samsung/clk.c |
@@ -157,7 +160,8 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, | |||
157 | return notifier_from_errno(ret); | 160 | return notifier_from_errno(ret); |
158 | } | 161 | } |
159 | 162 | ||
160 | static struct clk *rockchip_clk_register_frac_branch(const char *name, | 163 | static struct clk *rockchip_clk_register_frac_branch( |
164 | struct rockchip_clk_provider *ctx, const char *name, | ||
161 | const char *const *parent_names, u8 num_parents, | 165 | const char *const *parent_names, u8 num_parents, |
162 | void __iomem *base, int muxdiv_offset, u8 div_flags, | 166 | void __iomem *base, int muxdiv_offset, u8 div_flags, |
163 | int gate_offset, u8 gate_shift, u8 gate_flags, | 167 | int gate_offset, u8 gate_shift, u8 gate_flags, |
@@ -250,7 +254,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name, | |||
250 | if (IS_ERR(mux_clk)) | 254 | if (IS_ERR(mux_clk)) |
251 | return clk; | 255 | return clk; |
252 | 256 | ||
253 | rockchip_clk_add_lookup(mux_clk, child->id); | 257 | rockchip_clk_add_lookup(ctx, mux_clk, child->id); |
254 | 258 | ||
255 | /* notifier on the fraction divider to catch rate changes */ | 259 | /* notifier on the fraction divider to catch rate changes */ |
256 | if (frac->mux_frac_idx >= 0) { | 260 | if (frac->mux_frac_idx >= 0) { |
@@ -314,66 +318,94 @@ static struct clk *rockchip_clk_register_factor_branch(const char *name, | |||
314 | return clk; | 318 | return clk; |
315 | } | 319 | } |
316 | 320 | ||
317 | static DEFINE_SPINLOCK(clk_lock); | 321 | struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, |
318 | static struct clk **clk_table; | 322 | void __iomem *base, unsigned long nr_clks) |
319 | static void __iomem *reg_base; | ||
320 | static struct clk_onecell_data clk_data; | ||
321 | static struct device_node *cru_node; | ||
322 | static struct regmap *grf; | ||
323 | |||
324 | void __init rockchip_clk_init(struct device_node *np, void __iomem *base, | ||
325 | unsigned long nr_clks) | ||
326 | { | 323 | { |
327 | reg_base = base; | 324 | struct rockchip_clk_provider *ctx; |
328 | cru_node = np; | 325 | struct clk **clk_table; |
329 | grf = ERR_PTR(-EPROBE_DEFER); | 326 | int i; |
327 | |||
328 | ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL); | ||
329 | if (!ctx) { | ||
330 | pr_err("%s: Could not allocate clock provider context\n", | ||
331 | __func__); | ||
332 | return ERR_PTR(-ENOMEM); | ||
333 | } | ||
330 | 334 | ||
331 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); | 335 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); |
332 | if (!clk_table) | 336 | if (!clk_table) { |
333 | pr_err("%s: could not allocate clock lookup table\n", __func__); | 337 | pr_err("%s: Could not allocate clock lookup table\n", |
338 | __func__); | ||
339 | goto err_free; | ||
340 | } | ||
341 | |||
342 | for (i = 0; i < nr_clks; ++i) | ||
343 | clk_table[i] = ERR_PTR(-ENOENT); | ||
334 | 344 | ||
335 | clk_data.clks = clk_table; | 345 | ctx->reg_base = base; |
336 | clk_data.clk_num = nr_clks; | 346 | ctx->clk_data.clks = clk_table; |
337 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 347 | ctx->clk_data.clk_num = nr_clks; |
348 | ctx->cru_node = np; | ||
349 | ctx->grf = ERR_PTR(-EPROBE_DEFER); | ||
350 | spin_lock_init(&ctx->lock); | ||
351 | |||
352 | return ctx; | ||
353 | |||
354 | err_free: | ||
355 | kfree(ctx); | ||
356 | return ERR_PTR(-ENOMEM); | ||
357 | } | ||
358 | |||
359 | void __init rockchip_clk_of_add_provider(struct device_node *np, | ||
360 | struct rockchip_clk_provider *ctx) | ||
361 | { | ||
362 | if (np) { | ||
363 | if (of_clk_add_provider(np, of_clk_src_onecell_get, | ||
364 | &ctx->clk_data)) | ||
365 | pr_err("%s: could not register clk provider\n", __func__); | ||
366 | } | ||
338 | } | 367 | } |
339 | 368 | ||
340 | struct regmap *rockchip_clk_get_grf(void) | 369 | struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx) |
341 | { | 370 | { |
342 | if (IS_ERR(grf)) | 371 | if (IS_ERR(ctx->grf)) |
343 | grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf"); | 372 | ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node, "rockchip,grf"); |
344 | return grf; | 373 | return ctx->grf; |
345 | } | 374 | } |
346 | 375 | ||
347 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) | 376 | void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, |
377 | struct clk *clk, unsigned int id) | ||
348 | { | 378 | { |
349 | if (clk_table && id) | 379 | if (ctx->clk_data.clks && id) |
350 | clk_table[id] = clk; | 380 | ctx->clk_data.clks[id] = clk; |
351 | } | 381 | } |
352 | 382 | ||
353 | void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, | 383 | void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, |
384 | struct rockchip_pll_clock *list, | ||
354 | unsigned int nr_pll, int grf_lock_offset) | 385 | unsigned int nr_pll, int grf_lock_offset) |
355 | { | 386 | { |
356 | struct clk *clk; | 387 | struct clk *clk; |
357 | int idx; | 388 | int idx; |
358 | 389 | ||
359 | for (idx = 0; idx < nr_pll; idx++, list++) { | 390 | for (idx = 0; idx < nr_pll; idx++, list++) { |
360 | clk = rockchip_clk_register_pll(list->type, list->name, | 391 | clk = rockchip_clk_register_pll(ctx, list->type, list->name, |
361 | list->parent_names, list->num_parents, | 392 | list->parent_names, list->num_parents, |
362 | reg_base, list->con_offset, grf_lock_offset, | 393 | list->con_offset, grf_lock_offset, |
363 | list->lock_shift, list->mode_offset, | 394 | list->lock_shift, list->mode_offset, |
364 | list->mode_shift, list->rate_table, | 395 | list->mode_shift, list->rate_table, |
365 | list->pll_flags, &clk_lock); | 396 | list->pll_flags); |
366 | if (IS_ERR(clk)) { | 397 | if (IS_ERR(clk)) { |
367 | pr_err("%s: failed to register clock %s\n", __func__, | 398 | pr_err("%s: failed to register clock %s\n", __func__, |
368 | list->name); | 399 | list->name); |
369 | continue; | 400 | continue; |
370 | } | 401 | } |
371 | 402 | ||
372 | rockchip_clk_add_lookup(clk, list->id); | 403 | rockchip_clk_add_lookup(ctx, clk, list->id); |
373 | } | 404 | } |
374 | } | 405 | } |
375 | 406 | ||
376 | void __init rockchip_clk_register_branches( | 407 | void __init rockchip_clk_register_branches( |
408 | struct rockchip_clk_provider *ctx, | ||
377 | struct rockchip_clk_branch *list, | 409 | struct rockchip_clk_branch *list, |
378 | unsigned int nr_clk) | 410 | unsigned int nr_clk) |
379 | { | 411 | { |
@@ -389,56 +421,56 @@ void __init rockchip_clk_register_branches( | |||
389 | case branch_mux: | 421 | case branch_mux: |
390 | clk = clk_register_mux(NULL, list->name, | 422 | clk = clk_register_mux(NULL, list->name, |
391 | list->parent_names, list->num_parents, | 423 | list->parent_names, list->num_parents, |
392 | flags, reg_base + list->muxdiv_offset, | 424 | flags, ctx->reg_base + list->muxdiv_offset, |
393 | list->mux_shift, list->mux_width, | 425 | list->mux_shift, list->mux_width, |
394 | list->mux_flags, &clk_lock); | 426 | list->mux_flags, &ctx->lock); |
395 | break; | 427 | break; |
396 | case branch_divider: | 428 | case branch_divider: |
397 | if (list->div_table) | 429 | if (list->div_table) |
398 | clk = clk_register_divider_table(NULL, | 430 | clk = clk_register_divider_table(NULL, |
399 | list->name, list->parent_names[0], | 431 | list->name, list->parent_names[0], |
400 | flags, reg_base + list->muxdiv_offset, | 432 | flags, ctx->reg_base + list->muxdiv_offset, |
401 | list->div_shift, list->div_width, | 433 | list->div_shift, list->div_width, |
402 | list->div_flags, list->div_table, | 434 | list->div_flags, list->div_table, |
403 | &clk_lock); | 435 | &ctx->lock); |
404 | else | 436 | else |
405 | clk = clk_register_divider(NULL, list->name, | 437 | clk = clk_register_divider(NULL, list->name, |
406 | list->parent_names[0], flags, | 438 | list->parent_names[0], flags, |
407 | reg_base + list->muxdiv_offset, | 439 | ctx->reg_base + list->muxdiv_offset, |
408 | list->div_shift, list->div_width, | 440 | list->div_shift, list->div_width, |
409 | list->div_flags, &clk_lock); | 441 | list->div_flags, &ctx->lock); |
410 | break; | 442 | break; |
411 | case branch_fraction_divider: | 443 | case branch_fraction_divider: |
412 | clk = rockchip_clk_register_frac_branch(list->name, | 444 | clk = rockchip_clk_register_frac_branch(ctx, list->name, |
413 | list->parent_names, list->num_parents, | 445 | list->parent_names, list->num_parents, |
414 | reg_base, list->muxdiv_offset, list->div_flags, | 446 | ctx->reg_base, list->muxdiv_offset, list->div_flags, |
415 | list->gate_offset, list->gate_shift, | 447 | list->gate_offset, list->gate_shift, |
416 | list->gate_flags, flags, list->child, | 448 | list->gate_flags, flags, list->child, |
417 | &clk_lock); | 449 | &ctx->lock); |
418 | break; | 450 | break; |
419 | case branch_gate: | 451 | case branch_gate: |
420 | flags |= CLK_SET_RATE_PARENT; | 452 | flags |= CLK_SET_RATE_PARENT; |
421 | 453 | ||
422 | clk = clk_register_gate(NULL, list->name, | 454 | clk = clk_register_gate(NULL, list->name, |
423 | list->parent_names[0], flags, | 455 | list->parent_names[0], flags, |
424 | reg_base + list->gate_offset, | 456 | ctx->reg_base + list->gate_offset, |
425 | list->gate_shift, list->gate_flags, &clk_lock); | 457 | list->gate_shift, list->gate_flags, &ctx->lock); |
426 | break; | 458 | break; |
427 | case branch_composite: | 459 | case branch_composite: |
428 | clk = rockchip_clk_register_branch(list->name, | 460 | clk = rockchip_clk_register_branch(list->name, |
429 | list->parent_names, list->num_parents, | 461 | list->parent_names, list->num_parents, |
430 | reg_base, list->muxdiv_offset, list->mux_shift, | 462 | ctx->reg_base, list->muxdiv_offset, list->mux_shift, |
431 | list->mux_width, list->mux_flags, | 463 | list->mux_width, list->mux_flags, |
432 | list->div_shift, list->div_width, | 464 | list->div_shift, list->div_width, |
433 | list->div_flags, list->div_table, | 465 | list->div_flags, list->div_table, |
434 | list->gate_offset, list->gate_shift, | 466 | list->gate_offset, list->gate_shift, |
435 | list->gate_flags, flags, &clk_lock); | 467 | list->gate_flags, flags, &ctx->lock); |
436 | break; | 468 | break; |
437 | case branch_mmc: | 469 | case branch_mmc: |
438 | clk = rockchip_clk_register_mmc( | 470 | clk = rockchip_clk_register_mmc( |
439 | list->name, | 471 | list->name, |
440 | list->parent_names, list->num_parents, | 472 | list->parent_names, list->num_parents, |
441 | reg_base + list->muxdiv_offset, | 473 | ctx->reg_base + list->muxdiv_offset, |
442 | list->div_shift | 474 | list->div_shift |
443 | ); | 475 | ); |
444 | break; | 476 | break; |
@@ -446,16 +478,16 @@ void __init rockchip_clk_register_branches( | |||
446 | clk = rockchip_clk_register_inverter( | 478 | clk = rockchip_clk_register_inverter( |
447 | list->name, list->parent_names, | 479 | list->name, list->parent_names, |
448 | list->num_parents, | 480 | list->num_parents, |
449 | reg_base + list->muxdiv_offset, | 481 | ctx->reg_base + list->muxdiv_offset, |
450 | list->div_shift, list->div_flags, &clk_lock); | 482 | list->div_shift, list->div_flags, &ctx->lock); |
451 | break; | 483 | break; |
452 | case branch_factor: | 484 | case branch_factor: |
453 | clk = rockchip_clk_register_factor_branch( | 485 | clk = rockchip_clk_register_factor_branch( |
454 | list->name, list->parent_names, | 486 | list->name, list->parent_names, |
455 | list->num_parents, reg_base, | 487 | list->num_parents, ctx->reg_base, |
456 | list->div_shift, list->div_width, | 488 | list->div_shift, list->div_width, |
457 | list->gate_offset, list->gate_shift, | 489 | list->gate_offset, list->gate_shift, |
458 | list->gate_flags, flags, &clk_lock); | 490 | list->gate_flags, flags, &ctx->lock); |
459 | break; | 491 | break; |
460 | } | 492 | } |
461 | 493 | ||
@@ -472,11 +504,12 @@ void __init rockchip_clk_register_branches( | |||
472 | continue; | 504 | continue; |
473 | } | 505 | } |
474 | 506 | ||
475 | rockchip_clk_add_lookup(clk, list->id); | 507 | rockchip_clk_add_lookup(ctx, clk, list->id); |
476 | } | 508 | } |
477 | } | 509 | } |
478 | 510 | ||
479 | void __init rockchip_clk_register_armclk(unsigned int lookup_id, | 511 | void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, |
512 | unsigned int lookup_id, | ||
480 | const char *name, const char *const *parent_names, | 513 | const char *name, const char *const *parent_names, |
481 | u8 num_parents, | 514 | u8 num_parents, |
482 | const struct rockchip_cpuclk_reg_data *reg_data, | 515 | const struct rockchip_cpuclk_reg_data *reg_data, |
@@ -486,15 +519,15 @@ void __init rockchip_clk_register_armclk(unsigned int lookup_id, | |||
486 | struct clk *clk; | 519 | struct clk *clk; |
487 | 520 | ||
488 | clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, | 521 | clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents, |
489 | reg_data, rates, nrates, reg_base, | 522 | reg_data, rates, nrates, ctx->reg_base, |
490 | &clk_lock); | 523 | &ctx->lock); |
491 | if (IS_ERR(clk)) { | 524 | if (IS_ERR(clk)) { |
492 | pr_err("%s: failed to register clock %s: %ld\n", | 525 | pr_err("%s: failed to register clock %s: %ld\n", |
493 | __func__, name, PTR_ERR(clk)); | 526 | __func__, name, PTR_ERR(clk)); |
494 | return; | 527 | return; |
495 | } | 528 | } |
496 | 529 | ||
497 | rockchip_clk_add_lookup(clk, lookup_id); | 530 | rockchip_clk_add_lookup(ctx, clk, lookup_id); |
498 | } | 531 | } |
499 | 532 | ||
500 | void __init rockchip_clk_protect_critical(const char *const clocks[], | 533 | void __init rockchip_clk_protect_critical(const char *const clocks[], |
@@ -511,6 +544,7 @@ void __init rockchip_clk_protect_critical(const char *const clocks[], | |||
511 | } | 544 | } |
512 | } | 545 | } |
513 | 546 | ||
547 | static void __iomem *rst_base; | ||
514 | static unsigned int reg_restart; | 548 | static unsigned int reg_restart; |
515 | static void (*cb_restart)(void); | 549 | static void (*cb_restart)(void); |
516 | static int rockchip_restart_notify(struct notifier_block *this, | 550 | static int rockchip_restart_notify(struct notifier_block *this, |
@@ -519,7 +553,7 @@ static int rockchip_restart_notify(struct notifier_block *this, | |||
519 | if (cb_restart) | 553 | if (cb_restart) |
520 | cb_restart(); | 554 | cb_restart(); |
521 | 555 | ||
522 | writel(0xfdb9, reg_base + reg_restart); | 556 | writel(0xfdb9, rst_base + reg_restart); |
523 | return NOTIFY_DONE; | 557 | return NOTIFY_DONE; |
524 | } | 558 | } |
525 | 559 | ||
@@ -528,10 +562,12 @@ static struct notifier_block rockchip_restart_handler = { | |||
528 | .priority = 128, | 562 | .priority = 128, |
529 | }; | 563 | }; |
530 | 564 | ||
531 | void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)) | 565 | void __init rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, |
566 | unsigned int reg, void (*cb)(void)) | ||
532 | { | 567 | { |
533 | int ret; | 568 | int ret; |
534 | 569 | ||
570 | rst_base = ctx->reg_base; | ||
535 | reg_restart = reg; | 571 | reg_restart = reg; |
536 | cb_restart = cb; | 572 | cb_restart = cb; |
537 | ret = register_restart_handler(&rockchip_restart_handler); | 573 | ret = register_restart_handler(&rockchip_restart_handler); |
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 4133bfc8f827..e243d509da89 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define CLK_ROCKCHIP_CLK_H | 27 | #define CLK_ROCKCHIP_CLK_H |
28 | 28 | ||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/clk-provider.h> | ||
30 | 31 | ||
31 | struct clk; | 32 | struct clk; |
32 | 33 | ||
@@ -127,6 +128,22 @@ enum rockchip_pll_type { | |||
127 | .nb = _nb, \ | 128 | .nb = _nb, \ |
128 | } | 129 | } |
129 | 130 | ||
131 | /** | ||
132 | * struct rockchip_clk_provider: information about clock provider | ||
133 | * @reg_base: virtual address for the register base. | ||
134 | * @clk_data: holds clock related data like clk* and number of clocks. | ||
135 | * @cru_node: device-node of the clock-provider | ||
136 | * @grf: regmap of the general-register-files syscon | ||
137 | * @lock: maintains exclusion between callbacks for a given clock-provider. | ||
138 | */ | ||
139 | struct rockchip_clk_provider { | ||
140 | void __iomem *reg_base; | ||
141 | struct clk_onecell_data clk_data; | ||
142 | struct device_node *cru_node; | ||
143 | struct regmap *grf; | ||
144 | spinlock_t lock; | ||
145 | }; | ||
146 | |||
130 | struct rockchip_pll_rate_table { | 147 | struct rockchip_pll_rate_table { |
131 | unsigned long rate; | 148 | unsigned long rate; |
132 | unsigned int nr; | 149 | unsigned int nr; |
@@ -194,12 +211,13 @@ struct rockchip_pll_clock { | |||
194 | .rate_table = _rtable, \ | 211 | .rate_table = _rtable, \ |
195 | } | 212 | } |
196 | 213 | ||
197 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | 214 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
215 | enum rockchip_pll_type pll_type, | ||
198 | const char *name, const char *const *parent_names, | 216 | const char *name, const char *const *parent_names, |
199 | u8 num_parents, void __iomem *base, int con_offset, | 217 | u8 num_parents, int con_offset, int grf_lock_offset, |
200 | int grf_lock_offset, int lock_shift, int reg_mode, | 218 | int lock_shift, int mode_offset, int mode_shift, |
201 | int mode_shift, struct rockchip_pll_rate_table *rate_table, | 219 | struct rockchip_pll_rate_table *rate_table, |
202 | u8 clk_pll_flags, spinlock_t *lock); | 220 | u8 clk_pll_flags); |
203 | 221 | ||
204 | struct rockchip_cpuclk_clksel { | 222 | struct rockchip_cpuclk_clksel { |
205 | int reg; | 223 | int reg; |
@@ -558,21 +576,28 @@ struct rockchip_clk_branch { | |||
558 | .gate_flags = gf, \ | 576 | .gate_flags = gf, \ |
559 | } | 577 | } |
560 | 578 | ||
561 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | 579 | struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, |
562 | unsigned long nr_clks); | 580 | void __iomem *base, unsigned long nr_clks); |
563 | struct regmap *rockchip_clk_get_grf(void); | 581 | void rockchip_clk_of_add_provider(struct device_node *np, |
564 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); | 582 | struct rockchip_clk_provider *ctx); |
565 | void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, | 583 | struct regmap *rockchip_clk_get_grf(struct rockchip_clk_provider *ctx); |
584 | void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, | ||
585 | struct clk *clk, unsigned int id); | ||
586 | void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, | ||
587 | struct rockchip_clk_branch *list, | ||
566 | unsigned int nr_clk); | 588 | unsigned int nr_clk); |
567 | void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, | 589 | void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, |
590 | struct rockchip_pll_clock *pll_list, | ||
568 | unsigned int nr_pll, int grf_lock_offset); | 591 | unsigned int nr_pll, int grf_lock_offset); |
569 | void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, | 592 | void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, |
593 | unsigned int lookup_id, const char *name, | ||
570 | const char *const *parent_names, u8 num_parents, | 594 | const char *const *parent_names, u8 num_parents, |
571 | const struct rockchip_cpuclk_reg_data *reg_data, | 595 | const struct rockchip_cpuclk_reg_data *reg_data, |
572 | const struct rockchip_cpuclk_rate_table *rates, | 596 | const struct rockchip_cpuclk_rate_table *rates, |
573 | int nrates); | 597 | int nrates); |
574 | void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); | 598 | void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); |
575 | void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)); | 599 | void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, |
600 | unsigned int reg, void (*cb)(void)); | ||
576 | 601 | ||
577 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) | 602 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) |
578 | 603 | ||