ASM->C for interrupt masking
[rpi-open-firmware.git] / romstage.c
1 /*=============================================================================
2 Copyright (C) 2016-2017 Authors of rpi-open-firmware
3 All rights reserved.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 FILE DESCRIPTION
16 VideoCoreIV first stage bootloader.
17
18 =============================================================================*/
19
20 #include <lib/runtime.h>
21 #include <hardware.h>
22
23 uint32_t g_CPUID;
24
25 #define UART_IBRD (UART_BASE+0x24)
26 #define UART_FBRD (UART_BASE+0x28)
27 #define UART_LCRH (UART_BASE+0x2C)
28 #define UART_CR (UART_BASE+0x30)
29 #define UART_ICR (UART_BASE+0x44)
30
31 void uart_putc(unsigned int ch) {
32 while(UART_MSR & 0x20);
33 UART_RBRTHRDLL = ch;
34 }
35
36 void uart_init(void) {
37 unsigned int ra = GP_FSEL1;
38 ra &= ~(7 << 12);
39 ra |= 4 << 12;
40 ra &= ~(7 << 15);
41 ra |= 4 << 15;
42 GP_FSEL1 = ra;
43
44 mmio_write32(UART_CR, 0);
45
46 GP_PUD = 0;
47 udelay(150);
48 GP_PUDCLK0 = (1 << 14) | (1 << 15);
49 udelay(150);
50 GP_PUDCLK0 = 0;
51
52 CM_UARTDIV = CM_PASSWORD | 0x6666;
53 CM_UARTCTL = CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET;
54
55 mmio_write32(UART_ICR, 0x7FF);
56 mmio_write32(UART_IBRD, 1);
57 mmio_write32(UART_FBRD, 40);
58 mmio_write32(UART_LCRH, 0x70);
59 mmio_write32(UART_CR, 0x301);
60 }
61
62 void switch_vpu_to_pllc() {
63 A2W_XOSC_CTRL |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET;
64
65 A2W_PLLC_FRAC = A2W_PASSWORD | 87380;
66 A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000;
67
68 A2W_PLLC_ANA3 = A2W_PASSWORD | 0x100;
69 A2W_PLLC_ANA2 = A2W_PASSWORD | 0x0;
70 A2W_PLLC_ANA1 = A2W_PASSWORD | 0x144000;
71 A2W_PLLC_ANA0 = A2W_PASSWORD | 0x0;
72
73 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET;
74
75 /* hold all */
76 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
77 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
78 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
79
80 A2W_PLLC_DIG3 = A2W_PASSWORD | 0x0;
81 A2W_PLLC_DIG2 = A2W_PASSWORD | 0x400000;
82 A2W_PLLC_DIG1 = A2W_PASSWORD | 0x5;
83 A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
84
85 A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000 | A2W_PLLC_CTRL_PRSTN_SET;
86
87 A2W_PLLC_DIG3 = A2W_PASSWORD | 0x42;
88 A2W_PLLC_DIG2 = A2W_PASSWORD | 0x500401;
89 A2W_PLLC_DIG1 = A2W_PASSWORD | 0x4005;
90 A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
91
92 A2W_PLLC_CORE0 = A2W_PASSWORD | 2;
93
94 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
95 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
96 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET;
97
98 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
99 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
100 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
101
102 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
103 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
104 CM_PLLC_HOLDCORE1_SET;
105
106 CM_VPUCTL = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET;
107 CM_VPUDIV = CM_PASSWORD | (4 << 12);
108 CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET;
109 CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */
110
111 CM_TIMERDIV = CM_PASSWORD | (19 << 12) | 819;
112 CM_TIMERCTL = CM_PASSWORD | CM_SRC_OSC | 0x10;
113 }
114
115 void set_interrupt(int intno, bool enable, int core) {
116 int base = (core == 0) ? : IC0_BASE : IC1_Base;
117
118 int offset = 0x10 + ((intno >> 3) << 2);
119 uint32_t slot = 0xF << ((intno & 7) << 2);
120
121 uint32_t v = mmio_read32(base + offset) & ~slot;
122 mmio_write32(base + offset, enable ? v | slot : v);
123 }
124
125 extern void sdram_init();
126 extern void arm_init();
127 extern void monitor_start();
128 extern void PEStartPlatform();
129
130 int _main(unsigned int cpuid, unsigned int load_address) {
131 switch_vpu_to_pllc();
132
133 uart_init();
134
135 for(int i = 0; i < 64; ++i) {
136 set_interrupt(i, (i != (125 - 64)) && (i != (121 - 64)) && (i != (120 - 64)) && (i != (73 - 64)) && (i != (96 - 64)), 0);
137 set_interrupt(i, 0, 1);
138 }
139
140 IC0_VADDR = 0x1B000;
141 IC1_VADDR = 0x1B000;
142
143 __asm__ volatile("ei");
144
145 printf(
146 "==================================================================\n"
147 "::\n"
148 ":: kFW for bcm270x, Copyright 2016-2017 rpi-open-firmware authors \n"
149 "::\n"
150 ":: BUILDATE : %s %s \n"
151 ":: BUILDSTYLE: %s \n"
152 "::\n"
153 "==================================================================\n",
154 __DATE__, __TIME__,
155 "OPENSOURCE"
156 );
157
158 g_CPUID = cpuid;
159
160 __cxx_init();
161
162 /* bring up SDRAM */
163 sdram_init();
164 printf("SDRAM initialization completed successfully!\n");
165
166 PEStartPlatform();
167
168 /* start vpu monitor */
169 monitor_start();
170
171 panic("main exiting!");
172 }
This page took 0.089667 seconds and 4 git commands to generate.