summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.c146
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.h6
2 files changed, 151 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}
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.h b/firmware/target/mips/ingenic_x1000/boot-x1000.h
index 9faba649b5..fa918a3ead 100644
--- a/firmware/target/mips/ingenic_x1000/boot-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.h
@@ -51,6 +51,12 @@ void x1000_boot_linux(const void* source, size_t length,
51 void* load, void* entry, const char* args) 51 void* load, void* entry, const char* args)
52 __attribute__((section(".icode"))); 52 __attribute__((section(".icode")));
53 53
54/* dual boot support code */
55void x1000_dualboot_cleanup(void);
56void x1000_dualboot_init_clocktree(void);
57void x1000_dualboot_init_uart2(void);
58int x1000_dualboot_load_pdma_fw(void);
59
54/* Note: these functions are inlined to minimize SPL code size. 60/* Note: these functions are inlined to minimize SPL code size.
55 * They are private to the X1000 early boot code anyway... */ 61 * They are private to the X1000 early boot code anyway... */
56 62