diff options
author | Magnus Damm <damm@igel.co.jp> | 2009-06-04 01:31:41 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-06-11 02:12:58 -0400 |
commit | 098dee99d14e8324d3793df442d6078d0c134140 (patch) | |
tree | d2fedbcb58a917bc70a0244bc1da63ec8be97b23 /arch/sh | |
parent | c01641b42a88c475fd4b72cff2b10e42262a80fe (diff) |
sh: add enable()/disable()/set_rate() to div6 code
This patch updates the div6 clock helper code to add support
for enable(), disable() and set_rate() callbacks.
Needed by the camera clock enabling board code on Migo-R.
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 | 4 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/clock-cpg.c | 44 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/clock.c | 19 |
3 files changed, 67 insertions, 0 deletions
diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 026b9daa5584..9fe7d7f8af40 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h | |||
@@ -119,6 +119,10 @@ long clk_rate_table_round(struct clk *clk, | |||
119 | struct cpufreq_frequency_table *freq_table, | 119 | struct cpufreq_frequency_table *freq_table, |
120 | unsigned long rate); | 120 | unsigned long rate); |
121 | 121 | ||
122 | int clk_rate_table_find(struct clk *clk, | ||
123 | struct cpufreq_frequency_table *freq_table, | ||
124 | unsigned long rate); | ||
125 | |||
122 | #define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg, \ | 126 | #define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg, \ |
123 | _enable_bit, _flags) \ | 127 | _enable_bit, _flags) \ |
124 | { \ | 128 | { \ |
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index fedc8b84db4c..275942e58e4f 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -68,9 +68,53 @@ 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 | ||
71 | static int sh_clk_div6_set_rate(struct clk *clk, | ||
72 | unsigned long rate, int algo_id) | ||
73 | { | ||
74 | unsigned long value; | ||
75 | int idx; | ||
76 | |||
77 | idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
78 | if (idx < 0) | ||
79 | return idx; | ||
80 | |||
81 | value = __raw_readl(clk->enable_reg); | ||
82 | value &= ~0x3f; | ||
83 | value |= idx; | ||
84 | __raw_writel(value, clk->enable_reg); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int sh_clk_div6_enable(struct clk *clk) | ||
89 | { | ||
90 | unsigned long value; | ||
91 | int ret; | ||
92 | |||
93 | ret = sh_clk_div6_set_rate(clk, clk->rate, 0); | ||
94 | if (ret == 0) { | ||
95 | value = __raw_readl(clk->enable_reg); | ||
96 | value &= ~0x100; /* clear stop bit to enable clock */ | ||
97 | __raw_writel(value, clk->enable_reg); | ||
98 | } | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static void sh_clk_div6_disable(struct clk *clk) | ||
103 | { | ||
104 | unsigned long value; | ||
105 | |||
106 | value = __raw_readl(clk->enable_reg); | ||
107 | value |= 0x100; /* stop clock */ | ||
108 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ | ||
109 | __raw_writel(value, clk->enable_reg); | ||
110 | } | ||
111 | |||
71 | static struct clk_ops sh_clk_div6_clk_ops = { | 112 | static struct clk_ops sh_clk_div6_clk_ops = { |
72 | .recalc = sh_clk_div6_recalc, | 113 | .recalc = sh_clk_div6_recalc, |
73 | .round_rate = sh_clk_div_round_rate, | 114 | .round_rate = sh_clk_div_round_rate, |
115 | .set_rate = sh_clk_div6_set_rate, | ||
116 | .enable = sh_clk_div6_enable, | ||
117 | .disable = sh_clk_div6_disable, | ||
74 | }; | 118 | }; |
75 | 119 | ||
76 | int __init sh_clk_div6_register(struct clk *clks, int nr) | 120 | int __init sh_clk_div6_register(struct clk *clks, int nr) |
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index aa0fd0893585..f3a46be2ae81 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -111,6 +111,25 @@ long clk_rate_table_round(struct clk *clk, | |||
111 | return rate_best_fit; | 111 | return rate_best_fit; |
112 | } | 112 | } |
113 | 113 | ||
114 | int clk_rate_table_find(struct clk *clk, | ||
115 | struct cpufreq_frequency_table *freq_table, | ||
116 | unsigned long rate) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
121 | unsigned long freq = freq_table[i].frequency; | ||
122 | |||
123 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
124 | continue; | ||
125 | |||
126 | if (freq == rate) | ||
127 | return i; | ||
128 | } | ||
129 | |||
130 | return -ENOENT; | ||
131 | } | ||
132 | |||
114 | /* Used for clocks that always have same value as the parent clock */ | 133 | /* Used for clocks that always have same value as the parent clock */ |
115 | unsigned long followparent_recalc(struct clk *clk) | 134 | unsigned long followparent_recalc(struct clk *clk) |
116 | { | 135 | { |