summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES6
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c132
-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.c312
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.h49
6 files changed, 594 insertions, 0 deletions
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/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
new file mode 100644
index 0000000000..0ebe11e24d
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
@@ -0,0 +1,132 @@
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#include "spl-x1000.h"
23#include "gpio-x1000.h"
24#include "nand-x1000.h"
25#include "system.h"
26#include <string.h>
27
28/* Boot select button state must remain stable for this duration
29 * before the choice will be accepted. Currently 100ms.
30 */
31#define BTN_STABLE_TIME (100 * (X1000_EXCLK_FREQ / 4000))
32
33static const char normal_cmdline[] = "mem=64M@0x0\
34 no_console_suspend\
35 console=ttyS2,115200n8\
36 lpj=5009408\
37 ip=off\
38 init=/linuxrc\
39 ubi.mtd=3\
40 root=ubi0:rootfs\
41 ubi.mtd=4\
42 rootfstype=ubifs\
43 rw\
44 loglevel=8";
45
46static const char recovery_cmdline[] = "mem=64M@0x0\
47 no_console_suspend\
48 console=ttyS2,115200n8\
49 lpj=5009408\
50 ip=off";
51
52const struct spl_boot_option spl_boot_options[] = {
53 {
54 /* Rockbox: the first unused NAND page is 26 KiB in, and the
55 * remainder of the block is unused, giving us 102 KiB to use.
56 */
57 .nand_addr = 0x6800,
58 .nand_size = 0x19800,
59 .load_addr = 0x80003ff8, /* first 8 bytes are bootloader ID */
60 .exec_addr = 0x80004000,
61 .cmdline = NULL,
62 },
63 {
64 /* Original firmware */
65 .nand_addr = 0x20000,
66 .nand_size = 0x400000,
67 .load_addr = 0x80efffc0,
68 .exec_addr = 0x80f00000,
69 .cmdline = normal_cmdline,
70 },
71 {
72 /* Recovery image */
73 .nand_addr = 0x420000,
74 .nand_size = 0x500000,
75 .load_addr = 0x80efffc0,
76 .exec_addr = 0x80f00000,
77 .cmdline = recovery_cmdline,
78 },
79};
80
81void spl_error(void)
82{
83 const int pin = (1 << 24);
84
85 /* Turn on button light */
86 jz_clr(GPIO_INT(GPIO_C), pin);
87 jz_set(GPIO_MSK(GPIO_C), pin);
88 jz_clr(GPIO_PAT1(GPIO_C), pin);
89 jz_set(GPIO_PAT0(GPIO_C), pin);
90
91 while(1) {
92 /* Turn it off */
93 mdelay(100);
94 jz_set(GPIO_PAT0(GPIO_C), pin);
95
96 /* Turn it on */
97 mdelay(100);
98 jz_clr(GPIO_PAT0(GPIO_C), pin);
99 }
100}
101
102int spl_get_boot_option(void)
103{
104 const uint32_t pinmask = (1 << 17) | (1 << 19);
105
106 uint32_t pin = 1, lastpin = 0;
107 uint32_t deadline = 0;
108
109 /* Configure the button GPIOs as inputs */
110 gpio_config(GPIO_A, pinmask, GPIO_INPUT);
111
112 /* Poll the pins for a short duration to detect a keypress */
113 do {
114 lastpin = pin;
115 pin = ~REG_GPIO_PIN(GPIO_A) & pinmask;
116 if(pin != lastpin) {
117 /* This will always be set on the first iteration */
118 deadline = __ost_read32() + BTN_STABLE_TIME;
119 }
120 } while(__ost_read32() < deadline);
121
122 /* Play button boots original firmware */
123 if(pin == (1 << 17))
124 return SPL_BOOTOPT_ORIG_FW;
125
126 /* Volume up boots recovery */
127 if(pin == (1 << 19))
128 return SPL_BOOTOPT_RECOVERY;
129
130 /* Default is to boot Rockbox */
131 return SPL_BOOTOPT_ROCKBOX;
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/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c
new file mode 100644
index 0000000000..59e0fb687d
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c
@@ -0,0 +1,312 @@
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#include "spl-x1000.h"
23#include "spl-target.h"
24#include "clk-x1000.h"
25#include "nand-x1000.h"
26#include "system.h"
27#include "x1000/cpm.h"
28#include "x1000/ost.h"
29#include "x1000/ddrc.h"
30#include "x1000/ddrc_apb.h"
31#include "x1000/ddrphy.h"
32
33struct x1000_spl_arguments* const spl_arguments =
34 (struct x1000_spl_arguments*)SPL_ARGUMENTS_ADDRESS;
35
36struct x1000_spl_status* const spl_status =
37 (struct x1000_spl_status*)SPL_STATUS_ADDRESS;
38
39/* defined to be Linux compatible; Rockbox needs no arguments so there
40 * is no harm in passing them and we save a little code size */
41typedef void(*entry_fn)(int, char**, int, int);
42
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
45 * U-Boot code, but isn't entirely the same.
46 *
47 * I converted all the runtime conditionals to compile-time ones in order to
48 * save code space, since they should be constant for any given target.
49 *
50 * I haven't bothered to decode all the register fields. Some of the values
51 * written are going to bits documented as "Reserved" by Ingenic, but their
52 * documentation doesn't seem completely reliable, so either these are bits
53 * which _do_ have a purpose, or they're only defined on other Ingenic CPUs.
54 *
55 * The DDR PHY registers appear to be from Synopsys "PHY Utility Block Lite".
56 * These aren't documented by Ingenic, but the addresses and names can be found
57 * in their U-Boot code.
58 */
59static void ddr_init(void)
60{
61 REG_CPM_DRCG = 0x73;
62 mdelay(3);
63 REG_CPM_DRCG = 0x71;
64 mdelay(3);
65 REG_DDRC_APB_PHYRST_CFG = 0x1a00001;
66 mdelay(3);
67 REG_DDRC_APB_PHYRST_CFG = 0;
68 mdelay(3);
69 REG_DDRC_CTRL = 0xf00000;
70 mdelay(3);
71 REG_DDRC_CTRL = 0;
72 mdelay(3);
73
74 REG_DDRC_CFG = 0xa468a6c;
75 REG_DDRC_CTRL = 2;
76 REG_DDRPHY_DTAR = 0x150000;
77 REG_DDRPHY_DCR = 0;
78 REG_DDRPHY_MR0 = 0x42;
79 REG_DDRPHY_MR2 = 0x98;
80 REG_DDRPHY_PTR0 = 0x21000a;
81 REG_DDRPHY_PTR1 = 0xa09c40;
82 REG_DDRPHY_PTR2 = 0x280014;
83 REG_DDRPHY_DTPR0 = 0x1a69444a;
84 REG_DDRPHY_DTPR1 = 0x180090;
85 REG_DDRPHY_DTPR2 = 0x1ff99428;
86 REG_DDRPHY_DXGCR(0) = 0x90881;
87 REG_DDRPHY_DXGCR(1) = 0x90881;
88 REG_DDRPHY_DXGCR(2) = 0x90e80;
89 REG_DDRPHY_DXGCR(3) = 0x90e80;
90 REG_DDRPHY_PGCR = 0x1042e03;
91 REG_DDRPHY_ACIOCR = 0x30c00813;
92 REG_DDRPHY_DXCCR = 0x4912;
93
94 int i = 10000;
95 while(i > 0 && REG_DDRPHY_PGSR != 7 && REG_DDRPHY_PGSR != 0x1f)
96 i -= 1;
97 if(i == 0)
98 spl_error();
99
100#if SPL_DDR_NEED_BYPASS
101 REG_DDRPHY_ACDLLCR = 0x80000000;
102 REG_DDRPHY_DSGCR &= ~0x10;
103 REG_DDRPHY_DLLGCR |= 0x800000;
104 REG_DDRPHY_PIR = 0x20020041;
105#else
106 REG_DDRPHY_PIR = 0x41;
107#endif
108
109 while(i > 0 && REG_DDRPHY_PGSR != 0xf && REG_DDRPHY_PGSR != 0x1f)
110 i -= 1;
111 if(i == 0)
112 spl_error();
113
114 REG_DDRC_APB_PHYRST_CFG = 0x400000;
115 mdelay(3);
116 REG_DDRC_APB_PHYRST_CFG = 0;
117 mdelay(3);
118
119 REG_DDRC_CFG = 0xa468aec;
120 REG_DDRC_CTRL = 2;
121#if SPL_DDR_NEED_BYPASS
122 REG_DDRPHY_PIR = 0x20020081;
123#else
124 REG_DDRPHY_PIR = 0x85;
125#endif
126
127 i = 500000;
128 while(REG_DDRPHY_PGSR != 0x1f) {
129 if(REG_DDRPHY_PGSR & 0x70)
130 break;
131 i -= 1;
132 }
133
134 if(i == 0)
135 spl_error();
136
137 if((REG_DDRPHY_PGSR & 0x60) != 0 && REG_DDRPHY_PGSR != 0)
138 spl_error();
139
140 REG_DDRC_CTRL = 0;
141 REG_DDRC_CTRL = 10;
142 REG_DDRC_CTRL = 0;
143 REG_DDRC_CFG = 0xa468a6c;
144 REG_DDRC_TIMING1 = 0x2050501;
145 REG_DDRC_TIMING2 = 0x4090404;
146 REG_DDRC_TIMING3 = 0x2704030d;
147 REG_DDRC_TIMING4 = 0xb7a0251;
148 REG_DDRC_TIMING5 = 0xff090200;
149 REG_DDRC_TIMING6 = 0xa0a0202;
150#if SPL_DDR_MEMORYSIZE == 64
151 REG_DDRC_MMAP0 = 0x20fc;
152 REG_DDRC_MMAP1 = 0x2400;
153#elif SPL_DDR_MEMORYSIZE == 32
154 REG_DDRC_MMAP0 = 0x20fe;
155 REG_DDRC_MMAP1 = 0x2200;
156#else
157# error "Unsupported DDR_MEMORYSIZE"
158#endif
159 REG_DDRC_CTRL = 10;
160 REG_DDRC_REFCNT = 0x2f0003;
161 REG_DDRC_CTRL = 0xc91e;
162
163#if SPL_DDR_MEMORYSIZE == 64
164 REG_DDRC_REMAP1 = 0x03020c0b;
165 REG_DDRC_REMAP2 = 0x07060504;
166 REG_DDRC_REMAP3 = 0x000a0908;
167 REG_DDRC_REMAP4 = 0x0f0e0d01;
168 REG_DDRC_REMAP5 = 0x13121110;
169#elif SPL_DDR_MEMORYSIZE == 32
170 REG_DDRC_REMAP1 = 0x03020b0a;
171 REG_DDRC_REMAP2 = 0x07060504;
172 REG_DDRC_REMAP3 = 0x01000908;
173 REG_DDRC_REMAP4 = 0x0f0e0d0c;
174 REG_DDRC_REMAP5 = 0x13121110;
175#else
176# error "Unsupported DDR_MEMORYSIZE"
177#endif
178
179 REG_DDRC_STATUS &= ~0x40;
180
181#if SPL_DDR_AUTOSR_EN
182#if SPL_DDR_NEED_BYPASS
183 jz_writef(CPM_DDRCDR, GATE_EN(1));
184 REG_DDRC_APB_CLKSTP_CFG = 0x9000000f;
185#else
186 REG_DDRC_DLP = 0;
187#endif
188#endif
189
190 REG_DDRC_AUTOSR_EN = SPL_DDR_AUTOSR_EN;
191}
192
193static void init(void)
194{
195 /* from original firmware SPL */
196 REG_CPM_PSWC0ST = 0x00;
197 REG_CPM_PSWC1ST = 0x10;
198 REG_CPM_PSWC2ST = 0x18;
199 REG_CPM_PSWC3ST = 0x08;
200
201 /* enable MPLL */
202#if X1000_EXCLK_FREQ == 24000000
203 /* 24 * (24+1) = 600 MHz */
204 jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(24), PLLOD(0));
205#elif X1000_EXCLK_FREQ == 26000000
206 /* 26 * (22+1) = 598 MHz */
207 jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(22), PLLOD(0));
208#else
209# error "unknown EXCLK frequency"
210#endif
211 while(jz_readf(CPM_MPCR, ON) == 0);
212
213 /* set DDR clock to MPLL/3 = 200 MHz */
214 jz_writef(CPM_CLKGR, DDR(0));
215 clk_set_ddr(X1000_CLK_MPLL, 3);
216
217 /* start OST so we can use mdelay/udelay */
218 jz_writef(CPM_CLKGR, OST(0));
219 jz_writef(OST_CTRL, PRESCALE2_V(BY_4));
220 jz_writef(OST_CLEAR, OST2(1));
221 jz_write(OST_2CNTH, 0);
222 jz_write(OST_2CNTL, 0);
223 jz_setf(OST_ENABLE, OST2);
224
225 /* init DDR memory */
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;
253
254 rc = nand_write_bytes(addr, size, buffer);
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 }
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__ */