summaryrefslogtreecommitdiff
path: root/bootloader
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader')
-rw-r--r--bootloader/SOURCES7
-rw-r--r--bootloader/fiiom3k-spl.c206
-rw-r--r--bootloader/x1000-spl.c230
3 files changed, 1 insertions, 442 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
#elif defined(SANSA_CONNECT)
sansaconnect.c
show_logo.c
-#elif defined(FIIO_M3K)
-#ifdef BOOTLOADER_SPL
-x1000-spl.c
-fiiom3k-spl.c
-#else
+#elif defined(FIIO_M3K) && !defined(BOOTLOADER_SPL)
fiiom3k.c
#endif
-#endif
diff --git a/bootloader/fiiom3k-spl.c b/bootloader/fiiom3k-spl.c
deleted file mode 100644
index 67b4b0a59c..0000000000
--- a/bootloader/fiiom3k-spl.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2021 Aidan MacDonald
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "config.h"
-#include "nand-x1000.h"
-#include "gpio-x1000.h"
-#include "mmu-mips.h"
-#include <string.h>
-
-/* "fiio" in little endian */
-#define BOOTMAGIC 0x6f696966
-
-/* Argument structure needed by Linux */
-struct linux_kargs {
- void* arg0;
- void* arg1;
-};
-
-#define LINUX_KARGSADDR 0x80004000
-
-static const char recovery_cmdline[] = "mem=xxM@0x0\
- no_console_suspend\
- console=ttyS2,115200n8\
- lpj=5009408\
- ip=off";
-
-static const char normal_cmdline[] = "mem=64M@0x0\
- no_console_suspend\
- console=ttyS2,115200n8\
- lpj=5009408\
- ip=off\
- init=/linuxrc\
- ubi.mtd=3\
- root=ubi0:rootfs\
- ubi.mtd=4\
- rootfstype=ubifs\
- rw\
- loglevel=8";
-
-#define BOOTOPTION_ROCKBOX 0
-#define BOOTOPTION_FIIOLINUX 1
-#define BOOTOPTION_RECOVERY 2
-#define NUM_BOOTOPTIONS 3
-
-static const struct bootoption {
- uint32_t nand_addr;
- uint32_t nand_size;
- unsigned long load_addr;
- unsigned long exec_addr;
- const char* cmdline;
-} boot_options[NUM_BOOTOPTIONS] = {
- {
- /* Rockbox: the first unused NAND page is 26 KiB in, and the
- * remainder of the block is unused, giving us 102 KiB to use.
- */
- .nand_addr = 0x6800,
- .nand_size = 0x19800,
- .load_addr = 0x80003ff8, /* first 8 bytes are bootloader ID */
- .exec_addr = 0x80004000,
- .cmdline = NULL,
- },
- {
- /* Original firmware */
- .nand_addr = 0x20000,
- .nand_size = 0x400000,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = normal_cmdline,
- },
- {
- /* Recovery image */
- .nand_addr = 0x420000,
- .nand_size = 0x500000,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = recovery_cmdline,
- },
-};
-
-/* Simple diagnostic if something goes wrong -- a little nicer than wondering
- * what's going on when the machine hangs
- */
-void die(void)
-{
- const int pin = (1 << 24);
-
- /* Turn on button light */
- jz_clr(GPIO_INT(GPIO_C), pin);
- jz_set(GPIO_MSK(GPIO_C), pin);
- jz_clr(GPIO_PAT1(GPIO_C), pin);
- jz_set(GPIO_PAT0(GPIO_C), pin);
-
- while(1) {
- /* Turn it off */
- mdelay(100);
- jz_set(GPIO_PAT0(GPIO_C), pin);
-
- /* Turn it on */
- mdelay(100);
- jz_clr(GPIO_PAT0(GPIO_C), pin);
- }
-}
-
-/* Boot select button state must remain stable for this duration
- * before the choice will be accepted. Currently 100ms.
- */
-#define BTN_STABLE_TIME (100 * (X1000_EXCLK_FREQ / 4000))
-
-int get_boot_option(void)
-{
- const uint32_t pinmask = (1 << 17) | (1 << 19);
-
- uint32_t pin = 1, lastpin = 0;
- uint32_t deadline = 0;
-
- /* Configure the button GPIOs as inputs */
- gpio_config(GPIO_A, pinmask, GPIO_INPUT);
-
- /* Poll the pins for a short duration to detect a keypress */
- do {
- lastpin = pin;
- pin = ~REG_GPIO_PIN(GPIO_A) & pinmask;
- if(pin != lastpin) {
- /* This will always be set on the first iteration */
- deadline = __ost_read32() + BTN_STABLE_TIME;
- }
- } while(__ost_read32() < deadline);
-
- /* Play button boots original firmware */
- if(pin == (1 << 17))
- return BOOTOPTION_FIIOLINUX;
-
- /* Volume up boots recovery */
- if(pin == (1 << 19))
- return BOOTOPTION_RECOVERY;
-
- /* Default is to boot Rockbox */
- return BOOTOPTION_ROCKBOX;
-}
-
-void spl_main(void)
-{
- /* Get user boot option */
- int booti = get_boot_option();
- const struct bootoption* opt = &boot_options[booti];
-
- /* Load selected firmware from flash */
- if(nand_open())
- die();
- if(nand_read_bytes(opt->nand_addr, opt->nand_size, (void*)opt->load_addr))
- die();
-
- if(booti == BOOTOPTION_ROCKBOX) {
- /* If bootloader is not installed, return back to boot ROM.
- * Also read in the first eraseblock of NAND flash so it can be
- * dumped back over USB.
- */
- if(*(unsigned*)(opt->load_addr + 4) != BOOTMAGIC) {
- nand_read_bytes(0, 128 * 1024, (void*)0x80000000);
- commit_discard_idcache();
- return;
- }
- } else {
- /* TODO: Linux boot not implemented yet
- *
- * - Have to initialize UART2, as it's used for the serial console
- * - Must initialize APLL and change clocks over
- * - There are some other clocks which need to be initialized
- * - We should turn off OST since the OF SPL does not turn it on
- */
- die();
- }
-
- if(boot_options[booti].cmdline) {
- /* Handle Linux command line arguments */
- struct linux_kargs* kargs = (struct linux_kargs*)LINUX_KARGSADDR;
- kargs->arg0 = 0;
- kargs->arg1 = (void*)boot_options[booti].cmdline;
- }
-
- /* Flush caches and jump to address */
- void* execaddr = (void*)opt->exec_addr;
- commit_discard_idcache();
- __asm__ __volatile__ ("jr %0\n"
- "nop\n"
- :: "r"(execaddr));
- __builtin_unreachable();
-}
diff --git a/bootloader/x1000-spl.c b/bootloader/x1000-spl.c
deleted file mode 100644
index 1c780a9843..0000000000
--- a/bootloader/x1000-spl.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2021 Aidan MacDonald
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "system.h"
-#include "clk-x1000.h"
-#include "x1000/cpm.h"
-#include "x1000/ost.h"
-#include "x1000/ddrc.h"
-#include "x1000/ddrc_apb.h"
-#include "x1000/ddrphy.h"
-
-#ifdef FIIO_M3K
-# define DDR_USE_AUTOSR 1
-# define DDR_NEED_BYPASS 1
-# define DDR_MEMORYSIZE 64
-#else
-# error "Please add DDR definitions for new target!"
-#endif
-
-#define hang() do { } while(1)
-
-/* Target-specific routine to load & execute the Rockbox bootloader */
-extern void spl_main(void);
-
-/* Note: This is based purely on disassembly of the SPL from the FiiO M3K.
- * The code there is somewhat generic and corresponds roughly to Ingenic's
- * U-Boot code, but isn't entirely the same.
- *
- * I converted all the runtime conditionals to compile-time ones in order to
- * save code space, since they should be constant for any given target.
- *
- * I haven't bothered to decode all the register fields. Some of the values
- * written are going to bits documented as "Reserved" by Ingenic, but their
- * documentation doesn't seem completely reliable, so either these are bits
- * which _do_ have a purpose, or they're only defined on other Ingenic CPUs.
- *
- * The DDR PHY registers appear to be from Synopsys "PHY Utility Block Lite".
- * These aren't documented by Ingenic, but the addresses and names can be found
- * in their U-Boot code.
- */
-static void ddr_init(void)
-{
- REG_CPM_DRCG = 0x73;
- mdelay(3);
- REG_CPM_DRCG = 0x71;
- mdelay(3);
- REG_DDRC_APB_PHYRST_CFG = 0x1a00001;
- mdelay(3);
- REG_DDRC_APB_PHYRST_CFG = 0;
- mdelay(3);
- REG_DDRC_CTRL = 0xf00000;
- mdelay(3);
- REG_DDRC_CTRL = 0;
- mdelay(3);
-
- REG_DDRC_CFG = 0xa468a6c;
- REG_DDRC_CTRL = 2;
- REG_DDRPHY_DTAR = 0x150000;
- REG_DDRPHY_DCR = 0;
- REG_DDRPHY_MR0 = 0x42;
- REG_DDRPHY_MR2 = 0x98;
- REG_DDRPHY_PTR0 = 0x21000a;
- REG_DDRPHY_PTR1 = 0xa09c40;
- REG_DDRPHY_PTR2 = 0x280014;
- REG_DDRPHY_DTPR0 = 0x1a69444a;
- REG_DDRPHY_DTPR1 = 0x180090;
- REG_DDRPHY_DTPR2 = 0x1ff99428;
- REG_DDRPHY_DXGCR(0) = 0x90881;
- REG_DDRPHY_DXGCR(1) = 0x90881;
- REG_DDRPHY_DXGCR(2) = 0x90e80;
- REG_DDRPHY_DXGCR(3) = 0x90e80;
- REG_DDRPHY_PGCR = 0x1042e03;
- REG_DDRPHY_ACIOCR = 0x30c00813;
- REG_DDRPHY_DXCCR = 0x4912;
-
- int i = 10000;
- while(i > 0 && REG_DDRPHY_PGSR != 7 && REG_DDRPHY_PGSR != 0x1f)
- i -= 1;
- if(i == 0)
- hang();
-
-#if DDR_NEED_BYPASS
- REG_DDRPHY_ACDLLCR = 0x80000000;
- REG_DDRPHY_DSGCR &= ~0x10;
- REG_DDRPHY_DLLGCR |= 0x800000;
- REG_DDRPHY_PIR = 0x20020041;
-#else
- REG_DDRPHY_PIR = 0x41;
-#endif
-
- while(i > 0 && REG_DDRPHY_PGSR != 0xf && REG_DDRPHY_PGSR != 0x1f)
- i -= 1;
- if(i == 0)
- hang();
-
- REG_DDRC_APB_PHYRST_CFG = 0x400000;
- mdelay(3);
- REG_DDRC_APB_PHYRST_CFG = 0;
- mdelay(3);
-
- REG_DDRC_CFG = 0xa468aec;
- REG_DDRC_CTRL = 2;
-#if DDR_NEED_BYPASS
- REG_DDRPHY_PIR = 0x20020081;
-#else
- REG_DDRPHY_PIR = 0x85;
-#endif
-
- i = 500000;
- while(REG_DDRPHY_PGSR != 0x1f) {
- if(REG_DDRPHY_PGSR & 0x70)
- break;
- i -= 1;
- }
-
- if(i == 0)
- hang();
-
- if((REG_DDRPHY_PGSR & 0x60) != 0 && REG_DDRPHY_PGSR != 0)
- hang();
-
- REG_DDRC_CTRL = 0;
- REG_DDRC_CTRL = 10;
- REG_DDRC_CTRL = 0;
- REG_DDRC_CFG = 0xa468a6c;
- REG_DDRC_TIMING1 = 0x2050501;
- REG_DDRC_TIMING2 = 0x4090404;
- REG_DDRC_TIMING3 = 0x2704030d;
- REG_DDRC_TIMING4 = 0xb7a0251;
- REG_DDRC_TIMING5 = 0xff090200;
- REG_DDRC_TIMING6 = 0xa0a0202;
-#if DDR_MEMORYSIZE == 64
- REG_DDRC_MMAP0 = 0x20fc;
- REG_DDRC_MMAP1 = 0x2400;
-#elif DDR_MEMORYSIZE == 32
- REG_DDRC_MMAP0 = 0x20fe;
- REG_DDRC_MMAP1 = 0x2200;
-#else
-# error "Unsupported DDR_MEMORYSIZE"
-#endif
- REG_DDRC_CTRL = 10;
- REG_DDRC_REFCNT = 0x2f0003;
- REG_DDRC_CTRL = 0xc91e;
-
-#if DDR_MEMORYSIZE == 64
- REG_DDRC_REMAP1 = 0x03020c0b;
- REG_DDRC_REMAP2 = 0x07060504;
- REG_DDRC_REMAP3 = 0x000a0908;
- REG_DDRC_REMAP4 = 0x0f0e0d01;
- REG_DDRC_REMAP5 = 0x13121110;
-#elif DDR_MEMORYSIZE == 32
- REG_DDRC_REMAP1 = 0x03020b0a;
- REG_DDRC_REMAP2 = 0x07060504;
- REG_DDRC_REMAP3 = 0x01000908;
- REG_DDRC_REMAP4 = 0x0f0e0d0c;
- REG_DDRC_REMAP5 = 0x13121110;
-#else
-# error "Unsupported DDR_MEMORYSIZE"
-#endif
-
- REG_DDRC_STATUS &= ~0x40;
-
-#if DDR_USE_AUTOSR
-#if DDR_NEED_BYPASS
- jz_writef(CPM_DDRCDR, GATE_EN(1));
- REG_DDRC_APB_CLKSTP_CFG = 0x9000000f;
-#else
- REG_DDRC_DLP = 0;
-#endif
-#endif
-
- REG_DDRC_AUTOSR_EN = DDR_USE_AUTOSR;
-}
-
-void main(void)
-{
- /* from original firmware SPL */
- REG_CPM_PSWC0ST = 0x00;
- REG_CPM_PSWC1ST = 0x10;
- REG_CPM_PSWC2ST = 0x18;
- REG_CPM_PSWC3ST = 0x08;
-
- /* enable MPLL */
-#if X1000_EXCLK_FREQ == 24000000
- /* 24 * (24+1) = 600 MHz */
- jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(24), PLLOD(0));
-#elif X1000_EXCLK_FREQ == 26000000
- /* 26 * (22+1) = 598 MHz */
- jz_writef(CPM_MPCR, ENABLE(1), BS(1), PLLN(0), PLLM(22), PLLOD(0));
-#else
-# error "unknown EXCLK frequency"
-#endif
- while(jz_readf(CPM_MPCR, ON) == 0);
-
- /* set DDR clock to MPLL/3 = 200 MHz */
- jz_writef(CPM_CLKGR, DDR(0));
- clk_set_ddr(X1000_CLK_MPLL, 3);
-
- /* start OST so we can use mdelay/udelay */
- jz_writef(CPM_CLKGR, OST(0));
- jz_writef(OST_CTRL, PRESCALE2_V(BY_4));
- jz_writef(OST_CLEAR, OST2(1));
- jz_write(OST_2CNTH, 0);
- jz_write(OST_2CNTL, 0);
- jz_setf(OST_ENABLE, OST2);
-
- /* init DDR memory */
- ddr_init();
-
- /* jump to the target's main routine */
- spl_main();
-}