f08d2a326e032999590ec74193320a9eaddca728
[bertos.git] / bertos / cpu / arm / hw / init_lpc2.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \author Francesco Sacchi <batt@develer.com>
34  *
35  * \brief LPC2378 CRT.
36  * notest:arm
37  */
38 #include <cpu/irq.h>
39 #include <io/lpc23xx.h>
40
41 #if CPU_FREQ != 72000000UL
42         /* Avoid errors on nightly test */
43         #if !defined(ARCH_NIGHTTEST) || !(ARCH & ARCH_NIGHTTEST)
44                 #warning Clock registers set for 72MHz operation, revise following code if you want a different clock.
45         #endif
46 #endif
47
48 /*
49  * With a 12MHz cristal, master clock is:
50  * (((2 * 12 * (PLL_MUL_VAL + 1)) / (PLL_DIV_VAL + 1)) / (LPC2_CPUCLOCK_DIV + 1))= 72MHz
51  */
52 #define PLL_MUL_VAL  11
53 #define PLL_DIV_VAL  0
54 #define LPC2_CPUCLOCK_DIV 3
55
56
57 /* PLL feed sequence */
58 #define PLL_FEED_SEQ() ATOMIC(PLLFEED = 0xAA; PLLFEED = 0x55;)
59
60 static void configurePll(void)
61 {
62         /* Disconnect and disable the PLL, if already active */
63         if (PLLSTAT & (1 << 25))
64         {
65                 /* Disconnect PLL, but leave it enabled */
66                 PLLCON = 0x01;
67                 PLL_FEED_SEQ();
68                 /* Disable PLL */
69                 PLLCON = 0;
70                 PLL_FEED_SEQ();
71         }
72
73         /* Enable the main oscillator and wait for it to be stable */
74         SCS |= (1 << 5);
75     while (!(SCS & (1 << 6))) ;
76
77         /* Select the main oscillator as the PLL clock source */
78         CLKSRCSEL = 0x01;
79
80         /* Set up PLL mul and div */
81         PLLCFG = PLL_MUL_VAL | (PLL_DIV_VAL << 16);
82         PLL_FEED_SEQ();
83         
84         /* Enable PLL, disconnected */
85         PLLCON = 0x01;
86         PLL_FEED_SEQ();
87
88         /* Set clock divider */
89         CCLKCFG = LPC2_CPUCLOCK_DIV;
90
91         /* Wait for the PLL to lock */
92         while (!(PLLSTAT & (1 << 26))) ;
93     
94         /* Enable and connect the PLL */
95     PLLCON = 0x03;
96         PLL_FEED_SEQ();
97 }
98
99 void __init1(void);
100
101 void __init1(void)
102 {
103         /* Map irq vectors to internal flash */
104         MEMMAP = 0x01;
105         /* Configure PLL, switch from IRC to Main OSC */
106         configurePll();
107
108         /* Set memory accelerator module flash timings */
109 #if CPU_FREQ < 20000000UL
110         MAMTIM = 1;
111 #elif CPU_FREQ < 40000000UL
112         MAMTIM = 2;
113 #elif CPU_FREQ < 60000000UL
114         MAMTIM = 3;
115 #else
116         MAMTIM = 4;
117 #endif
118         
119         /* Memory accelerator module fully enabled */
120         MAMCR = 0x02;
121 }