diff options
author | Magnus Damm <damm@igel.co.jp> | 2009-06-02 04:53:54 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-06-11 02:07:13 -0400 |
commit | 2693e2740ddae364a80e6083043ba760b6366b69 (patch) | |
tree | b2c34eb52ec8d5f6914cb0114abf071556b532c1 /arch/sh/kernel | |
parent | a50de78dc6d21ee074e9561c800d194bec12128b (diff) |
sh: clock div6 helper code
This patch adds div6 clock helper code. The div6 clocks
are simply 6-bit divide-by-n modules where n is 1 to 64.
Needed for vclk on sh7722, sh7723, sh7343 and sh7366.
sh7724 needs this even more for vclk, fclka, fclkb,
irdaclk and spuclk.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/cpu/clock-cpg.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index e604a6f80194..fedc8b84db4c 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -38,6 +38,70 @@ int __init sh_clk_mstp32_register(struct clk *clks, int nr) | |||
38 | return ret; | 38 | return ret; |
39 | } | 39 | } |
40 | 40 | ||
41 | static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) | ||
42 | { | ||
43 | return clk_rate_table_round(clk, clk->freq_table, rate); | ||
44 | } | ||
45 | |||
46 | static int sh_clk_div6_divisors[64] = { | ||
47 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | ||
48 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, | ||
49 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | ||
50 | 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 | ||
51 | }; | ||
52 | |||
53 | static struct clk_div_mult_table sh_clk_div6_table = { | ||
54 | .divisors = sh_clk_div6_divisors, | ||
55 | .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), | ||
56 | }; | ||
57 | |||
58 | static unsigned long sh_clk_div6_recalc(struct clk *clk) | ||
59 | { | ||
60 | struct clk_div_mult_table *table = &sh_clk_div6_table; | ||
61 | unsigned int idx; | ||
62 | |||
63 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
64 | table, NULL); | ||
65 | |||
66 | idx = __raw_readl(clk->enable_reg) & 0x003f; | ||
67 | |||
68 | return clk->freq_table[idx].frequency; | ||
69 | } | ||
70 | |||
71 | static struct clk_ops sh_clk_div6_clk_ops = { | ||
72 | .recalc = sh_clk_div6_recalc, | ||
73 | .round_rate = sh_clk_div_round_rate, | ||
74 | }; | ||
75 | |||
76 | int __init sh_clk_div6_register(struct clk *clks, int nr) | ||
77 | { | ||
78 | struct clk *clkp; | ||
79 | void *freq_table; | ||
80 | int nr_divs = sh_clk_div6_table.nr_divisors; | ||
81 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
82 | int ret = 0; | ||
83 | int k; | ||
84 | |||
85 | freq_table_size *= (nr_divs + 1); | ||
86 | |||
87 | freq_table = alloc_bootmem(freq_table_size * nr); | ||
88 | if (!freq_table) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | for (k = 0; !ret && (k < nr); k++) { | ||
92 | clkp = clks + k; | ||
93 | |||
94 | clkp->ops = &sh_clk_div6_clk_ops; | ||
95 | clkp->id = -1; | ||
96 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
97 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
98 | |||
99 | ret = clk_register(clkp); | ||
100 | } | ||
101 | |||
102 | return ret; | ||
103 | } | ||
104 | |||
41 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | 105 | static unsigned long sh_clk_div4_recalc(struct clk *clk) |
42 | { | 106 | { |
43 | struct clk_div_mult_table *table = clk->priv; | 107 | struct clk_div_mult_table *table = clk->priv; |
@@ -51,14 +115,9 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) | |||
51 | return clk->freq_table[idx].frequency; | 115 | return clk->freq_table[idx].frequency; |
52 | } | 116 | } |
53 | 117 | ||
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 = { | 118 | static struct clk_ops sh_clk_div4_clk_ops = { |
60 | .recalc = sh_clk_div4_recalc, | 119 | .recalc = sh_clk_div4_recalc, |
61 | .round_rate = sh_clk_div4_round_rate, | 120 | .round_rate = sh_clk_div_round_rate, |
62 | }; | 121 | }; |
63 | 122 | ||
64 | int __init sh_clk_div4_register(struct clk *clks, int nr, | 123 | int __init sh_clk_div4_register(struct clk *clks, int nr, |