vserver 1.9.3
[linux-2.6.git] / arch / arm / mach-omap / clocks.c
1 /*
2  * Clock interface for OMAP
3  *
4  * Copyright (C) 2001 RidgeRun, Inc
5  * Written by Gordon McNutt <gmcnutt@ridgerun.com>
6  * Updated 2004 for Linux 2.6 by Tony Lindgren <tony@atomide.com>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  *
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, write to the Free Software Foundation, Inc.,
26  * 675 Mass Ave, Cambridge, MA 02139, USA.
27  */
28
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/spinlock.h>
34 #include <asm/errno.h>
35 #include <asm/io.h>
36 #include <asm/arch/clocks.h>
37 #include <asm/arch/board.h>
38
39 extern void start_mputimer1(unsigned long load_val);
40
41 /* Input clock in MHz */
42 static unsigned int source_clock = 12;
43
44 /*
45  * We use one spinlock for all clock registers for now. We may want to
46  * change this to be clock register specific later on. Before we can do
47  * that, we need to map out the shared clock registers.
48  */
49 static spinlock_t clock_lock = SPIN_LOCK_UNLOCKED;
50
51 typedef struct {
52         char            *name;
53         __u8            flags;
54         ck_t            parent;
55         unsigned long   rate_reg;       /* Clock rate register */
56         unsigned long   enbl_reg;       /* Enable register */
57         unsigned long   idle_reg;       /* Idle register */
58         unsigned long   slct_reg;       /* Select register */
59         __s8            rate_shift;     /* Clock rate bit shift */
60         __s8            enbl_shift;     /* Clock enable bit shift */
61         __s8            idle_shift;     /* Clock idle bit shift */
62         __s8            slct_shift;     /* Clock select bit shift */
63 } ck_info_t;
64
65 #define CK_NAME(ck)             ck_info_table[ck].name
66 #define CK_FLAGS(ck)            ck_info_table[ck].flags
67 #define CK_PARENT(ck)           ck_info_table[ck].parent
68 #define CK_RATE_REG(ck)         ck_info_table[ck].rate_reg
69 #define CK_ENABLE_REG(ck)       ck_info_table[ck].enbl_reg
70 #define CK_IDLE_REG(ck)         ck_info_table[ck].idle_reg
71 #define CK_SELECT_REG(ck)       ck_info_table[ck].slct_reg
72 #define CK_RATE_SHIFT(ck)       ck_info_table[ck].rate_shift
73 #define CK_ENABLE_SHIFT(ck)     ck_info_table[ck].enbl_shift
74 #define CK_IDLE_SHIFT(ck)       ck_info_table[ck].idle_shift
75 #define CK_SELECT_SHIFT(ck)     ck_info_table[ck].slct_shift
76 #define CK_CAN_CHANGE_RATE(cl)  (CK_FLAGS(ck) & CK_RATEF)
77 #define CK_CAN_DISABLE(cl)      (CK_FLAGS(ck) & CK_ENABLEF)
78 #define CK_CAN_IDLE(cl)         (CK_FLAGS(ck) & CK_IDLEF)
79 #define CK_CAN_SWITCH(cl)       (CK_FLAGS(ck) & CK_SELECTF)
80
81 static ck_info_t ck_info_table[] = {
82         {
83                 .name           = "clkin",
84                 .flags          = 0,
85                 .parent         = OMAP_CLKIN,
86         }, {
87                 .name           = "ck_gen1",
88                 .flags          = CK_RATEF | CK_IDLEF,
89                 .rate_reg       = DPLL_CTL,
90                 .idle_reg       = ARM_IDLECT1,
91                 .idle_shift     = IDLDPLL_ARM,
92                 .parent         = OMAP_CLKIN,
93         }, {
94                 .name           = "ck_gen2",
95                 .flags          = 0,
96                 .parent         = OMAP_CK_GEN1,
97         }, {
98                 .name           = "ck_gen3",
99                 .flags          = 0,
100                 .parent         = OMAP_CK_GEN1,
101         }, {
102                 .name           = "tc_ck",
103                 .flags          = CK_RATEF | CK_IDLEF,
104                 .parent         = OMAP_CK_GEN3,
105                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
106                 .idle_reg       = ARM_IDLECT1,
107                 .rate_shift     = TCDIV,
108                 .idle_shift     = IDLIF_ARM
109         }, {
110                 .name           = "arm_ck",
111                 .flags          = CK_IDLEF | CK_RATEF,
112                 .parent         = OMAP_CK_GEN1,
113                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[ARMDIV(5:4)] */
114                 .idle_reg       = ARM_IDLECT1,
115                 .rate_shift     = ARMDIV,
116                 .idle_shift     = SETARM_IDLE,
117         }, {
118                 .name           = "mpuper_ck",
119                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
120                 .parent         = OMAP_CK_GEN1,
121                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[PERDIV(1:0)] */
122                 .enbl_reg       = ARM_IDLECT2,
123                 .idle_reg       = ARM_IDLECT1,
124                 .rate_shift     = PERDIV,
125                 .enbl_shift     = EN_PERCK,
126                 .idle_shift     = IDLPER_ARM
127         }, {
128                 .name           = "arm_gpio_ck",
129                 .flags          = CK_ENABLEF,
130                 .parent         = OMAP_CK_GEN1,
131                 .enbl_reg       = ARM_IDLECT2,
132                 .enbl_shift     = EN_GPIOCK
133         }, {
134                 .name           = "mpuxor_ck",
135                 .flags          = CK_ENABLEF | CK_IDLEF,
136                 .parent         = OMAP_CLKIN,
137                 .idle_reg       = ARM_IDLECT1,
138                 .enbl_reg       = ARM_IDLECT2,
139                 .idle_shift     = IDLXORP_ARM,
140                 .enbl_shift     = EN_XORPCK
141         }, {
142                 .name           = "mputim_ck",
143                 .flags          = CK_IDLEF | CK_ENABLEF | CK_SELECTF,
144                 .parent         = OMAP_CLKIN,
145                 .idle_reg       = ARM_IDLECT1,
146                 .enbl_reg       = ARM_IDLECT2,
147                 .slct_reg       = ARM_CKCTL,
148                 .idle_shift     = IDLTIM_ARM,
149                 .enbl_shift     = EN_TIMCK,
150                 .slct_shift     = ARM_TIMXO
151         }, {
152                 .name           = "mpuwd_ck",
153                 .flags          = CK_IDLEF | CK_ENABLEF,
154                 .parent         = OMAP_CLKIN,
155                 .idle_reg       = ARM_IDLECT1,
156                 .enbl_reg       = ARM_IDLECT2,
157                 .idle_shift     = IDLWDT_ARM,
158                 .enbl_shift     = EN_WDTCK,
159         }, {
160                 .name           = "dsp_ck",
161                 .flags          = CK_RATEF | CK_ENABLEF,
162                 .parent         = OMAP_CK_GEN2,
163                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[DSPDIV(7:6)] */
164                 .enbl_reg       = ARM_CKCTL,
165                 .rate_shift     = DSPDIV,
166                 .enbl_shift     = EN_DSPCK,
167         }, {
168                 .name           = "dspmmu_ck",
169                 .flags          = CK_RATEF | CK_ENABLEF,
170                 .parent         = OMAP_CK_GEN2,
171                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[DSPMMUDIV(11:10)] */
172                 .enbl_reg       = ARM_CKCTL,
173                 .rate_shift     = DSPMMUDIV,
174                 .enbl_shift     = EN_DSPCK,
175         }, {
176                 .name           = "dma_ck",
177                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
178                 .parent         = OMAP_CK_GEN3,
179                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
180                 .idle_reg       = ARM_IDLECT1,
181                 .enbl_reg       = ARM_IDLECT2,
182                 .rate_shift     = TCDIV,
183                 .idle_shift     = IDLIF_ARM,
184                 .enbl_shift     = DMACK_REQ
185         }, {
186                 .name           = "api_ck",
187                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
188                 .parent         = OMAP_CK_GEN3,
189                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
190                 .idle_reg       = ARM_IDLECT1,
191                 .enbl_reg       = ARM_IDLECT2,
192                 .rate_shift     = TCDIV,
193                 .idle_shift     = IDLAPI_ARM,
194                 .enbl_shift     = EN_APICK,
195         }, {
196                 .name           = "hsab_ck",
197                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
198                 .parent         = OMAP_CK_GEN3,
199                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
200                 .idle_reg       = ARM_IDLECT1,
201                 .enbl_reg       = ARM_IDLECT2,
202                 .rate_shift     = TCDIV,
203                 .idle_shift     = IDLHSAB_ARM,
204                 .enbl_shift     = EN_HSABCK,
205         }, {
206                 .name           = "lbfree_ck",
207                 .flags          = CK_RATEF | CK_ENABLEF,
208                 .parent         = OMAP_CK_GEN3,
209                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
210                 .enbl_reg       = ARM_IDLECT2,
211                 .rate_shift     = TCDIV,
212                 .enbl_shift     = EN_LBFREECK,
213         }, {
214                 .name           = "lb_ck",
215                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
216                 .parent         = OMAP_CK_GEN3,
217                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[TCDIV(9:8)] */
218                 .idle_reg       = ARM_IDLECT1,
219                 .enbl_reg       = ARM_IDLECT2,
220                 .rate_shift     = TCDIV,
221                 .idle_shift     = IDLLB_ARM,
222                 .enbl_shift     = EN_LBCK,
223         }, {
224                 .name           = "lcd_ck",
225                 .flags          = CK_RATEF | CK_IDLEF | CK_ENABLEF,
226                 .parent         = OMAP_CK_GEN3,
227                 .rate_reg       = ARM_CKCTL,    /* ARM_CKCTL[LCDDIV(3:2)] */
228                 .idle_reg       = ARM_IDLECT1,
229                 .enbl_reg       = ARM_IDLECT2,
230                 .rate_shift     = LCDDIV,
231                 .idle_shift     = IDLLCD_ARM,
232                 .enbl_shift     = EN_LCDCK,
233         },
234 };
235
236 /*****************************************************************************/
237
238 #define CK_IN_RANGE(ck)         (!((ck < OMAP_CK_MIN) || (ck > OMAP_CK_MAX)))
239
240 int ck_auto_unclock = 1;
241 int ck_debug = 0;
242
243 #define CK_MAX_PLL_FREQ         OMAP_CK_MAX_RATE
244 static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
245 static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
246
247 int
248 ck_set_input(ck_t ck, ck_t input)
249 {
250         int ret = 0, shift;
251         unsigned short reg;
252         unsigned long flags;
253
254         if (!CK_IN_RANGE(ck) || !CK_CAN_SWITCH(ck)) {
255                 ret = -EINVAL;
256                 goto exit;
257         }
258
259         reg = omap_readw(CK_SELECT_REG(ck));
260         shift = CK_SELECT_SHIFT(ck);
261
262         spin_lock_irqsave(&clock_lock, flags);
263         if (input == OMAP_CLKIN) {
264                 reg &= ~(1 << shift);
265                 omap_writew(reg, CK_SELECT_REG(ck));
266                 goto exit;
267         } else if (input == CK_PARENT(ck)) {
268                 reg |= (1 << shift);
269                 omap_writew(reg, CK_SELECT_REG(ck));
270                 goto exit;
271         }
272
273         ret = -EINVAL;
274  exit:
275         spin_unlock_irqrestore(&clock_lock, flags);
276         return ret;
277 }
278
279 int
280 ck_get_input(ck_t ck, ck_t * input)
281 {
282         int ret = -EINVAL;
283         unsigned long flags;
284
285         if (!CK_IN_RANGE(ck))
286                 goto exit;
287
288         ret = 0;
289
290         spin_lock_irqsave(&clock_lock, flags);
291         if (CK_CAN_SWITCH(ck)) {
292                 int shift;
293                 unsigned short reg;
294
295                 reg = omap_readw(CK_SELECT_REG(ck));
296                 shift = CK_SELECT_SHIFT(ck);
297                 if (reg & (1 << shift)) {
298                         *input = CK_PARENT(ck);
299                         goto exit;
300                 }
301         }
302
303         *input = OMAP_CLKIN;
304
305  exit:
306         spin_unlock_irqrestore(&clock_lock, flags);
307         return ret;
308 }
309
310 static int
311 __ck_set_pll_rate(ck_t ck, int rate)
312 {
313         unsigned short pll;
314         unsigned long flags;
315
316         if ((rate < 0) || (rate > CK_MAX_PLL_FREQ))
317                 return -EINVAL;
318
319         /* Scan downward for the closest matching frequency */
320         while (rate && !test_bit(rate, (unsigned long *)&ck_valid_table))
321                 rate--;
322
323         if (!rate) {
324                 printk(KERN_ERR "%s: couldn't find a matching rate\n",
325                         __FUNCTION__);
326                 return -EINVAL;
327         }
328
329         spin_lock_irqsave(&clock_lock, flags);
330         pll = omap_readw(CK_RATE_REG(ck));
331
332         /* Clear the rate bits */
333         pll &= ~(0x1f << 5);
334
335         /* Set the rate bits */
336         pll |= (ck_lookup_table[rate - 1] << 5);
337
338         omap_writew(pll, CK_RATE_REG(ck));
339
340         spin_unlock_irqrestore(&clock_lock, flags);
341
342         return 0;
343 }
344
345 static int
346 __ck_set_clkm_rate(ck_t ck, int rate)
347 {
348         int shift, prate, div, ret;
349         unsigned short reg;
350         unsigned long flags;
351
352         spin_lock_irqsave(&clock_lock, flags);
353
354         /*
355          * We can only set this clock's value to a fraction of its
356          * parent's value. The interface says I'll round down when necessary.
357          * So first let's get the parent's current rate.
358          */
359         prate = ck_get_rate(CK_PARENT(ck));
360
361         /*
362          * Let's just start with the highest fraction and keep searching
363          * down through available rates until we find one less than or equal
364          * to the desired rate.
365          */
366         for (div = 0; div < 4; div++) {
367                 if (prate <= rate)
368                         break;
369                 prate = prate / 2;
370         }
371
372         /*
373          * Oops. Looks like the caller wants a rate lower than we can support.
374          */
375         if (div == 5) {
376                 printk(KERN_ERR "%s: %d is too low\n",
377                         __FUNCTION__, rate);
378                 ret = -EINVAL;
379                 goto exit;
380         }
381
382         /*
383          * One more detail: if this clock supports more than one parent, then
384          * we're going to automatically switch over to the parent which runs
385          * through the divisor. For omap this is not ambiguous because for all
386          * such clocks one choice is always OMAP_CLKIN (which doesn't run
387          * through the divisor) and the other is whatever I encoded as
388          * CK_PARENT. Note that I wait until we get this far because I don't
389          * want to switch the input until we're sure this is going to work.
390          */
391         if (CK_CAN_SWITCH(ck))
392                 if ((ret = ck_set_input(ck, CK_PARENT(ck))) < 0) {
393                         BUG();
394                         goto exit;
395                 }
396
397         /*
398          * At last, we can set the divisor. Clear the old rate bits and
399          * set the new ones.
400          */
401         reg = omap_readw(CK_RATE_REG(ck));
402         shift = CK_RATE_SHIFT(ck);
403         reg &= ~(3 << shift);
404         reg |= (div << shift);
405         omap_writew(reg, CK_RATE_REG(ck));
406
407         /* And return the new (actual, after rounding down) rate. */
408         ret = prate;
409
410  exit:
411         spin_unlock_irqrestore(&clock_lock, flags);
412         return ret;
413 }
414
415 int
416 ck_set_rate(ck_t ck, int rate)
417 {
418         int ret = -EINVAL;
419
420         if (!CK_IN_RANGE(ck) || !CK_CAN_CHANGE_RATE(ck))
421                 goto exit;
422
423         switch (ck) {
424
425         default:
426                 ret = __ck_set_clkm_rate(ck, rate);
427                 break;
428
429         case OMAP_CK_GEN1:
430                 ret = __ck_set_pll_rate(ck, rate);
431                 break;
432
433         };
434
435  exit:
436         return ret;
437 }
438
439 static int
440 __ck_get_pll_rate(ck_t ck)
441 {
442         int m, d;
443
444         unsigned short pll = omap_readw(CK_RATE_REG(ck));
445
446         m = (pll & (0x1f << 7)) >> 7;
447         m = m ? m : 1;
448         d = (pll & (3 << 5)) >> 5;
449         d++;
450
451         return ((source_clock * m) / d);
452 }
453
454 static int
455 __ck_get_clkm_rate(ck_t ck)
456 {
457         static int bits2div[] = { 1, 2, 4, 8 };
458         int in, bits, reg, shift;
459
460         reg = omap_readw(CK_RATE_REG(ck));
461         shift = CK_RATE_SHIFT(ck);
462
463         in = ck_get_rate(CK_PARENT(ck));
464         bits = (reg & (3 << shift)) >> shift;
465
466         return (in / bits2div[bits]);
467 }
468
469 int
470 ck_get_rate(ck_t ck)
471 {
472         int ret = 0;
473         ck_t parent;
474
475         if (!CK_IN_RANGE(ck)) {
476                 ret = -EINVAL;
477                 goto exit;
478         }
479
480         switch (ck) {
481
482         case OMAP_CK_GEN1:
483                 ret = __ck_get_pll_rate(ck);
484                 break;
485
486         case OMAP_CLKIN:
487                 ret = source_clock;
488                 break;
489
490         case OMAP_MPUXOR_CK:
491         case OMAP_CK_GEN2:
492         case OMAP_CK_GEN3:
493         case OMAP_ARM_GPIO_CK:
494                 ret = ck_get_rate(CK_PARENT(ck));
495                 break;
496
497         case OMAP_ARM_CK:
498         case OMAP_MPUPER_CK:
499         case OMAP_DSP_CK:
500         case OMAP_DSPMMU_CK:
501         case OMAP_LCD_CK:
502         case OMAP_TC_CK:
503         case OMAP_DMA_CK:
504         case OMAP_API_CK:
505         case OMAP_HSAB_CK:
506         case OMAP_LBFREE_CK:
507         case OMAP_LB_CK:
508                 ret = __ck_get_clkm_rate(ck);
509                 break;
510
511         case OMAP_MPUTIM_CK:
512                 ck_get_input(ck, &parent);
513                 ret = ck_get_rate(parent);
514                 break;
515
516         case OMAP_MPUWD_CK:
517                 /* Note that this evaluates to zero if source_clock is 12MHz. */
518                 ret = source_clock / 14;
519                 break;
520         default:
521                 ret = -EINVAL;
522                 break;
523         }
524
525  exit:
526         return ret;
527 }
528
529 int
530 ck_enable(ck_t ck)
531 {
532         unsigned short reg;
533         int ret = -EINVAL, shift;
534         unsigned long flags;
535
536         if (!CK_IN_RANGE(ck))
537                 goto exit;
538
539         if (ck_debug)
540                 printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
541
542         ret = 0;
543
544         if (!CK_CAN_DISABLE(ck))
545                 /* Then it must be on... */
546                 goto exit;
547
548         spin_lock_irqsave(&clock_lock, flags);
549         reg = omap_readw(CK_ENABLE_REG(ck));
550         shift = CK_ENABLE_SHIFT(ck);
551         reg |= (1 << shift);
552         omap_writew(reg, CK_ENABLE_REG(ck));
553         spin_unlock_irqrestore(&clock_lock, flags);
554
555  exit:
556         return ret;
557 }
558
559 int
560 ck_disable(ck_t ck)
561 {
562         unsigned short reg;
563         int ret = -EINVAL, shift;
564         unsigned long flags;
565
566         if (!CK_IN_RANGE(ck))
567                 goto exit;
568
569         if (ck_debug)
570                 printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
571
572         if (!CK_CAN_DISABLE(ck))
573                 goto exit;
574
575         ret = 0;
576
577         if (ck == OMAP_CLKIN)
578                 return -EINVAL;
579
580         spin_lock_irqsave(&clock_lock, flags);
581         reg = omap_readw(CK_ENABLE_REG(ck));
582         shift = CK_ENABLE_SHIFT(ck);
583         reg &= ~(1 << shift);
584         omap_writew(reg, CK_ENABLE_REG(ck));
585         spin_unlock_irqrestore(&clock_lock, flags);
586
587  exit:
588         return ret;
589 }
590
591 int ck_valid_rate(int rate)
592 {
593         return test_bit(rate, (unsigned long *)&ck_valid_table);
594 }
595
596 static void
597 __ck_make_lookup_table(void)
598 {
599         __u8 m, d;
600
601         memset(ck_valid_table, 0, sizeof (ck_valid_table));
602
603         for (m = 1; m < 32; m++)
604                 for (d = 1; d < 5; d++) {
605
606                         int rate = ((source_clock * m) / (d));
607
608                         if (rate > CK_MAX_PLL_FREQ)
609                                 continue;
610                         if (test_bit(rate, (unsigned long *)&ck_valid_table))
611                                 continue;
612                         set_bit(rate, (unsigned long *)&ck_valid_table);
613                         ck_lookup_table[rate - 1] = (m << 2) | (d - 1);
614                 }
615 }
616
617 int __init
618 init_ck(void)
619 {
620         const struct omap_clock_config *info;
621         int crystal_type = 0; /* Default 12 MHz */
622
623         __ck_make_lookup_table();
624         info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
625         if (info != NULL) {
626                 if (!cpu_is_omap1510())
627                         crystal_type = info->system_clock_type;
628         }
629
630         /* We want to be in syncronous scalable mode */
631         omap_writew(0x1000, ARM_SYSST);
632 #if defined(CONFIG_OMAP_ARM_30MHZ)
633         omap_writew(0x1555, ARM_CKCTL);
634         omap_writew(0x2290, DPLL_CTL);
635 #elif defined(CONFIG_OMAP_ARM_60MHZ)
636         omap_writew(0x1005, ARM_CKCTL);
637         omap_writew(0x2290, DPLL_CTL);
638 #elif defined(CONFIG_OMAP_ARM_96MHZ)
639         omap_writew(0x1005, ARM_CKCTL);
640         omap_writew(0x2410, DPLL_CTL);
641 #elif defined(CONFIG_OMAP_ARM_120MHZ)
642         omap_writew(0x110a, ARM_CKCTL);
643         omap_writew(0x2510, DPLL_CTL);
644 #elif defined(CONFIG_OMAP_ARM_168MHZ)
645         omap_writew(0x110f, ARM_CKCTL);
646         omap_writew(0x2710, DPLL_CTL);
647 #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
648         omap_writew(0x250E, ARM_CKCTL);
649         omap_writew(0x2710, DPLL_CTL);
650 #elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
651                                           || defined(CONFIG_ARCH_OMAP1710))
652         omap_writew(0x150f, ARM_CKCTL);
653         if (crystal_type == 2) {
654                 source_clock = 13;      /* MHz */
655                 omap_writew(0x2510, DPLL_CTL);
656         } else
657                 omap_writew(0x2810, DPLL_CTL);
658 #elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
659         omap_writew(0x250E, ARM_CKCTL);
660         omap_writew(0x2790, DPLL_CTL);
661 #else
662 #error "OMAP MHZ not set, please run make xconfig"
663 #endif
664
665 #ifdef CONFIG_MACH_OMAP_PERSEUS2
666         /* Select slicer output as OMAP input clock */
667         omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
668 #endif
669
670         /* Turn off some other junk the bootloader might have turned on */
671
672         /* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
673         omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
674
675         /* Put DSP/MPUI into reset until needed */
676         omap_writew(0, ARM_RSTCT1);
677         omap_writew(1, ARM_RSTCT2);
678         omap_writew(0x400, ARM_IDLECT1);
679
680         /*
681          * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
682          * of the ARM_IDLECT2 register must be set to zero. The power-on
683          * default value of this bit is one.
684          */
685         omap_writew(0x0000, ARM_IDLECT2);       /* Turn LCD clock off also */
686
687         /*
688          * Only enable those clocks we will need, let the drivers
689          * enable other clocks as necessary
690          */
691         ck_enable(OMAP_MPUPER_CK);
692         ck_enable(OMAP_ARM_GPIO_CK);
693         ck_enable(OMAP_MPUXOR_CK);
694         //ck_set_rate(OMAP_MPUTIM_CK, OMAP_CLKIN);
695         ck_enable(OMAP_MPUTIM_CK);
696         start_mputimer1(0xffffffff);
697
698         return 0;
699 }
700
701
702 EXPORT_SYMBOL(ck_get_rate);
703 EXPORT_SYMBOL(ck_set_rate);
704 EXPORT_SYMBOL(ck_enable);
705 EXPORT_SYMBOL(ck_disable);