summaryrefslogtreecommitdiffstats
path: root/rbutil/mkimxboot/dualboot
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-07-07 17:34:04 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-07-07 17:36:21 +0200
commit03a4ba54815c634f57d5be1ebd44354b40c962dd (patch)
tree5f5287657acc29c858980a29f933126562a116fe /rbutil/mkimxboot/dualboot
parent3afcb53fb94b7bb937147236f338dd89afb781d0 (diff)
downloadrockbox-03a4ba54815c634f57d5be1ebd44354b40c962dd.tar.gz
rockbox-03a4ba54815c634f57d5be1ebd44354b40c962dd.zip
mkimxboot: rewrite dualboot
Rewrite dualboot in C code instead of assembly. Also properly handle subtarget and simply Makefile. This should make the dualboot stub more readable and easier to extend. The new code also gracefully handles power up from RTC alarm on imx233. Change-Id: I7c225254b1463a97e76b6cb4de476aa2d2c9d2f9
Diffstat (limited to 'rbutil/mkimxboot/dualboot')
-rw-r--r--rbutil/mkimxboot/dualboot/Makefile41
-rw-r--r--rbutil/mkimxboot/dualboot/dualboot.S118
-rw-r--r--rbutil/mkimxboot/dualboot/dualboot.c167
-rw-r--r--rbutil/mkimxboot/dualboot/dualboot.lds1
4 files changed, 191 insertions, 136 deletions
diff --git a/rbutil/mkimxboot/dualboot/Makefile b/rbutil/mkimxboot/dualboot/Makefile
index 6386b7c622..4bad3a4a12 100644
--- a/rbutil/mkimxboot/dualboot/Makefile
+++ b/rbutil/mkimxboot/dualboot/Makefile
@@ -1,33 +1,38 @@
CC=gcc
-CROSS_PREFIX=arm-elf-eabi
-# Edit the following variables (plus copy/paste another set of rules) when
-# adding a new target. mkimxboot.c also needs to be edited to refer to these
-# new images.
-
-BOOTOBJS = dualboot_fuzeplus.o dualboot_zenxfi2.o dualboot_zenxfi3.o
-BOOTBINS = dualboot_fuzeplus.arm-bin dualboot_zenxfi2.arm-bin dualboot_zenxfi3.arm-bin
+LD=ld
+OC=objcopy
+CROSS_PREFIX=arm-elf-eabi-
+REGS_PATH=../../../firmware/target/arm/imx233/regs
+CFLAGS=-mcpu=arm926ej-s -std=gnu99 -I. -I$(REGS_PATH) -nostdlib -ffreestanding -fomit-frame-pointer -O
+# Edit the following variables when adding a new target.
+# mkimxboot.c also needs to be edited to refer to these
+# To add a new target x you need to:
+# 1) add x to the list in TARGETS
+# 2) create a variable named OPT_x of the form:
+# OPT_x=target specific defines
+TARGETS=fuzeplus zenxfi2 zenxfi3
+OPT_fuzeplus=-DSANSA_FUZEPLUS -DIMX233_SUBTARGET=3780
+OPT_zenxfi2=-DCREATIVE_ZENXFI2 -DIMX233_SUBTARGET=3780
+OPT_zenxfi3=-DCREATIVE_ZENXFI3 -DIMX233_SUBTARGET=3780
+
+BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS))
+BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS))
all: ../dualboot.h ../dualboot.c
# Dualboot bootloaders
-dualboot_fuzeplus.o: dualboot.S
- $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DSANSA_FUZEPLUS -c -o dualboot_fuzeplus.o dualboot.S
-
-dualboot_zenxfi2.o: dualboot.S
- $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DCREATIVE_ZENXFI2 -c -o dualboot_zenxfi2.o dualboot.S
+dualboot_%.o: dualboot.c
+ $(CROSS_PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^
-dualboot_zenxfi3.o: dualboot.S
- $(CROSS_PREFIX)-$(CC) -mcpu=arm926ej-s -DCREATIVE_ZENXFI3 -c -o dualboot_zenxfi3.o dualboot.S
+dualboot_%.arm-elf: dualboot_%.o
+ $(CROSS_PREFIX)$(LD) $(LDFLAGS) -Tdualboot.lds -o $@ $<
# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
# the binary code and finally convert to .h for building in mkamsboot
-%.arm-elf: %.o
- $(CROSS_PREFIX)-ld -Tdualboot.lds -o $@ $<
-
%.arm-bin: %.arm-elf
- $(CROSS_PREFIX)-objcopy -O binary $< $@
+ $(CROSS_PREFIX)$(OC) -O binary $< $@
../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c
./bin2c ../dualboot $(BOOTBINS)
diff --git a/rbutil/mkimxboot/dualboot/dualboot.S b/rbutil/mkimxboot/dualboot/dualboot.S
deleted file mode 100644
index 0508f7e16a..0000000000
--- a/rbutil/mkimxboot/dualboot/dualboot.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2011 by Amaury Pouly
- *
- * 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.
- *
- ****************************************************************************/
-
-.text
-.global start
-@ int start(uint32_t arg, uint32_t *result_id)
-start:
-#if defined(SANSA_FUZEPLUS)
- /* If volume down key is hold, return so that the OF can boot */
- ldr r2, =0x80018610 @ HW_PINCTRL_DIN1
- ldr r2, [r2]
- tst r2, #0x40000000 @ bit 30, active low
- moveq r0, #0 @ return 0, continue boot
- bxeq lr
- /* save registers for the ROM */
- stmfd sp!, {r4-r6,lr}
- /* if the power source was 5v (ie usb), bypass the power button delay */
- ldr r2, =0x800440c0 @ HW_POWER_STS
- ldr r2, [r2]
- mov r2, r2, lsl#2
- mov r2, r2, lsr#26 @ extract PWRUP_SOURCE
- tst r2, #0x20 @ bit 5: five volts
- bne boot_rockbox
- /* otherwise monitor the power button for a short time */
- ldr r2, =550000 @ loop count
- ldr r4, =0 @ number of times PSWITCH was 1
-pswitch_monitor_loop:
- ldr r3, =0x800440c0 @ HW_POWER_STS
- ldr r3, [r3]
- mov r3, r3, lsl#10
- mov r3, r3, lsr#30 @ extract PSWITCH
- cmp r3, #1
- addeq r4, r3 @ add one if PSWITCH=1 (means power hold)
- subs r2, #1
- bne pswitch_monitor_loop
- /* power down if power wasn't hold long enough */
- ldr r2, =400000
- cmp r4, r2
- bcc power_down
- /* jump to section given as argument */
-boot_rockbox:
- str r0, [r1]
- mov r0, #1
- ldmfd sp!, {r4-r6,pc}
-power_down:
- ldr r0, =0x80044100 @ HW_POWER_RESET
- ldr r1, =0x3E770001 @ unlock key + power down
- str r1, [r0]
- b power_down
-#elif defined(CREATIVE_ZENXFI2)
- /* We are lacking buttons on the Zen X-Fi2 because on USB, the select button
- * enters recovery mode ! So we can only use power but power is used to power up
- * on normal boots and then select is free ! Thus use a non-uniform scheme:
- * - normal boot:
- * - no key: Rockbox
- * - select: OF
- * - USB boot:
- * - no key: Rockbox
- * - power: OF
- */
- /* if the power source was 5v (ie usb), check for power (pswitch) */
- ldr r2, =0x800440c0 @ HW_POWER_STS
- ldr r2, [r2]
- mov r2, r2, lsl#2
- mov r2, r2, lsr#26 @ extract PWRUP_SOURCE
- tst r2, #0x20 @ bit 5: five volts
- beq boot_normal
- /* check pswitch*/
- ldr r2, =0x800440c0 @ HW_POWER_STS
- ldr r2, [r2]
- mov r2, r2, lsl#10
- mov r2, r2, lsr#30 @ extract PSWITCH
- cmp r2, #1
- moveq r0, #0 @ 1 => boot OF
- b do_boot
-boot_normal:
- /* If select key is hold, return so that the OF can boot */
- ldr r2, =0x80018600 @ HW_PINCTRL_DIN0
- ldr r2, [r2]
- tst r2, #0x4000 @ bit 14, active low
- moveq r0, #0 @ return 0, continue boot
- /* r0 must contain the 0 to boot OF and 1 to boot RB */
-do_boot:
- bxeq lr
- str r0, [r1]
- mov r0, #1
- bx lr
-#elif defined(CREATIVE_ZENXFI3)
- /* If volume down key is hold, return so that the OF can boot */
- ldr r2, =0x80018620 @ HW_PINCTRL_DIN2
- ldr r2, [r2]
- tst r2, #0x80 @ bit 7, active low
- moveq r0, #0 @ return 0, continue boot
- bxeq lr
- str r0, [r1]
- mov r0, #1
- bx lr
-#else
-#error No target defined !
-#endif
diff --git a/rbutil/mkimxboot/dualboot/dualboot.c b/rbutil/mkimxboot/dualboot/dualboot.c
new file mode 100644
index 0000000000..301eca87ad
--- /dev/null
+++ b/rbutil/mkimxboot/dualboot/dualboot.c
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 by Amaury Pouly
+ *
+ * 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 "regs-pinctrl.h"
+#include "regs-power.h"
+
+#define BOOT_ROM_CONTINUE 0 /* continue boot */
+#define BOOT_ROM_SECTION 1 /* switch to new section *result_id */
+
+typedef unsigned long uint32_t;
+
+// target specific boot context
+enum context_t
+{
+ CONTEXT_NORMAL, /* normal boot */
+ CONTEXT_USB, /* USB plugged boot */
+ CONTEXT_RTC, /* RTC wake up boot */
+};
+// target specific boot decision
+enum boot_t
+{
+ BOOT_STOP, /* power down */
+ BOOT_ROCK, /* boot to Rockbox */
+ BOOT_OF, /* boot to OF */
+};
+
+/**
+ * Helper functions
+ */
+
+static inline int __attribute__((always_inline)) read_gpio(int bank, int pin)
+{
+ return (HW_PINCTRL_DINn(bank) >> pin) & 1;
+}
+
+static inline int __attribute__((always_inline)) read_pswitch(void)
+{
+#if IMX233_SUBTARGET >= 3700
+ return BF_RD(POWER_STS, PSWITCH);
+#else
+ return BF_RD(DIGCTL_STATUS, PSWITCH);
+#endif
+}
+
+static inline void __attribute__((noreturn)) power_down()
+{
+#ifdef SANSA_FUZEPLUS
+ /* B0P09: this pin seems to be important to shutdown the hardware properly */
+ HW_PINCTRL_MUXSELn_SET(0) = 3 << 18;
+ HW_PINCTRL_DOEn(0) = 1 << 9;
+ HW_PINCTRL_DOUTn(0) = 1 << 9;
+#endif
+ /* power down */
+ HW_POWER_RESET = BM_OR2(POWER_RESET, UNLOCK, PWD);
+ while(1);
+}
+
+/**
+ * Boot decision functions
+ */
+
+#if defined(SANSA_FUZEPLUS)
+static enum boot_t boot_decision(enum context_t context)
+{
+ /* if volume down is hold, boot to OF */
+ if(!read_gpio(1, 30))
+ return BOOT_OF;
+ /* on normal boot, make sure power button is hold long enough */
+ if(context == CONTEXT_NORMAL)
+ {
+ // monitor PSWITCH
+ int count = 0;
+ for(int i = 0; i < 550000; i++)
+ if(read_pswitch() == 1)
+ count++;
+ if(count < 400000)
+ return BOOT_STOP;
+ }
+ return BOOT_ROCK;
+}
+#elif defined(CREATIVE_ZENXFI2)
+static int boot_decision(int context)
+{
+ /* We are lacking buttons on the Zen X-Fi2 because on USB, the select button
+ * enters recovery mode ! So we can only use power but power is used to power up
+ * on normal boots and then select is free ! Thus use a non-uniform scheme:
+ * - normal boot/RTC:
+ * - no key: Rockbox
+ * - select: OF
+ * - USB boot:
+ * - no key: Rockbox
+ * - power: OF
+ */
+ if(context == CONTEXT_USB)
+ return read_pswitch() == 1 ? BOOT_OF : BOOT_ROCK;
+ else
+ return !read_gpio(0, 14) ? BOOT_OF : BOOT_ROCK;
+}
+#elif defined(CREATIVE_ZENXFI3)
+static int boot_decision(int context)
+{
+ /* if volume down is hold, boot to OF */
+ return !read_gpio(2, 7) ? BOOT_OF : BOOT_ROCK;
+}
+#else
+#warning You should define a target specific boot decision function
+static int boot_decision(int context)
+{
+ return BOOT_ROCK;
+}
+#endif
+
+/**
+ * Context functions
+ */
+static inline enum context_t get_context(void)
+{
+#if IMX233_SUBTARGET >= 3780
+ /* On the imx233 it's easy because we know the power up source */
+ unsigned pwrup_src = BF_RD(POWER_STS, PWRUP_SOURCE);
+ if(pwrup_src & (1 << 5))
+ return CONTEXT_USB;
+ else if(pwrup_src & (1 << 4))
+ return CONTEXT_RTC;
+ else
+ return CONTEXT_NORMAL;
+#else
+ /* On the other targets, we need to poke a few more registers */
+#endif
+}
+
+int main(uint32_t arg, uint32_t *result_id)
+{
+ switch(boot_decision(get_context()))
+ {
+ case BOOT_ROCK:
+ *result_id = arg;
+ return BOOT_ROM_SECTION;
+ case BOOT_OF:
+ return BOOT_ROM_CONTINUE;
+ case BOOT_STOP:
+ default:
+ power_down();
+ }
+}
+
+int __attribute__((section(".start"))) start(uint32_t arg, uint32_t *result_id)
+{
+ return main(arg, result_id);
+} \ No newline at end of file
diff --git a/rbutil/mkimxboot/dualboot/dualboot.lds b/rbutil/mkimxboot/dualboot/dualboot.lds
index caaff1a41d..09739aee15 100644
--- a/rbutil/mkimxboot/dualboot/dualboot.lds
+++ b/rbutil/mkimxboot/dualboot/dualboot.lds
@@ -11,6 +11,7 @@ SECTIONS
{
.text 0 :
{
+ *(.start*)
*(.text*)
} > OCRAM
}