aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2014-07-04 16:24:52 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2014-09-27 02:58:01 -0400
commit601da9d0a54c0fea7f5a208bc107d7ef1de4f570 (patch)
tree7ef940807784343319cf92c4c23a56e7157964d6 /drivers/clk
parent9824cf73c3a5e677bee6fcba43c4807e01ff1b4a (diff)
clk: sunxi: factors: Invert the probing logic
Until now, the factors clock probing was done directly by sunxi_init_clocks, with the factors registration being called directly with the clocks data passed as an argument. This approch has shown its limits when we added more clocks, since we couldn't really split code with such a logic in smaller files, and led to a huge file having all the clocks. Introduce an intermediate probing function, so that factor clocks will be able to directly be called by CLK_OF_DECLARE, which will in turn ease the split into several files. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/sunxi/clk-factors.c101
-rw-r--r--drivers/clk/sunxi/clk-factors.h16
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c95
3 files changed, 113 insertions, 99 deletions
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 2057c8ac648f..f83ba097126c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -9,18 +9,18 @@
9 */ 9 */
10 10
11#include <linux/clk-provider.h> 11#include <linux/clk-provider.h>
12#include <linux/delay.h>
13#include <linux/err.h>
14#include <linux/io.h>
12#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/of_address.h>
13#include <linux/slab.h> 17#include <linux/slab.h>
14#include <linux/io.h>
15#include <linux/err.h>
16#include <linux/string.h> 18#include <linux/string.h>
17 19
18#include <linux/delay.h>
19
20#include "clk-factors.h" 20#include "clk-factors.h"
21 21
22/* 22/*
23 * DOC: basic adjustable factor-based clock that cannot gate 23 * DOC: basic adjustable factor-based clock
24 * 24 *
25 * Traits of this clock: 25 * Traits of this clock:
26 * prepare - clk_prepare only ensures that parents are prepared 26 * prepare - clk_prepare only ensures that parents are prepared
@@ -32,6 +32,8 @@
32 32
33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) 33#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
34 34
35#define FACTORS_MAX_PARENTS 5
36
35#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos)) 37#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
36#define CLRMASK(len, pos) (~(SETMASK(len, pos))) 38#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
37#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) 39#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
@@ -147,9 +149,96 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
147 return 0; 149 return 0;
148} 150}
149 151
150const struct clk_ops clk_factors_ops = { 152static const struct clk_ops clk_factors_ops = {
151 .determine_rate = clk_factors_determine_rate, 153 .determine_rate = clk_factors_determine_rate,
152 .recalc_rate = clk_factors_recalc_rate, 154 .recalc_rate = clk_factors_recalc_rate,
153 .round_rate = clk_factors_round_rate, 155 .round_rate = clk_factors_round_rate,
154 .set_rate = clk_factors_set_rate, 156 .set_rate = clk_factors_set_rate,
155}; 157};
158
159struct clk * __init sunxi_factors_register(struct device_node *node,
160 const struct factors_data *data,
161 spinlock_t *lock)
162{
163 struct clk *clk;
164 struct clk_factors *factors;
165 struct clk_gate *gate = NULL;
166 struct clk_mux *mux = NULL;
167 struct clk_hw *gate_hw = NULL;
168 struct clk_hw *mux_hw = NULL;
169 const char *clk_name = node->name;
170 const char *parents[FACTORS_MAX_PARENTS];
171 void __iomem *reg;
172 int i = 0;
173
174 reg = of_iomap(node, 0);
175
176 /* if we have a mux, we will have >1 parents */
177 while (i < FACTORS_MAX_PARENTS &&
178 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
179 i++;
180
181 /*
182 * some factor clocks, such as pll5 and pll6, may have multiple
183 * outputs, and have their name designated in factors_data
184 */
185 if (data->name)
186 clk_name = data->name;
187 else
188 of_property_read_string(node, "clock-output-names", &clk_name);
189
190 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
191 if (!factors)
192 return NULL;
193
194 /* set up factors properties */
195 factors->reg = reg;
196 factors->config = data->table;
197 factors->get_factors = data->getter;
198 factors->lock = lock;
199
200 /* Add a gate if this factor clock can be gated */
201 if (data->enable) {
202 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
203 if (!gate) {
204 kfree(factors);
205 return NULL;
206 }
207
208 /* set up gate properties */
209 gate->reg = reg;
210 gate->bit_idx = data->enable;
211 gate->lock = factors->lock;
212 gate_hw = &gate->hw;
213 }
214
215 /* Add a mux if this factor clock can be muxed */
216 if (data->mux) {
217 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
218 if (!mux) {
219 kfree(factors);
220 kfree(gate);
221 return NULL;
222 }
223
224 /* set up gate properties */
225 mux->reg = reg;
226 mux->shift = data->mux;
227 mux->mask = SUNXI_FACTORS_MUX_MASK;
228 mux->lock = factors->lock;
229 mux_hw = &mux->hw;
230 }
231
232 clk = clk_register_composite(NULL, clk_name,
233 parents, i,
234 mux_hw, &clk_mux_ops,
235 &factors->hw, &clk_factors_ops,
236 gate_hw, &clk_gate_ops, 0);
237
238 if (!IS_ERR(clk)) {
239 of_clk_add_provider(node, of_clk_src_simple_get, clk);
240 clk_register_clkdev(clk, clk_name, NULL);
241 }
242
243 return clk;
244}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index d2d0efa39379..9913840018d3 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -3,9 +3,12 @@
3 3
4#include <linux/clk-provider.h> 4#include <linux/clk-provider.h>
5#include <linux/clkdev.h> 5#include <linux/clkdev.h>
6#include <linux/spinlock.h>
6 7
7#define SUNXI_FACTORS_NOT_APPLICABLE (0) 8#define SUNXI_FACTORS_NOT_APPLICABLE (0)
8 9
10#define SUNXI_FACTORS_MUX_MASK 0x3
11
9struct clk_factors_config { 12struct clk_factors_config {
10 u8 nshift; 13 u8 nshift;
11 u8 nwidth; 14 u8 nwidth;
@@ -18,6 +21,14 @@ struct clk_factors_config {
18 u8 n_start; 21 u8 n_start;
19}; 22};
20 23
24struct factors_data {
25 int enable;
26 int mux;
27 struct clk_factors_config *table;
28 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
29 const char *name;
30};
31
21struct clk_factors { 32struct clk_factors {
22 struct clk_hw hw; 33 struct clk_hw hw;
23 void __iomem *reg; 34 void __iomem *reg;
@@ -26,5 +37,8 @@ struct clk_factors {
26 spinlock_t *lock; 37 spinlock_t *lock;
27}; 38};
28 39
29extern const struct clk_ops clk_factors_ops; 40struct clk * __init sunxi_factors_register(struct device_node *node,
41 const struct factors_data *data,
42 spinlock_t *lock);
43
30#endif 44#endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 2cf6581329a6..393df321010b 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -19,6 +19,7 @@
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/reset-controller.h> 21#include <linux/reset-controller.h>
22#include <linux/spinlock.h>
22 23
23#include "clk-factors.h" 24#include "clk-factors.h"
24 25
@@ -440,16 +441,6 @@ EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
440 * sunxi_factors_clk_setup() - Setup function for factor clocks 441 * sunxi_factors_clk_setup() - Setup function for factor clocks
441 */ 442 */
442 443
443#define SUNXI_FACTORS_MUX_MASK 0x3
444
445struct factors_data {
446 int enable;
447 int mux;
448 struct clk_factors_config *table;
449 void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
450 const char *name;
451};
452
453static struct clk_factors_config sun4i_pll1_config = { 444static struct clk_factors_config sun4i_pll1_config = {
454 .nshift = 8, 445 .nshift = 8,
455 .nwidth = 5, 446 .nwidth = 5,
@@ -583,89 +574,9 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
583}; 574};
584 575
585static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 576static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
586 const struct factors_data *data) 577 const struct factors_data *data)
587{ 578{
588 struct clk *clk; 579 return sunxi_factors_register(node, data, &clk_lock);
589 struct clk_factors *factors;
590 struct clk_gate *gate = NULL;
591 struct clk_mux *mux = NULL;
592 struct clk_hw *gate_hw = NULL;
593 struct clk_hw *mux_hw = NULL;
594 const char *clk_name = node->name;
595 const char *parents[SUNXI_MAX_PARENTS];
596 void __iomem *reg;
597 int i = 0;
598
599 reg = of_iomap(node, 0);
600
601 /* if we have a mux, we will have >1 parents */
602 while (i < SUNXI_MAX_PARENTS &&
603 (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
604 i++;
605
606 /*
607 * some factor clocks, such as pll5 and pll6, may have multiple
608 * outputs, and have their name designated in factors_data
609 */
610 if (data->name)
611 clk_name = data->name;
612 else
613 of_property_read_string(node, "clock-output-names", &clk_name);
614
615 factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
616 if (!factors)
617 return NULL;
618
619 /* Add a gate if this factor clock can be gated */
620 if (data->enable) {
621 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
622 if (!gate) {
623 kfree(factors);
624 return NULL;
625 }
626
627 /* set up gate properties */
628 gate->reg = reg;
629 gate->bit_idx = data->enable;
630 gate->lock = &clk_lock;
631 gate_hw = &gate->hw;
632 }
633
634 /* Add a mux if this factor clock can be muxed */
635 if (data->mux) {
636 mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
637 if (!mux) {
638 kfree(factors);
639 kfree(gate);
640 return NULL;
641 }
642
643 /* set up gate properties */
644 mux->reg = reg;
645 mux->shift = data->mux;
646 mux->mask = SUNXI_FACTORS_MUX_MASK;
647 mux->lock = &clk_lock;
648 mux_hw = &mux->hw;
649 }
650
651 /* set up factors properties */
652 factors->reg = reg;
653 factors->config = data->table;
654 factors->get_factors = data->getter;
655 factors->lock = &clk_lock;
656
657 clk = clk_register_composite(NULL, clk_name,
658 parents, i,
659 mux_hw, &clk_mux_ops,
660 &factors->hw, &clk_factors_ops,
661 gate_hw, &clk_gate_ops, 0);
662
663 if (!IS_ERR(clk)) {
664 of_clk_add_provider(node, of_clk_src_simple_get, clk);
665 clk_register_clkdev(clk, clk_name, NULL);
666 }
667
668 return clk;
669} 580}
670 581
671 582