diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-04-12 06:50:40 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-04-12 06:50:40 -0400 |
commit | 104fa61a7dd83197160d5cafedc0e94ad9cd7fcc (patch) | |
tree | fb450f850e0a92e6017d6343671c55e97639ad18 /drivers/sh | |
parent | 4d6ddb08acc48368c5b7ac431f9d00db7227d2ed (diff) |
sh: clkfwk: Support variable size accesses for div4/div6 clocks.
This follows the MSTP clock change and implements variable access size
support for the rest of the CPG clocks, too. Upcoming SH-2A support has
need of this for 16-bit div4 clocks, while others will follow.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/clk/cpg.c | 71 |
1 files changed, 37 insertions, 34 deletions
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 6cbda4841589..f0d015dd0fef 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
@@ -14,32 +14,35 @@ | |||
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/sh_clk.h> | 15 | #include <linux/sh_clk.h> |
16 | 16 | ||
17 | static int sh_clk_mstp_enable(struct clk *clk) | 17 | static unsigned int sh_clk_read(struct clk *clk) |
18 | { | 18 | { |
19 | if (clk->flags & CLK_ENABLE_REG_8BIT) | 19 | if (clk->flags & CLK_ENABLE_REG_8BIT) |
20 | iowrite8(ioread8(clk->mapped_reg) & ~(1 << clk->enable_bit), | 20 | return ioread8(clk->mapped_reg); |
21 | clk->mapped_reg); | ||
22 | else if (clk->flags & CLK_ENABLE_REG_16BIT) | 21 | else if (clk->flags & CLK_ENABLE_REG_16BIT) |
23 | iowrite16(ioread16(clk->mapped_reg) & ~(1 << clk->enable_bit), | 22 | return ioread16(clk->mapped_reg); |
24 | clk->mapped_reg); | ||
25 | else | ||
26 | iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), | ||
27 | clk->mapped_reg); | ||
28 | 23 | ||
29 | return 0; | 24 | return ioread32(clk->mapped_reg); |
30 | } | 25 | } |
31 | 26 | ||
32 | static void sh_clk_mstp_disable(struct clk *clk) | 27 | static void sh_clk_write(int value, struct clk *clk) |
33 | { | 28 | { |
34 | if (clk->flags & CLK_ENABLE_REG_8BIT) | 29 | if (clk->flags & CLK_ENABLE_REG_8BIT) |
35 | iowrite8(ioread8(clk->mapped_reg) | (1 << clk->enable_bit), | 30 | iowrite8(value, clk->mapped_reg); |
36 | clk->mapped_reg); | ||
37 | else if (clk->flags & CLK_ENABLE_REG_16BIT) | 31 | else if (clk->flags & CLK_ENABLE_REG_16BIT) |
38 | iowrite16(ioread16(clk->mapped_reg) | (1 << clk->enable_bit), | 32 | iowrite16(value, clk->mapped_reg); |
39 | clk->mapped_reg); | ||
40 | else | 33 | else |
41 | iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), | 34 | iowrite32(value, clk->mapped_reg); |
42 | clk->mapped_reg); | 35 | } |
36 | |||
37 | static int sh_clk_mstp_enable(struct clk *clk) | ||
38 | { | ||
39 | sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static void sh_clk_mstp_disable(struct clk *clk) | ||
44 | { | ||
45 | sh_clk_write(sh_clk_read(clk) | (1 << clk->enable_bit), clk); | ||
43 | } | 46 | } |
44 | 47 | ||
45 | static struct sh_clk_ops sh_clk_mstp_clk_ops = { | 48 | static struct sh_clk_ops sh_clk_mstp_clk_ops = { |
@@ -88,7 +91,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) | |||
88 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 91 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
89 | table, NULL); | 92 | table, NULL); |
90 | 93 | ||
91 | idx = ioread32(clk->mapped_reg) & 0x003f; | 94 | idx = sh_clk_read(clk) & 0x003f; |
92 | 95 | ||
93 | return clk->freq_table[idx].frequency; | 96 | return clk->freq_table[idx].frequency; |
94 | } | 97 | } |
@@ -114,10 +117,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) | |||
114 | if (ret < 0) | 117 | if (ret < 0) |
115 | return ret; | 118 | return ret; |
116 | 119 | ||
117 | value = ioread32(clk->mapped_reg) & | 120 | value = sh_clk_read(clk) & |
118 | ~(((1 << clk->src_width) - 1) << clk->src_shift); | 121 | ~(((1 << clk->src_width) - 1) << clk->src_shift); |
119 | 122 | ||
120 | iowrite32(value | (i << clk->src_shift), clk->mapped_reg); | 123 | sh_clk_write(value | (i << clk->src_shift), clk); |
121 | 124 | ||
122 | /* Rebuild the frequency table */ | 125 | /* Rebuild the frequency table */ |
123 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 126 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
@@ -135,10 +138,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) | |||
135 | if (idx < 0) | 138 | if (idx < 0) |
136 | return idx; | 139 | return idx; |
137 | 140 | ||
138 | value = ioread32(clk->mapped_reg); | 141 | value = sh_clk_read(clk); |
139 | value &= ~0x3f; | 142 | value &= ~0x3f; |
140 | value |= idx; | 143 | value |= idx; |
141 | iowrite32(value, clk->mapped_reg); | 144 | sh_clk_write(value, clk); |
142 | return 0; | 145 | return 0; |
143 | } | 146 | } |
144 | 147 | ||
@@ -149,9 +152,9 @@ static int sh_clk_div6_enable(struct clk *clk) | |||
149 | 152 | ||
150 | ret = sh_clk_div6_set_rate(clk, clk->rate); | 153 | ret = sh_clk_div6_set_rate(clk, clk->rate); |
151 | if (ret == 0) { | 154 | if (ret == 0) { |
152 | value = ioread32(clk->mapped_reg); | 155 | value = sh_clk_read(clk); |
153 | value &= ~0x100; /* clear stop bit to enable clock */ | 156 | value &= ~0x100; /* clear stop bit to enable clock */ |
154 | iowrite32(value, clk->mapped_reg); | 157 | sh_clk_write(value, clk); |
155 | } | 158 | } |
156 | return ret; | 159 | return ret; |
157 | } | 160 | } |
@@ -160,10 +163,10 @@ static void sh_clk_div6_disable(struct clk *clk) | |||
160 | { | 163 | { |
161 | unsigned long value; | 164 | unsigned long value; |
162 | 165 | ||
163 | value = ioread32(clk->mapped_reg); | 166 | value = sh_clk_read(clk); |
164 | value |= 0x100; /* stop clock */ | 167 | value |= 0x100; /* stop clock */ |
165 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ | 168 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ |
166 | iowrite32(value, clk->mapped_reg); | 169 | sh_clk_write(value, clk); |
167 | } | 170 | } |
168 | 171 | ||
169 | static struct sh_clk_ops sh_clk_div6_clk_ops = { | 172 | static struct sh_clk_ops sh_clk_div6_clk_ops = { |
@@ -198,7 +201,7 @@ static int __init sh_clk_init_parent(struct clk *clk) | |||
198 | return -EINVAL; | 201 | return -EINVAL; |
199 | } | 202 | } |
200 | 203 | ||
201 | val = (ioread32(clk->mapped_reg) >> clk->src_shift); | 204 | val = (sh_clk_read(clk) >> clk->src_shift); |
202 | val &= (1 << clk->src_width) - 1; | 205 | val &= (1 << clk->src_width) - 1; |
203 | 206 | ||
204 | if (val >= clk->parent_num) { | 207 | if (val >= clk->parent_num) { |
@@ -268,7 +271,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) | |||
268 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 271 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
269 | table, &clk->arch_flags); | 272 | table, &clk->arch_flags); |
270 | 273 | ||
271 | idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f; | 274 | idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f; |
272 | 275 | ||
273 | return clk->freq_table[idx].frequency; | 276 | return clk->freq_table[idx].frequency; |
274 | } | 277 | } |
@@ -286,15 +289,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | |||
286 | */ | 289 | */ |
287 | 290 | ||
288 | if (parent->flags & CLK_ENABLE_ON_INIT) | 291 | if (parent->flags & CLK_ENABLE_ON_INIT) |
289 | value = ioread32(clk->mapped_reg) & ~(1 << 7); | 292 | value = sh_clk_read(clk) & ~(1 << 7); |
290 | else | 293 | else |
291 | value = ioread32(clk->mapped_reg) | (1 << 7); | 294 | value = sh_clk_read(clk) | (1 << 7); |
292 | 295 | ||
293 | ret = clk_reparent(clk, parent); | 296 | ret = clk_reparent(clk, parent); |
294 | if (ret < 0) | 297 | if (ret < 0) |
295 | return ret; | 298 | return ret; |
296 | 299 | ||
297 | iowrite32(value, clk->mapped_reg); | 300 | sh_clk_write(value, clk); |
298 | 301 | ||
299 | /* Rebiuld the frequency table */ | 302 | /* Rebiuld the frequency table */ |
300 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | 303 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, |
@@ -311,10 +314,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) | |||
311 | if (idx < 0) | 314 | if (idx < 0) |
312 | return idx; | 315 | return idx; |
313 | 316 | ||
314 | value = ioread32(clk->mapped_reg); | 317 | value = sh_clk_read(clk); |
315 | value &= ~(0xf << clk->enable_bit); | 318 | value &= ~(0xf << clk->enable_bit); |
316 | value |= (idx << clk->enable_bit); | 319 | value |= (idx << clk->enable_bit); |
317 | iowrite32(value, clk->mapped_reg); | 320 | sh_clk_write(value, clk); |
318 | 321 | ||
319 | if (d4t->kick) | 322 | if (d4t->kick) |
320 | d4t->kick(clk); | 323 | d4t->kick(clk); |
@@ -324,13 +327,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) | |||
324 | 327 | ||
325 | static int sh_clk_div4_enable(struct clk *clk) | 328 | static int sh_clk_div4_enable(struct clk *clk) |
326 | { | 329 | { |
327 | iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg); | 330 | sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk); |
328 | return 0; | 331 | return 0; |
329 | } | 332 | } |
330 | 333 | ||
331 | static void sh_clk_div4_disable(struct clk *clk) | 334 | static void sh_clk_div4_disable(struct clk *clk) |
332 | { | 335 | { |
333 | iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg); | 336 | sh_clk_write(sh_clk_read(clk) | (1 << 8), clk); |
334 | } | 337 | } |
335 | 338 | ||
336 | static struct sh_clk_ops sh_clk_div4_clk_ops = { | 339 | static struct sh_clk_ops sh_clk_div4_clk_ops = { |