From 01d1eb425874813864d12d72c93e6e74ab92ac1f Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 15 Apr 2021 03:00:04 +0100 Subject: FiiO M3K/X1000: Do system clock initialization in the SPL Initializing the clocks in the SPL brings Rockbox in line with how the FiiO M3K's original SPL works. It's likely other X1000 devices do this too. There was a logic error in the previous setup: the code falsely assumed that DDR memory would always be running from MPLL, but it would be switched to APLL by the bootloader. Rockbox would then try to re-init APLL, albeit with the same parameters. Maybe this was the cause of the boot hang on some units. Change-Id: I64064585e491bbdf1e95fe9428c91a9314f2a917 --- .../mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c | 35 +++++++++++++++++++- firmware/target/mips/ingenic_x1000/spl-x1000.c | 3 +- firmware/target/mips/ingenic_x1000/spl-x1000.h | 8 ++++- firmware/target/mips/ingenic_x1000/system-x1000.c | 38 ++-------------------- 4 files changed, 45 insertions(+), 39 deletions(-) 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)); -- cgit v1.2.3