]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC43XX/system_LPC43xx.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_NXP / TARGET_LPC43XX / system_LPC43xx.c
1 /*
2  * @brief LPC43xx System Initialization
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products.  This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights.  NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers.  This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  *
31  * Modified by Micromint USA <support@micromint.com>
32  */
33 #include "LPC43xx.h"
34
35 #define COUNT_OF(a) (sizeof(a)/sizeof(a[0]))
36
37 /* Clock variables */
38 #if (CLOCK_SETUP)
39 uint32_t SystemCoreClock = MAX_CLOCK_FREQ;
40 #else
41 uint32_t SystemCoreClock = CRYSTAL_MAIN_FREQ_IN;
42 #endif
43
44 #if !defined(CORE_M0)
45 /* SCU pin definitions for pin muxing */
46 typedef struct {
47     __IO uint32_t *reg; /* SCU register address */
48     uint16_t mode;      /* SCU pin mode and function */
49 } PINMUX_GRP_T;
50
51 /* Pins to initialize before clocks are configured */
52 static const PINMUX_GRP_T pre_clock_mux[] = {
53     /* SPIFI pins */
54     {SCU_REG(0x3, 3), (SCU_PINIO_FAST | 0x3)},  /* P3_3 SPIFI CLK */
55     {SCU_REG(0x3, 4), (SCU_PINIO_FAST | 0x3)},  /* P3_4 SPIFI D3  */
56     {SCU_REG(0x3, 5), (SCU_PINIO_FAST | 0x3)},  /* P3_5 SPIFI D2  */
57     {SCU_REG(0x3, 6), (SCU_PINIO_FAST | 0x3)},  /* P3_6 SPIFI D1  */
58     {SCU_REG(0x3, 7), (SCU_PINIO_FAST | 0x3)},  /* P3_7 SPIFI D0  */
59     {SCU_REG(0x3, 8), (SCU_PINIO_FAST | 0x3)}   /* P3_8 SPIFI CS/SSEL */
60 };
61
62 /* Pins to initialize after clocks are configured */
63 static const PINMUX_GRP_T post_clock_mux[] = {
64     /* Boot pins */
65     {SCU_REG(0x1, 1), (SCU_PINIO_FAST | 0x0)},  /* P1_1  BOOT0 */
66     {SCU_REG(0x1, 2), (SCU_PINIO_FAST | 0x0)},  /* P1_2  BOOT1 */
67     {SCU_REG(0x2, 8), (SCU_PINIO_FAST | 0x0)},  /* P2_8  BOOT2 */
68     {SCU_REG(0x2, 9), (SCU_PINIO_FAST | 0x0)},  /* P2_9  BOOT3 */
69     /* Micromint Bambino 200/210 */
70     {SCU_REG(0x6, 11), (SCU_PINIO_FAST | 0x0)}, /* P6_11 LED1 */
71     {SCU_REG(0x2, 5), (SCU_PINIO_FAST | 0x0)},  /* P2_5  LED2 */
72     {SCU_REG(0x2, 7), (SCU_PINIO_FAST | 0x0)},  /* P2_7  BTN1 */
73     /* Micromint Bambino 210 */
74     {SCU_REG(0x6, 1), (SCU_PINIO_FAST | 0x0)},  /* P6_1  LED3 */
75     {SCU_REG(0x6, 2), (SCU_PINIO_FAST | 0x0)},  /* P6_2  LED4 */
76 };
77
78 #if (CLOCK_SETUP)
79 /* Structure for initial base clock states */
80 struct CLK_BASE_STATES {
81     CGU_BASE_CLK_T clk; /* Base clock */
82     CGU_CLKIN_T clkin;  /* Base clock source */
83     uint8_t powerdn;    /* Set to 1 if base clock is initially powered down */
84 };
85
86 /* Initial base clock states are mostly on */
87 static const struct CLK_BASE_STATES clock_states[] = {
88     {CLK_BASE_SAFE, CLKIN_IRC, 0},
89     {CLK_BASE_APB1, CLKIN_MAINPLL, 0},
90     {CLK_BASE_APB3, CLKIN_MAINPLL, 0},
91     {CLK_BASE_USB0, CLKIN_USBPLL, 1},
92     {CLK_BASE_PERIPH, CLKIN_MAINPLL, 0},
93     {CLK_BASE_SPI, CLKIN_MAINPLL, 0},
94     {CLK_BASE_PHY_TX, CLKIN_ENET_TX, 0},
95 #if defined(USE_RMII)
96     {CLK_BASE_PHY_RX, CLKIN_ENET_TX, 0},
97 #else
98     {CLK_BASE_PHY_RX, CLKIN_ENET_RX, 0},
99 #endif
100     {CLK_BASE_SDIO, CLKIN_MAINPLL, 0},
101     {CLK_BASE_SSP0, CLKIN_IDIVC, 0},
102     {CLK_BASE_SSP1, CLKIN_IDIVC, 0},
103     {CLK_BASE_UART0, CLKIN_MAINPLL, 0},
104     {CLK_BASE_UART1, CLKIN_MAINPLL, 0},
105     {CLK_BASE_UART2, CLKIN_MAINPLL, 0},
106     {CLK_BASE_UART3, CLKIN_MAINPLL, 0},
107     {CLK_BASE_OUT, CLKINPUT_PD, 0},
108     {CLK_BASE_APLL, CLKINPUT_PD, 0},
109     {CLK_BASE_CGU_OUT0, CLKINPUT_PD, 0},
110     {CLK_BASE_CGU_OUT1, CLKINPUT_PD, 0},
111
112     /* Clocks derived from dividers */
113     {CLK_BASE_LCD, CLKIN_IDIVC, 0},
114     {CLK_BASE_USB1, CLKIN_IDIVD, 1}
115 };
116 #endif /* defined(CLOCK_SETUP) */
117
118 /* Local functions */
119 static uint32_t SystemGetMainPLLHz(void);
120 static void SystemSetupClock(void);
121 static void SystemSetupPins(const PINMUX_GRP_T *mux, uint32_t n);
122 static void SystemSetupMemory(void);
123 static void WaitUs(uint32_t us);
124
125 #endif /* !defined(CORE_M0) */
126
127 /*
128  * SystemInit() - Initialize the system
129  */
130 void SystemInit(void)
131 {
132 #if !defined(CORE_M0)
133
134     /* Initialize vector table in flash */
135 #if defined(__ARMCC_VERSION)
136     extern void *__Vectors;
137
138     SCB->VTOR = (unsigned int) &__Vectors;
139 #elif defined(__IAR_SYSTEMS_ICC__)
140     extern void *__vector_table;
141
142     SCB->VTOR = (unsigned int) &__vector_table;
143 #elif defined(TOOLCHAIN_GCC_ARM)
144     extern void *__isr_vector;
145
146     SCB->VTOR = (unsigned int) &__isr_vector;
147 #else /* defined(__GNUC__) and others */
148     extern void *g_pfnVectors;
149
150     SCB->VTOR = (unsigned int) &g_pfnVectors;
151 #endif
152
153 #if defined(__FPU_PRESENT) && __FPU_PRESENT == 1
154     /* Initialize floating point */
155     fpuInit();
156 #endif
157
158     SystemSetupPins(pre_clock_mux, COUNT_OF(pre_clock_mux)); /* Configure pins */
159     SystemSetupClock();   /* Configure processor and peripheral clocks */
160     SystemSetupPins(post_clock_mux, COUNT_OF(post_clock_mux)); /* Configure pins */
161     SystemSetupMemory();  /* Configure external memory */
162 #endif /* !defined(CORE_M0) */
163
164     SystemCoreClockUpdate(); /* Update SystemCoreClock variable */
165 }
166
167 /*
168  * SystemCoreClockUpdate() - Update SystemCoreClock variable
169  */
170 void SystemCoreClockUpdate(void)
171 {
172     uint32_t reg, div, rate;
173
174     /* Get main PLL rate */
175     rate = SystemGetMainPLLHz();
176
177     /* Get clock divider */
178     reg = LPC_CCU1->CLKCCU[CLK_MX_MXCORE].CFG;
179     if (((reg >> 5) & 0x7) == 0) {
180         div = 1;
181     }
182     else {
183         div = 2;
184     }
185     rate = rate / div;
186
187     SystemCoreClock = rate;
188 }
189
190 /* Returns the frequency of the main PLL */
191 uint32_t SystemGetMainPLLHz(void)
192 {
193     uint32_t PLLReg = LPC_CGU->PLL1_CTRL;
194     uint32_t freq = CRYSTAL_MAIN_FREQ_IN;
195     uint32_t msel, nsel, psel, direct, fbsel;
196     uint32_t m, n, p;
197     const uint8_t ptab[] = {1, 2, 4, 8};
198
199     msel = (PLLReg >> 16) & 0xFF;
200     nsel = (PLLReg >> 12) & 0x3;
201     psel = (PLLReg >> 8) & 0x3;
202     direct = (PLLReg >> 7) & 0x1;
203     fbsel = (PLLReg >> 6) & 0x1;
204
205     m = msel + 1;
206     n = nsel + 1;
207     p = ptab[psel];
208
209     if (direct || fbsel) {
210         return m * (freq / n);
211     }
212
213     return (m / (2 * p)) * (freq / n);
214 }
215
216 #if !defined(CORE_M0)
217 /*
218  * SystemSetupClock() - Set processor and peripheral clocks
219  *
220  *    Clock       Frequency    Source
221  * CLK_BASE_MX     204 MHz    CLKIN_MAINPLL            (CLKIN_PLL1)
222  * CLK_BASE_SPIFI  102 MHz    CLKIN_IDIVE
223  * CLK_BASE_USB0   480 MHz    CLKIN_USBPLL  (Disabled) (CLKIN_PLL0USB)
224  * CLK_BASE_USB1    60 MHz    CLKIN_IDIVE   (Disabled)
225  *                 120 MHz    CLKIN_IDIVD   (Disabled)
226  *
227  *                  12 MHz    CLKIN_IDIVB
228  *                  12 MHz    CLKIN_IDIVC
229  *
230  */
231 void SystemSetupClock(void)
232 {
233 #if (CLOCK_SETUP)
234     uint32_t i;
235
236     /* Switch main clock to Internal RC (IRC) while setting up PLL1 */
237     LPC_CGU->BASE_CLK[CLK_BASE_MX] = (1 << 11) | (CLKIN_IRC << 24);
238     /* Set prescaler/divider on SSP1 assuming 204 MHz clock */
239     LPC_SSP1->CR1 &= ~(1 << 1);
240     LPC_SSP1->CPSR = 0x0002;
241     LPC_SSP1->CR0 = 0x00006507;
242     LPC_SSP1->CR1 |= (1 << 1);
243
244     /* Enable the oscillator and wait 100 us */
245     LPC_CGU->XTAL_OSC_CTRL = 0;
246     WaitUs(100);
247
248 #if (SPIFI_INIT)
249     /* Setup SPIFI control register and no-opcode mode */
250     LPC_SPIFI->CTRL = (0x100 << 0) | (1 << 16) | (1 << 29) | (1 << 30);
251     LPC_SPIFI->IDATA = 0xA5;
252     /* Switch IDIVE clock to IRC and connect to SPIFI clock */
253     LPC_CGU->IDIV_CTRL[CLK_IDIV_E] = ((1 << 11) | (CLKIN_IRC << 24));
254     LPC_CGU->BASE_CLK[CLK_BASE_SPIFI] = ((1 << 11) | (CLKIN_IDIVE << 24));
255 #endif /* SPIFI_INIT */
256
257     /* Configure PLL1 (MAINPLL) for main clock */
258     LPC_CGU->PLL1_CTRL |= 1; /* Power down PLL1 */
259
260     /* Change PLL1 to 108 Mhz (msel=9, 12 MHz*9=108 MHz) */
261     LPC_CGU->PLL1_CTRL = (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (8 << 16)
262                          | (CLKIN_MAINPLL << 24);
263     while (!(LPC_CGU->PLL1_STAT & 1)); /* Wait for PLL1 to lock */
264     WaitUs(100);
265
266     /* Change PLL1 to 204 Mhz (msel=17, 12 MHz*17=204 MHz) */
267     LPC_CGU->PLL1_CTRL = (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (16 << 16)
268                          | (CLKIN_MAINPLL << 24);
269     while (!(LPC_CGU->PLL1_STAT & 1)); /* Wait for PLL1 to lock */
270
271     /* Connect main clock to PLL1 */
272     LPC_CGU->BASE_CLK[CLK_BASE_MX] = (1 << 11) | (CLKIN_MAINPLL << 24);
273
274     /* Set USB PLL dividers for 480 MHz (for USB0) */
275     LPC_CGU->PLL[CGU_USB_PLL].PLL_MDIV = 0x06167FFA;
276     LPC_CGU->PLL[CGU_USB_PLL].PLL_NP_DIV = 0x00302062;
277     LPC_CGU->PLL[CGU_USB_PLL].PLL_CTRL = 0x0000081D | (CLKIN_CRYSTAL << 24);
278
279     /* Set IDIVE clock to PLL1/2 = 102 MHz */
280     LPC_CGU->IDIV_CTRL[CLK_IDIV_E] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL << 24); /* PLL1/2 */
281
282     /* Set IDIVD clock to ((USBPLL/4) / 2) = 60 MHz (for USB1) */
283     LPC_CGU->IDIV_CTRL[CLK_IDIV_A] = (3 << 2) | (1 << 11) | (CLKIN_USBPLL << 24); /* USBPLL/4 */
284     LPC_CGU->IDIV_CTRL[CLK_IDIV_D] = (1 << 2) | (1 << 11) | (CLKIN_IDIVA << 24); /* IDIVA/2 */
285
286     /* Configure remaining integer dividers */
287     LPC_CGU->IDIV_CTRL[CLK_IDIV_B] = (0 << 2) | (1 << 11) | (CLKIN_IRC << 24); /* IRC */
288     LPC_CGU->IDIV_CTRL[CLK_IDIV_C] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL << 24); /* PLL1/2 */
289
290     /* Connect base clocks */
291     for (i = 0; i < COUNT_OF(clock_states); i++) {
292         LPC_CGU->BASE_CLK[clock_states[i].clk] =
293                          ( clock_states[i].powerdn << 0)
294                          | (1 << 11) | (clock_states[i].clkin << 24);
295     }
296 #endif /* CLOCK_SETUP */
297     /* Reset peripherals */
298     LPC_RGU->RESET_CTRL0 = 0x105F0000;
299     LPC_RGU->RESET_CTRL1 = 0x01DFF7FF;
300 }
301
302 /*
303  * SystemSetupPins() - Configure MCU pins
304  */
305 void SystemSetupPins(const PINMUX_GRP_T *mux, uint32_t n)
306 {
307     uint32_t i;
308
309     for (i = 0; i < n; i++) {
310         *(mux[i].reg) = mux[i].mode;
311     }
312 }
313
314 /*
315  * SystemSetupMemory() - Configure external memory
316  */
317 void SystemSetupMemory(void)
318 {
319 #if (MEMORY_SETUP)
320     /* None required for boards without external memory */
321 #endif /* MEMORY_SETUP */
322 }
323
324 #if defined(__FPU_PRESENT) && __FPU_PRESENT == 1
325 /*
326  * fpuInit() - Early initialization of the FPU
327  */
328 void fpuInit(void)
329 {
330    /*
331     * from ARM TRM manual:
332     *   ; CPACR is located at address 0xE000ED88
333     *   LDR.W R0, =0xE000ED88
334     *   ; Read CPACR
335     *   LDR R1, [R0]
336     *   ; Set bits 20-23 to enable CP10 and CP11 coprocessors
337     *   ORR R1, R1, #(0xF << 20)
338     *   ; Write back the modified value to the CPACR
339     *   STR R1, [R0]
340     */
341
342     volatile uint32_t *regCpacr = (uint32_t *) LPC_CPACR;
343     volatile uint32_t *regMvfr0 = (uint32_t *) SCB_MVFR0;
344     volatile uint32_t *regMvfr1 = (uint32_t *) SCB_MVFR1;
345     volatile uint32_t Cpacr;
346     volatile uint32_t Mvfr0;
347     volatile uint32_t Mvfr1;
348     char vfpPresent = 0;
349
350     Mvfr0 = *regMvfr0;
351     Mvfr1 = *regMvfr1;
352
353     vfpPresent = ((SCB_MVFR0_RESET == Mvfr0) && (SCB_MVFR1_RESET == Mvfr1));
354
355     if (vfpPresent) {
356         Cpacr = *regCpacr;
357         Cpacr |= (0xF << 20);
358         *regCpacr = Cpacr;  /* enable CP10 and CP11 for full access */
359     }
360 }
361 #endif /* defined(__FPU_PRESENT) && __FPU_PRESENT == 1 */
362
363 /* Approximate delay function */
364 #define CPU_NANOSEC(x)  (((uint64_t) (x) * SystemCoreClock) / 1000000000)
365
366 static void WaitUs(uint32_t us)
367 {
368     volatile uint32_t  cyc = us * CPU_NANOSEC(1000) / 4;
369     while (cyc--)
370         ;
371 }
372
373 #endif /* !defined(CORE_M0) */