1 /* -----------------------------------------------------------------------------
2  * Copyright (c) 2013 - 2015 ARM Ltd.
3  *
4  * This software is provided 'as-is', without any express or implied warranty.
5  * In no event will the authors be held liable for any damages arising from
6  * the use of this software. Permission is granted to anyone to use this
7  * software for any purpose, including commercial applications, and to alter
8  * it and redistribute it freely, subject to the following restrictions:
9  *
10  * 1. The origin of this software must not be misrepresented; you must not
11  *    claim that you wrote the original software. If you use this software in
12  *    a product, an acknowledgment in the product documentation would be
13  *    appreciated but is not required.
14  *
15  * 2. Altered source versions must be plainly marked as such, and must not be
16  *    misrepresented as being the original software.
17  *
18  * 3. This notice may not be removed or altered from any source distribution.
19  *
20  * $Date:        26. August 2015
21  * $Revision:    V5.0.1
22  *
23  * Project:      NXP LPC18xx System initialization
24  * -------------------------------------------------------------------------- */
25 
26 #include "LPC18xx.h"
27 
28 /*----------------------------------------------------------------------------
29   This file configures the clocks as follows:
30  -----------------------------------------------------------------------------
31  Clock Unit  |  Output clock  |  Source clock  |          Note
32  -----------------------------------------------------------------------------
33    PLL0USB   |    480 MHz     |      XTAL      | External crystal @ 12 MHz
34  -----------------------------------------------------------------------------
35     PLL1     |    180 MHz     |      XTAL      | External crystal @ 12 MHz
36  -----------------------------------------------------------------------------
37     CPU      |    180 MHz     |      PLL1      | CPU Clock ==  BASE_M4_CLK
38  -----------------------------------------------------------------------------
39    IDIV A    |     60 MHz     |      PLL1      | To the USB1 peripheral
40  -----------------------------------------------------------------------------
41    IDIV B    |     25 MHz     |   ENET_TX_CLK  | ENET_TX_CLK @ 50MHz
42  -----------------------------------------------------------------------------
43    IDIV C    |     12 MHz     |      IRC       | Internal oscillator @ 12 MHz
44  -----------------------------------------------------------------------------
45    IDIV D    |     12 MHz     |      IRC       | Internal oscillator @ 12 MHz
46  -----------------------------------------------------------------------------
47    IDIV E    |    5.3 MHz     |      PLL1      | To the LCD controller
48  -----------------------------------------------------------------------------*/
49 
50 
51 /*----------------------------------------------------------------------------
52   Clock source selection definitions (do not change)
53  *----------------------------------------------------------------------------*/
54 #define CLK_SRC_32KHZ       0x00
55 #define CLK_SRC_IRC         0x01
56 #define CLK_SRC_ENET_RX     0x02
57 #define CLK_SRC_ENET_TX     0x03
58 #define CLK_SRC_GP_CLKIN    0x04
59 #define CLK_SRC_XTAL        0x06
60 #define CLK_SRC_PLL0U       0x07
61 #define CLK_SRC_PLL0A       0x08
62 #define CLK_SRC_PLL1        0x09
63 #define CLK_SRC_IDIVA       0x0C
64 #define CLK_SRC_IDIVB       0x0D
65 #define CLK_SRC_IDIVC       0x0E
66 #define CLK_SRC_IDIVD       0x0F
67 #define CLK_SRC_IDIVE       0x10
68 
69 
70 /*----------------------------------------------------------------------------
71   Define external input frequency values
72  *----------------------------------------------------------------------------*/
73 #define CLK_32KHZ            32768UL    /* 32 kHz oscillator frequency        */
74 #define CLK_IRC           12000000UL    /* Internal oscillator frequency      */
75 #define CLK_ENET_RX       50000000UL    /* Ethernet Rx frequency              */
76 #define CLK_ENET_TX       50000000UL    /* Ethernet Tx frequency              */
77 #define CLK_GP_CLKIN      12000000UL    /* General purpose clock input freq.  */
78 #define CLK_XTAL          12000000UL    /* Crystal oscilator frequency        */
79 
80 
81 /*----------------------------------------------------------------------------
82   Define clock sources
83  *----------------------------------------------------------------------------*/
84 #define PLL1_CLK_SEL      CLK_SRC_XTAL    /* PLL1 input clock: XTAL           */
85 #define PLL0USB_CLK_SEL   CLK_SRC_XTAL    /* PLL0USB input clock: XTAL        */
86 #define IDIVA_CLK_SEL     CLK_SRC_PLL1    /* IDIVA input clock: PLL1          */
87 #define IDIVB_CLK_SEL     CLK_SRC_ENET_TX /* IDIVB input clock: ENET TX       */
88 #define IDIVC_CLK_SEL     CLK_SRC_IRC     /* IDIVC input clock: IRC           */
89 #define IDIVD_CLK_SEL     CLK_SRC_IRC     /* IDIVD input clock: IRC           */
90 #define IDIVE_CLK_SEL     CLK_SRC_PLL1    /* IDIVD input clock: PLL1          */
91 
92 
93 /*----------------------------------------------------------------------------
94   Configure integer divider values
95  *----------------------------------------------------------------------------*/
96 #define IDIVA_IDIV        2             /* Divide input clock by 3            */
97 #define IDIVB_IDIV        1             /* Divide input clock by 2            */
98 #define IDIVC_IDIV        0             /* Divide input clock by 1            */
99 #define IDIVD_IDIV        0             /* Divide input clock by 1            */
100 #define IDIVE_IDIV       33             /* Divide input clock by 34           */
101 
102 
103 /*----------------------------------------------------------------------------
104   Define CPU clock input
105  *----------------------------------------------------------------------------*/
106 #define CPU_CLK_SEL       CLK_SRC_PLL1  /* Default CPU clock source is PLL1   */
107 
108 
109 /*----------------------------------------------------------------------------
110   Configure external memory controller options
111  *----------------------------------------------------------------------------*/
112 #define USE_EXT_STAT_MEM_CS0 1          /* Use ext. static  memory with CS0   */
113 #define USE_EXT_DYN_MEM_CS0  1          /* Use ext. dynamic memory with CS0   */
114 
115 
116 /*----------------------------------------------------------------------------
117  * Configure PLL1
118  *----------------------------------------------------------------------------
119  * Integer mode:
120  *    - PLL1_DIRECT = 0 (Post divider enabled)
121  *    - PLL1_FBSEL  = 1 (Feedback divider runs from PLL output)
122  *    - Output frequency:
123  *                        FCLKOUT = (FCLKIN / N) * M
124  *                        FCCO    = FCLKOUT * 2 * P
125  *
126  * Non-integer:
127  *    - PLL1_DIRECT = 0 (Post divider enabled)
128  *    - PLL1_FBSEL  = 0 (Feedback divider runs from CCO clock)
129  *    - Output frequency:
130  *                        FCLKOUT = (FCLKIN / N) * M / (2 * P)
131  *                        FCCO    = FCLKOUT * 2 * P
132  *
133  * Direct mode:
134  *    - PLL1_DIRECT = 1         (Post divider disabled)
135  *    - PLL1_FBSEL  = dont care (Feedback divider runs from CCO clock)
136  *    - Output frequency:
137  *                        FCLKOUT = (FCLKIN / N) * M
138  *                        FCCO    = FCLKOUT
139  *
140  *----------------------------------------------------------------------------
141  * PLL1 requirements:
142  * | Frequency |  Minimum  |  Maximum  |               Note                   |
143  * |  FCLKIN   |    1MHz   |   25MHz   |   Clock source is external crystal   |
144  * |  FCLKIN   |    1MHz   |   50MHz   |                                      |
145  * |   FCCO    |  156MHz   |  320MHz   |                                      |
146  * |  FCLKOUT  | 9.75MHz   |  320MHz   |                                      |
147  *----------------------------------------------------------------------------
148  * Configuration examples:
149  * | Fclkout |  Fcco  |  N  |  M  |  P  | DIRECT | FBSEL | BYPASS |
150  * |  36MHz | 288MHz |  1  |  24 |  4  |   0    |   0   |    0   |
151  * |  72MHz | 288MHz |  1  |  24 |  2  |   0    |   0   |    0   |
152  * | 100MHz | 200MHz |  3  |  50 |  1  |   0    |   0   |    0   |
153  * | 120MHz | 240MHz |  1  |  20 |  1  |   0    |   0   |    0   |
154  * | 160MHz | 160MHz |  3  |  40 |  x  |   1    |   0   |    0   |
155  * | 180MHz | 180MHz |  1  |  15 |  x  |   1    |   0   |    0   |
156  *----------------------------------------------------------------------------
157  * Relations beetwen PLL dividers and definitions:
158  * N = PLL1_NSEL + 1,     M = PLL1_MSEL + 1,     P = 2 ^ PLL1_PSEL
159  *----------------------------------------------------------------------------*/
160 
161 /* PLL1 output clock: 180MHz, Fcco: 180MHz, N = 1, M = 15, P = x              */
162 #define PLL1_NSEL   0           /* Range [0 -   3]: Pre-divider ratio N       */
163 #define PLL1_MSEL  14           /* Range [0 - 255]: Feedback-divider ratio M  */
164 #define PLL1_PSEL   0           /* Range [0 -   3]: Post-divider ratio P      */
165 
166 #define PLL1_BYPASS 0           /* 0: Use PLL, 1: PLL is bypassed             */
167 #define PLL1_DIRECT 1           /* 0: Use PSEL, 1: Don't use PSEL             */
168 #define PLL1_FBSEL  0           /* 0: FCCO is used as PLL feedback            */
169                                 /* 1: FCLKOUT is used as PLL feedback         */
170 
171 
172 /*----------------------------------------------------------------------------
173  * Configure PLL0USB
174  *----------------------------------------------------------------------------
175  *
176  *   Normal operating mode without post-divider and without pre-divider
177  *    - PLL0USB_DIRECTI = 1
178  *    - PLL0USB_DIRECTO = 1
179  *    - PLL0USB_BYPASS  = 0
180  *    - Output frequency:
181  *                        FOUT = FIN * 2 * M
182  *                        FCCO = FOUT
183  *
184  *   Normal operating mode with post-divider and without pre-divider
185  *    - PLL0USB_DIRECTI = 1
186  *    - PLL0USB_DIRECTO = 0
187  *    - PLL0USB_BYPASS  = 0
188  *    - Output frequency:
189  *                        FOUT = FIN * (M / P)
190  *                        FCCO = FOUT * 2 * P
191  *
192  *   Normal operating mode without post-divider and with pre-divider
193  *    - PLL0USB_DIRECTI = 0
194  *    - PLL0USB_DIRECTO = 1
195  *    - PLL0USB_BYPASS  = 0
196  *    - Output frequency:
197  *                        FOUT = FIN * 2 * M / N
198  *                        FCCO = FOUT
199  *
200  *   Normal operating mode with post-divider and with pre-divider
201  *    - PLL0USB_DIRECTI = 0
202  *    - PLL0USB_DIRECTO = 0
203  *    - PLL0USB_BYPASS  = 0
204  *    - Output frequency:
205  *                        FOUT = FIN * M / (P * N)
206  *                        FCCO = FOUT * 2 * P
207  *----------------------------------------------------------------------------
208  * PLL0 requirements:
209  * | Frequency |  Minimum  |  Maximum  |               Note                   |
210  * |  FCLKIN   |   14kHz   |   25MHz   |   Clock source is external crystal   |
211  * |  FCLKIN   |   14kHz   |  150MHz   |                                      |
212  * |   FCCO    |  275MHz   |  550MHz   |                                      |
213  * |  FCLKOUT  |  4.3MHz   |  550MHz   |                                      |
214  *----------------------------------------------------------------------------
215  * Configuration examples:
216  * | Fclkout |  Fcco  |  N  |  M  |  P  | DIRECTI | DIRECTO | BYPASS |
217  * | 120MHz | 480MHz |  x  |  20 |  2  |    1    |    0    |    0   |
218  * | 480MHz | 480MHz |  1  |  20 |  1  |    1    |    1    |    0   |
219  *----------------------------------------------------------------------------*/
220 
221 /* PLL0USB output clock: 480MHz, Fcco: 480MHz, N = 1, M = 20, P = 1           */
222 #define PLL0USB_N       1       /* Range [1 -  256]: Pre-divider              */
223 #define PLL0USB_M      20       /* Range [1 - 2^15]: Feedback-divider         */
224 #define PLL0USB_P       1       /* Range [1 -   32]: Post-divider             */
225 
226 #define PLL0USB_DIRECTI 1       /* 0: Use N_DIV, 1: Don't use N_DIV           */
227 #define PLL0USB_DIRECTO 1       /* 0: Use P_DIV, 1: Don't use P_DIV           */
228 #define PLL0USB_BYPASS  0       /* 0: Use PLL, 1: PLL is bypassed             */
229 
230 
231 /*----------------------------------------------------------------------------
232   End of configuration
233  *----------------------------------------------------------------------------*/
234 
235 /* PLL0 Setting Check */
236 #if (PLL0USB_BYPASS == 0)
237  #if (PLL0USB_CLK_SEL == CLK_SRC_XTAL)
238   #define PLL0USB_CLKIN CLK_XTAL
239  #else
240   #define PLL0USB_CLKIN CLK_IRC
241  #endif
242 
243  #if   ((PLL0USB_DIRECTI == 1) && (PLL0USB_DIRECTO == 1)) /* Mode 1a          */
244   #define PLL0USB_FOUT (PLL0USB_CLKIN * 2 * PLL0USB_M)
245   #define PLL0USB_FCCO (PLL0USB_FOUT)
246  #elif ((PLL0USB_DIRECTI == 1) && (PLL0USB_DIRECTO == 0)) /* Mode 1b          */
247   #define PLL0USB_FOUT (PLL0USB_CLKIN * PLL0USB_M / PLL0USB_P)
248   #define PLL0USB_FCCO (PLL0USB_FOUT * 2 * PLL0USB_P)
249  #elif ((PLL0USB_DIRECTI == 0) && (PLL0USB_DIRECTO == 1)) /* Mode 1c          */
250   #define PLL0USB_FOUT (PLL0USB_CLKIN * 2 * PLL0USB_M / PLL0USB_N)
251   #define PLL0USB_FCCO (PLL0USB_FOUT)
252  #else                                                    /* Mode 1d          */
253   #define PLL0USB_FOUT (PLL0USB_CLKIN * PLL0USB_M / (PLL0USB_P * PLL0USB_N))
254   #define PLL0USB_FCCO (PLL0USB_FOUT * 2 * PLL0USB_P)
255  #endif
256 
257  #if (PLL0USB_FCCO < 275000000UL || PLL0USB_FCCO > 550000000UL)
258   #error "PLL0USB Fcco frequency out of range! (275MHz >= Fcco <= 550MHz)"
259  #endif
260  #if (PLL0USB_FOUT < 4300000UL || PLL0USB_FOUT > 550000000UL)
261   #error "PLL0USB output frequency out of range! (4.3MHz >= Fclkout <= 550MHz)"
262  #endif
263 #endif
264 
265 /* PLL1 Setting Check */
266 #if (PLL1_BYPASS == 0)
267  #if (PLL1_CLK_SEL == CLK_SRC_XTAL)
268   #define PLL1_CLKIN CLK_XTAL
269  #else
270   #define PLL1_CLKIN CLK_IRC
271  #endif
272 
273  #if   (PLL1_DIRECT == 1)               /* Direct Mode                        */
274   #define PLL1_FCCO ((PLL1_MSEL + 1) * (PLL1_CLKIN / (PLL1_NSEL + 1)))
275   #define PLL1_FOUT ((PLL1_MSEL + 1) * (PLL1_CLKIN / (PLL1_NSEL + 1)))
276  #elif (PLL1_FBSEL  == 1)               /* Integer Mode                       */
277   #define PLL1_FCCO ((2 * (1 << PLL1_PSEL)) * (PLL1_MSEL + 1) * (PLL1_CLKIN / (PLL1_NSEL + 1)))
278   #define PLL1_FOUT ((PLL1_MSEL + 1) * (PLL1_CLKIN / (PLL1_NSEL + 1)))
279  #else                                  /* Noninteger Mode                    */
280   #define PLL1_FCCO ((PLL1_MSEL + 1) * (PLL1_CLKIN / (PLL1_NSEL + 1)))
281   #define PLL1_FOUT (PLL1_FCCO / (2 * (1 << PLL1_PSEL)))
282  #endif
283  #if (PLL1_FCCO < 156000000UL || PLL1_FCCO > 320000000UL)
284   #error "PLL1 Fcco frequency out of range! (156MHz >= Fcco <= 320MHz)"
285  #endif
286  #if (PLL1_FOUT < 9750000UL || PLL1_FOUT > 204000000UL)
287   #error "PLL1 output frequency out of range! (9.75MHz >= Fclkout <= 204MHz)"
288  #endif
289 #endif
290 
291 
292 /*----------------------------------------------------------------------------
293   System Core Clock variable
294  *----------------------------------------------------------------------------*/
295 uint32_t SystemCoreClock = CLK_IRC;    /* System Clock Frequency (Core Clock) */
296 
297 
298 /******************************************************************************
299  * SetClock
300  ******************************************************************************/
SetClock(void)301 void SetClock (void) {
302   uint32_t x, i;
303   uint32_t selp, seli;
304 
305   /* Set flash wait states to maximum                                         */
306   LPC_EMC->STATICWAITRD0  = 0x1F;
307 
308   /* Switch BASE_M3_CLOCK to IRC                                              */
309   LPC_CGU->BASE_M3_CLK = (0x01        << 11) |  /* Autoblock En               */
310                          (CLK_SRC_IRC << 24) ;  /* Set clock source           */
311 
312   /* Configure input to crystal oscilator                                     */
313   LPC_CGU->XTAL_OSC_CTRL = (0 << 0) |   /* Enable oscillator-pad              */
314                            (0 << 1) |   /* Operation with crystal connected   */
315                            (0 << 2) ;   /* Low-frequency mode                 */
316 
317   /* Wait ~250us @ 12MHz */
318   for (i = 1500; i; i--);
319 
320 #if (USE_SPIFI)
321 /* configure SPIFI clk to IRC via IDIVA (later IDIVA is configured to PLL1/3) */
322   LPC_CGU->IDIVA_CTRL     = (0              <<  0) |  /* Disable Power-down   */
323                             (0              <<  2) |  /* IDIV                 */
324                             (1              << 11) |  /* Autoblock En         */
325                             (CLK_SRC_IRC    << 24) ;  /* Clock source         */
326 
327   LPC_CGU->BASE_SPIFI_CLK = (0              <<  0) |  /* Disable Power-down   */
328                             (0              <<  2) |  /* IDIV                 */
329                             (1              << 11) |  /* Autoblock En         */
330                             (CLK_SRC_IDIVA  << 24) ;  /* Clock source         */
331 #endif
332 
333 /*----------------------------------------------------------------------------
334   PLL1 Setup
335  *----------------------------------------------------------------------------*/
336   /* Power down PLL                                                           */
337   LPC_CGU->PLL1_CTRL |= 1;
338 
339 #if ((PLL1_FOUT > 110000000UL) && (CPU_CLK_SEL == CLK_SRC_PLL1))
340   /* To run at full speed, CPU must first run at an intermediate speed        */
341   LPC_CGU->PLL1_CTRL = (0            << 0) | /* PLL1 Enabled                  */
342                        (PLL1_BYPASS  << 1) | /* CCO out sent to post-dividers */
343                        (PLL1_FBSEL   << 6) | /* PLL output used as feedback   */
344                        (0            << 7) | /* Direct on/off                 */
345                        (PLL1_PSEL    << 8) | /* PSEL                          */
346                        (0            << 11)| /* Autoblock Disabled            */
347                        (PLL1_NSEL    << 12)| /* NSEL                          */
348                        (PLL1_MSEL    << 16)| /* MSEL                          */
349                        (PLL1_CLK_SEL << 24); /* Clock source                  */
350   /* Wait for lock                                                            */
351   while (!(LPC_CGU->PLL1_STAT & 1));
352 
353   /* CPU base clock is in the mid frequency range before final clock set      */
354   LPC_CGU->BASE_M3_CLK     = (0x01 << 11) |  /* Autoblock En                  */
355                              (0x09 << 24) ;  /* Clock source: PLL1            */
356 
357   /* Max. BASE_M3_CLK frequency here is 102MHz, wait at least 20us */
358   for (i = 1050; i; i--);                    /* Wait minimum 2100 cycles      */
359 #endif
360   /* Configure PLL1                                                           */
361   LPC_CGU->PLL1_CTRL = (0            << 0) | /* PLL1 Enabled                  */
362                        (PLL1_BYPASS  << 1) | /* CCO out sent to post-dividers */
363                        (PLL1_FBSEL   << 6) | /* PLL output used as feedback   */
364                        (PLL1_DIRECT  << 7) | /* Direct on/off                 */
365                        (PLL1_PSEL    << 8) | /* PSEL                          */
366                        (1            << 11)| /* Autoblock En                  */
367                        (PLL1_NSEL    << 12)| /* NSEL                          */
368                        (PLL1_MSEL    << 16)| /* MSEL                          */
369                        (PLL1_CLK_SEL << 24); /* Clock source                  */
370 
371   /* Wait for lock                                                            */
372   while (!(LPC_CGU->PLL1_STAT & 1));
373 
374   /* Set CPU base clock source                                                */
375   LPC_CGU->BASE_M3_CLK = (0x01        << 11) |  /* Autoblock En               */
376                          (CPU_CLK_SEL << 24) ;  /* Set clock source           */
377 
378 /*----------------------------------------------------------------------------
379   PLL0USB Setup
380  *----------------------------------------------------------------------------*/
381 
382   /* Power down PLL0USB                                                       */
383   LPC_CGU->PLL0USB_CTRL  |= 1;
384 
385   /* M divider                                                                */
386   x = 0x00004000;
387   switch (PLL0USB_M) {
388     case 0:  x = 0xFFFFFFFF;
389       break;
390     case 1:  x = 0x00018003;
391       break;
392     case 2:  x = 0x00010003;
393       break;
394     default:
395       for (i = PLL0USB_M; i <= 0x8000; i++) {
396         x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0x3FFF);
397       }
398   }
399 
400   if (PLL0USB_M < 60) selp = (PLL0USB_M >> 1) + 1;
401   else        selp = 31;
402 
403   if      (PLL0USB_M > 16384) seli = 1;
404   else if (PLL0USB_M >  8192) seli = 2;
405   else if (PLL0USB_M >  2048) seli = 4;
406   else if (PLL0USB_M >=  501) seli = 8;
407   else if (PLL0USB_M >=   60) seli = 4 * (1024 / (PLL0USB_M + 9));
408   else                        seli = (PLL0USB_M & 0x3C) + 4;
409   LPC_CGU->PLL0USB_MDIV   =  (selp   << 17) |
410                              (seli   << 22) |
411                              (x      <<  0);
412 
413   /* N divider                                                                */
414   x = 0x80;
415   switch (PLL0USB_N) {
416     case 0:  x = 0xFFFFFFFF;
417       break;
418     case 1:  x = 0x00000302;
419       break;
420     case 2:  x = 0x00000202;
421       break;
422     default:
423       for (i = PLL0USB_N; i <= 0x0100; i++) {
424         x =(((x ^ (x >> 2) ^ (x >> 3) ^ (x >> 4)) & 1) << 7) | ((x >> 1) & 0x7F);
425       }
426   }
427   LPC_CGU->PLL0USB_NP_DIV = (x << 12);
428 
429   /* P divider                                                                */
430   x = 0x10;
431   switch (PLL0USB_P) {
432     case 0:  x = 0xFFFFFFFF;
433       break;
434     case 1:  x = 0x00000062;
435       break;
436     case 2:  x = 0x00000042;
437       break;
438     default:
439       for (i = PLL0USB_P; i <= 0x200; i++) {
440         x = (((x ^ (x >> 2)) & 1) << 4) | ((x >> 1) &0x0F);
441       }
442   }
443   LPC_CGU->PLL0USB_NP_DIV |= x;
444 
445   LPC_CGU->PLL0USB_CTRL  = (PLL0USB_CLK_SEL   << 24) | /* Clock source sel    */
446                            (1                 << 11) | /* Autoblock En        */
447                            (1                 << 4 ) | /* PLL0USB clock en    */
448                            (PLL0USB_DIRECTO   << 3 ) | /* Direct output       */
449                            (PLL0USB_DIRECTI   << 2 ) | /* Direct input        */
450                            (PLL0USB_BYPASS    << 1 ) | /* PLL bypass          */
451                            (0                 << 0 ) ; /* PLL0USB Enabled     */
452   while (!(LPC_CGU->PLL0USB_STAT & 1));
453 
454 
455 /*----------------------------------------------------------------------------
456   Integer divider Setup
457  *----------------------------------------------------------------------------*/
458 
459   /* Configure integer dividers                                               */
460   LPC_CGU->IDIVA_CTRL = (0              <<  0) |  /* Disable Power-down       */
461                         (IDIVA_IDIV     <<  2) |  /* IDIV                     */
462                         (1              << 11) |  /* Autoblock En             */
463                         (IDIVA_CLK_SEL  << 24) ;  /* Clock source             */
464 
465   LPC_CGU->IDIVB_CTRL = (0              <<  0) |  /* Disable Power-down       */
466                         (IDIVB_IDIV     <<  2) |  /* IDIV                     */
467                         (1              << 11) |  /* Autoblock En             */
468                         (IDIVB_CLK_SEL  << 24) ;  /* Clock source             */
469 
470   LPC_CGU->IDIVC_CTRL = (0              <<  0) |  /* Disable Power-down       */
471                         (IDIVC_IDIV     <<  2) |  /* IDIV                     */
472                         (1              << 11) |  /* Autoblock En             */
473                         (IDIVC_CLK_SEL  << 24) ;  /* Clock source             */
474 
475   LPC_CGU->IDIVD_CTRL = (0              <<  0) |  /* Disable Power-down       */
476                         (IDIVD_IDIV     <<  2) |  /* IDIV                     */
477                         (1              << 11) |  /* Autoblock En             */
478                         (IDIVD_CLK_SEL  << 24) ;  /* Clock source             */
479 
480   LPC_CGU->IDIVE_CTRL = (0              <<  0) |  /* Disable Power-down       */
481                         (IDIVE_IDIV     <<  2) |  /* IDIV                     */
482                         (1              << 11) |  /* Autoblock En             */
483                         (IDIVE_CLK_SEL  << 24) ;  /* Clock source             */
484 }
485 
486 
487 /*----------------------------------------------------------------------------
488   Approximate delay function (must be used after SystemCoreClockUpdate() call)
489  *----------------------------------------------------------------------------*/
490 #define CPU_NANOSEC(x) (((uint64_t)(x) * SystemCoreClock)/1000000000)
491 
WaitUs(uint32_t us)492 static void WaitUs (uint32_t us) {
493   uint32_t cyc = us * CPU_NANOSEC(1000)/4;
494   while(cyc--);
495 }
496 
497 
498 /*----------------------------------------------------------------------------
499   External Memory Controller Definitions
500  *----------------------------------------------------------------------------*/
501 #define SDRAM_ADDR_BASE 0x28000000      /* SDRAM base address                 */
502 /* Write Mode register macro                                                  */
503 #define WR_MODE(x) (*((volatile uint32_t *)(SDRAM_ADDR_BASE | (x))))
504 
505 /* Pin Settings: Glith filter DIS, Input buffer EN, Fast Slew Rate, No Pullup */
506 #define EMC_PIN_SET ((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4))
507 #define EMC_NANOSEC(ns, freq, div) (((uint64_t)(ns) * ((freq)/((div)+1)))/1000000000)
508 
509 #define EMC_CLK_DLY_TIM_2  (0x7777)     /* 3.5 ns delay for the EMC clock out */
510 #define EMC_CLK_DLY_TIM_0  (0x0000)     /* No delay for the EMC clock out     */
511 
512 typedef void (*emcdivby2) (volatile uint32_t *creg6, volatile uint32_t *emcdiv, uint32_t cfg);
513 
514 const uint16_t emcdivby2_opc[] =  {
515   0x6803,        /*      LDR  R3,[R0,#0]      ; Load CREG6          */
516   0xF443,0x3380, /*      ORR  R3,R3,#0x10000  ; Set Divided by 2    */
517   0x6003,        /*      STR  R3,[R0,#0]      ; Store CREG6         */
518   0x600A,        /*      STR  R2,[R1,#0]      ; EMCDIV_CFG = cfg    */
519   0x684B,        /* loop LDR  R3,[R1,#4]      ; Load EMCDIV_STAT    */
520   0x07DB,        /*      LSLS R3,R3,#31       ; Check EMCDIV_STAT.0 */
521   0xD0FC,        /*      BEQ  loop            ; Jump if 0           */
522   0x4770,        /*      BX   LR              ; Exit                */
523   0,
524 };
525 
526 #define        emcdivby2_szw ((sizeof(emcdivby2_opc)+3)/4)
527 #define        emcdivby2_ram 0x10000000
528 
529 /*----------------------------------------------------------------------------
530   Initialize external memory controller
531  *----------------------------------------------------------------------------*/
532 
SystemInit_ExtMemCtl(void)533 void SystemInit_ExtMemCtl (void) {
534   uint32_t emcdivby2_buf[emcdivby2_szw];
535   uint32_t div, n;
536 
537   /* Select and enable EMC branch clock */
538   LPC_CCU1->CLK_M3_EMC_CFG = (1 << 2) | (1 << 1) | 1;
539   while (!(LPC_CCU1->CLK_M3_EMC_STAT & 1));
540 
541   /* Set EMC clock output delay */
542   if (SystemCoreClock < 80000000UL) {
543     LPC_SCU->EMCDELAYCLK = EMC_CLK_DLY_TIM_0; /* No EMC clock out delay       */
544   }
545   else {
546     LPC_SCU->EMCDELAYCLK = EMC_CLK_DLY_TIM_2; /* 2.0 ns EMC clock out delay   */
547   }
548 
549   /* Configure EMC port pins */
550   LPC_SCU->SFSP1_0  = EMC_PIN_SET | 2;  /* P1_0:  A5                          */
551   LPC_SCU->SFSP1_1  = EMC_PIN_SET | 2;  /* P1_1:  A6                          */
552   LPC_SCU->SFSP1_2  = EMC_PIN_SET | 2;  /* P1_2:  A7                          */
553   LPC_SCU->SFSP1_3  = EMC_PIN_SET | 3;  /* P1_3:  OE                          */
554   LPC_SCU->SFSP1_4  = EMC_PIN_SET | 3;  /* P1_4:  BLS0                        */
555   LPC_SCU->SFSP1_5  = EMC_PIN_SET | 3;  /* P1_5:  CS0                         */
556   LPC_SCU->SFSP1_6  = EMC_PIN_SET | 3;  /* P1_6:  WE                          */
557   LPC_SCU->SFSP1_7  = EMC_PIN_SET | 3;  /* P1_7:  D0                          */
558   LPC_SCU->SFSP1_8  = EMC_PIN_SET | 3;  /* P1_8:  D1                          */
559   LPC_SCU->SFSP1_9  = EMC_PIN_SET | 3;  /* P1_9:  D2                          */
560   LPC_SCU->SFSP1_10 = EMC_PIN_SET | 3;  /* P1_10: D3                          */
561   LPC_SCU->SFSP1_11 = EMC_PIN_SET | 3;  /* P1_11: D4                          */
562   LPC_SCU->SFSP1_12 = EMC_PIN_SET | 3;  /* P1_12: D5                          */
563   LPC_SCU->SFSP1_13 = EMC_PIN_SET | 3;  /* P1_13: D6                          */
564   LPC_SCU->SFSP1_14 = EMC_PIN_SET | 3;  /* P1_14: D7                          */
565 
566   LPC_SCU->SFSP2_0  = EMC_PIN_SET | 2;  /* P2_0:  A13                         */
567   LPC_SCU->SFSP2_1  = EMC_PIN_SET | 2;  /* P2_1:  A12                         */
568   LPC_SCU->SFSP2_2  = EMC_PIN_SET | 2;  /* P2_2:  A11                         */
569   LPC_SCU->SFSP2_6  = EMC_PIN_SET | 2;  /* P2_6:  A10                         */
570   LPC_SCU->SFSP2_7  = EMC_PIN_SET | 3;  /* P2_7:  A9                          */
571   LPC_SCU->SFSP2_8  = EMC_PIN_SET | 3;  /* P2_8:  A8                          */
572   LPC_SCU->SFSP2_9  = EMC_PIN_SET | 3;  /* P2_9:  A0                          */
573   LPC_SCU->SFSP2_10 = EMC_PIN_SET | 3;  /* P2_10: A1                          */
574   LPC_SCU->SFSP2_11 = EMC_PIN_SET | 3;  /* P2_11: A2                          */
575   LPC_SCU->SFSP2_12 = EMC_PIN_SET | 3;  /* P2_12: A3                          */
576   LPC_SCU->SFSP2_13 = EMC_PIN_SET | 3;  /* P2_13: A4                          */
577 
578   LPC_SCU->SFSP5_0  = EMC_PIN_SET | 2;  /* P5_0:  D12                         */
579   LPC_SCU->SFSP5_1  = EMC_PIN_SET | 2;  /* P5_1:  D13                         */
580   LPC_SCU->SFSP5_2  = EMC_PIN_SET | 2;  /* P5_2:  D14                         */
581   LPC_SCU->SFSP5_3  = EMC_PIN_SET | 2;  /* P5_3:  D15                         */
582   LPC_SCU->SFSP5_4  = EMC_PIN_SET | 2;  /* P5_4:  D8                          */
583   LPC_SCU->SFSP5_5  = EMC_PIN_SET | 2;  /* P5_5:  D9                          */
584   LPC_SCU->SFSP5_6  = EMC_PIN_SET | 2;  /* P5_6:  D10                         */
585   LPC_SCU->SFSP5_7  = EMC_PIN_SET | 2;  /* P5_7:  D11                         */
586 
587   LPC_SCU->SFSP6_1  = EMC_PIN_SET | 1;  /* P6_1:  DYCS1                       */
588   LPC_SCU->SFSP6_2  = EMC_PIN_SET | 1;  /* P6_3:  CKEOUT1                     */
589   LPC_SCU->SFSP6_3  = EMC_PIN_SET | 3;  /* P6_3:  CS1                         */
590   LPC_SCU->SFSP6_4  = EMC_PIN_SET | 3;  /* P6_4:  CAS                         */
591   LPC_SCU->SFSP6_5  = EMC_PIN_SET | 3;  /* P6_5:  RAS                         */
592   LPC_SCU->SFSP6_6  = EMC_PIN_SET | 1;  /* P6_6:  BLS1                        */
593   LPC_SCU->SFSP6_7  = EMC_PIN_SET | 1;  /* P6_7:  A15                         */
594   LPC_SCU->SFSP6_8  = EMC_PIN_SET | 1;  /* P6_8:  A14                         */
595   LPC_SCU->SFSP6_9  = EMC_PIN_SET | 3;  /* P6_9:  DYCS0                       */
596   LPC_SCU->SFSP6_10 = EMC_PIN_SET | 3;  /* P6_10: DQMOUT1                     */
597   LPC_SCU->SFSP6_11 = EMC_PIN_SET | 3;  /* P6_11: CKEOUT0                     */
598   LPC_SCU->SFSP6_12 = EMC_PIN_SET | 3;  /* P6_12: DQMOUT0                     */
599 
600   LPC_SCU->SFSPA_4  = EMC_PIN_SET | 3;  /* PA_4:  A23                         */
601 
602   LPC_SCU->SFSPD_0  = EMC_PIN_SET | 2;  /* PD_0:  DQMOUT2                     */
603   LPC_SCU->SFSPD_1  = EMC_PIN_SET | 2;  /* PD_1:  CKEOUT2                     */
604   LPC_SCU->SFSPD_2  = EMC_PIN_SET | 2;  /* PD_2:  D16                         */
605   LPC_SCU->SFSPD_3  = EMC_PIN_SET | 2;  /* PD_3:  D17                         */
606   LPC_SCU->SFSPD_4  = EMC_PIN_SET | 2;  /* PD_4:  D18                         */
607   LPC_SCU->SFSPD_5  = EMC_PIN_SET | 2;  /* PD_5:  D19                         */
608   LPC_SCU->SFSPD_6  = EMC_PIN_SET | 2;  /* PD_6:  D20                         */
609   LPC_SCU->SFSPD_7  = EMC_PIN_SET | 2;  /* PD_7:  D21                         */
610   LPC_SCU->SFSPD_8  = EMC_PIN_SET | 2;  /* PD_8:  D22                         */
611   LPC_SCU->SFSPD_9  = EMC_PIN_SET | 2;  /* PD_9:  D23                         */
612   LPC_SCU->SFSPD_10 = EMC_PIN_SET | 2;  /* PD_10: BLS3                        */
613   LPC_SCU->SFSPD_11 = EMC_PIN_SET | 2;  /* PD_11: CS3                         */
614   LPC_SCU->SFSPD_12 = EMC_PIN_SET | 2;  /* PD_12: CS2                         */
615   LPC_SCU->SFSPD_13 = EMC_PIN_SET | 2;  /* PD_13: BLS2                        */
616   LPC_SCU->SFSPD_14 = EMC_PIN_SET | 2;  /* PD_14: DYCS2                       */
617   LPC_SCU->SFSPD_15 = EMC_PIN_SET | 2;  /* PD_15: A17                         */
618   LPC_SCU->SFSPD_16 = EMC_PIN_SET | 2;  /* PD_16: A16                         */
619 
620   LPC_SCU->SFSPE_0  = EMC_PIN_SET | 3;  /* PE_0:  A18                         */
621   LPC_SCU->SFSPE_1  = EMC_PIN_SET | 3;  /* PE_1:  A19                         */
622   LPC_SCU->SFSPE_2  = EMC_PIN_SET | 3;  /* PE_2:  A20                         */
623   LPC_SCU->SFSPE_3  = EMC_PIN_SET | 3;  /* PE_3:  A21                         */
624   LPC_SCU->SFSPE_4  = EMC_PIN_SET | 3;  /* PE_4:  A22                         */
625   LPC_SCU->SFSPE_5  = EMC_PIN_SET | 3;  /* PE_5:  D24                         */
626   LPC_SCU->SFSPE_6  = EMC_PIN_SET | 3;  /* PE_6:  D25                         */
627   LPC_SCU->SFSPE_7  = EMC_PIN_SET | 3;  /* PE_7:  D26                         */
628   LPC_SCU->SFSPE_8  = EMC_PIN_SET | 3;  /* PE_8:  D27                         */
629   LPC_SCU->SFSPE_9  = EMC_PIN_SET | 3;  /* PE_9:  D28                         */
630   LPC_SCU->SFSPE_10 = EMC_PIN_SET | 3;  /* PE_10: D29                         */
631   LPC_SCU->SFSPE_11 = EMC_PIN_SET | 3;  /* PE_11: D30                         */
632   LPC_SCU->SFSPE_12 = EMC_PIN_SET | 3;  /* PE_12: D31                         */
633   LPC_SCU->SFSPE_13 = EMC_PIN_SET | 3;  /* PE_13: DQMOUT3                     */
634   LPC_SCU->SFSPE_14 = EMC_PIN_SET | 3;  /* PE_14: DYCS3                       */
635   LPC_SCU->SFSPE_15 = EMC_PIN_SET | 3;  /* PE_15: CKEOUT3                     */
636 
637   LPC_EMC->CONTROL  = 0x00000001;       /* EMC Enable                         */
638   LPC_EMC->CONFIG   = 0x00000000;       /* Little-endian, Clock Ratio 1:1     */
639 
640   div = 0;
641   if (SystemCoreClock > 120000000UL) {
642     /* Use EMC clock divider and EMC clock output delay */
643     div = 1;
644     /* Following code must be executed in RAM to ensure stable operation      */
645     /* LPC_CCU1->CLK_M3_EMCDIV_CFG = (1 << 5) | (1 << 2) | (1 << 1) | 1;      */
646     /* LPC_CREG->CREG6 |= (1 << 16);       // EMC_CLK_DIV divided by 2        */
647     /* while (!(LPC_CCU1->CLK_M3_EMCDIV_STAT & 1));                           */
648 
649     /* This code configures EMC clock divider and is executed in RAM          */
650     for (n = 0; n < emcdivby2_szw; n++) {
651       emcdivby2_buf[n] =  *((uint32_t *)emcdivby2_ram + n);
652       *((uint32_t *)emcdivby2_ram + n) = *((uint32_t *)emcdivby2_opc + n);
653     }
654     __ISB();
655     ((emcdivby2 )(emcdivby2_ram+1))(&LPC_CREG->CREG6, &LPC_CCU1->CLK_M3_EMCDIV_CFG, (1 << 5) | (1 << 2) | (1 << 1) | 1);
656     for (n = 0; n < emcdivby2_szw; n++) {
657       *((uint32_t *)emcdivby2_ram + n) = emcdivby2_buf[n];
658     }
659   }
660 
661   /* Configure EMC clock-out pins                                             */
662   LPC_SCU->SFSCLK_0 = EMC_PIN_SET | 0;  /* CLK0                               */
663   LPC_SCU->SFSCLK_1 = EMC_PIN_SET | 0;  /* CLK1                               */
664   LPC_SCU->SFSCLK_2 = EMC_PIN_SET | 0;  /* CLK2                               */
665   LPC_SCU->SFSCLK_3 = EMC_PIN_SET | 0;  /* CLK3                               */
666 
667   /* Static memory configuration (chip select 0)                              */
668 #if (USE_EXT_STAT_MEM_CS0)
669   LPC_EMC->STATICCONFIG0  = (1 <<  7) | /* Byte lane state: use WE signal     */
670                             (2 <<  0) | /* Memory width 32-bit                */
671                             (1 <<  3);  /* Async page mode enable             */
672 
673   LPC_EMC->STATICWAITOEN0 = (0 <<  0) ; /* Wait output enable: No delay       */
674 
675   LPC_EMC->STATICWAITPAG0 = 2;
676 
677   /* Set Static Memory Read Delay for 90ns External NOR Flash                 */
678   LPC_EMC->STATICWAITRD0  = 1 + EMC_NANOSEC(90, SystemCoreClock, div);
679   LPC_EMC->STATICCONFIG0 |= (1 << 19) ; /* Enable buffer                      */
680 #endif
681 
682   /* Dynamic memory configuration (chip select 0)                             */
683 #if (USE_EXT_DYN_MEM_CS0)
684 
685   /* Set Address mapping: 128Mb(4Mx32), 4 banks, row len = 12, column len = 8 */
686   LPC_EMC->DYNAMICCONFIG0    = (1 << 14) |  /* AM[14]   = 1                   */
687                                (0 << 12) |  /* AM[12]   = 0                   */
688                                (2 <<  9) |  /* AM[11:9] = 2                   */
689                                (2 <<  7) ;  /* AM[8:7]  = 2                   */
690 
691   LPC_EMC->DYNAMICRASCAS0    = 0x00000303;  /* Latency: RAS 3, CAS 3 CCLK cyc.*/
692   LPC_EMC->DYNAMICREADCONFIG = 0x00000001;  /* Command delayed by 1/2 CCLK    */
693 
694   LPC_EMC->DYNAMICRP         = EMC_NANOSEC (20, SystemCoreClock, div);
695   LPC_EMC->DYNAMICRAS        = EMC_NANOSEC (42, SystemCoreClock, div);
696   LPC_EMC->DYNAMICSREX       = EMC_NANOSEC (63, SystemCoreClock, div);
697   LPC_EMC->DYNAMICAPR        = EMC_NANOSEC (70, SystemCoreClock, div);
698   LPC_EMC->DYNAMICDAL        = EMC_NANOSEC (70, SystemCoreClock, div);
699   LPC_EMC->DYNAMICWR         = EMC_NANOSEC (30, SystemCoreClock, div);
700   LPC_EMC->DYNAMICRC         = EMC_NANOSEC (63, SystemCoreClock, div);
701   LPC_EMC->DYNAMICRFC        = EMC_NANOSEC (63, SystemCoreClock, div);
702   LPC_EMC->DYNAMICXSR        = EMC_NANOSEC (63, SystemCoreClock, div);
703   LPC_EMC->DYNAMICRRD        = EMC_NANOSEC (14, SystemCoreClock, div);
704   LPC_EMC->DYNAMICMRD        = EMC_NANOSEC (30, SystemCoreClock, div);
705 
706   WaitUs (100);
707   LPC_EMC->DYNAMICCONTROL    = 0x00000183;  /* Issue NOP command              */
708   WaitUs (10);
709   LPC_EMC->DYNAMICCONTROL    = 0x00000103;  /* Issue PALL command             */
710   WaitUs (1);
711   LPC_EMC->DYNAMICCONTROL    = 0x00000183;  /* Issue NOP command              */
712   WaitUs (1);
713   LPC_EMC->DYNAMICREFRESH    = EMC_NANOSEC(  200, SystemCoreClock, div) / 16 + 1;
714   WaitUs (10);
715   LPC_EMC->DYNAMICREFRESH    = EMC_NANOSEC(15625, SystemCoreClock, div) / 16 + 1;
716   WaitUs (10);
717   LPC_EMC->DYNAMICCONTROL    = 0x00000083;  /* Issue MODE command             */
718 
719   /* Mode register: Burst Length: 4, Burst Type: Sequential, CAS Latency: 3   */
720   WR_MODE(((3 << 4) | 2) << 12);
721 
722   WaitUs (10);
723   LPC_EMC->DYNAMICCONTROL    = 0x00000002;  /* Issue NORMAL command           */
724   LPC_EMC->DYNAMICCONFIG0   |= (1 << 19);   /* Enable buffer                  */
725 #endif
726 }
727 
728 
729 /*----------------------------------------------------------------------------
730   Measure frequency using frequency monitor
731  *----------------------------------------------------------------------------*/
MeasureFreq(uint32_t clk_sel)732 uint32_t MeasureFreq (uint32_t clk_sel) {
733   uint32_t fcnt, rcnt, fout;
734 
735   /* Set register values */
736   LPC_CGU->FREQ_MON &= ~(1 << 23);                /* Stop frequency counters  */
737   LPC_CGU->FREQ_MON  = (clk_sel << 24) | 511;     /* RCNT == 511              */
738   LPC_CGU->FREQ_MON |= (1 << 23);                 /* Start RCNT and FCNT      */
739   while (LPC_CGU->FREQ_MON & (1 << 23)) {
740     fcnt = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF;
741     rcnt = (LPC_CGU->FREQ_MON     ) & 0x01FF;
742     if (fcnt == 0 && rcnt == 0) {
743       return (0);                                 /* No input clock present   */
744     }
745   }
746   fcnt = (LPC_CGU->FREQ_MON >> 9) & 0x3FFF;
747   fout = fcnt * (12000000U/511U);                 /* FCNT * (IRC_CLK / RCNT)  */
748 
749   return (fout);
750 }
751 
752 
753 /*----------------------------------------------------------------------------
754   Get PLL1 (divider and multiplier) parameters
755  *----------------------------------------------------------------------------*/
GetPLL1Param(void)756 static __inline uint32_t GetPLL1Param (void) {
757   uint32_t ctrl;
758   uint32_t p;
759   uint32_t div, mul;
760 
761   ctrl = LPC_CGU->PLL1_CTRL;
762   div = ((ctrl >> 12) & 0x03) + 1;
763   mul = ((ctrl >> 16) & 0xFF) + 1;
764   p = 1 << ((ctrl >>  8) & 0x03);
765 
766   if (ctrl & (1 << 1)) {
767     /* Bypass = 1, PLL1 input clock sent to post-dividers */
768     if (ctrl & (1 << 7)) {
769       div *= (2*p);
770     }
771   }
772   else {
773     /* Direct and integer mode */
774     if (((ctrl & (1 << 7)) == 0) && ((ctrl & (1 << 6)) == 0)) {
775       /* Non-integer mode */
776       div *= (2*p);
777     }
778   }
779   return ((div << 8) | (mul));
780 }
781 
782 
783 /*----------------------------------------------------------------------------
784   Get input clock source for specified clock generation block
785  *----------------------------------------------------------------------------*/
GetClkSel(uint32_t clk_src)786 int32_t GetClkSel (uint32_t clk_src) {
787   uint32_t reg;
788   int32_t clk_sel = -1;
789 
790   switch (clk_src) {
791     case CLK_SRC_IRC:
792     case CLK_SRC_ENET_RX:
793     case CLK_SRC_ENET_TX:
794     case CLK_SRC_GP_CLKIN:
795       return (clk_src);
796 
797     case CLK_SRC_32KHZ:
798       return ((LPC_CREG->CREG0 & 0x0A) != 0x02) ? (-1) : (CLK_SRC_32KHZ);
799     case CLK_SRC_XTAL:
800      return  (LPC_CGU->XTAL_OSC_CTRL & 1)       ? (-1) : (CLK_SRC_XTAL);
801 
802     case CLK_SRC_PLL0U: reg = LPC_CGU->PLL0USB_CTRL;    break;
803     case CLK_SRC_PLL0A: reg = LPC_CGU->PLL0AUDIO_CTRL;  break;
804     case CLK_SRC_PLL1:  reg = (LPC_CGU->PLL1_STAT & 1) ? (LPC_CGU->PLL1_CTRL) : (0); break;
805 
806     case CLK_SRC_IDIVA: reg = LPC_CGU->IDIVA_CTRL;      break;
807     case CLK_SRC_IDIVB: reg = LPC_CGU->IDIVB_CTRL;      break;
808     case CLK_SRC_IDIVC: reg = LPC_CGU->IDIVC_CTRL;      break;
809     case CLK_SRC_IDIVD: reg = LPC_CGU->IDIVD_CTRL;      break;
810     case CLK_SRC_IDIVE: reg = LPC_CGU->IDIVE_CTRL;      break;
811 
812     default:
813       return (clk_sel);
814   }
815   if (!(reg & 1)) {
816     clk_sel = (reg >> 24) & 0x1F;
817   }
818   return (clk_sel);
819 }
820 
821 
822 /*----------------------------------------------------------------------------
823   Get clock frequency for specified clock source
824  *----------------------------------------------------------------------------*/
GetClockFreq(uint32_t clk_src)825 uint32_t GetClockFreq (uint32_t clk_src) {
826   uint32_t tmp;
827   uint32_t mul        =  1;
828   uint32_t div        =  1;
829   uint32_t main_freq  =  0;
830   int32_t  clk_sel    = clk_src;
831 
832   do {
833     switch (clk_sel) {
834       case CLK_SRC_32KHZ:    main_freq = CLK_32KHZ;     break;
835       case CLK_SRC_IRC:      main_freq = CLK_IRC;       break;
836       case CLK_SRC_ENET_RX:  main_freq = CLK_ENET_RX;   break;
837       case CLK_SRC_ENET_TX:  main_freq = CLK_ENET_TX;   break;
838       case CLK_SRC_GP_CLKIN: main_freq = CLK_GP_CLKIN;  break;
839       case CLK_SRC_XTAL:     main_freq = CLK_XTAL;      break;
840 
841       case CLK_SRC_IDIVA: div *= ((LPC_CGU->IDIVA_CTRL >> 2) & 0x3) + 1; break;
842       case CLK_SRC_IDIVB: div *= ((LPC_CGU->IDIVB_CTRL >> 2) & 0x3) + 1; break;
843       case CLK_SRC_IDIVC: div *= ((LPC_CGU->IDIVC_CTRL >> 2) & 0x3) + 1; break;
844       case CLK_SRC_IDIVD: div *= ((LPC_CGU->IDIVD_CTRL >> 2) & 0x3) + 1; break;
845       case CLK_SRC_IDIVE: div *= ((LPC_CGU->IDIVE_CTRL >> 2) & 0x3) + 1; break;
846 
847       case CLK_SRC_PLL0U: /* Not implemented */  break;
848       case CLK_SRC_PLL0A: /* Not implemented */  break;
849 
850       case CLK_SRC_PLL1:
851         tmp = GetPLL1Param ();
852         mul *= (tmp     ) & 0xFF;       /* PLL input clock multiplier         */
853         div *= (tmp >> 8) & 0xFF;       /* PLL input clock divider            */
854         break;
855 
856       default:
857         return (0);                     /* Clock not running or not supported */
858     }
859     if (main_freq == 0) {
860       clk_sel = GetClkSel (clk_sel);
861     }
862   }
863   while (main_freq == 0);
864 
865   return ((main_freq * mul) / div);
866 }
867 
868 
869 /*----------------------------------------------------------------------------
870   System Core Clock update
871  *----------------------------------------------------------------------------*/
SystemCoreClockUpdate(void)872 void SystemCoreClockUpdate (void) {
873   /* Check BASE_M3_CLK connection */
874   uint32_t base_src = (LPC_CGU->BASE_M3_CLK >> 24) & 0x1F;
875 
876   /* Update core clock frequency */
877   SystemCoreClock = GetClockFreq (base_src);
878 }
879 
880 
881 extern uint32_t __Vectors;                         /* see startup_LPC18xx.s   */
882 
883 /*----------------------------------------------------------------------------
884   Initialize the system
885  *----------------------------------------------------------------------------*/
SystemInit(void)886 void SystemInit (void) {
887   /* Disable SysTick timer                                                    */
888   SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
889 
890   /* Set vector table pointer */
891   SCB->VTOR = ((uint32_t)(&__Vectors)) & 0xFFF00000UL;
892 
893   /* Configure PLL0 and PLL1, connect CPU clock to selected clock source */
894   SetClock();
895 
896   /* Update SystemCoreClock variable */
897   SystemCoreClockUpdate();
898 
899   /* Configure External Memory Controller */
900   SystemInit_ExtMemCtl ();
901 }
902