aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx/clock.c
diff options
context:
space:
mode:
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 };