LPC2xxx: Add Vectored Interrupt Controller (VIC) driver.
[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 <drv/vic_lpc2.h>
40 #include <io/lpc23xx.h>
41
42 #if CPU_FREQ != 72000000UL
43         /* Avoid errors on nightly test */
44         #if !defined(ARCH_NIGHTTEST) || !(ARCH & ARCH_NIGHTTEST)
45                 #warning Clock registers set for 72MHz operation, revise following code if you want a different clock.
46         #endif
47 #endif
48
49 /*
50  * With a 12MHz cristal, master clock is:
51  * (((2 * 12 * (PLL_MUL_VAL + 1)) / (PLL_DIV_VAL + 1)) / (LPC2_CPUCLOCK_DIV + 1))= 72MHz
52  */
53 #define PLL_MUL_VAL  11
54 #define PLL_DIV_VAL  0
55 #define LPC2_CPUCLOCK_DIV 3
56
57
58 /* PLL feed sequence */
59 #define PLL_FEED_SEQ() ATOMIC(PLLFEED = 0xAA; PLLFEED = 0x55;)
60
61 static void configurePll(void)
62 {
63         /* Disconnect and disable the PLL, if already active */
64         if (PLLSTAT & (1 << 25))
65         {
66                 /* Disconnect PLL, but leave it enabled */
67                 PLLCON = 0x01;
68                 PLL_FEED_SEQ();
69                 /* Disable PLL */
70                 PLLCON = 0;
71                 PLL_FEED_SEQ();
72         }
73
74         /* Enable the main oscillator and wait for it to be stable */
75         SCS |= (1 << 5);
76     while (!(SCS & (1 << 6))) ;
77
78         /* Select the main oscillator as the PLL clock source */
79         CLKSRCSEL = 0x01;
80
81         /* Set up PLL mul and div */
82         PLLCFG = PLL_MUL_VAL | (PLL_DIV_VAL << 16);
83         PLL_FEED_SEQ();
84         
85         /* Enable PLL, disconnected */
86         PLLCON = 0x01;
87         PLL_FEED_SEQ();
88
89         /* Set clock divider */
90         CCLKCFG = LPC2_CPUCLOCK_DIV;
91
92         /* Wait for the PLL to lock */
93         while (!(PLLSTAT & (1 << 26))) ;
94     
95         /* Enable and connect the PLL */
96     PLLCON = 0x03;
97         PLL_FEED_SEQ();
98 }
99
100 void __init1(void);
101
102 void __init1(void)
103 {
104         /* Map irq vectors to internal flash */
105         MEMMAP = 0x01;
106         /* Configure PLL, switch from IRC to Main OSC */
107         configurePll();
108
109         /* Set memory accelerator module flash timings */
110 #if CPU_FREQ < 20000000UL
111         MAMTIM = 1;
112 #elif CPU_FREQ < 40000000UL
113         MAMTIM = 2;
114 #elif CPU_FREQ < 60000000UL
115         MAMTIM = 3;
116 #else
117         MAMTIM = 4;
118 #endif
119         
120         /* Memory accelerator module fully enabled */
121         MAMCR = 0x02;
122 }
123
124 void __init2(void);
125
126 void __init2(void)
127 {
128         vic_init();
129 }