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