1 /*
2 * Copyright (c) 2015 Brian Swetland
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <lk/debug.h>
10 #include <arch/arm/cm.h>
11 #include <kernel/thread.h>
12 #include <platform.h>
13
14 #include <platform/lpc43xx-clocks.h>
15
16 void lpc43xx_debug_early_init(void);
17 void lpc43xx_debug_init(void);
18
19 uint8_t __lpc43xx_main_clock_sel;
20 uint32_t __lpc43xx_main_clock_mhz;
21
platform_early_init(void)22 void platform_early_init(void) {
23 #ifndef WITH_NO_CLOCK_INIT
24 unsigned cfg;
25 // Different boot modes will enable different sets of clocks.
26 // To keep it simple, we drop back to the 12MHz internal osc,
27 // power down the other clocks, and bring things back up in an
28 // orderly fashion. This costs a few hundred microseconds.
29
30 // switch CPU clock to 12MHz internal osc
31 writel(readl(BASE_M4_CLK) | BASE_AUTOBLOCK, BASE_M4_CLK);
32 writel(BASE_CLK_SEL(CLK_IRC) | BASE_AUTOBLOCK, BASE_M4_CLK);
33
34 // Disable PLL1, if it was already running
35 writel(PLL1_CTRL_PD, PLL1_CTRL);
36
37 // Disable PLL0USB, if it was already running
38 writel(PLL0_CTRL_PD, PLL0USB_CTRL);
39
40 // Disable XTAL osc if it was already running
41 writel(readl(XTAL_OSC_CTRL) | 1, XTAL_OSC_CTRL);
42 // Disable BYPASS or HF modes:
43 writel(1, XTAL_OSC_CTRL);
44 // Enable, HF=0 BYPASS=0
45 writel(0, XTAL_OSC_CTRL);
46 // Wait
47 spin_cycles(3000); // 250uS @ 12MHz
48
49 // PLL1: 12MHz -> N=(/2) -> M=(x32) -> P=(/2) 96MHz
50 cfg = PLL1_CTRL_NSEL_2 | PLL1_CTRL_PSEL_1 | PLL1_CTRL_MSEL(32) |
51 PLL1_CTRL_CLK_SEL(CLK_XTAL) | PLL1_CTRL_AUTOBLOCK;
52 writel(cfg, PLL1_CTRL);
53 while (!(readl(PLL1_STAT) & PLL1_STAT_LOCK)) ;
54
55 writel(BASE_CLK_SEL(CLK_PLL1) | BASE_AUTOBLOCK, BASE_M4_CLK);
56
57 // when moving from < 90 MHz to > 110MHz, must spend 50uS
58 // at 90-110MHz before shifting to high speeds
59 spin_cycles(4800); // 50uS @ 96MHz
60
61 // disable P divider 192MHz
62 writel(cfg | PLL1_CTRL_DIRECT, PLL1_CTRL);
63
64 // 12MHz -> 480MHz settings, per boot rom
65 writel(0x01967FFA, PLL0USB_MDIV);
66 writel(0x00302062, PLL0USB_NP_DIV);
67 // Enable PLL, wait for lock
68 cfg = PLL0_CTRL_CLK_SEL(CLK_XTAL) | PLL0_CTRL_DIRECTO | PLL0_CTRL_AUTOBLOCK;
69 writel(cfg, PLL0USB_CTRL);
70 while (!(readl(PLL0USB_STAT) & PLL0_STAT_LOCK)) ;
71 // Enable clock output
72 writel(cfg | PLL0_CTRL_CLKEN, PLL0USB_CTRL);
73
74 #if 0
75 // route PLL1 / 2 to CLK0 pin for verification
76 writel(0x11, 0x40086C00); // CLK0 = CLK_OUT, no PU/PD
77 writel(IDIV_CLK_SEL(CLK_PLL1) | IDIV_N(2), IDIVE_CTRL);
78 writel(BASE_CLK_SEL(CLK_IDIVE), BASE_OUT_CLK);
79 #endif
80 #if 0
81 // route PLL0USB / 4 to CLK0 pin for verification
82 writel(0x11, 0x40086C00); // CLK0 = CLK_OUT, no PU/PD
83 writel(IDIV_CLK_SEL(CLK_PLL0USB) | IDIV_N(4), IDIVA_CTRL);
84 writel(BASE_CLK_SEL(CLK_IDIVA), BASE_OUT_CLK);
85 #endif
86 __lpc43xx_main_clock_mhz = 192000000;
87 __lpc43xx_main_clock_sel = CLK_PLL1;
88 #else
89 __lpc43xx_main_clock_mhz = 96000000;
90 __lpc43xx_main_clock_sel = CLK_IDIVC;
91 #endif
92 arm_cm_systick_init(__lpc43xx_main_clock_mhz);
93 lpc43xx_debug_early_init();
94 }
95
96 void lpc43xx_usb_init(u32 dmabase, size_t dmasize);
97
platform_init(void)98 void platform_init(void) {
99 lpc43xx_debug_init();
100 lpc43xx_usb_init(0x20000000, 4096);
101 }
102
platform_halt(platform_halt_action suggested_action,platform_halt_reason reason)103 void platform_halt(platform_halt_action suggested_action,
104 platform_halt_reason reason) {
105 arch_disable_ints();
106 if (suggested_action == HALT_ACTION_REBOOT) {
107 // CORE reset
108 writel(1, 0x40053100);
109 } else {
110 dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason);
111 }
112 for (;;);
113 }
114