5 #include "microwatt_soc.h"
14 static inline uint32_t read32(const void *addr
)
16 return *(volatile uint32_t *)addr
;
19 static inline void write32(void *addr
, uint32_t value
)
21 *(volatile uint32_t *)addr
= value
;
31 uint32_t zero0
; // reserved
32 uint32_t zero1
; // reserved
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
);
44 for (i
= 0; i
< 4; i
++) {
45 putchar(lut
[(val_arr
[3-i
] >> 4) & 0xF]);
46 putchar(lut
[val_arr
[3-i
] & 0xF]);
50 void memcpy(void *dest
, void *src
, size_t n
) {
52 //cast src and dest to char*
53 char *src_char
= (char *)src
;
54 char *dest_char
= (char *)dest
;
57 if ((i
% 4096) == 0) {
63 dest_char
[i
] = src_char
[i
]; //copy contents byte by byte
73 #define TERCEL_SPI_REG_SYS_PHY_CFG1 0x10
74 #define TERCEL_SPI_REG_SYS_FLASH_CFG5 0x24
75 #define TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK 0xff
76 #define TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT 0
77 #define TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK 0x1
78 #define TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT 0
79 static inline uint32_t read_tercel_register(uint8_t reg
)
81 return readl((unsigned long)(SPI_FCTRL_BASE
+reg
));
84 static inline void write_tercel_register(uint8_t reg
, uint32_t value
)
86 writel(value
, (unsigned long)(SPI_FCTRL_BASE
+reg
));
89 // TODO: need to use this
90 // https://gitlab.raptorengineering.com/kestrel-collaboration/kestrel-litex/litex/-/blob/master/litex/soc/software/bios/boot.c#L575
91 static bool fl_read(void *dst
, uint32_t offset
, uint32_t size
)
94 memcpy(d
, (void *)(unsigned long)(SPI_FLASH_BASE
+ offset
), size
);
98 static unsigned long copy_flash(unsigned int offset
)
102 unsigned int i
, poff
, size
, off
;
107 // Set SPI clock cycle divider to 1
109 dword
= read_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1
);
110 dword
&= ~(TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK
<<
111 TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT
);
112 dword
|= ((1 & TERCEL_SPI_PHY_CLOCK_DIVISOR_MASK
) <<
113 TERCEL_SPI_PHY_CLOCK_DIVISOR_SHIFT
);
114 write_tercel_register(TERCEL_SPI_REG_SYS_PHY_CFG1
, dword
);
115 // Enable read merging
116 dword
= read_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5
);
117 dword
|= (TERCEL_SPI_FLASH_EN_MULTCYC_READ_MASK
<<
118 TERCEL_SPI_FLASH_EN_MULTCYC_READ_SHIFT
);
119 write_tercel_register(TERCEL_SPI_REG_SYS_FLASH_CFG5
, dword
);
121 puts("Trying flash...\r\n");
122 if (!fl_read(&ehdr
, offset
, sizeof(ehdr
)))
124 if (!IS_ELF(ehdr
) || ehdr
.e_ident
[EI_CLASS
] != ELFCLASS64
) {
125 puts("Doesn't look like an elf64\r\n");
128 if (ehdr
.e_ident
[EI_DATA
] != ELFDATA2LSB
||
129 ehdr
.e_machine
!= EM_PPC64
) {
130 puts("Not a ppc64le binary\r\n");
134 poff
= offset
+ ehdr
.e_phoff
;
135 for (i
= 0; i
< ehdr
.e_phnum
; i
++) {
136 if (!fl_read(&ph
, poff
, sizeof(ph
)))
138 if (ph
.p_type
!= PT_LOAD
)
141 /* XXX Add bound checking ! */
143 addr
= (void *)ph
.p_vaddr
;
144 off
= offset
+ ph
.p_offset
;
145 //printf("Copy segment %d (0x%x bytes) to %p\n", i, size, addr);
146 puts("Copy segment ");
149 uart_writeuint32(size
);
151 uart_writeuint32((uint32_t)(unsigned long)addr
);
153 fl_read(addr
, off
, size
);
154 poff
+= ehdr
.e_phentsize
;
157 puts("Booting from DRAM at");
158 uart_writeuint32((unsigned int)ehdr
.e_entry
);
161 puts("Dump DRAM\r\n");
162 for (i
= 0; i
< 64; i
++) {
163 uart_writeuint32(readl(ehdr
.e_entry
+(i
*4)));
165 if ((i
& 7) == 7) puts("\r\n");
169 //flush_cpu_icache();
173 for (i
= 0; i
< 8; i
++) {
174 uart_writeuint32(ehdr
.e_ident
[i
]);
183 // Defining gram_[read|write] allows a trace of all register
184 // accesses to be dumped to console for debugging purposes.
185 // To use, define GRAM_RW_FUNC in gram.h
186 uint32_t gram_read(const struct gramCtx
*ctx
, void *addr
) {
190 uart_writeuint32((unsigned long)addr
);
191 dword
= readl((unsigned long)addr
);
193 uart_writeuint32((unsigned long)dword
);
199 int gram_write(const struct gramCtx
*ctx
, void *addr
, uint32_t value
) {
200 puts("gram_write: ");
201 uart_writeuint32((unsigned long)addr
);
203 uart_writeuint32((unsigned long)value
);
204 writel(value
, (unsigned long)addr
);
211 const int kNumIterations
= 14;
212 int res
, failcnt
= 0;
214 unsigned long ftr
, spi_offs
=0x0;
215 volatile uint32_t *ram
= (uint32_t*)MEMORY_BASE
;
218 //puts("Firmware launched...\n");
221 puts(" Soc signature: ");
222 tmp
= readl(SYSCON_BASE
+ SYS_REG_SIGNATURE
);
223 uart_writeuint32(tmp
);
224 puts(" Soc features: ");
225 ftr
= readl(SYSCON_BASE
+ SYS_REG_INFO
);
226 if (ftr
& SYS_REG_INFO_HAS_UART
)
228 if (ftr
& SYS_REG_INFO_HAS_DRAM
)
230 if (ftr
& SYS_REG_INFO_HAS_BRAM
)
232 if (ftr
& SYS_REG_INFO_HAS_SPI_FLASH
)
234 if (ftr
& SYS_REG_INFO_HAS_LITEETH
)
238 if (ftr
& SYS_REG_INFO_HAS_SPI_FLASH
) {
239 puts("SPI Offset: ");
240 spi_offs
= readl(SYSCON_BASE
+ SYS_REG_SPI_INFO
);
241 uart_writeuint32(spi_offs
);
249 // print out configuration parameters for QSPI
250 volatile uint32_t *qspi_cfg
= (uint32_t*)SPI_FCTRL_BASE
;
251 for (int k
=0; k
< 2; k
++) {
252 tmp
= readl((unsigned long)&(qspi_cfg
[k
]));
256 uart_writeuint32(tmp
);
260 volatile uint32_t *qspi
= (uint32_t*)spi_offs
;
261 //volatile uint8_t *qspi_bytes = (uint8_t*)spi_offs;
262 // let's not, eh? writel(0xDEAF0123, (unsigned long)&(qspi[0]));
263 // tmp = readl((unsigned long)&(qspi[0]));
264 for (int i
=0;i
<256;i
++) {
265 tmp
= readl((unsigned long)&(qspi
[i
]));
266 uart_writeuint32(tmp
);
268 if ((i
& 0x7) == 0x7) puts("\r\n");
272 for (i=0;i<256;i++) {
273 tmp = readb((unsigned long)&(qspi_bytes[i]));
274 uart_writeuint32(tmp);
281 tmp
= readl((unsigned long)&(qspi
[0x1000/4]));
283 uart_writeuint32(tmp
);
287 unsigned char c
= getchar();
289 if (c
== 13) { // if CR send LF
292 tmp
= readl((unsigned long)&(qspi
[1<<i
]));
294 uart_writeuint32(1<<i
);
296 uart_writeuint32(tmp
);
306 volatile uint32_t *hyperram
= (uint32_t*)0xa0000000;
307 writel(0xDEAF0123, (unsigned long)&(hyperram
[0]));
308 tmp
= readl((unsigned long)&(hyperram
[0]));
310 unsigned char c
= getchar();
312 if (c
== 13) { // if CR send LF
315 writel(0xDEAF0123+i
, (unsigned long)&(hyperram
[1<<i
]));
316 tmp
= readl((unsigned long)&(hyperram
[1<<i
]));
318 uart_writeuint32(1<<i
);
320 uart_writeuint32(tmp
);
329 // init DRAM only if SYSCON says it exists (duh)
330 if (ftr
& SYS_REG_INFO_HAS_DRAM
)
332 puts("DRAM init... ");
336 struct gramProfile profile
= {
338 0xb20, 0x806, 0x200, 0x0
345 struct gramProfile profile
= {
347 0x0320, 0x0006, 0x0200, 0x0000
353 struct gramProfile profile2
;
354 gram_init(&ctx
, &profile
, (void*)MEMORY_BASE
,
355 (void*)DRAM_CTRL_BASE
,
356 (void*)DRAM_INIT_BASE
);
359 puts("MR profile: ");
360 uart_writeuint32(profile
.mode_registers
[0]);
362 uart_writeuint32(profile
.mode_registers
[1]);
364 uart_writeuint32(profile
.mode_registers
[2]);
366 uart_writeuint32(profile
.mode_registers
[3]);
370 // Early read test for WB access sim
371 //uart_writeuint32(*ram);
375 for (size_t i
= 0; i
< 8; i
++) {
376 profile2
.rdly_p0
= i
;
377 gram_load_calibration(&ctx
, &profile2
);
378 gram_reset_burstdet(&ctx
);
380 for (size_t j
= 0; j
< 128; j
++) {
381 tmp
= readl((unsigned long)&(ram
[i
]));
383 if (gram_read_burstdet(&ctx
, 0)) {
392 for (size_t i
= 0; i
< 8; i
++) {
393 profile2
.rdly_p1
= i
;
394 gram_load_calibration(&ctx
, &profile2
);
395 gram_reset_burstdet(&ctx
);
396 for (size_t j
= 0; j
< 128; j
++) {
397 tmp
= readl((unsigned long)&(ram
[i
]));
399 if (gram_read_burstdet(&ctx
, 1)) {
407 puts("Auto calibrating... ");
408 res
= gram_generate_calibration(&ctx
, &profile2
);
409 if (res
!= GRAM_ERR_NONE
) {
411 gram_load_calibration(&ctx
, &profile
);
413 gram_load_calibration(&ctx
, &profile2
);
417 puts("Auto calibration profile:");
419 uart_writeuint32(profile2
.rdly_p0
);
421 uart_writeuint32(profile2
.rdly_p1
);
425 puts("Reloading built-in calibration profile...");
426 gram_load_calibration(&ctx
, &profile
);
428 puts("DRAM test... \n");
429 for (size_t i
= 0; i
< kNumIterations
; i
++) {
430 writel(0xDEAF0000 | i
*4, (unsigned long)&(ram
[i
]));
434 for (int dly
= 0; dly
< 8; dly
++) {
436 profile2
.rdly_p0
= dly
;
437 profile2
.rdly_p1
= dly
;
439 uart_writeuint32(profile2
.rdly_p0
);
441 uart_writeuint32(profile2
.rdly_p1
);
442 gram_load_calibration(&ctx
, &profile2
);
443 for (size_t i
= 0; i
< kNumIterations
; i
++) {
444 if (readl((unsigned long)&(ram
[i
])) != (0xDEAF0000 | i
*4)) {
446 uart_writeuint32((unsigned long)(&ram
[i
]));
448 uart_writeuint32(readl((unsigned long)&(ram
[i
])));
453 puts("Test canceled (more than 10 errors)\n");
461 for (size_t i
= 0; i
< kNumIterations
; i
++) {
462 if (readl((unsigned long)&(ram
[i
])) != (0xDEAF0000 | i
*4)) {
464 uart_writeuint32((unsigned long)(&ram
[i
]));
466 uart_writeuint32(readl((unsigned long)&(ram
[i
])));
471 puts("Test canceled (more than 10 errors)\n");
480 // memcpy from SPI Flash then boot
481 if ((ftr
& SYS_REG_INFO_HAS_SPI_FLASH
) &&
484 // identify ELF, copy if present, and get the start address
485 unsigned long faddr
= copy_flash(spi_offs
);
487 // jump to absolute address