aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2008-03-18 09:09:51 -0400
committerTony Lindgren <tony@atomide.com>2008-04-14 13:29:39 -0400
commit02e19a960a519224a74da4d190965201044c1583 (patch)
treeee4bda760efdd18c1c9860251ec69fcb02d75f18 /arch/arm
parentb045d0809871eae4341e60a1db2b7d31703d8175 (diff)
ARM: OMAP2: Add 34xx clock code
This patch add 34xx clock code. Signed-off-by: Paul Walmsley <paul@pwsan.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/Makefile1
-rw-r--r--arch/arm/mach-omap2/clock34xx.c235
2 files changed, 236 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 2eabadc81083..2feb6870b735 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PM) += pm.o sleep.o
11 11
12# Clock framework 12# Clock framework
13obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o 13obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
14obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
14 15
15# Specific board support 16# Specific board support
16obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o 17obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
new file mode 100644
index 000000000000..f6c82a333815
--- /dev/null
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -0,0 +1,235 @@
1/*
2 * OMAP3-specific clock framework functions
3 *
4 * Copyright (C) 2007 Texas Instruments, Inc.
5 * Copyright (C) 2007 Nokia Corporation
6 *
7 * Written by Paul Walmsley
8 *
9 * Parts of this code are based on code written by
10 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16#undef DEBUG
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <linux/list.h>
22#include <linux/errno.h>
23#include <linux/delay.h>
24#include <linux/clk.h>
25#include <linux/io.h>
26
27#include <asm/arch/clock.h>
28#include <asm/arch/sram.h>
29#include <asm/div64.h>
30#include <asm/bitops.h>
31
32#include "memory.h"
33#include "clock.h"
34#include "clock34xx.h"
35#include "prm.h"
36#include "prm-regbits-34xx.h"
37#include "cm.h"
38#include "cm-regbits-34xx.h"
39
40/* CM_CLKEN_PLL*.EN* bit values */
41#define DPLL_LOCKED 0x7
42
43/**
44 * omap3_dpll_recalc - recalculate DPLL rate
45 * @clk: DPLL struct clk
46 *
47 * Recalculate and propagate the DPLL rate.
48 */
49static void omap3_dpll_recalc(struct clk *clk)
50{
51 clk->rate = omap2_get_dpll_rate(clk);
52
53 propagate_rate(clk);
54}
55
56/**
57 * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
58 * @clk: DPLL output struct clk
59 *
60 * Using parent clock DPLL data, look up DPLL state. If locked, set our
61 * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
62 */
63static void omap3_clkoutx2_recalc(struct clk *clk)
64{
65 const struct dpll_data *dd;
66 u32 v;
67 struct clk *pclk;
68
69 /* Walk up the parents of clk, looking for a DPLL */
70 pclk = clk->parent;
71 while (pclk && !pclk->dpll_data)
72 pclk = pclk->parent;
73
74 /* clk does not have a DPLL as a parent? */
75 WARN_ON(!pclk);
76
77 dd = pclk->dpll_data;
78
79 WARN_ON(!dd->control_reg || !dd->enable_mask);
80
81 v = __raw_readl(dd->control_reg) & dd->enable_mask;
82 v >>= __ffs(dd->enable_mask);
83 if (v != DPLL_LOCKED)
84 clk->rate = clk->parent->rate;
85 else
86 clk->rate = clk->parent->rate * 2;
87
88 if (clk->flags & RATE_PROPAGATES)
89 propagate_rate(clk);
90}
91
92/*
93 * As it is structured now, this will prevent an OMAP2/3 multiboot
94 * kernel from compiling. This will need further attention.
95 */
96#if defined(CONFIG_ARCH_OMAP3)
97
98static struct clk_functions omap2_clk_functions = {
99 .clk_enable = omap2_clk_enable,
100 .clk_disable = omap2_clk_disable,
101 .clk_round_rate = omap2_clk_round_rate,
102 .clk_set_rate = omap2_clk_set_rate,
103 .clk_set_parent = omap2_clk_set_parent,
104 .clk_disable_unused = omap2_clk_disable_unused,
105};
106
107/*
108 * Set clocks for bypass mode for reboot to work.
109 */
110void omap2_clk_prepare_for_reboot(void)
111{
112 /* REVISIT: Not ready for 343x */
113#if 0
114 u32 rate;
115
116 if (vclk == NULL || sclk == NULL)
117 return;
118
119 rate = clk_get_rate(sclk);
120 clk_set_rate(vclk, rate);
121#endif
122}
123
124/* REVISIT: Move this init stuff out into clock.c */
125
126/*
127 * Switch the MPU rate if specified on cmdline.
128 * We cannot do this early until cmdline is parsed.
129 */
130static int __init omap2_clk_arch_init(void)
131{
132 if (!mpurate)
133 return -EINVAL;
134
135 /* REVISIT: not yet ready for 343x */
136#if 0
137 if (omap2_select_table_rate(&virt_prcm_set, mpurate))
138 printk(KERN_ERR "Could not find matching MPU rate\n");
139#endif
140
141 recalculate_root_clocks();
142
143 printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
144 "%ld.%01ld/%ld/%ld MHz\n",
145 (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
146 (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
147
148 return 0;
149}
150arch_initcall(omap2_clk_arch_init);
151
152int __init omap2_clk_init(void)
153{
154 /* struct prcm_config *prcm; */
155 struct clk **clkp;
156 /* u32 clkrate; */
157 u32 cpu_clkflg;
158
159 /* REVISIT: Ultimately this will be used for multiboot */
160#if 0
161 if (cpu_is_omap242x()) {
162 cpu_mask = RATE_IN_242X;
163 cpu_clkflg = CLOCK_IN_OMAP242X;
164 clkp = onchip_24xx_clks;
165 } else if (cpu_is_omap2430()) {
166 cpu_mask = RATE_IN_243X;
167 cpu_clkflg = CLOCK_IN_OMAP243X;
168 clkp = onchip_24xx_clks;
169 }
170#endif
171 if (cpu_is_omap34xx()) {
172 cpu_mask = RATE_IN_343X;
173 cpu_clkflg = CLOCK_IN_OMAP343X;
174 clkp = onchip_34xx_clks;
175
176 /*
177 * Update this if there are further clock changes between ES2
178 * and production parts
179 */
180 if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0)) {
181 /* No 3430ES1-only rates exist, so no RATE_IN_3430ES1 */
182 cpu_clkflg |= CLOCK_IN_OMAP3430ES1;
183 } else {
184 cpu_mask |= RATE_IN_3430ES2;
185 cpu_clkflg |= CLOCK_IN_OMAP3430ES2;
186 }
187 }
188
189 clk_init(&omap2_clk_functions);
190
191 for (clkp = onchip_34xx_clks;
192 clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
193 clkp++) {
194 if ((*clkp)->flags & cpu_clkflg)
195 clk_register(*clkp);
196 }
197
198 /* REVISIT: Not yet ready for OMAP3 */
199#if 0
200 /* Check the MPU rate set by bootloader */
201 clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
202 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
203 if (!(prcm->flags & cpu_mask))
204 continue;
205 if (prcm->xtal_speed != sys_ck.rate)
206 continue;
207 if (prcm->dpll_speed <= clkrate)
208 break;
209 }
210 curr_prcm_set = prcm;
211#endif
212
213 recalculate_root_clocks();
214
215 printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
216 "%ld.%01ld/%ld/%ld MHz\n",
217 (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
218 (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
219
220 /*
221 * Only enable those clocks we will need, let the drivers
222 * enable other clocks as necessary
223 */
224 clk_enable_init_clocks();
225
226 /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
227 /* REVISIT: not yet ready for 343x */
228#if 0
229 vclk = clk_get(NULL, "virt_prcm_set");
230 sclk = clk_get(NULL, "sys_ck");
231#endif
232 return 0;
233}
234
235#endif