aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2009-06-02 04:53:54 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-06-11 02:07:13 -0400
commit2693e2740ddae364a80e6083043ba760b6366b69 (patch)
treeb2c34eb52ec8d5f6914cb0114abf071556b532c1 /arch/sh/kernel
parenta50de78dc6d21ee074e9561c800d194bec12128b (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.c71
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
41static 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
46static 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
53static 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
58static 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
71static struct clk_ops sh_clk_div6_clk_ops = {
72 .recalc = sh_clk_div6_recalc,
73 .round_rate = sh_clk_div_round_rate,
74};
75
76int __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
41static unsigned long sh_clk_div4_recalc(struct clk *clk) 105static 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
54static 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
59static struct clk_ops sh_clk_div4_clk_ops = { 118static 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
64int __init sh_clk_div4_register(struct clk *clks, int nr, 123int __init sh_clk_div4_register(struct clk *clks, int nr,