summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/SOURCES7
-rw-r--r--firmware/SOURCES6
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c (renamed from bootloader/fiiom3k-spl.c)112
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h29
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000-defs.h66
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c (renamed from bootloader/x1000-spl.c)136
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.h49
7 files changed, 279 insertions, 126 deletions
diff --git a/bootloader/SOURCES b/bootloader/SOURCES
index db9e05644c..446bdac0e1 100644
--- a/bootloader/SOURCES
+++ b/bootloader/SOURCES
@@ -89,11 +89,6 @@ show_logo.c
89#elif defined(SANSA_CONNECT) 89#elif defined(SANSA_CONNECT)
90sansaconnect.c 90sansaconnect.c
91show_logo.c 91show_logo.c
92#elif defined(FIIO_M3K) 92#elif defined(FIIO_M3K) && !defined(BOOTLOADER_SPL)
93#ifdef BOOTLOADER_SPL
94x1000-spl.c
95fiiom3k-spl.c
96#else
97fiiom3k.c 93fiiom3k.c
98#endif 94#endif
99#endif
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 3a42381003..ce3d8d52e2 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1747,6 +1747,9 @@ target/mips/ingenic_x1000/msc-x1000.c
1747#if (CONFIG_STORAGE & STORAGE_SD) 1747#if (CONFIG_STORAGE & STORAGE_SD)
1748target/mips/ingenic_x1000/sd-x1000.c 1748target/mips/ingenic_x1000/sd-x1000.c
1749#endif 1749#endif
1750#ifdef BOOTLOADER_SPL
1751target/mips/ingenic_x1000/spl-x1000.c
1752#endif
1750#endif /* CONFIG_CPU == X1000 */ 1753#endif /* CONFIG_CPU == X1000 */
1751 1754
1752#if defined(ONDA_VX747) || defined(ONDA_VX747P) || defined(ONDA_VX777) 1755#if defined(ONDA_VX747) || defined(ONDA_VX747P) || defined(ONDA_VX777)
@@ -1780,6 +1783,9 @@ target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c
1780target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c 1783target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c
1781target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c 1784target/mips/ingenic_x1000/fiiom3k/nand-fiiom3k.c
1782target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c 1785target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
1786#ifdef BOOTLOADER_SPL
1787target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
1788#endif
1783#endif /* FIIO_M3K */ 1789#endif /* FIIO_M3K */
1784 1790
1785#if defined(LYRE_PROTO1) 1791#if defined(LYRE_PROTO1)
diff --git a/bootloader/fiiom3k-spl.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
index 67b4b0a59c..0ebe11e24d 100644
--- a/bootloader/fiiom3k-spl.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
@@ -19,28 +19,16 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "config.h" 22#include "spl-x1000.h"
23#include "nand-x1000.h"
24#include "gpio-x1000.h" 23#include "gpio-x1000.h"
25#include "mmu-mips.h" 24#include "nand-x1000.h"
25#include "system.h"
26#include <string.h> 26#include <string.h>
27 27
28/* "fiio" in little endian */ 28/* Boot select button state must remain stable for this duration
29#define BOOTMAGIC 0x6f696966 29 * before the choice will be accepted. Currently 100ms.
30 30 */
31/* Argument structure needed by Linux */ 31#define BTN_STABLE_TIME (100 * (X1000_EXCLK_FREQ / 4000))
32struct linux_kargs {
33 void* arg0;
34 void* arg1;
35};
36
37#define LINUX_KARGSADDR 0x80004000
38
39static const char recovery_cmdline[] = "mem=xxM@0x0\
40 no_console_suspend\
41 console=ttyS2,115200n8\
42 lpj=5009408\
43 ip=off";
44 32
45static const char normal_cmdline[] = "mem=64M@0x0\ 33static const char normal_cmdline[] = "mem=64M@0x0\
46 no_console_suspend\ 34 no_console_suspend\
@@ -55,18 +43,13 @@ static const char normal_cmdline[] = "mem=64M@0x0\
55 rw\ 43 rw\
56 loglevel=8"; 44 loglevel=8";
57 45
58#define BOOTOPTION_ROCKBOX 0 46static const char recovery_cmdline[] = "mem=64M@0x0\
59#define BOOTOPTION_FIIOLINUX 1 47 no_console_suspend\
60#define BOOTOPTION_RECOVERY 2 48 console=ttyS2,115200n8\
61#define NUM_BOOTOPTIONS 3 49 lpj=5009408\
62 50 ip=off";
63static const struct bootoption { 51
64 uint32_t nand_addr; 52const struct spl_boot_option spl_boot_options[] = {
65 uint32_t nand_size;
66 unsigned long load_addr;
67 unsigned long exec_addr;
68 const char* cmdline;
69} boot_options[NUM_BOOTOPTIONS] = {
70 { 53 {
71 /* Rockbox: the first unused NAND page is 26 KiB in, and the 54 /* Rockbox: the first unused NAND page is 26 KiB in, and the
72 * remainder of the block is unused, giving us 102 KiB to use. 55 * remainder of the block is unused, giving us 102 KiB to use.
@@ -95,10 +78,7 @@ static const struct bootoption {
95 }, 78 },
96}; 79};
97 80
98/* Simple diagnostic if something goes wrong -- a little nicer than wondering 81void spl_error(void)
99 * what's going on when the machine hangs
100 */
101void die(void)
102{ 82{
103 const int pin = (1 << 24); 83 const int pin = (1 << 24);
104 84
@@ -119,12 +99,7 @@ void die(void)
119 } 99 }
120} 100}
121 101
122/* Boot select button state must remain stable for this duration 102int spl_get_boot_option(void)
123 * before the choice will be accepted. Currently 100ms.
124 */
125#define BTN_STABLE_TIME (100 * (X1000_EXCLK_FREQ / 4000))
126
127int get_boot_option(void)
128{ 103{
129 const uint32_t pinmask = (1 << 17) | (1 << 19); 104 const uint32_t pinmask = (1 << 17) | (1 << 19);
130 105
@@ -146,61 +121,12 @@ int get_boot_option(void)
146 121
147 /* Play button boots original firmware */ 122 /* Play button boots original firmware */
148 if(pin == (1 << 17)) 123 if(pin == (1 << 17))
149 return BOOTOPTION_FIIOLINUX; 124 return SPL_BOOTOPT_ORIG_FW;
150 125
151 /* Volume up boots recovery */ 126 /* Volume up boots recovery */
152 if(pin == (1 << 19)) 127 if(pin == (1 << 19))
153 return BOOTOPTION_RECOVERY; 128 return SPL_BOOTOPT_RECOVERY;
154 129
155 /* Default is to boot Rockbox */ 130 /* Default is to boot Rockbox */
156 return BOOTOPTION_ROCKBOX; 131 return SPL_BOOTOPT_ROCKBOX;
157}
158
159void spl_main(void)
160{
161 /* Get user boot option */
162 int booti = get_boot_option();
163 const struct bootoption* opt = &boot_options[booti];
164
165 /* Load selected firmware from flash */
166 if(nand_open())
167 die();
168 if(nand_read_bytes(opt->nand_addr, opt->nand_size, (void*)opt->load_addr))
169 die();
170
171 if(booti == BOOTOPTION_ROCKBOX) {
172 /* If bootloader is not installed, return back to boot ROM.
173 * Also read in the first eraseblock of NAND flash so it can be
174 * dumped back over USB.
175 */
176 if(*(unsigned*)(opt->load_addr + 4) != BOOTMAGIC) {
177 nand_read_bytes(0, 128 * 1024, (void*)0x80000000);
178 commit_discard_idcache();
179 return;
180 }
181 } else {
182 /* TODO: Linux boot not implemented yet
183 *
184 * - Have to initialize UART2, as it's used for the serial console
185 * - Must initialize APLL and change clocks over
186 * - There are some other clocks which need to be initialized
187 * - We should turn off OST since the OF SPL does not turn it on
188 */
189 die();
190 }
191
192 if(boot_options[booti].cmdline) {
193 /* Handle Linux command line arguments */
194 struct linux_kargs* kargs = (struct linux_kargs*)LINUX_KARGSADDR;
195 kargs->arg0 = 0;
196 kargs->arg1 = (void*)boot_options[booti].cmdline;
197 }
198
199 /* Flush caches and jump to address */
200 void* execaddr = (void*)opt->exec_addr;
201 commit_discard_idcache();
202 __asm__ __volatile__ ("jr %0\n"
203 "nop\n"
204 :: "r"(execaddr));
205 __builtin_unreachable();
206} 132}
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h
new file mode 100644
index 0000000000..ac90508f44
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h
@@ -0,0 +1,29 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __SPL_TARGET_H__
23#define __SPL_TARGET_H__
24
25#define SPL_DDR_MEMORYSIZE 64
26#define SPL_DDR_AUTOSR_EN 1
27#define SPL_DDR_NEED_BYPASS 1
28
29#endif /* __SPL_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000-defs.h b/firmware/target/mips/ingenic_x1000/spl-x1000-defs.h
new file mode 100644
index 0000000000..1d9f120ee2
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000-defs.h
@@ -0,0 +1,66 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __SPL_X1000_DEFS_H__
23#define __SPL_X1000_DEFS_H__
24
25#include <stdint.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31#define SPL_CMD_BOOT 0
32#define SPL_CMD_FLASH_READ 1
33#define SPL_CMD_FLASH_WRITE 2
34
35#define SPL_BOOTOPT_CHOOSE 0
36#define SPL_BOOTOPT_ROCKBOX 1
37#define SPL_BOOTOPT_ORIG_FW 2
38#define SPL_BOOTOPT_RECOVERY 3
39#define SPL_BOOTOPT_NONE 4
40
41#define SPL_FLAG_SKIP_INIT (1 << 0)
42
43#define SPL_MAX_SIZE (12 * 1024)
44#define SPL_LOAD_ADDRESS 0xf4001000
45#define SPL_EXEC_ADDRESS 0xf4001800
46#define SPL_ARGUMENTS_ADDRESS 0xf40011f0
47#define SPL_STATUS_ADDRESS 0xf40011e0
48#define SPL_BUFFER_ADDRESS 0xa0004000
49
50struct x1000_spl_arguments {
51 uint32_t command;
52 uint32_t param1;
53 uint32_t param2;
54 uint32_t flags;
55};
56
57struct x1000_spl_status {
58 int err_code;
59 int reserved;
60};
61
62#ifdef __cplusplus
63}
64#endif
65
66#endif /* __SPL_X1000_DEFS_H__ */
diff --git a/bootloader/x1000-spl.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c
index 1c780a9843..59e0fb687d 100644
--- a/bootloader/x1000-spl.c
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c
@@ -19,26 +19,26 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "system.h" 22#include "spl-x1000.h"
23#include "spl-target.h"
23#include "clk-x1000.h" 24#include "clk-x1000.h"
25#include "nand-x1000.h"
26#include "system.h"
24#include "x1000/cpm.h" 27#include "x1000/cpm.h"
25#include "x1000/ost.h" 28#include "x1000/ost.h"
26#include "x1000/ddrc.h" 29#include "x1000/ddrc.h"
27#include "x1000/ddrc_apb.h" 30#include "x1000/ddrc_apb.h"
28#include "x1000/ddrphy.h" 31#include "x1000/ddrphy.h"
29 32
30#ifdef FIIO_M3K 33struct x1000_spl_arguments* const spl_arguments =
31# define DDR_USE_AUTOSR 1 34 (struct x1000_spl_arguments*)SPL_ARGUMENTS_ADDRESS;
32# define DDR_NEED_BYPASS 1
33# define DDR_MEMORYSIZE 64
34#else
35# error "Please add DDR definitions for new target!"
36#endif
37 35
38#define hang() do { } while(1) 36struct x1000_spl_status* const spl_status =
37 (struct x1000_spl_status*)SPL_STATUS_ADDRESS;
39 38
40/* Target-specific routine to load & execute the Rockbox bootloader */ 39/* defined to be Linux compatible; Rockbox needs no arguments so there
41extern void spl_main(void); 40 * is no harm in passing them and we save a little code size */
41typedef void(*entry_fn)(int, char**, int, int);
42 42
43/* Note: This is based purely on disassembly of the SPL from the FiiO M3K. 43/* 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 44 * The code there is somewhat generic and corresponds roughly to Ingenic's
@@ -95,9 +95,9 @@ static void ddr_init(void)
95 while(i > 0 && REG_DDRPHY_PGSR != 7 && REG_DDRPHY_PGSR != 0x1f) 95 while(i > 0 && REG_DDRPHY_PGSR != 7 && REG_DDRPHY_PGSR != 0x1f)
96 i -= 1; 96 i -= 1;
97 if(i == 0) 97 if(i == 0)
98 hang(); 98 spl_error();
99 99
100#if DDR_NEED_BYPASS 100#if SPL_DDR_NEED_BYPASS
101 REG_DDRPHY_ACDLLCR = 0x80000000; 101 REG_DDRPHY_ACDLLCR = 0x80000000;
102 REG_DDRPHY_DSGCR &= ~0x10; 102 REG_DDRPHY_DSGCR &= ~0x10;
103 REG_DDRPHY_DLLGCR |= 0x800000; 103 REG_DDRPHY_DLLGCR |= 0x800000;
@@ -109,7 +109,7 @@ static void ddr_init(void)
109 while(i > 0 && REG_DDRPHY_PGSR != 0xf && REG_DDRPHY_PGSR != 0x1f) 109 while(i > 0 && REG_DDRPHY_PGSR != 0xf && REG_DDRPHY_PGSR != 0x1f)
110 i -= 1; 110 i -= 1;
111 if(i == 0) 111 if(i == 0)
112 hang(); 112 spl_error();
113 113
114 REG_DDRC_APB_PHYRST_CFG = 0x400000; 114 REG_DDRC_APB_PHYRST_CFG = 0x400000;
115 mdelay(3); 115 mdelay(3);
@@ -118,7 +118,7 @@ static void ddr_init(void)
118 118
119 REG_DDRC_CFG = 0xa468aec; 119 REG_DDRC_CFG = 0xa468aec;
120 REG_DDRC_CTRL = 2; 120 REG_DDRC_CTRL = 2;
121#if DDR_NEED_BYPASS 121#if SPL_DDR_NEED_BYPASS
122 REG_DDRPHY_PIR = 0x20020081; 122 REG_DDRPHY_PIR = 0x20020081;
123#else 123#else
124 REG_DDRPHY_PIR = 0x85; 124 REG_DDRPHY_PIR = 0x85;
@@ -132,10 +132,10 @@ static void ddr_init(void)
132 } 132 }
133 133
134 if(i == 0) 134 if(i == 0)
135 hang(); 135 spl_error();
136 136
137 if((REG_DDRPHY_PGSR & 0x60) != 0 && REG_DDRPHY_PGSR != 0) 137 if((REG_DDRPHY_PGSR & 0x60) != 0 && REG_DDRPHY_PGSR != 0)
138 hang(); 138 spl_error();
139 139
140 REG_DDRC_CTRL = 0; 140 REG_DDRC_CTRL = 0;
141 REG_DDRC_CTRL = 10; 141 REG_DDRC_CTRL = 10;
@@ -147,10 +147,10 @@ static void ddr_init(void)
147 REG_DDRC_TIMING4 = 0xb7a0251; 147 REG_DDRC_TIMING4 = 0xb7a0251;
148 REG_DDRC_TIMING5 = 0xff090200; 148 REG_DDRC_TIMING5 = 0xff090200;
149 REG_DDRC_TIMING6 = 0xa0a0202; 149 REG_DDRC_TIMING6 = 0xa0a0202;
150#if DDR_MEMORYSIZE == 64 150#if SPL_DDR_MEMORYSIZE == 64
151 REG_DDRC_MMAP0 = 0x20fc; 151 REG_DDRC_MMAP0 = 0x20fc;
152 REG_DDRC_MMAP1 = 0x2400; 152 REG_DDRC_MMAP1 = 0x2400;
153#elif DDR_MEMORYSIZE == 32 153#elif SPL_DDR_MEMORYSIZE == 32
154 REG_DDRC_MMAP0 = 0x20fe; 154 REG_DDRC_MMAP0 = 0x20fe;
155 REG_DDRC_MMAP1 = 0x2200; 155 REG_DDRC_MMAP1 = 0x2200;
156#else 156#else
@@ -160,13 +160,13 @@ static void ddr_init(void)
160 REG_DDRC_REFCNT = 0x2f0003; 160 REG_DDRC_REFCNT = 0x2f0003;
161 REG_DDRC_CTRL = 0xc91e; 161 REG_DDRC_CTRL = 0xc91e;
162 162
163#if DDR_MEMORYSIZE == 64 163#if SPL_DDR_MEMORYSIZE == 64
164 REG_DDRC_REMAP1 = 0x03020c0b; 164 REG_DDRC_REMAP1 = 0x03020c0b;
165 REG_DDRC_REMAP2 = 0x07060504; 165 REG_DDRC_REMAP2 = 0x07060504;
166 REG_DDRC_REMAP3 = 0x000a0908; 166 REG_DDRC_REMAP3 = 0x000a0908;
167 REG_DDRC_REMAP4 = 0x0f0e0d01; 167 REG_DDRC_REMAP4 = 0x0f0e0d01;
168 REG_DDRC_REMAP5 = 0x13121110; 168 REG_DDRC_REMAP5 = 0x13121110;
169#elif DDR_MEMORYSIZE == 32 169#elif SPL_DDR_MEMORYSIZE == 32
170 REG_DDRC_REMAP1 = 0x03020b0a; 170 REG_DDRC_REMAP1 = 0x03020b0a;
171 REG_DDRC_REMAP2 = 0x07060504; 171 REG_DDRC_REMAP2 = 0x07060504;
172 REG_DDRC_REMAP3 = 0x01000908; 172 REG_DDRC_REMAP3 = 0x01000908;
@@ -178,8 +178,8 @@ static void ddr_init(void)
178 178
179 REG_DDRC_STATUS &= ~0x40; 179 REG_DDRC_STATUS &= ~0x40;
180 180
181#if DDR_USE_AUTOSR 181#if SPL_DDR_AUTOSR_EN
182#if DDR_NEED_BYPASS 182#if SPL_DDR_NEED_BYPASS
183 jz_writef(CPM_DDRCDR, GATE_EN(1)); 183 jz_writef(CPM_DDRCDR, GATE_EN(1));
184 REG_DDRC_APB_CLKSTP_CFG = 0x9000000f; 184 REG_DDRC_APB_CLKSTP_CFG = 0x9000000f;
185#else 185#else
@@ -187,10 +187,10 @@ static void ddr_init(void)
187#endif 187#endif
188#endif 188#endif
189 189
190 REG_DDRC_AUTOSR_EN = DDR_USE_AUTOSR; 190 REG_DDRC_AUTOSR_EN = SPL_DDR_AUTOSR_EN;
191} 191}
192 192
193void main(void) 193static void init(void)
194{ 194{
195 /* from original firmware SPL */ 195 /* from original firmware SPL */
196 REG_CPM_PSWC0ST = 0x00; 196 REG_CPM_PSWC0ST = 0x00;
@@ -224,7 +224,89 @@ void main(void)
224 224
225 /* init DDR memory */ 225 /* init DDR memory */
226 ddr_init(); 226 ddr_init();
227}
228
229static int nandread(uint32_t addr, uint32_t size, void* buffer)
230{
231 int rc;
232
233 if((rc = nand_open()))
234 return rc;
235
236 rc = nand_read_bytes(addr, size, buffer);
237 nand_close();
238 return rc;
239}
240
241static int nandwrite(uint32_t addr, uint32_t size, void* buffer)
242{
243 int rc;
244
245 if((rc = nand_open()))
246 return rc;
247
248 if((rc = nand_enable_writes(true)))
249 goto _end;
250
251 if((rc = nand_erase_bytes(addr, size)))
252 goto _end1;
227 253
228 /* jump to the target's main routine */ 254 rc = nand_write_bytes(addr, size, buffer);
229 spl_main(); 255
256 _end1:
257 /* an error here is very unlikely, so ignore it */
258 nand_enable_writes(false);
259
260 _end:
261 nand_close();
262 return rc;
263}
264
265void main(void)
266{
267 if(!(SPL_ARGUMENTS->flags & SPL_FLAG_SKIP_INIT))
268 init();
269
270 switch(SPL_ARGUMENTS->command) {
271 case SPL_CMD_BOOT: {
272 int option = SPL_ARGUMENTS->param1;
273 if(option == SPL_BOOTOPT_CHOOSE)
274 option = spl_get_boot_option();
275 if(option == SPL_BOOTOPT_NONE)
276 return;
277
278 const struct spl_boot_option* opt = &spl_boot_options[option-1];
279 if(nandread(opt->nand_addr, opt->nand_size, (void*)opt->load_addr))
280 spl_error();
281
282 /* TODO: implement dual boot */
283
284 /* Reading the Linux command line from the bootloader is handled by
285 * arch/mips/xburst/core/prom.c -- see Ingenic kernel sources.
286 *
287 * Rockbox doesn't use arguments, but passing them does not hurt and it
288 * saves an unnecessary branch.
289 */
290 entry_fn entry = (entry_fn)opt->exec_addr;
291 char** argv = (char**)0x80004000;
292 argv[0] = 0;
293 argv[1] = (char*)opt->cmdline;
294
295 commit_discard_idcache();
296 entry(2, argv, 0, 0);
297 __builtin_unreachable();
298 }
299
300 case SPL_CMD_FLASH_READ:
301 SPL_STATUS->err_code = nandread(SPL_ARGUMENTS->param1,
302 SPL_ARGUMENTS->param2,
303 (void*)SPL_BUFFER_ADDRESS);
304 return;
305
306 case SPL_CMD_FLASH_WRITE:
307 SPL_STATUS->err_code = nandwrite(SPL_ARGUMENTS->param1,
308 SPL_ARGUMENTS->param2,
309 (void*)SPL_BUFFER_ADDRESS);
310 return;
311 }
230} 312}
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.h b/firmware/target/mips/ingenic_x1000/spl-x1000.h
new file mode 100644
index 0000000000..44601438f3
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.h
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __SPL_X1000_H__
23#define __SPL_X1000_H__
24
25#include "spl-x1000-defs.h"
26
27#define SPL_ARGUMENTS ((struct x1000_spl_arguments*)SPL_ARGUMENTS_ADDRESS)
28#define SPL_STATUS ((struct x1000_spl_status*)SPL_STATUS_ADDRESS)
29
30struct spl_boot_option {
31 uint32_t nand_addr;
32 uint32_t nand_size;
33 uint32_t load_addr;
34 uint32_t exec_addr;
35 const char* cmdline; /* for Linux */
36};
37
38/* Defined by target, indices are 0 = ROCKBOX, 1 = ORIG_FW, etc... */
39extern const struct spl_boot_option spl_boot_options[];
40
41/* Called on a fatal error */
42void spl_error(void) __attribute__((noreturn));
43
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
46 * user is pressing */
47extern int spl_get_boot_option(void);
48
49#endif /* __SPL_X1000_H__ */