summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/boot-x1000.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-03-04 17:37:40 +0000
committerAidan MacDonald <amachronic@protonmail.com>2022-03-12 18:25:10 +0000
commitd56964cc2b52bb4cbcc3770d1c8ce270eaf64f9d (patch)
treecac2f9c3757b1ff3b56eb1d50bae706ba99ddd5d /firmware/target/mips/ingenic_x1000/boot-x1000.c
parenta87f93d8ffc6cf224947e88aee9cb912b8ec6f50 (diff)
downloadrockbox-d56964cc2b52bb4cbcc3770d1c8ce270eaf64f9d.tar.gz
rockbox-d56964cc2b52bb4cbcc3770d1c8ce270eaf64f9d.zip
x1000: add dual boot helpers for the main bootloader
Two helpers (_init_clocktree and _init_uart2) already existed in the SPL and are copied verbatim from there. The SPL versions are still present and will be removed when dual boot works from the main bootloader. The other two helpers (_cleanup and _load_pdma_fw) are new. Change-Id: I4661667966e26f52e6c5142f1947d2a34b7008ef
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/boot-x1000.c')
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.c146
1 files changed, 145 insertions, 1 deletions
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.c b/firmware/target/mips/ingenic_x1000/boot-x1000.c
index 3ba060ffc4..feb67994b7 100644
--- a/firmware/target/mips/ingenic_x1000/boot-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.c
@@ -19,8 +19,14 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "boot-x1000.h"
23#include "system.h" 22#include "system.h"
23#include "boot-x1000.h"
24#include "nand-x1000.h"
25#include "gpio-x1000.h"
26#include "clk-x1000.h"
27#include "x1000/cpm.h"
28#include "x1000/lcd.h"
29#include "x1000/uart.h"
24#include <string.h> 30#include <string.h>
25 31
26#define HDR_BEGIN 128 /* header must begin within this many bytes */ 32#define HDR_BEGIN 128 /* header must begin within this many bytes */
@@ -136,3 +142,141 @@ void rolo_restart(const unsigned char* source, unsigned char* dest, int length)
136 (void)dest; 142 (void)dest;
137 x1000_boot_rockbox(source, length); 143 x1000_boot_rockbox(source, length);
138} 144}
145
146void x1000_dualboot_cleanup(void)
147{
148#ifdef SHANLING_Q1
149 /* hack for the Q1 since OF kernels don't reset this bit,
150 * leading to garbled graphics. */
151 if(!jz_readf(CPM_CLKGR, LCD)) {
152 jz_writef(LCD_CTRL, BEDN(0));
153 }
154#endif
155
156 /* clear USB PHY voodoo bits, not all kernels use them */
157 jz_writef(CPM_OPCR, GATE_USBPHY_CLK(0));
158 jz_writef(CPM_USBCDR, PHY_GATE(0));
159
160#if defined(FIIO_M3K) || defined(EROS_QN)
161 /*
162 * Need to bring up MPLL before booting Linux
163 * (Doesn't apply to Q1 since it sticks with the default Ingenic config)
164 */
165
166 /* 24 MHz * 25 = 600 MHz */
167 jz_writef(CPM_MPCR, BS(1), PLLM(25 - 1), PLLN(0), PLLOD(0), ENABLE(1));
168 while(jz_readf(CPM_MPCR, ON) == 0);
169
170 /* 600 MHz / 3 = 200 MHz */
171 clk_set_ddr(X1000_CLK_MPLL, 3);
172
173 clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
174 CLKMUX_CPU(SCLK_A) |
175 CLKMUX_AHB0(MPLL) |
176 CLKMUX_AHB2(MPLL));
177 clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
178 CLKDIV_L2(2) | /* 504 MHz */
179 CLKDIV_AHB0(3) | /* 200 MHz */
180 CLKDIV_AHB2(3) | /* 200 MHz */
181 CLKDIV_PCLK(6)); /* 100 MHz */
182#endif
183}
184
185void x1000_dualboot_init_clocktree(void)
186{
187 /* Make sure these are gated to match the OF behavior. */
188 jz_writef(CPM_CLKGR, PCM(1), MAC(1), LCD(1), MSC0(1), MSC1(1), OTG(1), CIM(1));
189
190 /* Set clock sources, and make sure every clock starts out stopped */
191 jz_writef(CPM_I2SCDR, CS_V(EXCLK));
192 jz_writef(CPM_PCMCDR, CS_V(EXCLK));
193
194 jz_writef(CPM_MACCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
195 while(jz_readf(CPM_MACCDR, BUSY));
196
197 jz_writef(CPM_LPCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
198 while(jz_readf(CPM_LPCDR, BUSY));
199
200 jz_writef(CPM_MSC0CDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
201 while(jz_readf(CPM_MSC0CDR, BUSY));
202
203 jz_writef(CPM_MSC1CDR, CE(1), STOP(1), CLKDIV(0xfe));
204 while(jz_readf(CPM_MSC1CDR, BUSY));
205
206 jz_writef(CPM_CIMCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
207 while(jz_readf(CPM_CIMCDR, BUSY));
208
209 jz_writef(CPM_USBCDR, CLKSRC_V(EXCLK), CE(1), STOP(1));
210 while(jz_readf(CPM_USBCDR, BUSY));
211}
212
213void x1000_dualboot_init_uart2(void)
214{
215 /* Ungate the clock and select UART2 device function */
216 jz_writef(CPM_CLKGR, UART2(0));
217 gpioz_configure(GPIO_C, 3 << 30, GPIOF_DEVICE(1));
218
219 /* Disable all interrupts */
220 jz_write(UART_UIER(2), 0);
221
222 /* FIFO configuration */
223 jz_overwritef(UART_UFCR(2),
224 RDTR(3), /* FIFO trigger level = 60? */
225 UME(0), /* UART module disable */
226 DME(1), /* DMA mode enable? */
227 TFRT(1), /* transmit FIFO reset */
228 RFRT(1), /* receive FIFO reset */
229 FME(1)); /* FIFO mode enable */
230
231 /* IR mode configuration */
232 jz_overwritef(UART_ISR(2),
233 RDPL(1), /* Zero is negative pulse for receive */
234 TDPL(1), /* ... and for transmit */
235 XMODE(1), /* Pulse width 1.6us */
236 RCVEIR(0), /* Disable IR for recieve */
237 XMITIR(0)); /* ... and for transmit */
238
239 /* Line configuration */
240 jz_overwritef(UART_ULCR(2), DLAB(0),
241 WLS_V(8BITS), /* 8 bit words */
242 SBLS_V(1_STOP_BIT), /* 1 stop bit */
243 PARE(0), /* no parity */
244 SBK(0)); /* don't set break */
245
246 /* Set the baud rate... not too sure how this works. (Docs unclear!) */
247 const unsigned divisor = 0x0004;
248 jz_writef(UART_ULCR(2), DLAB(1));
249 jz_write(UART_UDLHR(2), (divisor >> 8) & 0xff);
250 jz_write(UART_UDLLR(2), divisor & 0xff);
251 jz_write(UART_UMR(2), 16);
252 jz_write(UART_UACR(2), 0);
253 jz_writef(UART_ULCR(2), DLAB(0));
254
255 /* Enable UART */
256 jz_overwritef(UART_UFCR(2),
257 RDTR(0), /* FIFO trigger level = 1 */
258 DME(0), /* DMA mode disable */
259 UME(1), /* UART module enable */
260 TFRT(1), /* transmit FIFO reset */
261 RFRT(1), /* receive FIFO reset */
262 FME(1)); /* FIFO mode enable */
263}
264
265int x1000_dualboot_load_pdma_fw(void)
266{
267 nand_drv* n = nand_init();
268 nand_lock(n);
269
270 int ret = nand_open(n);
271 if(ret != NAND_SUCCESS)
272 goto err_unlock;
273
274 /* NOTE: hardcoded address is used by all current targets */
275 jz_writef(CPM_CLKGR, PDMA(0));
276 ret = nand_read_bytes(n, 0x4000, 0x2000, (void*)0xb3422000);
277
278 nand_close(n);
279 err_unlock:
280 nand_unlock(n);
281 return ret;
282}