diff options
author | Alex Elder <elder@linaro.org> | 2014-04-21 17:11:41 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2014-04-30 14:51:35 -0400 |
commit | 03548ec06ad3ec75d5b212fa832e4e617334ea09 (patch) | |
tree | 3746d54ef058113437fea44065947de4aa05a47f /drivers/clk/bcm/clk-kona-setup.c | |
parent | b12151ca5cd76e5ed9c75ef02b2f5d2aa5b45808 (diff) |
clk: bcm281xx: define CCU clock data statically
Rather than "manually" setting up each CCU's clock entries at run
time, define a flexible array of generic Kona clock structures
within the CCU structure itself. Each of these entries contains
generic kona clock information (like its CCU pointer and clock
framework initialization data). Each also has a pointer to a
structure contianing clock type-dependent initialization data
(like register definitions).
Since we'll iterate over these arrays we need to be sure they have
slots for all potential clock index values. (E.g. for the root CCU
we must have at least BCM281XX_ROOT_CCU_CLOCK_COUNT slots.) To
ensure this we always define an extra entry and fill it using the
special initializer LAST_KONA_CLK.
Just about everything we need to know about a clock can be defined
statically. As a result, kona_clk_setup() can be changed to take
just a kona_clk structure as its argument, and peri_clk_setup() can
be simplified. With the information pre-defined we are also able
to handle most clock setup genericially. We can do away with the
CCU-specific callback functions that previously were needed to set
up the entries in CCU's clock array.
Move the definition of the ccu_data structure down in "clk-kona.h"
to avoid a forward dependency.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/bcm/clk-kona-setup.c')
-rw-r--r-- | drivers/clk/bcm/clk-kona-setup.c | 60 |
1 files changed, 25 insertions, 35 deletions
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index 4d1ca5372eff..825a2f2ab052 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c | |||
@@ -567,7 +567,6 @@ static void peri_clk_teardown(struct peri_clk_data *data, | |||
567 | struct clk_init_data *init_data) | 567 | struct clk_init_data *init_data) |
568 | { | 568 | { |
569 | clk_sel_teardown(&data->sel, init_data); | 569 | clk_sel_teardown(&data->sel, init_data); |
570 | init_data->ops = NULL; | ||
571 | } | 570 | } |
572 | 571 | ||
573 | /* | 572 | /* |
@@ -576,10 +575,9 @@ static void peri_clk_teardown(struct peri_clk_data *data, | |||
576 | * that can be assigned if the clock has one or more parent clocks | 575 | * that can be assigned if the clock has one or more parent clocks |
577 | * associated with it. | 576 | * associated with it. |
578 | */ | 577 | */ |
579 | static int peri_clk_setup(struct ccu_data *ccu, struct peri_clk_data *data, | 578 | static int |
580 | struct clk_init_data *init_data) | 579 | peri_clk_setup(struct peri_clk_data *data, struct clk_init_data *init_data) |
581 | { | 580 | { |
582 | init_data->ops = &kona_peri_clk_ops; | ||
583 | init_data->flags = CLK_IGNORE_UNUSED; | 581 | init_data->flags = CLK_IGNORE_UNUSED; |
584 | 582 | ||
585 | return clk_sel_setup(data->clocks, &data->sel, init_data); | 583 | return clk_sel_setup(data->clocks, &data->sel, init_data); |
@@ -617,39 +615,26 @@ static void kona_clk_teardown(struct clk *clk) | |||
617 | bcm_clk_teardown(bcm_clk); | 615 | bcm_clk_teardown(bcm_clk); |
618 | } | 616 | } |
619 | 617 | ||
620 | struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | 618 | struct clk *kona_clk_setup(struct kona_clk *bcm_clk) |
621 | enum bcm_clk_type type, void *data) | ||
622 | { | 619 | { |
623 | struct kona_clk *bcm_clk; | 620 | struct clk_init_data *init_data = &bcm_clk->init_data; |
624 | struct clk_init_data *init_data; | ||
625 | struct clk *clk = NULL; | 621 | struct clk *clk = NULL; |
626 | 622 | ||
627 | bcm_clk = kzalloc(sizeof(*bcm_clk), GFP_KERNEL); | 623 | switch (bcm_clk->type) { |
628 | if (!bcm_clk) { | ||
629 | pr_err("%s: failed to allocate bcm_clk for %s\n", __func__, | ||
630 | name); | ||
631 | return NULL; | ||
632 | } | ||
633 | bcm_clk->ccu = ccu; | ||
634 | bcm_clk->init_data.name = name; | ||
635 | |||
636 | init_data = &bcm_clk->init_data; | ||
637 | init_data->name = name; | ||
638 | switch (type) { | ||
639 | case bcm_clk_peri: | 624 | case bcm_clk_peri: |
640 | if (peri_clk_setup(ccu, data, init_data)) | 625 | if (peri_clk_setup(bcm_clk->u.data, init_data)) |
641 | goto out_free; | 626 | return NULL; |
642 | break; | 627 | break; |
643 | default: | 628 | default: |
644 | data = NULL; | 629 | pr_err("%s: clock type %d invalid for %s\n", __func__, |
645 | break; | 630 | (int)bcm_clk->type, init_data->name); |
631 | return NULL; | ||
646 | } | 632 | } |
647 | bcm_clk->type = type; | ||
648 | bcm_clk->u.data = data; | ||
649 | 633 | ||
650 | /* Make sure everything makes sense before we set it up */ | 634 | /* Make sure everything makes sense before we set it up */ |
651 | if (!kona_clk_valid(bcm_clk)) { | 635 | if (!kona_clk_valid(bcm_clk)) { |
652 | pr_err("%s: clock data invalid for %s\n", __func__, name); | 636 | pr_err("%s: clock data invalid for %s\n", __func__, |
637 | init_data->name); | ||
653 | goto out_teardown; | 638 | goto out_teardown; |
654 | } | 639 | } |
655 | 640 | ||
@@ -657,7 +642,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | |||
657 | clk = clk_register(NULL, &bcm_clk->hw); | 642 | clk = clk_register(NULL, &bcm_clk->hw); |
658 | if (IS_ERR(clk)) { | 643 | if (IS_ERR(clk)) { |
659 | pr_err("%s: error registering clock %s (%ld)\n", __func__, | 644 | pr_err("%s: error registering clock %s (%ld)\n", __func__, |
660 | name, PTR_ERR(clk)); | 645 | init_data->name, PTR_ERR(clk)); |
661 | goto out_teardown; | 646 | goto out_teardown; |
662 | } | 647 | } |
663 | BUG_ON(!clk); | 648 | BUG_ON(!clk); |
@@ -665,8 +650,6 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name, | |||
665 | return clk; | 650 | return clk; |
666 | out_teardown: | 651 | out_teardown: |
667 | bcm_clk_teardown(bcm_clk); | 652 | bcm_clk_teardown(bcm_clk); |
668 | out_free: | ||
669 | kfree(bcm_clk); | ||
670 | 653 | ||
671 | return NULL; | 654 | return NULL; |
672 | } | 655 | } |
@@ -701,11 +684,11 @@ static void kona_ccu_teardown(struct ccu_data *ccu) | |||
701 | * initialize the array of clocks provided by the CCU. | 684 | * initialize the array of clocks provided by the CCU. |
702 | */ | 685 | */ |
703 | void __init kona_dt_ccu_setup(struct ccu_data *ccu, | 686 | void __init kona_dt_ccu_setup(struct ccu_data *ccu, |
704 | struct device_node *node, | 687 | struct device_node *node) |
705 | int (*ccu_clks_setup)(struct ccu_data *)) | ||
706 | { | 688 | { |
707 | struct resource res = { 0 }; | 689 | struct resource res = { 0 }; |
708 | resource_size_t range; | 690 | resource_size_t range; |
691 | unsigned int i; | ||
709 | int ret; | 692 | int ret; |
710 | 693 | ||
711 | if (ccu->clk_data.clk_num) { | 694 | if (ccu->clk_data.clk_num) { |
@@ -744,9 +727,16 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu, | |||
744 | ccu->node = of_node_get(node); | 727 | ccu->node = of_node_get(node); |
745 | list_add_tail(&ccu->links, &ccu_list); | 728 | list_add_tail(&ccu->links, &ccu_list); |
746 | 729 | ||
747 | /* Set up clocks array (in ccu->clk_data) */ | 730 | /* |
748 | if (ccu_clks_setup(ccu)) | 731 | * Set up each defined kona clock and save the result in |
749 | goto out_err; | 732 | * the clock framework clock array (in ccu->data). Then |
733 | * register as a provider for these clocks. | ||
734 | */ | ||
735 | for (i = 0; i < ccu->clk_data.clk_num; i++) { | ||
736 | if (!ccu->kona_clks[i].ccu) | ||
737 | continue; | ||
738 | ccu->clk_data.clks[i] = kona_clk_setup(&ccu->kona_clks[i]); | ||
739 | } | ||
750 | 740 | ||
751 | ret = of_clk_add_provider(node, of_clk_src_onecell_get, &ccu->clk_data); | 741 | ret = of_clk_add_provider(node, of_clk_src_onecell_get, &ccu->clk_data); |
752 | if (ret) { | 742 | if (ret) { |