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