diff options
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/spl-x1000.c')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/spl-x1000.c | 118 |
1 files changed, 65 insertions, 53 deletions
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c index 1abbdcd7a4..05196e8270 100644 --- a/firmware/target/mips/ingenic_x1000/spl-x1000.c +++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c | |||
@@ -34,16 +34,46 @@ | |||
34 | #include "ucl_decompress.h" | 34 | #include "ucl_decompress.h" |
35 | #include <string.h> | 35 | #include <string.h> |
36 | 36 | ||
37 | #if defined(FIIO_M3K) || defined(SHANLING_Q1) | 37 | #if defined(FIIO_M3K) |
38 | # define SPL_DDR_MEMORYSIZE 64 | 38 | /* Size of memory, either 64 or 32 is legal. */ |
39 | # define SPL_DDR_AUTOSR_EN 1 | 39 | # define SPL_DDR_MEMORYSIZE 64 |
40 | # define SPL_DDR_NEED_BYPASS 1 | 40 | /* Pin to flash on spl_error(). Should be a backlight. */ |
41 | # define SPL_ERROR_PIN GPIO_PC(24) | ||
42 | /* Address and size of the bootloader on the storage medium used by the SPL */ | ||
43 | # define BOOT_STORAGE_ADDR 0x6800 | ||
44 | # define BOOT_STORAGE_SIZE (102 * 1024) | ||
45 | #elif defined(SHANLING_Q1) | ||
46 | # define SPL_DDR_MEMORYSIZE 64 | ||
47 | # define SPL_ERROR_PIN GPIO_PC(25) | ||
48 | # define BOOT_STORAGE_ADDR 0x6800 | ||
49 | # define BOOT_STORAGE_SIZE (102 * 1024) | ||
41 | #elif defined(EROS_QN) | 50 | #elif defined(EROS_QN) |
42 | # define SPL_DDR_MEMORYSIZE 32 | 51 | # define SPL_DDR_MEMORYSIZE 32 |
43 | # define SPL_DDR_AUTOSR_EN 1 | 52 | # define SPL_ERROR_PIN GPIO_PC(25) |
44 | # define SPL_DDR_NEED_BYPASS 1 | 53 | # define BOOT_STORAGE_ADDR 0x6800 |
54 | # define BOOT_STORAGE_SIZE (102 * 1024) | ||
45 | #else | 55 | #else |
46 | # error "please define DRAM settings" | 56 | # error "please define SPL config" |
57 | #endif | ||
58 | |||
59 | /* Hardcode this since the SPL is considered part of the bootloader, | ||
60 | * and should never get built or updated separately. */ | ||
61 | #define BOOT_LOAD_ADDR X1000_DRAM_BASE | ||
62 | #define BOOT_EXEC_ADDR BOOT_LOAD_ADDR | ||
63 | |||
64 | /* Whether the bootloader is UCL-compressed */ | ||
65 | #ifndef SPL_USE_UCLPACK | ||
66 | # define SPL_USE_UCLPACK 1 | ||
67 | #endif | ||
68 | |||
69 | /* Whether auto-self-refresh should be enabled (seems it always should be?) */ | ||
70 | #ifndef SPL_DDR_AUTOSR_EN | ||
71 | # define SPL_DDR_AUTOSR_EN 1 | ||
72 | #endif | ||
73 | |||
74 | /* Whether DLL bypass is necessary (probably always?) */ | ||
75 | #ifndef SPL_DDR_NEED_BYPASS | ||
76 | # define SPL_DDR_NEED_BYPASS 1 | ||
47 | #endif | 77 | #endif |
48 | 78 | ||
49 | static void* heap = (void*)(X1000_SDRAM_BASE + X1000_SDRAM_SIZE); | 79 | static void* heap = (void*)(X1000_SDRAM_BASE + X1000_SDRAM_SIZE); |
@@ -55,6 +85,16 @@ void* spl_alloc(size_t count) | |||
55 | return heap; | 85 | return heap; |
56 | } | 86 | } |
57 | 87 | ||
88 | void spl_error(void) | ||
89 | { | ||
90 | int level = 0; | ||
91 | while(1) { | ||
92 | gpio_set_function(SPL_ERROR_PIN, GPIOF_OUTPUT(level)); | ||
93 | mdelay(100); | ||
94 | level = 1 - level; | ||
95 | } | ||
96 | } | ||
97 | |||
58 | static void init_ost(void) | 98 | static void init_ost(void) |
59 | { | 99 | { |
60 | /* NOTE: the prescaler needs to be the same as in system-x1000.c */ | 100 | /* NOTE: the prescaler needs to be the same as in system-x1000.c */ |
@@ -235,14 +275,14 @@ static int init_dram(void) | |||
235 | return 0; | 275 | return 0; |
236 | } | 276 | } |
237 | 277 | ||
238 | static void* get_load_buffer(const struct spl_boot_option* opt) | 278 | static void* get_load_buffer(void) |
239 | { | 279 | { |
240 | /* read to a temporary location if we need to decompress, | 280 | /* read to a temporary location if we need to decompress, |
241 | * otherwise simply read directly to the load address. */ | 281 | * otherwise simply read directly to the load address. */ |
242 | if(opt->flags & BOOTFLAG_UCLPACK) | 282 | if(SPL_USE_UCLPACK) |
243 | return spl_alloc(opt->storage_size); | 283 | return spl_alloc(BOOT_STORAGE_SIZE); |
244 | else | 284 | else |
245 | return (void*)opt->load_addr; | 285 | return (void*)BOOT_LOAD_ADDR; |
246 | } | 286 | } |
247 | 287 | ||
248 | /* Mapping of boot_sel[1:0] pins. | 288 | /* Mapping of boot_sel[1:0] pins. |
@@ -266,15 +306,10 @@ static uint32_t get_boot_sel(void) | |||
266 | return (*(uint32_t*)0xf40001ec) & 3; | 306 | return (*(uint32_t*)0xf40001ec) & 3; |
267 | } | 307 | } |
268 | 308 | ||
269 | typedef void(*entry_fn)(int, char**, int, int) __attribute__((noreturn)); | ||
270 | |||
271 | void spl_main(void) | 309 | void spl_main(void) |
272 | { | 310 | { |
273 | int rc, boot_option; | 311 | int rc; |
274 | const struct spl_boot_option* opt; | ||
275 | void* load_buffer; | 312 | void* load_buffer; |
276 | char** kargv = NULL; | ||
277 | int kargc = 0; | ||
278 | 313 | ||
279 | /* magic */ | 314 | /* magic */ |
280 | REG_CPM_PSWC0ST = 0x00; | 315 | REG_CPM_PSWC0ST = 0x00; |
@@ -298,14 +333,6 @@ void spl_main(void) | |||
298 | return; | 333 | return; |
299 | } | 334 | } |
300 | 335 | ||
301 | /* find out what we should boot */ | ||
302 | boot_option = spl_get_boot_option(); | ||
303 | opt = &spl_boot_options[boot_option]; | ||
304 | load_buffer = get_load_buffer(opt); | ||
305 | |||
306 | /* save the selection for later */ | ||
307 | set_boot_option(boot_option); | ||
308 | |||
309 | /* finish up clock init */ | 336 | /* finish up clock init */ |
310 | clk_init(); | 337 | clk_init(); |
311 | 338 | ||
@@ -314,44 +341,29 @@ void spl_main(void) | |||
314 | if(rc != 0) | 341 | if(rc != 0) |
315 | spl_error(); | 342 | spl_error(); |
316 | 343 | ||
317 | rc = spl_storage_read(opt->storage_addr, opt->storage_size, load_buffer); | 344 | load_buffer = get_load_buffer(); |
345 | rc = spl_storage_read(BOOT_STORAGE_ADDR, BOOT_STORAGE_SIZE, load_buffer); | ||
318 | if(rc != 0) | 346 | if(rc != 0) |
319 | spl_error(); | 347 | spl_error(); |
320 | 348 | ||
321 | /* handle compression */ | 349 | /* decompress */ |
322 | switch(opt->flags & BOOTFLAG_COMPRESSED) { | 350 | if(SPL_USE_UCLPACK) { |
323 | case BOOTFLAG_UCLPACK: { | 351 | uint32_t out_size = X1000_SDRAM_END - BOOT_LOAD_ADDR; |
324 | uint32_t out_size = X1000_SDRAM_END - opt->load_addr; | 352 | rc = ucl_unpack((uint8_t*)load_buffer, BOOT_STORAGE_SIZE, |
325 | rc = ucl_unpack((uint8_t*)load_buffer, opt->storage_size, | 353 | (uint8_t*)BOOT_LOAD_ADDR, &out_size); |
326 | (uint8_t*)opt->load_addr, &out_size); | 354 | } else { |
327 | } break; | 355 | rc = 0; |
328 | |||
329 | default: | ||
330 | break; | ||
331 | } | 356 | } |
332 | 357 | ||
333 | if(rc != 0) | 358 | if(rc != 0) |
334 | spl_error(); | 359 | spl_error(); |
335 | 360 | ||
336 | /* call the setup hook */ | ||
337 | if(opt->setup) { | ||
338 | rc = opt->setup(); | ||
339 | if(rc != 0) | ||
340 | spl_error(); | ||
341 | } | ||
342 | |||
343 | /* close off storage access */ | 361 | /* close off storage access */ |
344 | spl_storage_close(); | 362 | spl_storage_close(); |
345 | 363 | ||
346 | /* handle kernel command line, if specified */ | ||
347 | if(opt->cmdline) { | ||
348 | kargv = (char**)opt->cmdline_addr; | ||
349 | kargv[kargc++] = 0; | ||
350 | kargv[kargc++] = (char*)opt->cmdline; | ||
351 | } | ||
352 | |||
353 | /* jump to the entry point */ | 364 | /* jump to the entry point */ |
354 | entry_fn fn = (entry_fn)opt->exec_addr; | 365 | typedef void(*entry_fn)(void); |
366 | entry_fn fn = (entry_fn)BOOT_EXEC_ADDR; | ||
355 | commit_discard_idcache(); | 367 | commit_discard_idcache(); |
356 | fn(kargc, kargv, 0, 0); | 368 | fn(); |
357 | } | 369 | } |