aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2010-07-21 06:13:10 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-08-04 03:12:01 -0400
commitb3dd51a8a6ce2e618e8a1be8fa0e7d3d4733c300 (patch)
tree7a843ef70cb0a680dbf118d1e7a9a73e56f0d45c /drivers/sh
parentb5272b509a8570bb559156001e74ee162c5cb96a (diff)
sh: add a reparent function to DIV6 clocks
Add support for reparenting of div6 clocks on SuperH and SH-Mobile SoCs. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/clk-cpg.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c
index f5c80ba9ab1c..8c024b984ed8 100644
--- a/drivers/sh/clk-cpg.c
+++ b/drivers/sh/clk-cpg.c
@@ -68,6 +68,39 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
68 return clk->freq_table[idx].frequency; 68 return clk->freq_table[idx].frequency;
69} 69}
70 70
71static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
72{
73 struct clk_div_mult_table *table = &sh_clk_div6_table;
74 u32 value;
75 int ret, i;
76
77 if (!clk->parent_table || !clk->parent_num)
78 return -EINVAL;
79
80 /* Search the parent */
81 for (i = 0; i < clk->parent_num; i++)
82 if (clk->parent_table[i] == parent)
83 break;
84
85 if (i == clk->parent_num)
86 return -ENODEV;
87
88 ret = clk_reparent(clk, parent);
89 if (ret < 0)
90 return ret;
91
92 value = __raw_readl(clk->enable_reg) &
93 ~(((1 << clk->src_width) - 1) << clk->src_shift);
94
95 __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
96
97 /* Rebuild the frequency table */
98 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
99 table, &clk->arch_flags);
100
101 return 0;
102}
103
71static int sh_clk_div6_set_rate(struct clk *clk, 104static int sh_clk_div6_set_rate(struct clk *clk,
72 unsigned long rate, int algo_id) 105 unsigned long rate, int algo_id)
73{ 106{
@@ -117,7 +150,17 @@ static struct clk_ops sh_clk_div6_clk_ops = {
117 .disable = sh_clk_div6_disable, 150 .disable = sh_clk_div6_disable,
118}; 151};
119 152
120int __init sh_clk_div6_register(struct clk *clks, int nr) 153static struct clk_ops sh_clk_div6_reparent_clk_ops = {
154 .recalc = sh_clk_div6_recalc,
155 .round_rate = sh_clk_div_round_rate,
156 .set_rate = sh_clk_div6_set_rate,
157 .enable = sh_clk_div6_enable,
158 .disable = sh_clk_div6_disable,
159 .set_parent = sh_clk_div6_set_parent,
160};
161
162static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
163 struct clk_ops *ops)
121{ 164{
122 struct clk *clkp; 165 struct clk *clkp;
123 void *freq_table; 166 void *freq_table;
@@ -136,7 +179,7 @@ int __init sh_clk_div6_register(struct clk *clks, int nr)
136 for (k = 0; !ret && (k < nr); k++) { 179 for (k = 0; !ret && (k < nr); k++) {
137 clkp = clks + k; 180 clkp = clks + k;
138 181
139 clkp->ops = &sh_clk_div6_clk_ops; 182 clkp->ops = ops;
140 clkp->id = -1; 183 clkp->id = -1;
141 clkp->freq_table = freq_table + (k * freq_table_size); 184 clkp->freq_table = freq_table + (k * freq_table_size);
142 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; 185 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
@@ -147,6 +190,17 @@ int __init sh_clk_div6_register(struct clk *clks, int nr)
147 return ret; 190 return ret;
148} 191}
149 192
193int __init sh_clk_div6_register(struct clk *clks, int nr)
194{
195 return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
196}
197
198int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
199{
200 return sh_clk_div6_register_ops(clks, nr,
201 &sh_clk_div6_reparent_clk_ops);
202}
203
150static unsigned long sh_clk_div4_recalc(struct clk *clk) 204static unsigned long sh_clk_div4_recalc(struct clk *clk)
151{ 205{
152 struct clk_div4_table *d4t = clk->priv; 206 struct clk_div4_table *d4t = clk->priv;