aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx/clock.c
diff options
context:
space:
mode:
authorHartley Sweeten <hartleys@visionengravers.com>2009-06-30 18:06:43 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-07-09 11:10:51 -0400
commit701fac823e24676ea42451c6597f96d81d9b6aba (patch)
tree3eb175f82590b8bf4330cd050977c371f2586244 /arch/arm/mach-ep93xx/clock.c
parent02239f0a4264608686cc0015d906c7b2dead89df (diff)
[ARM] 5578/1: ep93xx: add ep93xx-keypad clock
Add clkdev support for the ep93xx_keypad driver. A matrix keypad driver for the ep93xx just got merged via the input subsystem group. For this driver to work the keypad clock needs to be added to the ep93xx clkdev support. In order to accomplish this the following changes are implemented: 1) Move the EP93XX_EXT_*_RATE defines to mach/include/hardware.h. 2) Add EP93XX_KEYTCHCLK_DIV{4/16} for the keypad driver. 3) Add support for programmable clocks (set_rate() callback). 4) Add clk_keypad for the keypad driver. 5) tab indent the clk_lookup table for easier reading. 6) Add the set_rate() callback to program the keypad clock. This callback is generalized since the ADC clock (touchscreen) can use the same callback. 7) Use the ep93xx_syscon_swlocked_write() core function for updating the software locked register. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ep93xx/clock.c')
-rw-r--r--arch/arm/mach-ep93xx/clock.c101
1 files changed, 68 insertions, 33 deletions
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index c7642acfd022..207e27699410 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -22,18 +22,6 @@
22#include <mach/hardware.h> 22#include <mach/hardware.h>
23 23
24 24
25/*
26 * The EP93xx has two external crystal oscillators. To generate the
27 * required high-frequency clocks, the processor uses two phase-locked-
28 * loops (PLLs) to multiply the incoming external clock signal to much
29 * higher frequencies that are then divided down by programmable dividers
30 * to produce the needed clocks. The PLLs operate independently of one
31 * another.
32 */
33#define EP93XX_EXT_CLK_RATE 14745600
34#define EP93XX_EXT_RTC_RATE 32768
35
36
37struct clk { 25struct clk {
38 unsigned long rate; 26 unsigned long rate;
39 int users; 27 int users;
@@ -42,11 +30,14 @@ struct clk {
42 u32 enable_mask; 30 u32 enable_mask;
43 31
44 unsigned long (*get_rate)(struct clk *clk); 32 unsigned long (*get_rate)(struct clk *clk);
33 int (*set_rate)(struct clk *clk, unsigned long rate);
45}; 34};
46 35
47 36
48static unsigned long get_uart_rate(struct clk *clk); 37static unsigned long get_uart_rate(struct clk *clk);
49 38
39static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
40
50 41
51static struct clk clk_uart1 = { 42static struct clk clk_uart1 = {
52 .sw_locked = 1, 43 .sw_locked = 1,
@@ -75,6 +66,12 @@ static struct clk clk_usb_host = {
75 .enable_reg = EP93XX_SYSCON_PWRCNT, 66 .enable_reg = EP93XX_SYSCON_PWRCNT,
76 .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN, 67 .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN,
77}; 68};
69static struct clk clk_keypad = {
70 .sw_locked = 1,
71 .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV,
72 .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
73 .set_rate = set_keytchclk_rate,
74};
78 75
79/* DMA Clocks */ 76/* DMA Clocks */
80static struct clk clk_m2p0 = { 77static struct clk clk_m2p0 = {
@@ -130,27 +127,28 @@ static struct clk clk_m2m1 = {
130 { .dev_id = dev, .con_id = con, .clk = ck } 127 { .dev_id = dev, .con_id = con, .clk = ck }
131 128
132static struct clk_lookup clocks[] = { 129static struct clk_lookup clocks[] = {
133 INIT_CK("apb:uart1", NULL, &clk_uart1), 130 INIT_CK("apb:uart1", NULL, &clk_uart1),
134 INIT_CK("apb:uart2", NULL, &clk_uart2), 131 INIT_CK("apb:uart2", NULL, &clk_uart2),
135 INIT_CK("apb:uart3", NULL, &clk_uart3), 132 INIT_CK("apb:uart3", NULL, &clk_uart3),
136 INIT_CK(NULL, "pll1", &clk_pll1), 133 INIT_CK(NULL, "pll1", &clk_pll1),
137 INIT_CK(NULL, "fclk", &clk_f), 134 INIT_CK(NULL, "fclk", &clk_f),
138 INIT_CK(NULL, "hclk", &clk_h), 135 INIT_CK(NULL, "hclk", &clk_h),
139 INIT_CK(NULL, "pclk", &clk_p), 136 INIT_CK(NULL, "pclk", &clk_p),
140 INIT_CK(NULL, "pll2", &clk_pll2), 137 INIT_CK(NULL, "pll2", &clk_pll2),
141 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), 138 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
142 INIT_CK(NULL, "m2p0", &clk_m2p0), 139 INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
143 INIT_CK(NULL, "m2p1", &clk_m2p1), 140 INIT_CK(NULL, "m2p0", &clk_m2p0),
144 INIT_CK(NULL, "m2p2", &clk_m2p2), 141 INIT_CK(NULL, "m2p1", &clk_m2p1),
145 INIT_CK(NULL, "m2p3", &clk_m2p3), 142 INIT_CK(NULL, "m2p2", &clk_m2p2),
146 INIT_CK(NULL, "m2p4", &clk_m2p4), 143 INIT_CK(NULL, "m2p3", &clk_m2p3),
147 INIT_CK(NULL, "m2p5", &clk_m2p5), 144 INIT_CK(NULL, "m2p4", &clk_m2p4),
148 INIT_CK(NULL, "m2p6", &clk_m2p6), 145 INIT_CK(NULL, "m2p5", &clk_m2p5),
149 INIT_CK(NULL, "m2p7", &clk_m2p7), 146 INIT_CK(NULL, "m2p6", &clk_m2p6),
150 INIT_CK(NULL, "m2p8", &clk_m2p8), 147 INIT_CK(NULL, "m2p7", &clk_m2p7),
151 INIT_CK(NULL, "m2p9", &clk_m2p9), 148 INIT_CK(NULL, "m2p8", &clk_m2p8),
152 INIT_CK(NULL, "m2m0", &clk_m2m0), 149 INIT_CK(NULL, "m2p9", &clk_m2p9),
153 INIT_CK(NULL, "m2m1", &clk_m2m1), 150 INIT_CK(NULL, "m2m0", &clk_m2m0),
151 INIT_CK(NULL, "m2m1", &clk_m2m1),
154}; 152};
155 153
156 154
@@ -206,6 +204,43 @@ unsigned long clk_get_rate(struct clk *clk)
206} 204}
207EXPORT_SYMBOL(clk_get_rate); 205EXPORT_SYMBOL(clk_get_rate);
208 206
207static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
208{
209 u32 val;
210 u32 div_bit;
211
212 val = __raw_readl(clk->enable_reg);
213
214 /*
215 * The Key Matrix and ADC clocks are configured using the same
216 * System Controller register. The clock used will be either
217 * 1/4 or 1/16 the external clock rate depending on the
218 * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV
219 * bit being set or cleared.
220 */
221 div_bit = clk->enable_mask >> 15;
222
223 if (rate == EP93XX_KEYTCHCLK_DIV4)
224 val |= div_bit;
225 else if (rate == EP93XX_KEYTCHCLK_DIV16)
226 val &= ~div_bit;
227 else
228 return -EINVAL;
229
230 ep93xx_syscon_swlocked_write(val, clk->enable_reg);
231 clk->rate = rate;
232 return 0;
233}
234
235int clk_set_rate(struct clk *clk, unsigned long rate)
236{
237 if (clk->set_rate)
238 return clk->set_rate(clk, rate);
239
240 return -EINVAL;
241}
242EXPORT_SYMBOL(clk_set_rate);
243
209 244
210static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; 245static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
211static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; 246static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };