aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2013-12-01 15:42:45 -0500
committerMike Turquette <mturquette@linaro.org>2013-12-01 15:42:45 -0500
commit1d9438f7b560862fd0832355b4ad199b30e67478 (patch)
tree483dd72ab0064cf9690d4371056c2ed801220709
parent4d04391cfe6446fb2f184d063b56a4dcce425334 (diff)
parente71c69fc3362b88b09194d486dda6d721a8004f6 (diff)
Merge tag 'sunxi-clk-for-3.13' of https://github.com/mripard/linux into clk-next-sunxi-rebase
Allwinner sunXi SoCs clock changes Those are mostly random fixes, except for one patch to the composite clock that adds support for automatic reparenting. Conflicts: drivers/clk/sunxi/clk-sunxi.c
-rw-r--r--drivers/clk/clk-composite.c28
-rw-r--r--drivers/clk/sunxi/clk-factors.c4
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c58
3 files changed, 76 insertions, 14 deletions
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index a33f46f20a41..753d0b784762 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -55,6 +55,30 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
55 return rate_ops->recalc_rate(rate_hw, parent_rate); 55 return rate_ops->recalc_rate(rate_hw, parent_rate);
56} 56}
57 57
58static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
59 unsigned long *best_parent_rate,
60 struct clk **best_parent_p)
61{
62 struct clk_composite *composite = to_clk_composite(hw);
63 const struct clk_ops *rate_ops = composite->rate_ops;
64 const struct clk_ops *mux_ops = composite->mux_ops;
65 struct clk_hw *rate_hw = composite->rate_hw;
66 struct clk_hw *mux_hw = composite->mux_hw;
67
68 if (rate_hw && rate_ops && rate_ops->determine_rate) {
69 rate_hw->clk = hw->clk;
70 return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
71 best_parent_p);
72 } else if (mux_hw && mux_ops && mux_ops->determine_rate) {
73 mux_hw->clk = hw->clk;
74 return mux_ops->determine_rate(rate_hw, rate, best_parent_rate,
75 best_parent_p);
76 } else {
77 pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
78 return 0;
79 }
80}
81
58static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, 82static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
59 unsigned long *prate) 83 unsigned long *prate)
60{ 84{
@@ -147,6 +171,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
147 composite->mux_ops = mux_ops; 171 composite->mux_ops = mux_ops;
148 clk_composite_ops->get_parent = clk_composite_get_parent; 172 clk_composite_ops->get_parent = clk_composite_get_parent;
149 clk_composite_ops->set_parent = clk_composite_set_parent; 173 clk_composite_ops->set_parent = clk_composite_set_parent;
174 if (mux_ops->determine_rate)
175 clk_composite_ops->determine_rate = clk_composite_determine_rate;
150 } 176 }
151 177
152 if (rate_hw && rate_ops) { 178 if (rate_hw && rate_ops) {
@@ -170,6 +196,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
170 composite->rate_hw = rate_hw; 196 composite->rate_hw = rate_hw;
171 composite->rate_ops = rate_ops; 197 composite->rate_ops = rate_ops;
172 clk_composite_ops->recalc_rate = clk_composite_recalc_rate; 198 clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
199 if (rate_ops->determine_rate)
200 clk_composite_ops->determine_rate = clk_composite_determine_rate;
173 } 201 }
174 202
175 if (gate_hw && gate_ops) { 203 if (gate_hw && gate_ops) {
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 88523f91d9b7..f05207a27e5f 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -40,7 +40,7 @@ struct clk_factors {
40 40
41#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) 41#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
42 42
43#define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) 43#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
44#define CLRMASK(len, pos) (~(SETMASK(len, pos))) 44#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
45#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) 45#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
46 46
@@ -88,7 +88,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
88static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, 88static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
89 unsigned long parent_rate) 89 unsigned long parent_rate)
90{ 90{
91 u8 n, k, m, p; 91 u8 n = 0, k = 0, m = 0, p = 0;
92 u32 reg; 92 u32 reg;
93 struct clk_factors *factors = to_clk_factors(hw); 93 struct clk_factors *factors = to_clk_factors(hw);
94 struct clk_factors_config *config = factors->config; 94 struct clk_factors_config *config = factors->config;
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 9bbd03514540..98fec4e4baa7 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -37,18 +37,16 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
37 const char *clk_name = node->name; 37 const char *clk_name = node->name;
38 u32 rate; 38 u32 rate;
39 39
40 if (of_property_read_u32(node, "clock-frequency", &rate))
41 return;
42
40 /* allocate fixed-rate and gate clock structs */ 43 /* allocate fixed-rate and gate clock structs */
41 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); 44 fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
42 if (!fixed) 45 if (!fixed)
43 return; 46 return;
44 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); 47 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
45 if (!gate) { 48 if (!gate)
46 kfree(fixed); 49 goto err_free_fixed;
47 return;
48 }
49
50 if (of_property_read_u32(node, "clock-frequency", &rate))
51 return;
52 50
53 /* set up gate and fixed rate properties */ 51 /* set up gate and fixed rate properties */
54 gate->reg = of_iomap(node, 0); 52 gate->reg = of_iomap(node, 0);
@@ -63,10 +61,18 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
63 &gate->hw, &clk_gate_ops, 61 &gate->hw, &clk_gate_ops,
64 CLK_IS_ROOT); 62 CLK_IS_ROOT);
65 63
66 if (!IS_ERR(clk)) { 64 if (IS_ERR(clk))
67 of_clk_add_provider(node, of_clk_src_simple_get, clk); 65 goto err_free_gate;
68 clk_register_clkdev(clk, clk_name, NULL); 66
69 } 67 of_clk_add_provider(node, of_clk_src_simple_get, clk);
68 clk_register_clkdev(clk, clk_name, NULL);
69
70 return;
71
72err_free_gate:
73 kfree(gate);
74err_free_fixed:
75 kfree(fixed);
70} 76}
71CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); 77CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
72 78
@@ -616,7 +622,32 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
616 } 622 }
617} 623}
618 624
619static void __init sunxi_init_clocks(struct device_node *np) 625/**
626 * System clock protection
627 *
628 * By enabling these critical clocks, we prevent their accidental gating
629 * by the framework
630 */
631static void __init sunxi_clock_protect(void)
632{
633 struct clk *clk;
634
635 /* memory bus clock - sun5i+ */
636 clk = clk_get(NULL, "mbus");
637 if (!IS_ERR(clk)) {
638 clk_prepare_enable(clk);
639 clk_put(clk);
640 }
641
642 /* DDR clock - sun4i+ */
643 clk = clk_get(NULL, "pll5_ddr");
644 if (!IS_ERR(clk)) {
645 clk_prepare_enable(clk);
646 clk_put(clk);
647 }
648}
649
650static void __init sunxi_init_clocks(void)
620{ 651{
621 /* Register factor clocks */ 652 /* Register factor clocks */
622 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); 653 of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
@@ -629,6 +660,9 @@ static void __init sunxi_init_clocks(struct device_node *np)
629 660
630 /* Register gate clocks */ 661 /* Register gate clocks */
631 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); 662 of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
663
664 /* Enable core system clocks */
665 sunxi_clock_protect();
632} 666}
633CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); 667CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks);
634CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks); 668CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);