Determine precisely where interrupts came from
[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_DR (UART_BASE+0x00)
26 #define UART_RSRECR (UART_BASE+0x04)
27 #define UART_FR (UART_BASE+0x18)
28 #define UART_ILPR (UART_BASE+0x20)
29 #define UART_IBRD (UART_BASE+0x24)
30 #define UART_FBRD (UART_BASE+0x28)
31 #define UART_LCRH (UART_BASE+0x2C)
32 #define UART_CR (UART_BASE+0x30)
33 #define UART_IFLS (UART_BASE+0x34)
34 #define UART_IMSC (UART_BASE+0x38)
35 #define UART_RIS (UART_BASE+0x3C)
36 #define UART_MIS (UART_BASE+0x40)
37 #define UART_ICR (UART_BASE+0x44)
38 #define UART_DMACR (UART_BASE+0x48)
39 #define UART_ITCR (UART_BASE+0x80)
40 #define UART_ITIP (UART_BASE+0x84)
41 #define UART_ITOP (UART_BASE+0x88)
42 #define UART_TDR (UART_BASE+0x8C)
43
44 void uart_putc(unsigned int ch) {
45 while(UART_MSR & 0x20);
46 UART_RBRTHRDLL = ch;
47 }
48
49 void uart_init(void) {
50 unsigned int ra = GP_FSEL1;
51 ra &= ~(7 << 12);
52 ra |= 4 << 12;
53 ra &= ~(7 << 15);
54 ra |= 4 << 15;
55 GP_FSEL1 = ra;
56
57 mmio_write32(UART_CR, 0);
58
59 GP_PUD = 0;
60 udelay(150);
61 GP_PUDCLK0 = (1 << 14) | (1 << 15);
62 udelay(150);
63 GP_PUDCLK0 = 0;
64
65 CM_UARTDIV = CM_PASSWORD | 0x6666;
66 CM_UARTCTL = CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET;
67
68 mmio_write32(UART_ICR, 0x7FF);
69 mmio_write32(UART_IBRD, 1);
70 mmio_write32(UART_FBRD, 40);
71 mmio_write32(UART_LCRH, 0x70);
72 mmio_write32(UART_CR, 0x301);
73 }
74
75 void led_init(void) {
76 unsigned int ra;
77
78 ra = GP_FSEL1;
79 ra &= ~(7 << 18);
80 ra |= 1 << 18;
81
82 GP_FSEL1 = ra;
83 }
84
85 /*
86 #define CM_PLLC_DIGRST_BITS 9:9
87 #define CM_PLLC_DIGRST_SET 0x00000200
88 #define CM_PLLC_ANARST_BITS 8:8
89 #define CM_PLLC_ANARST_SET 0x00000100
90 #define CM_PLLC_HOLDPER_BITS 7:7
91 #define CM_PLLC_HOLDPER_SET 0x00000080
92 #define CM_PLLC_LOADPER_BITS 6:6
93 #define CM_PLLC_LOADPER_SET 0x00000040
94 #define CM_PLLC_HOLDCORE2_BITS 5:5
95 #define CM_PLLC_HOLDCORE2_SET 0x00000020
96 #define CM_PLLC_LOADCORE2_BITS 4:4
97 #define CM_PLLC_LOADCORE2_SET 0x00000010
98 #define CM_PLLC_HOLDCORE1_BITS 3:3
99 #define CM_PLLC_HOLDCORE1_SET 0x00000008
100 #define CM_PLLC_LOADCORE1_BITS 2:2
101 #define CM_PLLC_LOADCORE1_SET 0x00000004
102 #define CM_PLLC_HOLDCORE0_BITS 1:1
103 #define CM_PLLC_HOLDCORE0_SET 0x00000002
104 #define CM_PLLC_LOADCORE0_BITS 0:0
105 #define CM_PLLC_LOADCORE0_SET 0x00000001
106 */
107
108 void switch_vpu_to_pllc() {
109 A2W_XOSC_CTRL |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET;
110
111 A2W_PLLC_FRAC = A2W_PASSWORD | 87380;
112 A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000;
113
114 A2W_PLLC_ANA3 = A2W_PASSWORD | 0x100;
115 A2W_PLLC_ANA2 = A2W_PASSWORD | 0x0;
116 A2W_PLLC_ANA1 = A2W_PASSWORD | 0x144000;
117 A2W_PLLC_ANA0 = A2W_PASSWORD | 0x0;
118
119 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET;
120
121 /* hold all */
122 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
123 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
124 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
125
126 A2W_PLLC_DIG3 = A2W_PASSWORD | 0x0;
127 A2W_PLLC_DIG2 = A2W_PASSWORD | 0x400000;
128 A2W_PLLC_DIG1 = A2W_PASSWORD | 0x5;
129 A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
130
131 A2W_PLLC_CTRL = A2W_PASSWORD | 52 | 0x1000 | A2W_PLLC_CTRL_PRSTN_SET;
132
133 A2W_PLLC_DIG3 = A2W_PASSWORD | 0x42;
134 A2W_PLLC_DIG2 = A2W_PASSWORD | 0x500401;
135 A2W_PLLC_DIG1 = A2W_PASSWORD | 0x4005;
136 A2W_PLLC_DIG0 = A2W_PASSWORD | 52 | 0x555000;
137
138 A2W_PLLC_CORE0 = A2W_PASSWORD | 2;
139
140 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
141 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
142 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET;
143
144 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
145 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
146 CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET;
147
148 CM_PLLC = CM_PASSWORD | CM_PLLC_DIGRST_SET |
149 CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET |
150 CM_PLLC_HOLDCORE1_SET;
151
152 CM_VPUCTL = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET;
153 CM_VPUDIV = CM_PASSWORD | (4 << 12);
154 CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET;
155 CM_VPUCTL = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */
156
157 CM_TIMERDIV = CM_PASSWORD | (19 << 12) | 819;
158 CM_TIMERCTL = CM_PASSWORD | CM_SRC_OSC | 0x10;
159 }
160
161 void set_interrupt(int intno, bool enable) {
162 int offset = 0x10 + ((intno >> 3) << 2);
163 uint32_t slot = 0xF << ((intno & 7) << 2);
164
165 uint32_t v = mmio_read32(IC0_BASE + offset) & ~slot;
166 mmio_write32(IC0_BASE + offset, enable ? v | slot : v);
167
168 printf("%d: %X\n", intno, mmio_read32(IC0_BASE + offset));
169 }
170
171 extern void sdram_init();
172 extern void arm_init();
173 extern void monitor_start();
174 extern void PEStartPlatform();
175
176 void print_crap() {
177 printf("TB_BOOT_OPT = 0x%X\n", TB_BOOT_OPT);
178 }
179
180 int _main(unsigned int cpuid, unsigned int load_address) {
181 switch_vpu_to_pllc();
182
183 uart_init();
184
185 for(int i = 0; i < 64; ++i) {
186 set_interrupt(i, (i != (125 - 64)) && (i != (121 - 64)) && (i != (120 - 64)) && (i != (73 - 64)) && (i != (96 - 64)));
187 }
188
189 led_init();
190
191 printf(
192 "==================================================================\n"
193 "::\n"
194 ":: kFW for bcm270x, Copyright 2016-2017 rpi-open-firmware authors \n"
195 "::\n"
196 ":: BUILDATE : %s %s \n"
197 ":: BUILDSTYLE: %s \n"
198 "::\n"
199 "==================================================================\n",
200 __DATE__, __TIME__,
201 "OPENSOURCE"
202 );
203
204 printf("CPUID = 0x%X\n", cpuid);
205 printf("LoadAddr = 0x%X\n", load_address);
206
207 print_crap();
208
209 g_CPUID = cpuid;
210
211 __cxx_init();
212
213 /* bring up SDRAM */
214 sdram_init();
215 printf("SDRAM initialization completed successfully!\n");
216
217 PEStartPlatform();
218
219 /* start vpu monitor */
220 monitor_start();
221
222 panic("main exiting!");
223 }
224
This page took 0.09577 seconds and 5 git commands to generate.