summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/spl-x1000.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/spl-x1000.c')
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c118
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
49static void* heap = (void*)(X1000_SDRAM_BASE + X1000_SDRAM_SIZE); 79static 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
88void 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
58static void init_ost(void) 98static 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
238static void* get_load_buffer(const struct spl_boot_option* opt) 278static 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
269typedef void(*entry_fn)(int, char**, int, int) __attribute__((noreturn));
270
271void spl_main(void) 309void 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}