Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / arch / arm / mach-omap2 / clock34xx.c
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
26 #include <linux/io.h>
27
28 #include <asm/arch/clock.h>
29 #include <asm/arch/sram.h>
30 #include <asm/div64.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  */
49 static 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  */
63 static 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 = cm_read_reg(dd->control_reg) & dd->enable_mask;
82         if (v != DPLL_LOCKED)
83                 clk->rate = clk->parent->rate;
84         else
85                 clk->rate = clk->parent->rate * 2;
86
87         if (clk->flags & RATE_PROPAGATES)
88                 propagate_rate(clk);
89 }
90
91 /*
92  * As it is structured now, this will prevent an OMAP2/3 multiboot
93  * kernel from compiling.  This will need further attention.
94  */
95 #if defined(CONFIG_ARCH_OMAP3)
96
97 static struct clk_functions omap2_clk_functions = {
98         .clk_enable             = omap2_clk_enable,
99         .clk_disable            = omap2_clk_disable,
100         .clk_round_rate         = omap2_clk_round_rate,
101         .clk_set_rate           = omap2_clk_set_rate,
102         .clk_set_parent         = omap2_clk_set_parent,
103         .clk_disable_unused     = omap2_clk_disable_unused,
104 };
105
106 /*
107  * Set clocks for bypass mode for reboot to work.
108  */
109 void omap2_clk_prepare_for_reboot(void)
110 {
111         /* REVISIT: Not ready for 343x */
112 #if 0
113         u32 rate;
114
115         if (vclk == NULL || sclk == NULL)
116                 return;
117
118         rate = clk_get_rate(sclk);
119         clk_set_rate(vclk, rate);
120 #endif
121 }
122
123 /* REVISIT: Move this init stuff out into clock.c */
124
125 /*
126  * Switch the MPU rate if specified on cmdline.
127  * We cannot do this early until cmdline is parsed.
128  */
129 static int __init omap2_clk_arch_init(void)
130 {
131         if (!mpurate)
132                 return -EINVAL;
133
134         /* REVISIT: not yet ready for 343x */
135 #if 0
136         if (omap2_select_table_rate(&virt_prcm_set, mpurate))
137                 printk(KERN_ERR "Could not find matching MPU rate\n");
138 #endif
139
140         recalculate_root_clocks();
141
142         printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
143                "%ld.%01ld/%ld/%ld MHz\n",
144                (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
145                (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
146
147         return 0;
148 }
149 arch_initcall(omap2_clk_arch_init);
150
151 int __init omap2_clk_init(void)
152 {
153         /* struct prcm_config *prcm; */
154         struct clk **clkp;
155         /* u32 clkrate; */
156         u32 cpu_clkflg;
157
158         /* REVISIT: Ultimately this will be used for multiboot */
159 #if 0
160         if (cpu_is_omap242x()) {
161                 cpu_mask = RATE_IN_242X;
162                 cpu_clkflg = CLOCK_IN_OMAP242X;
163                 clkp = onchip_24xx_clks;
164         } else if (cpu_is_omap2430()) {
165                 cpu_mask = RATE_IN_243X;
166                 cpu_clkflg = CLOCK_IN_OMAP243X;
167                 clkp = onchip_24xx_clks;
168         }
169 #endif
170         if (cpu_is_omap34xx()) {
171                 cpu_mask = RATE_IN_343X;
172                 cpu_clkflg = CLOCK_IN_OMAP343X;
173                 clkp = onchip_34xx_clks;
174         }
175
176         clk_init(&omap2_clk_functions);
177
178         for (clkp = onchip_34xx_clks;
179              clkp < onchip_34xx_clks + ARRAY_SIZE(onchip_34xx_clks);
180              clkp++) {
181                 if ((*clkp)->flags & cpu_clkflg)
182                         clk_register(*clkp);
183         }
184
185         /* REVISIT: Not yet ready for OMAP3 */
186 #if 0
187         /* Check the MPU rate set by bootloader */
188         clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
189         for (prcm = rate_table; prcm->mpu_speed; prcm++) {
190                 if (!(prcm->flags & cpu_mask))
191                         continue;
192                 if (prcm->xtal_speed != sys_ck.rate)
193                         continue;
194                 if (prcm->dpll_speed <= clkrate)
195                          break;
196         }
197         curr_prcm_set = prcm;
198 #endif
199
200         recalculate_root_clocks();
201
202         printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
203                "%ld.%01ld/%ld/%ld MHz\n",
204                (osc_sys_ck.rate / 1000000), (osc_sys_ck.rate / 100000) % 10,
205                (core_ck.rate / 1000000), (dpll1_fck.rate / 1000000)) ;
206
207         /*
208          * Only enable those clocks we will need, let the drivers
209          * enable other clocks as necessary
210          */
211         clk_enable_init_clocks();
212
213         /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
214         /* REVISIT: not yet ready for 343x */
215 #if 0
216         vclk = clk_get(NULL, "virt_prcm_set");
217         sclk = clk_get(NULL, "sys_ck");
218 #endif
219         return 0;
220 }
221
222 #endif