summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-04-15 03:00:04 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-04-17 20:24:07 +0000
commit01d1eb425874813864d12d72c93e6e74ab92ac1f (patch)
treee4bc6171342e1ef4160b2e32653f5668f9be3d69
parente123c5d2f27e9efbef8b4264f1576e4e10ba7b82 (diff)
downloadrockbox-01d1eb425874813864d12d72c93e6e74ab92ac1f.tar.gz
rockbox-01d1eb425874813864d12d72c93e6e74ab92ac1f.zip
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
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c35
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c3
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.h8
-rw-r--r--firmware/target/mips/ingenic_x1000/system-x1000.c38
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 @@
21 21
22#include "spl-x1000.h" 22#include "spl-x1000.h"
23#include "gpio-x1000.h" 23#include "gpio-x1000.h"
24#include "nand-x1000.h" 24#include "clk-x1000.h"
25#include "system.h" 25#include "system.h"
26#include <string.h> 26#include <string.h>
27 27
@@ -130,3 +130,36 @@ int spl_get_boot_option(void)
130 /* Default is to boot Rockbox */ 130 /* Default is to boot Rockbox */
131 return SPL_BOOTOPT_ROCKBOX; 131 return SPL_BOOTOPT_ROCKBOX;
132} 132}
133
134void spl_handle_pre_boot(int bootopt)
135{
136 /* Move system to EXCLK so we can manipulate the PLLs */
137 clk_set_ccr_mux(CLKMUX_SCLK_A(EXCLK) | CLKMUX_CPU(SCLK_A) |
138 CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A));
139 clk_set_ccr_div(1, 1, 1, 1, 1);
140
141 /* Enable APLL @ 1008 MHz (24 MHz EXCLK * 42 = 1008 MHz) */
142 jz_writef(CPM_APCR, BS(1), PLLM(41), PLLN(0), PLLOD(0), ENABLE(1));
143 while(jz_readf(CPM_APCR, ON) == 0);
144
145 /* System clock setup -- common to Rockbox and FiiO firmware
146 * ----
147 * CPU at 1 GHz, L2 cache at 500 MHz
148 * AHB0 and AHB2 and 200 MHz
149 * PCLK at 100 MHz
150 * DDR at 200 MHz
151 */
152 clk_set_ccr_div(1, 2, 5, 5, 10);
153 clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) |
154 CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A));
155
156 if(bootopt == SPL_BOOTOPT_ROCKBOX) {
157 /* We don't use MPLL in Rockbox, so switch DDR memory to APLL */
158 clk_set_ddr(X1000_CLK_SCLK_A, 5);
159
160 /* Turn off MPLL */
161 jz_writef(CPM_MPCR, ENABLE(0));
162 } else {
163 /* TODO: Original firmware needs a lot of other clocks turned on */
164 }
165}
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)
279 if(nandread(opt->nand_addr, opt->nand_size, (void*)opt->load_addr)) 279 if(nandread(opt->nand_addr, opt->nand_size, (void*)opt->load_addr))
280 spl_error(); 280 spl_error();
281 281
282 /* TODO: implement dual boot */ 282 /* Let target handle necessary pre-boot setup */
283 spl_handle_pre_boot(option);
283 284
284 /* Reading the Linux command line from the bootloader is handled by 285 /* Reading the Linux command line from the bootloader is handled by
285 * arch/mips/xburst/core/prom.c -- see Ingenic kernel sources. 286 * 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 {
39extern const struct spl_boot_option spl_boot_options[]; 39extern const struct spl_boot_option spl_boot_options[];
40 40
41/* Called on a fatal error */ 41/* Called on a fatal error */
42void spl_error(void) __attribute__((noreturn)); 42extern void spl_error(void) __attribute__((noreturn));
43 43
44/* When SPL boots with SPL_BOOTOPTION_CHOOSE, this function is invoked 44/* When SPL boots with SPL_BOOTOPTION_CHOOSE, this function is invoked
45 * to let the target figure out the boot option based on buttons the 45 * to let the target figure out the boot option based on buttons the
46 * user is pressing */ 46 * user is pressing */
47extern int spl_get_boot_option(void); 47extern int spl_get_boot_option(void);
48 48
49/* Do any setup/initialization needed for the given boot option, this
50 * will be called right before flushing caches + jumping to the image.
51 * Typical use is to set up system clocks, etc.
52 */
53extern void spl_handle_pre_boot(int bootopt);
54
49#endif /* __SPL_X1000_H__ */ 55#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;
40uint32_t __cpu_idle_ticks = 0; 40uint32_t __cpu_idle_ticks = 0;
41uint32_t __cpu_idle_reftick = 0; 41uint32_t __cpu_idle_reftick = 0;
42 42
43static void system_init_clk(void)
44{
45 /* Gate all clocks except CPU/bus/memory/RTC */
46 REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC);
47
48 /* Switch to EXCLK */
49 clk_set_ccr_mux(CLKMUX_SCLK_A(EXCLK) | CLKMUX_CPU(SCLK_A) |
50 CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A));
51 clk_set_ccr_div(1, 1, 1, 1, 1);
52
53#ifdef FIIO_M3K
54 /* Nominal clock configuration
55 * ---------------------------
56 * APLL at 1 GHz, MPLL disabled
57 * CPU at 1 GHz, L2 cache at 500 MHz
58 * AHB0 and AHB2 at 200 MHz
59 * PCLK at 100 MHz
60 * DDR at 200 MHz
61 */
62 jz_writef(CPM_APCR, BS(1), PLLM(41), PLLN(0), PLLOD(0), ENABLE(1));
63 while(jz_readf(CPM_APCR, ON) == 0);
64
65 clk_set_ccr_div(1, 2, 5, 5, 10);
66 clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) |
67 CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A));
68 clk_set_ddr(X1000_CLK_SCLK_A, 5);
69
70 /* Shut off MPLL, since nobody should be using it now */
71 jz_writef(CPM_MPCR, ENABLE(0));
72#else
73# error "Please define system clock configuration for target"
74#endif
75}
76
77/* Prepare the CPU to process interrupts, but don't enable them yet */ 43/* Prepare the CPU to process interrupts, but don't enable them yet */
78static void system_init_irq(void) 44static void system_init_irq(void)
79{ 45{
@@ -94,8 +60,8 @@ static void system_init_irq(void)
94/* First thing called from Rockbox main() */ 60/* First thing called from Rockbox main() */
95void system_init(void) 61void system_init(void)
96{ 62{
97 /* Setup system clocks */ 63 /* Gate all clocks except CPU/bus/memory/RTC */
98 system_init_clk(); 64 REG_CPM_CLKGR = ~jz_orm(CPM_CLKGR, CPU_BIT, DDR, AHB0, APB0, RTC);
99 65
100 /* Ungate timers and turn them all off by default */ 66 /* Ungate timers and turn them all off by default */
101 jz_writef(CPM_CLKGR, TCU(0), OST(0)); 67 jz_writef(CPM_CLKGR, TCU(0), OST(0));