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.c141
1 files changed, 63 insertions, 78 deletions
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c
index 6505cabbef..07453f6182 100644
--- a/firmware/target/mips/ingenic_x1000/spl-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c
@@ -20,7 +20,6 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "spl-x1000.h" 22#include "spl-x1000.h"
23#include "spl-target.h"
24#include "clk-x1000.h" 23#include "clk-x1000.h"
25#include "nand-x1000.h" 24#include "nand-x1000.h"
26#include "system.h" 25#include "system.h"
@@ -29,16 +28,15 @@
29#include "x1000/ddrc.h" 28#include "x1000/ddrc.h"
30#include "x1000/ddrc_apb.h" 29#include "x1000/ddrc_apb.h"
31#include "x1000/ddrphy.h" 30#include "x1000/ddrphy.h"
31#include "ucl_decompress.h"
32 32
33struct x1000_spl_arguments* const spl_arguments = 33#ifdef FIIO_M3K
34 (struct x1000_spl_arguments*)SPL_ARGUMENTS_ADDRESS; 34# define SPL_DDR_MEMORYSIZE 64
35 35# define SPL_DDR_AUTOSR_EN 1
36struct x1000_spl_status* const spl_status = 36# define SPL_DDR_NEED_BYPASS 1
37 (struct x1000_spl_status*)SPL_STATUS_ADDRESS; 37#else
38 38# error "please add SPL memory definitions"
39/* defined to be Linux compatible; Rockbox needs no arguments so there 39#endif
40 * is no harm in passing them and we save a little code size */
41typedef void(*entry_fn)(int, char**, int, int);
42 40
43/* Note: This is based purely on disassembly of the SPL from the FiiO M3K. 41/* Note: This is based purely on disassembly of the SPL from the FiiO M3K.
44 * The code there is somewhat generic and corresponds roughly to Ingenic's 42 * The code there is somewhat generic and corresponds roughly to Ingenic's
@@ -243,83 +241,70 @@ static int nandread(uint32_t addr, uint32_t size, void* buffer)
243 return rc; 241 return rc;
244} 242}
245 243
246static int nandwrite(uint32_t addr, uint32_t size, const void* buffer) 244/* Entry point function type, defined to be Linux compatible. */
247{ 245typedef void(*entry_fn)(int, char**, int, int);
248 int rc;
249 int mf_id, dev_id;
250 246
251 if((rc = nand_open())) 247/* Kernel command line arguments */
252 return rc; 248static char* argv[2];
253 if((rc = nand_identify(&mf_id, &dev_id))) {
254 nand_close();
255 return rc;
256 }
257 249
258 if((rc = nand_enable_writes(true))) 250/* This variable is defined by the maskrom. It's simply the level of the
259 goto _end; 251 * boot_sel[2:0] pins (GPIOs B28-30) at boot time. Meaning of the bits:
252 *
253 * boot_sel[2] boot_sel[1] boot_sel[0] Description
254 * -----------------------------------------------------------------
255 * 1 X X EXCLK is 26 MHz
256 * 0 X X EXCLK is 24 MHz
257 * X 1 1 Boot from SFC0
258 * X 0 1 Boot from MSC0
259 * X 1 0 Boot from USB 2.0 device
260 * -----------------------------------------------------------------
261 * Source: X1000 PM pg. 687, "XBurst Boot ROM Specification"
262 */
263extern const uint32_t boot_sel;
260 264
261 if((rc = nand_erase(addr, size))) 265void spl_main(void)
262 goto _end1; 266{
267 int opt_index;
268 uint8_t* load_addr;
269 const struct spl_boot_option* opt;
263 270
264 rc = nand_write(addr, size, (const uint8_t*)buffer); 271 /* Basic hardware init */
272 init();
265 273
266 _end1: 274 /* If doing a USB boot, host PC will upload 2nd stage itself,
267 /* an error here is very unlikely, so ignore it */ 275 * we should not load anything from flash or change clocks. */
268 nand_enable_writes(false); 276 if((boot_sel & 3) == 2)
277 return;
269 278
270 _end: 279 /* Get the boot option */
271 nand_close(); 280 opt_index = spl_get_boot_option();
272 return rc; 281 opt = &spl_boot_options[opt_index];
273} 282 load_addr = (uint8_t*)opt->load_addr;
274 283
275/* Kernel command line arguments */ 284 /* Set up hardware, load stuff from flash */
276static char* argv[2]; 285 spl_handle_pre_boot(opt_index);
286 if(nandread(opt->nand_addr, opt->nand_size, load_addr))
287 spl_error();
277 288
278void main(void) 289 if(!opt->cmdline) {
279{ 290 /* No command line => we are booting Rockbox, decompress bootloader.
280 if(!(SPL_ARGUMENTS->flags & SPL_FLAG_SKIP_INIT)) 291 * In the case of Rockbox, load binary directly to exec address */
281 init(); 292 uint32_t out_size = X1000_DRAM_END - opt->exec_addr;
282 293 int rc = ucl_unpack(load_addr, opt->nand_size,
283 switch(SPL_ARGUMENTS->command) { 294 (uint8_t*)opt->exec_addr, &out_size);
284 case SPL_CMD_BOOT: { 295 if(rc != UCL_E_OK)
285 int option = SPL_ARGUMENTS->param1;
286 if(option == SPL_BOOTOPT_CHOOSE)
287 option = spl_get_boot_option();
288 if(option == SPL_BOOTOPT_NONE)
289 return;
290
291 const struct spl_boot_option* opt = &spl_boot_options[option-1];
292 if(nandread(opt->nand_addr, opt->nand_size, (void*)opt->load_addr))
293 spl_error(); 296 spl_error();
294
295 /* Let target handle necessary pre-boot setup */
296 spl_handle_pre_boot(option);
297
298 /* Reading the Linux command line from the bootloader is handled by
299 * arch/mips/xburst/core/prom.c -- see Ingenic kernel sources.
300 *
301 * Rockbox doesn't use arguments, but passing them does not hurt and it
302 * saves an unnecessary branch.
303 */
304 entry_fn entry = (entry_fn)opt->exec_addr;
305 argv[0] = 0;
306 argv[1] = (char*)opt->cmdline;
307
308 commit_discard_idcache();
309 entry(2, argv, 0, 0);
310 __builtin_unreachable();
311 } 297 }
312 298
313 case SPL_CMD_FLASH_READ: 299 /* Reading the Linux command line from the bootloader is handled by
314 SPL_STATUS->err_code = nandread(SPL_ARGUMENTS->param1, 300 * arch/mips/xburst/core/prom.c -- see Ingenic kernel sources. It's
315 SPL_ARGUMENTS->param2, 301 * simply an (int argc, char* argv[]) thing.
316 (void*)SPL_BUFFER_ADDRESS); 302 */
317 return; 303 entry_fn entry = (entry_fn)opt->exec_addr;
318 304 argv[0] = 0;
319 case SPL_CMD_FLASH_WRITE: 305 argv[1] = (char*)opt->cmdline;
320 SPL_STATUS->err_code = nandwrite(SPL_ARGUMENTS->param1, 306
321 SPL_ARGUMENTS->param2, 307 commit_discard_idcache();
322 (const void*)SPL_BUFFER_ADDRESS); 308 entry(2, argv, 0, 0);
323 return; 309 __builtin_unreachable();
324 }
325} 310}