diff options
author | Magnus Damm <damm@igel.co.jp> | 2009-05-28 09:11:31 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-06-01 05:07:37 -0400 |
commit | a1153e27eec25e9963f5843ba8932952bd9847ac (patch) | |
tree | 76ef9b57aa5734797a862ad576f4f4e74ab8a3f0 /arch/sh | |
parent | e89d53e60593ee7066e1d36ab5c1ccf2648f5f53 (diff) |
sh: shared div4 clock code
Add shared code for 4-bit divisor clocks.
Processor specific code can use SH_CLK_DIV4()
to initialize div4 clocks, and then use
sh_clk_div4_register() for registration.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/clock.h | 15 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/clock-cpg.c | 55 |
2 files changed, 70 insertions, 0 deletions
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index f43d3e72d266..7435e40022e6 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/seq_file.h> | 5 | #include <linux/seq_file.h> |
6 | #include <linux/cpufreq.h> | ||
6 | #include <linux/clk.h> | 7 | #include <linux/clk.h> |
7 | #include <linux/err.h> | 8 | #include <linux/err.h> |
8 | 9 | ||
@@ -41,6 +42,7 @@ struct clk { | |||
41 | unsigned long arch_flags; | 42 | unsigned long arch_flags; |
42 | void *priv; | 43 | void *priv; |
43 | struct dentry *dentry; | 44 | struct dentry *dentry; |
45 | struct cpufreq_frequency_table *freq_table; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | struct clk_lookup { | 48 | struct clk_lookup { |
@@ -130,4 +132,17 @@ long clk_rate_table_round(struct clk *clk, | |||
130 | 132 | ||
131 | int sh_clk_mstp32_register(struct clk *clks, int nr); | 133 | int sh_clk_mstp32_register(struct clk *clks, int nr); |
132 | 134 | ||
135 | #define SH_CLK_DIV4(_name, _parent, _reg, _shift, _div_bitmap, _flags) \ | ||
136 | { \ | ||
137 | .name = _name, \ | ||
138 | .parent = _parent, \ | ||
139 | .enable_reg = (void __iomem *)_reg, \ | ||
140 | .enable_bit = _shift, \ | ||
141 | .arch_flags = _div_bitmap, \ | ||
142 | .flags = _flags, \ | ||
143 | } | ||
144 | |||
145 | int sh_clk_div4_register(struct clk *clks, int nr, | ||
146 | struct clk_div_mult_table *table); | ||
147 | |||
133 | #endif /* __ASM_SH_CLOCK_H */ | 148 | #endif /* __ASM_SH_CLOCK_H */ |
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 72228d2945ac..88fc30d2f5fd 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/clk.h> | 1 | #include <linux/clk.h> |
2 | #include <linux/compiler.h> | 2 | #include <linux/compiler.h> |
3 | #include <linux/bootmem.h> | ||
3 | #include <linux/io.h> | 4 | #include <linux/io.h> |
4 | #include <asm/clock.h> | 5 | #include <asm/clock.h> |
5 | 6 | ||
@@ -37,6 +38,60 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr) | |||
37 | return ret; | 38 | return ret; |
38 | } | 39 | } |
39 | 40 | ||
41 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | ||
42 | { | ||
43 | struct clk_div_mult_table *table = clk->priv; | ||
44 | unsigned int idx; | ||
45 | |||
46 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
47 | table, &clk->arch_flags); | ||
48 | |||
49 | idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; | ||
50 | |||
51 | return clk->freq_table[idx].frequency; | ||
52 | } | ||
53 | |||
54 | static long sh_clk_div4_round_rate(struct clk *clk, unsigned long rate) | ||
55 | { | ||
56 | return clk_rate_table_round(clk, clk->freq_table, rate); | ||
57 | } | ||
58 | |||
59 | static struct clk_ops sh_clk_div4_clk_ops = { | ||
60 | .recalc = sh_clk_div4_recalc, | ||
61 | .round_rate = sh_clk_div4_round_rate, | ||
62 | }; | ||
63 | |||
64 | int __init sh_clk_div4_register(struct clk *clks, int nr, | ||
65 | struct clk_div_mult_table *table) | ||
66 | { | ||
67 | struct clk *clkp; | ||
68 | void *freq_table; | ||
69 | int nr_divs = table->nr_divisors; | ||
70 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
71 | int ret = 0; | ||
72 | int k; | ||
73 | |||
74 | k = nr_divs + 1; | ||
75 | freq_table = alloc_bootmem(freq_table_size * nr * (nr_divs + 1)); | ||
76 | if (!freq_table) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | for (k = 0; !ret && (k < nr); k++) { | ||
80 | clkp = clks + k; | ||
81 | |||
82 | clkp->ops = &sh_clk_div4_clk_ops; | ||
83 | clkp->id = -1; | ||
84 | clkp->priv = table; | ||
85 | |||
86 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
87 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
88 | |||
89 | ret = clk_register(clkp); | ||
90 | } | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | |||
40 | #ifdef CONFIG_SH_CLK_CPG_LEGACY | 95 | #ifdef CONFIG_SH_CLK_CPG_LEGACY |
41 | static struct clk master_clk = { | 96 | static struct clk master_clk = { |
42 | .name = "master_clk", | 97 | .name = "master_clk", |