diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c index 0ebe11e24d..7f4441c109 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c @@ -21,7 +21,7 @@ #include "spl-x1000.h" #include "gpio-x1000.h" -#include "nand-x1000.h" +#include "clk-x1000.h" #include "system.h" #include @@ -130,3 +130,36 @@ int spl_get_boot_option(void) /* Default is to boot Rockbox */ return SPL_BOOTOPT_ROCKBOX; } + +void spl_handle_pre_boot(int bootopt) +{ + /* Move system to EXCLK so we can manipulate the PLLs */ + clk_set_ccr_mux(CLKMUX_SCLK_A(EXCLK) | CLKMUX_CPU(SCLK_A) | + CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); + clk_set_ccr_div(1, 1, 1, 1, 1); + + /* Enable APLL @ 1008 MHz (24 MHz EXCLK * 42 = 1008 MHz) */ + jz_writef(CPM_APCR, BS(1), PLLM(41), PLLN(0), PLLOD(0), ENABLE(1)); + while(jz_readf(CPM_APCR, ON) == 0); + + /* System clock setup -- common to Rockbox and FiiO firmware + * ---- + * CPU at 1 GHz, L2 cache at 500 MHz + * AHB0 and AHB2 and 200 MHz + * PCLK at 100 MHz + * DDR at 200 MHz + */ + clk_set_ccr_div(1, 2, 5, 5, 10); + clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) | + CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); + + if(bootopt == SPL_BOOTOPT_ROCKBOX) { + /* We don't use MPLL in Rockbox, so switch DDR memory to APLL */ + clk_set_ddr(X1000_CLK_SCLK_A, 5); + + /* Turn off MPLL */ + jz_writef(CPM_MPCR, ENABLE(0)); + } else { + /* TODO: Original firmware needs a lot of other clocks turned on */ + } +} diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c index 59e0fb687d..e6d87066b5 100644 --- a/firmware/target/mips/ingenic_x1000/spl-x1000.c +++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c @@ -279,7 +279,8 @@ void main(void) if(nandread(opt->nand_addr, opt->nand_size, (void*)opt->load_addr)) spl_error(); - /* TODO: implement dual boot */ + /* Let target handle necessary pre-boot setup */ + spl_handle_pre_boot(option); /* Reading the Linux command line from the bootloader is handled by * arch/mips/xburst/core/prom.c -- see Ingenic kernel sources. diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.h b/firmware/target/mips/ingenic_x1000/spl-x1000.h index 44601438f3..d2255a8d05 100644 --- a/firmware/target/mips/ingenic_x1000/spl-x1000.h +++ b/firmware/target/mips/ingenic_x1000/spl-x1000.h @@ -39,11 +39,17 @@ struct spl_boot_option { extern const struct spl_boot_option spl_boot_options[]; /* Called on a fatal error */ -void spl_error(void) __attribute__((noreturn)); +extern void spl_error(void) __attribute__((noreturn)); /* When SPL boots with SPL_BOOTOPTION_CHOOSE, this function is invoked * to let the target figure out the boot option based on buttons the * user is pressing */ extern int spl_get_boot_option(void); +/* Do any setup/initialization needed for the given boot option, this + * will be called right before flushing caches + jumping to the image. + * Typical use is to set up system clocks, etc. + */ +extern void spl_handle_pre_boot(int bootopt); + #endif /* __SPL_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/system-x1000.c b/firmware/target/mips/ingenic_x1000/system-x1000.c index 54513cffb2..d841a274ed 100644 --- a/firmware/target/mips/ingenic_x1000/system-x1000.c +++ b/firmware/target/mips/ingenic_x1000/system-x1000.c @@ -40,40 +40,6 @@ int __cpu_idle_cur = 0; uint32_t __cpu_idle_ticks = 0; uint32_t __cpu_idle_reftick = 0; -static void system_init_clk(void) -{ - /* Gate all clocks except CPU/bus/memory/RTC */ - REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC); - - /* Switch to EXCLK */ - clk_set_ccr_mux(CLKMUX_SCLK_A(EXCLK) | CLKMUX_CPU(SCLK_A) | - CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); - clk_set_ccr_div(1, 1, 1, 1, 1); - -#ifdef FIIO_M3K - /* Nominal clock configuration - * --------------------------- - * APLL at 1 GHz, MPLL disabled - * CPU at 1 GHz, L2 cache at 500 MHz - * AHB0 and AHB2 at 200 MHz - * PCLK at 100 MHz - * DDR at 200 MHz - */ - jz_writef(CPM_APCR, BS(1), PLLM(41), PLLN(0), PLLOD(0), ENABLE(1)); - while(jz_readf(CPM_APCR, ON) == 0); - - clk_set_ccr_div(1, 2, 5, 5, 10); - clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) | - CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); - clk_set_ddr(X1000_CLK_SCLK_A, 5); - - /* Shut off MPLL, since nobody should be using it now */ - jz_writef(CPM_MPCR, ENABLE(0)); -#else -# error "Please define system clock configuration for target" -#endif -} - /* Prepare the CPU to process interrupts, but don't enable them yet */ static void system_init_irq(void) { @@ -94,8 +60,8 @@ static void system_init_irq(void) /* First thing called from Rockbox main() */ void system_init(void) { - /* Setup system clocks */ - system_init_clk(); + /* Gate all clocks except CPU/bus/memory/RTC */ + REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC); /* Ungate timers and turn them all off by default */ jz_writef(CPM_CLKGR, TCU(0), OST(0));