need to merge in tercel flash code
[ls2.git] / coldboot / coldboot.c
1 #include <stdint.h>
2 #include <stdbool.h>
3
4 #include "console.h"
5 #include "microwatt_soc.h"
6 #include "io.h"
7
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <gram.h>
11
12 #include "elf64.h"
13
14 static inline uint32_t read32(const void *addr)
15 {
16 return *(volatile uint32_t *)addr;
17 }
18
19 static inline void write32(void *addr, uint32_t value)
20 {
21 *(volatile uint32_t *)addr = value;
22 }
23
24 struct uart_regs {
25 uint32_t divisor;
26 uint32_t rx_data;
27 uint32_t rx_rdy;
28 uint32_t rx_err;
29 uint32_t tx_data;
30 uint32_t tx_rdy;
31 uint32_t zero0; // reserved
32 uint32_t zero1; // reserved
33 uint32_t ev_status;
34 uint32_t ev_pending;
35 uint32_t ev_enable;
36 };
37
38 void uart_writeuint32(uint32_t val) {
39 const char lut[] = { '0', '1', '2', '3', '4', '5', '6', '7',
40 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
41 uint8_t *val_arr = (uint8_t*)(&val);
42 size_t i;
43
44 for (i = 0; i < 4; i++) {
45 putchar(lut[(val_arr[3-i] >> 4) & 0xF]);
46 putchar(lut[val_arr[3-i] & 0xF]);
47 }
48 }
49
50 void memcpy(void *dest, void *src, size_t n) {
51 int i;
52 //cast src and dest to char*
53 char *src_char = (char *)src;
54 char *dest_char = (char *)dest;
55 for (i=0; i<n; i++) {
56 #if 1
57 if ((i % 1024) == 1023) {
58 puts("memcpy ");
59 uart_writeuint32(i);
60 puts("\r\n");
61 }
62 #endif
63 dest_char[i] = src_char[i]; //copy contents byte by byte
64 }
65 }
66
67 void isr(void) {
68
69 }
70
71 // TODO: need to use this
72 // https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-litex/litex/-/blob/master/litex/soc/software/bios/boot.c#L575
73 static bool fl_read(void *dst, uint32_t offset, uint32_t size)
74 {
75 uint8_t *d = dst;
76 memcpy(d, (void *)(unsigned long)(SPI_FLASH_BASE + offset), size);
77 return true;
78 }
79
80 static unsigned long copy_flash(unsigned int offset)
81 {
82 Elf64_Ehdr ehdr;
83 Elf64_Phdr ph;
84 unsigned int i, poff, size, off;
85 void *addr;
86
87 puts("Trying flash...\r\n");
88 if (!fl_read(&ehdr, offset, sizeof(ehdr)))
89 return -1ul;
90 if (!IS_ELF(ehdr) || ehdr.e_ident[EI_CLASS] != ELFCLASS64) {
91 puts("Doesn't look like an elf64\r\n");
92 goto dump;
93 }
94 if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB ||
95 ehdr.e_machine != EM_PPC64) {
96 puts("Not a ppc64le binary\r\n");
97 goto dump;
98 }
99
100 poff = offset + ehdr.e_phoff;
101 for (i = 0; i < ehdr.e_phnum; i++) {
102 if (!fl_read(&ph, poff, sizeof(ph)))
103 goto dump;
104 if (ph.p_type != PT_LOAD)
105 continue;
106
107 /* XXX Add bound checking ! */
108 size = ph.p_filesz;
109 addr = (void *)ph.p_vaddr;
110 off = offset + ph.p_offset;
111 //printf("Copy segment %d (0x%x bytes) to %p\n", i, size, addr);
112 puts("Copy segment ");
113 uart_writeuint32(i);
114 puts(" size ");
115 uart_writeuint32(size);
116 puts(" addr ");
117 uart_writeuint32((uint32_t)(unsigned long)addr);
118 puts("\r\n");
119 fl_read(addr, off, size);
120 poff += ehdr.e_phentsize;
121 }
122
123 puts("Booting from DRAM at");
124 uart_writeuint32((unsigned int)ehdr.e_entry);
125 //flush_cpu_icache();
126 return ehdr.e_entry;
127 dump:
128 puts("HDR: \r\n");
129 for (i = 0; i < 8; i++) {
130 uart_writeuint32(ehdr.e_ident[i]);
131 puts("\r\n");
132 }
133
134 return -1ul;
135 }
136
137
138 // XXX
139 // Defining gram_[read|write] allows a trace of all register
140 // accesses to be dumped to console for debugging purposes.
141 // To use, define GRAM_RW_FUNC in gram.h
142 uint32_t gram_read(const struct gramCtx *ctx, void *addr) {
143 uint32_t dword;
144
145 puts("gram_read: ");
146 uart_writeuint32((unsigned long)addr);
147 dword = readl((unsigned long)addr);
148 puts(": ");
149 uart_writeuint32((unsigned long)dword);
150 puts("\n");
151
152 return dword;
153 }
154
155 int gram_write(const struct gramCtx *ctx, void *addr, uint32_t value) {
156 puts("gram_write: ");
157 uart_writeuint32((unsigned long)addr);
158 puts(": ");
159 uart_writeuint32((unsigned long)value);
160 writel(value, (unsigned long)addr);
161 puts("\n");
162
163 return 0;
164 }
165
166 int main(void) {
167 const int kNumIterations = 14;
168 int res, failcnt = 0;
169 uint32_t tmp;
170 unsigned long ftr, spi_offs=0x0;
171 volatile uint32_t *ram = (uint32_t*)MEMORY_BASE;
172
173 console_init();
174 //puts("Firmware launched...\n");
175
176 #if 1
177 puts(" Soc signature: ");
178 tmp = readl(SYSCON_BASE + SYS_REG_SIGNATURE);
179 uart_writeuint32(tmp);
180 puts(" Soc features: ");
181 ftr = readl(SYSCON_BASE + SYS_REG_INFO);
182 if (ftr & SYS_REG_INFO_HAS_UART)
183 puts("UART ");
184 if (ftr & SYS_REG_INFO_HAS_DRAM)
185 puts("DRAM ");
186 if (ftr & SYS_REG_INFO_HAS_BRAM)
187 puts("BRAM ");
188 if (ftr & SYS_REG_INFO_HAS_SPI_FLASH)
189 puts("SPIFLASH ");
190 if (ftr & SYS_REG_INFO_HAS_LITEETH)
191 puts("ETHERNET ");
192 puts("\r\n");
193
194 if (ftr & SYS_REG_INFO_HAS_SPI_FLASH) {
195 puts("SPI Offset: ");
196 spi_offs = readl(SYSCON_BASE + SYS_REG_SPI_INFO);
197 uart_writeuint32(spi_offs);
198 puts("\r\n");
199 }
200
201 #endif
202
203 #if 1
204 #if 1
205 // print out configuration parameters for QSPI
206 volatile uint32_t *qspi_cfg = (uint32_t*)SPI_FCTRL_BASE;
207 for (int k=0; k < 2; k++) {
208 tmp = readl((unsigned long)&(qspi_cfg[k]));
209 puts("cfg");
210 uart_writeuint32(k);
211 puts(" ");
212 uart_writeuint32(tmp);
213 puts("\n");
214 }
215 #endif
216 volatile uint32_t *qspi = (uint32_t*)spi_offs;
217 //volatile uint8_t *qspi_bytes = (uint8_t*)spi_offs;
218 // let's not, eh? writel(0xDEAF0123, (unsigned long)&(qspi[0]));
219 // tmp = readl((unsigned long)&(qspi[0]));
220 for (int i=0;i<256;i++) {
221 tmp = readl((unsigned long)&(qspi[i]));
222 uart_writeuint32(tmp);
223 puts(" ");
224 if ((i & 0x7) == 0x7) puts("\r\n");
225 }
226 puts("\r\n");
227 /*
228 for (i=0;i<256;i++) {
229 tmp = readb((unsigned long)&(qspi_bytes[i]));
230 uart_writeuint32(tmp);
231 puts(" ");
232 }
233 */
234 #if 0
235 while (1) {
236 // quick read
237 tmp = readl((unsigned long)&(qspi[0x1000/4]));
238 puts("read 0x1000");
239 uart_writeuint32(tmp);
240 putchar(10);
241 }
242 while (1) {
243 unsigned char c = getchar();
244 putchar(c);
245 if (c == 13) { // if CR send LF
246
247 // quick read
248 tmp = readl((unsigned long)&(qspi[1<<i]));
249 puts("read ");
250 uart_writeuint32(1<<i);
251 puts(" ");
252 uart_writeuint32(tmp);
253 putchar(10);
254 i++;
255 }
256 }
257
258 return 0;
259 #endif
260 #endif
261 #if 0
262 volatile uint32_t *hyperram = (uint32_t*)0xa0000000;
263 writel(0xDEAF0123, (unsigned long)&(hyperram[0]));
264 tmp = readl((unsigned long)&(hyperram[0]));
265 while (1) {
266 unsigned char c = getchar();
267 putchar(c);
268 if (c == 13) { // if CR send LF
269
270 // quick write/read
271 writel(0xDEAF0123+i, (unsigned long)&(hyperram[1<<i]));
272 tmp = readl((unsigned long)&(hyperram[1<<i]));
273 puts("read ");
274 uart_writeuint32(1<<i);
275 puts(" ");
276 uart_writeuint32(tmp);
277 putchar(10);
278 i++;
279 }
280 }
281
282 return 0;
283 #endif
284
285 for (int persistence=0; persistence < 1000; persistence++) {
286 puts("DRAM init... ");
287
288 struct gramCtx ctx;
289 #if 1
290 struct gramProfile profile = {
291 .mode_registers = {
292 0xb20, 0x806, 0x200, 0x0
293 },
294 .rdly_p0 = 2,
295 .rdly_p1 = 2,
296 };
297 #endif
298 #if 0
299 struct gramProfile profile = {
300 .mode_registers = {
301 0x0320, 0x0006, 0x0200, 0x0000
302 },
303 .rdly_p0 = 1,
304 .rdly_p1 = 1,
305 };
306 #endif
307 struct gramProfile profile2;
308 gram_init(&ctx, &profile, (void*)MEMORY_BASE,
309 (void*)DRAM_CTRL_BASE,
310 (void*)DRAM_INIT_BASE);
311 puts("done\n");
312
313 puts("MR profile: ");
314 uart_writeuint32(profile.mode_registers[0]);
315 puts(" ");
316 uart_writeuint32(profile.mode_registers[1]);
317 puts(" ");
318 uart_writeuint32(profile.mode_registers[2]);
319 puts(" ");
320 uart_writeuint32(profile.mode_registers[3]);
321 puts("\n");
322
323 // FIXME
324 // Early read test for WB access sim
325 //uart_writeuint32(*ram);
326
327 #if 1
328 puts("Rdly\np0: ");
329 for (size_t i = 0; i < 8; i++) {
330 profile2.rdly_p0 = i;
331 gram_load_calibration(&ctx, &profile2);
332 gram_reset_burstdet(&ctx);
333
334 for (size_t j = 0; j < 128; j++) {
335 tmp = readl((unsigned long)&(ram[i]));
336 }
337 if (gram_read_burstdet(&ctx, 0)) {
338 puts("1");
339 } else {
340 puts("0");
341 }
342 }
343 puts("\n");
344
345 puts("Rdly\np1: ");
346 for (size_t i = 0; i < 8; i++) {
347 profile2.rdly_p1 = i;
348 gram_load_calibration(&ctx, &profile2);
349 gram_reset_burstdet(&ctx);
350 for (size_t j = 0; j < 128; j++) {
351 tmp = readl((unsigned long)&(ram[i]));
352 }
353 if (gram_read_burstdet(&ctx, 1)) {
354 puts("1");
355 } else {
356 puts("0");
357 }
358 }
359 puts("\n");
360
361 puts("Auto calibrating... ");
362 res = gram_generate_calibration(&ctx, &profile2);
363 if (res != GRAM_ERR_NONE) {
364 puts("failed\n");
365 gram_load_calibration(&ctx, &profile);
366 } else {
367 gram_load_calibration(&ctx, &profile2);
368 }
369 puts("done\n");
370
371 puts("Auto calibration profile:");
372 puts("p0 rdly:");
373 uart_writeuint32(profile2.rdly_p0);
374 puts(" p1 rdly:");
375 uart_writeuint32(profile2.rdly_p1);
376 puts("\n");
377 #endif
378
379 puts("Reloading built-in calibration profile...");
380 gram_load_calibration(&ctx, &profile);
381
382 puts("DRAM test... \n");
383 for (size_t i = 0; i < kNumIterations; i++) {
384 writel(0xDEAF0000 | i*4, (unsigned long)&(ram[i]));
385 }
386
387 #if 0
388 for (int dly = 0; dly < 8; dly++) {
389 failcnt = 0;
390 profile2.rdly_p0 = dly;
391 profile2.rdly_p1 = dly;
392 puts("p0 rdly:");
393 uart_writeuint32(profile2.rdly_p0);
394 puts(" p1 rdly:");
395 uart_writeuint32(profile2.rdly_p1);
396 gram_load_calibration(&ctx, &profile2);
397 for (size_t i = 0; i < kNumIterations; i++) {
398 if (readl((unsigned long)&(ram[i])) != (0xDEAF0000 | i*4)) {
399 puts("fail : *(0x");
400 uart_writeuint32((unsigned long)(&ram[i]));
401 puts(") = ");
402 uart_writeuint32(readl((unsigned long)&(ram[i])));
403 puts("\n");
404 failcnt++;
405
406 if (failcnt > 10) {
407 puts("Test canceled (more than 10 errors)\n");
408 break;
409 }
410 }
411 }
412 }
413 #else
414 failcnt = 0;
415 for (size_t i = 0; i < kNumIterations; i++) {
416 if (readl((unsigned long)&(ram[i])) != (0xDEAF0000 | i*4)) {
417 puts("fail : *(0x");
418 uart_writeuint32((unsigned long)(&ram[i]));
419 puts(") = ");
420 uart_writeuint32(readl((unsigned long)&(ram[i])));
421 puts("\n");
422 failcnt++;
423
424 if (failcnt > 10) {
425 puts("Test canceled (more than 10 errors)\n");
426 break;
427 }
428 }
429 }
430 if (failcnt == 0) { // fiinally...
431 break;
432 }
433 }
434 #endif
435 puts("done\n");
436
437 // memcpy from SPI Flash to SDRAM then boot
438 if ((ftr & SYS_REG_INFO_HAS_SPI_FLASH) &&
439 (ftr & SYS_REG_INFO_HAS_DRAM) &&
440 (failcnt == 0))
441 {
442 // identify ELF, copy if present, and get the start address
443 unsigned long faddr = copy_flash(spi_offs);
444 if (faddr != -1ul) {
445 // jump to absolute address
446 return faddr;
447 }
448 }
449
450 return 0;
451 }
452