summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2016-02-05 02:02:02 +0100
committerCástor Muñoz <cmvidal@gmail.com>2017-02-09 20:47:16 +0100
commit882921efb64218e9b8cc3a7d9c7308734f9b12f3 (patch)
treefca2e1b77104419156a07c6b6d80fa7af9fa3969
parent0d0b163dd15c35a427c8bb2bbd7b906afe9c491d (diff)
ipod6g: bootloader v1
- dual boot - USB mode - battery trap Change-Id: I8586cfeb21ee63f45ab965430725225fdfc4212d
-rw-r--r--bootloader/SOURCES2
-rw-r--r--bootloader/ipod6g.c462
-rw-r--r--firmware/SOURCES12
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/config/ipod6g.h13
-rw-r--r--firmware/target/arm/s5l8702/boot.lds54
-rw-r--r--firmware/target/arm/s5l8702/crt0.S67
7 files changed, 582 insertions, 32 deletions
diff --git a/bootloader/SOURCES b/bootloader/SOURCES
index 12347c57c9..a9c6aebd37 100644
--- a/bootloader/SOURCES
+++ b/bootloader/SOURCES
@@ -2,6 +2,8 @@ common.c
#if defined(IPOD_NANO2G)
ipodnano2g.c
+#elif defined(IPOD_6G)
+ipod6g.c
#elif defined(IPOD_ARCH)
ipod.c
#elif defined(GIGABEAT_F)
diff --git a/bootloader/ipod6g.c b/bootloader/ipod6g.c
new file mode 100644
index 0000000000..0ab9444578
--- /dev/null
+++ b/bootloader/ipod6g.c
@@ -0,0 +1,462 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Dave Chapman
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "config.h"
+
+#include "inttypes.h"
+#include "cpu.h"
+#include "system.h"
+#include "lcd.h"
+#include "../kernel-internal.h"
+#include "file_internal.h"
+#include "storage.h"
+#include "fat.h"
+#include "disk.h"
+#include "font.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "button.h"
+#include "panic.h"
+#include "power.h"
+#include "file.h"
+#include "common.h"
+#include "rb-loader.h"
+#include "loader_strerror.h"
+#include "version.h"
+#include "powermgmt.h"
+#include "usb.h"
+#ifdef HAVE_SERIAL
+#include "serial.h"
+#endif
+
+#include "s5l8702.h"
+#include "clocking-s5l8702.h"
+#include "spi-s5l8702.h"
+#include "i2c-s5l8702.h"
+#include "gpio-s5l8702.h"
+#include "pmu-target.h"
+#include "nor-target.h"
+
+
+#define FW_ROCKBOX 0
+#define FW_APPLE 1
+
+#define ERR_RB 0
+#define ERR_OF 1
+#define ERR_HDD 2
+
+/* Safety measure - maximum allowed firmware image size.
+ The largest known current (October 2009) firmware is about 6.2MB so
+ we set this to 8MB.
+*/
+#define MAX_LOADSIZE (8*1024*1024)
+
+#define LCD_RBYELLOW LCD_RGBPACK(255,192,0)
+#define LCD_REDORANGE LCD_RGBPACK(255,70,0)
+
+extern void bss_init(void);
+extern uint32_t _movestart;
+extern uint32_t start_loc;
+
+extern int line;
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+static void usb_mode(void)
+{
+ int button;
+
+ verbose = true;
+
+ printf("Entering USB mode...");
+
+ powermgmt_init();
+
+ /* The code will ask for the maximum possible value */
+ usb_charging_enable(USB_CHARGING_ENABLE);
+
+ usb_init();
+ usb_start_monitoring();
+
+ /* Wait until USB is plugged */
+ while (usb_detect() != USB_INSERTED)
+ {
+ printf("Plug USB cable");
+ line--;
+ sleep(HZ/10);
+ }
+
+ while(1)
+ {
+ button = button_get_w_tmo(HZ/10);
+
+ if (button == SYS_USB_CONNECTED)
+ break; /* Hit */
+
+ if (usb_detect() == USB_EXTRACTED)
+ break; /* Cable pulled */
+
+ /* Wait for threads to connect or cable is pulled */
+ printf("USB: Connecting...");
+ line--;
+ }
+
+ if (button == SYS_USB_CONNECTED)
+ {
+ /* Got the message - wait for disconnect */
+ printf("Bootloader USB mode");
+
+ /* Ack the SYS_USB_CONNECTED polled from the button queue */
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+
+ while(1)
+ {
+ button = button_get_w_tmo(HZ/2);
+ if (button == SYS_USB_DISCONNECTED)
+ break;
+ }
+ }
+
+ /* We don't want the HDD to spin up if the USB is attached again */
+ usb_close();
+ printf("USB mode exit ");
+}
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+
+void fatal_error(int err)
+{
+ verbose = true;
+
+ /* System font is 6 pixels wide */
+ line++;
+ switch (err)
+ {
+ case ERR_RB:
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ usb_mode();
+ printf("Hold MENU+SELECT to reboot");
+ break;
+#endif
+ case ERR_HDD:
+ printf("Hold MENU+SELECT to reboot");
+ printf("then SELECT+PLAY for disk mode");
+ break;
+ case ERR_OF:
+ printf("Hold MENU+SELECT to reboot");
+ printf("and enter Rockbox firmware");
+ break;
+ }
+
+ if (ide_powered())
+ ata_sleepnow(); /* Immediately spindown the disk. */
+
+ line++;
+ lcd_set_foreground(LCD_REDORANGE);
+ while (1) {
+ lcd_puts(0, line, button_hold() ? "Hold switch on!"
+ : " ");
+ lcd_update();
+ }
+}
+
+static void battery_trap(void)
+{
+ int vbat, old_verb;
+ int th = 50;
+
+ old_verb = verbose;
+ verbose = true;
+
+ usb_charging_maxcurrent_change(100);
+
+ while (1)
+ {
+ vbat = _battery_voltage();
+
+ /* Two reasons to use this threshold (may require adjustments):
+ * - when USB (or wall adaptor) is plugged/unplugged, Vbat readings
+ * differ as much as more than 200 mV when charge current is at
+ * maximum (~340 mA).
+ * - RB uses some sort of average/compensation for battery voltage
+ * measurements, battery icon blinks at battery_level_dangerous,
+ * when the HDD is used heavily (large database) the level drops
+ * to battery_level_shutoff quickly.
+ */
+ if (vbat >= battery_level_dangerous[0] + th)
+ break;
+ th = 200;
+
+ if (power_input_status() != POWER_INPUT_NONE) {
+ lcd_set_foreground(LCD_RBYELLOW);
+ printf("Low battery: %d mV, charging... ", vbat);
+ sleep(HZ*3);
+ }
+ else {
+ /* Wait for the user to insert a charger */
+ int tmo = 10;
+ lcd_set_foreground(LCD_REDORANGE);
+ while (1) {
+ vbat = _battery_voltage();
+ printf("Low battery: %d mV, power off in %d ", vbat, tmo);
+ if (!tmo--) {
+ /* Raise Vsysok (hyst=0.02*Vsysok) to avoid PMU
+ standby<->active looping */
+ if (vbat < 3200)
+ pmu_write(PCF5063X_REG_SVMCTL, 0xA /*3200mV*/);
+ power_off();
+ }
+ sleep(HZ*1);
+ if (power_input_status() != POWER_INPUT_NONE)
+ break;
+ line--;
+ }
+ }
+ line--;
+ }
+
+ verbose = old_verb;
+ lcd_set_foreground(LCD_WHITE);
+ printf("Battery status ok: %d mV ", vbat);
+}
+
+static int launch_onb(int clkdiv)
+{
+ /* SPI clock = PClk/(clkdiv+1) */
+ spi_clkdiv(SPI_PORT, clkdiv);
+
+ /* Actually IRAM1_ORIG contains current RB bootloader IM3 header,
+ it will be replaced by ONB IM3 header, so this function must
+ be called once!!! */
+ struct Im3Info *hinfo = (struct Im3Info*)IRAM1_ORIG;
+
+ /* Loads ONB in IRAM0, exception vector table is destroyed !!! */
+ int rc = im3_read(
+ NORBOOT_OFF + im3_nor_sz(hinfo), hinfo, (void*)IRAM0_ORIG);
+
+ if (rc != 0) {
+ /* Restore exception vector table */
+ memcpy((void*)IRAM0_ORIG, &_movestart, 4*(&start_loc-&_movestart));
+ commit_discard_idcache();
+ return rc;
+ }
+
+ /* Disable all external interrupts */
+ eint_init();
+
+ commit_discard_idcache();
+
+ /* Branch to start of IRAM */
+ asm volatile("mov pc, %0"::"r"(IRAM0_ORIG));
+ while(1);
+}
+
+/* Launch OF when kernel mode is running */
+static int kernel_launch_onb(void)
+{
+ disable_irq();
+ int rc = launch_onb(3); /* 54/4 = 13.5 MHz. */
+ enable_irq();
+ return rc;
+}
+
+static bool pmu_is_hibernated(void)
+{
+ /* OF sets GPIO3 to low when SDRAM is hibernated */
+ return !(pmu_rd(PCF5063X_REG_GPIO3CFG) & 7) &&
+ !(pmu_rd(PCF5063X_REG_OOCSHDWN) & PCF5063X_OOCSHDWN_COLDBOOT);
+}
+
+/* The boot sequence is executed on power-on or reset. After power-up
+ * the device could come from a state of hibernation, OF hibernates
+ * the iPod after an inactive period of ~30 minutes (FW 1.1.2), on
+ * this state the SDRAM is in self-refresh mode.
+ *
+ * t0 = 0
+ * S5L8702 BOOTROM loads an IM3 image located at NOR:
+ * - IM3 header (first 0x800 bytes) is loaded at IRAM1_ORIG
+ * - IM3 body (decrypted RB bootloader) is loaded at IRAM0_ORIG
+ * The time needed to load the RB bootloader (~90 Kb) is estimated
+ * on 200~250 ms. Once executed, RB booloader moves itself from
+ * IRAM0_ORIG to IRAM1_ORIG+0x800, preserving current IM3 header
+ * that contains the NOR offset where the ONB (original NOR boot),
+ * is located (see dualboot.c for details).
+ *
+ * t1 = ~250 ms.
+ * If the PMU is hibernated, decrypted ONB (size 128Kb) is loaded
+ * and executed, it takes ~120 ms. Then the ONB restores the
+ * iPod to the state prior to hibernation.
+ * If not, initialize system and RB kernel, wait for t2.
+ *
+ * t2 = ~650 ms.
+ * Check user button selection.
+ * If OF, diagmode, or diskmode is selected then launch ONB.
+ * If not, wait for LCD initialization.
+ *
+ * t3 = ~700,~900 ms. (lcd_type_01,lcd_type_23)
+ * LCD is initialized, baclight ON.
+ * Wait for HDD spin-up.
+ *
+ * t4 = ~2600,~2800 ms.
+ * HDD is ready.
+ * If hold switch is locked, then load and launch ONB.
+ * If not, load rockbox.ipod file from HDD.
+ *
+ * t5 = ~2800,~3000 ms.
+ * rockbox.ipod is executed.
+ */
+void main(void)
+{
+ int fw = FW_ROCKBOX;
+ int rc = 0;
+ unsigned char *loadbuffer;
+ int (*kernel_entry)(void);
+
+ usec_timer_init();
+
+ /* Configure I2C0 */
+ i2c_preinit(0);
+
+ if (pmu_is_hibernated()) {
+ fw = FW_APPLE;
+ rc = launch_onb(1); /* 27/2 = 13.5 MHz. */
+ }
+
+ system_preinit();
+ memory_init();
+ /*
+ * XXX: BSS is initialized here, do not use .bss before this line
+ */
+ bss_init();
+
+ system_init();
+ kernel_init();
+ i2c_init();
+ power_init();
+
+ enable_irq();
+
+#ifdef HAVE_SERIAL
+ serial_setup();
+#endif
+
+ button_init();
+ if (rc == 0) {
+ /* User button selection timeout */
+ while (USEC_TIMER < 400000);
+ int btn = button_read_device();
+ /* This prevents HDD spin-up when the user enters DFU */
+ if (btn == (BUTTON_SELECT|BUTTON_MENU)) {
+ while (button_read_device() == (BUTTON_SELECT|BUTTON_MENU))
+ sleep(HZ/10);
+ sleep(HZ);
+ btn = button_read_device();
+ }
+ /* Enter OF, diagmode and diskmode using ONB */
+ if ((btn == BUTTON_MENU)
+ || (btn == (BUTTON_SELECT|BUTTON_LEFT))
+ || (btn == (BUTTON_SELECT|BUTTON_PLAY))) {
+ fw = FW_APPLE;
+ rc = kernel_launch_onb();
+ }
+ }
+
+ lcd_init();
+ lcd_set_foreground(LCD_WHITE);
+ lcd_set_background(LCD_BLACK);
+ lcd_clear_display();
+ font_init();
+ lcd_setfont(FONT_SYSFIXED);
+ lcd_update();
+ sleep(HZ/40);
+
+ verbose = true;
+
+ printf("Rockbox boot loader");
+ printf("Version: %s", rbversion);
+
+ backlight_init(); /* Turns on the backlight */
+
+ if (rc == 0) {
+ /* Wait until there is enought power to spin-up HDD */
+ battery_trap();
+
+ rc = storage_init();
+ if (rc != 0) {
+ printf("ATA error: %d", rc);
+ fatal_error(ERR_HDD);
+ }
+
+ filesystem_init();
+
+ /* We wait until HDD spins up to check for hold button */
+ if (button_hold()) {
+ fw = FW_APPLE;
+ printf("Executing OF...");
+ ata_sleepnow();
+ rc = kernel_launch_onb();
+ }
+ }
+
+ if (rc != 0) {
+ printf("Load OF error: %d", rc);
+ fatal_error(ERR_OF);
+ }
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ /* Enter USB mode if SELECT+RIGHT are pressed */
+ if (button_read_device() == (BUTTON_SELECT|BUTTON_RIGHT))
+ usb_mode();
+#endif
+
+ rc = disk_mount_all();
+ if (rc <= 0) {
+ printf("No partition found");
+ fatal_error(ERR_RB);
+ }
+
+ printf("Loading Rockbox...");
+ loadbuffer = (unsigned char *)DRAM_ORIG;
+ rc = load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
+
+ if (rc <= EFILE_EMPTY) {
+ printf("Error!");
+ printf("Can't load " BOOTFILE ": ");
+ printf(loader_strerror(rc));
+ fatal_error(ERR_RB);
+ }
+
+ printf("Rockbox loaded.");
+
+ /* If we get here, we have a new firmware image at 0x08000000, run it */
+ disable_irq();
+
+ kernel_entry = (void*) loadbuffer;
+ commit_discard_idcache();
+ rc = kernel_entry();
+
+ /* End stop - should not get here */
+ enable_irq();
+ printf("ERR: Failed to boot");
+ while(1);
+}
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 88e40fa74f..09716be40e 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1597,12 +1597,12 @@ target/arm/s5l8700/ipodnano2g/piezo-nano2g.c
#ifdef IPOD_6G
target/arm/ipod/button-clickwheel.c
target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
-target/arm/s5l8702/ipod6g/cscodec-ipod6g.c
target/arm/s5l8702/ipod6g/backlight-ipod6g.c
target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c
target/arm/s5l8702/ipod6g/power-ipod6g.c
target/arm/s5l8702/kernel-s5l8702.c
target/arm/s5l8702/system-s5l8702.c
+target/arm/s5l8702/timer-s5l8702.c
target/arm/s5l8702/gpio-s5l8702.c
target/arm/s5l8702/pl080.c
target/arm/s5l8702/dma-s5l8702.c
@@ -1615,24 +1615,26 @@ target/arm/s5l8702/postmortemstub.S
#endif
target/arm/s5l8702/ipod6g/pmu-ipod6g.c
target/arm/s5l8702/ipod6g/rtc-ipod6g.c
+target/arm/s5l8702/ipod6g/adc-ipod6g.c
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
target/arm/s5l8702/usb-s5l8702.c
+#endif
#ifdef HAVE_SERIAL
target/arm/uc870x.c
target/arm/s5l8702/uart-s5l8702.c
target/arm/s5l8702/ipod6g/serial-ipod6g.c
#endif
#ifndef BOOTLOADER
-target/arm/s5l8702/timer-s5l8702.c
target/arm/s5l8702/debug-s5l8702.c
target/arm/s5l8702/pcm-s5l8702.c
target/arm/s5l8702/ipod6g/audio-ipod6g.c
-target/arm/s5l8702/ipod6g/adc-ipod6g.c
+target/arm/s5l8702/ipod6g/cscodec-ipod6g.c
#else
target/arm/s5l8702/spi-s5l8702.c
target/arm/s5l8702/crypto-s5l8702.c
target/arm/s5l8702/nor-s5l8702.c
-#endif
-#endif
+#endif /* BOOTLOADER */
+#endif /* IPOD_6G */
#if CONFIG_CPU == RK27XX
target/arm/rk27xx/audio-rk27xx.c
diff --git a/firmware/export/config.h b/firmware/export/config.h
index e7cfc698df..efad75f1b2 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -872,8 +872,12 @@ Lyre prototype 1 */
#ifdef HAVE_BOOTLOADER_USB_MODE
/* Priority in bootloader is wanted */
#define HAVE_PRIORITY_SCHEDULING
+#if (CONFIG_CPU == S5L8702)
+#define USB_DRIVER_CLOSE
+#else
#define USB_STATUS_BY_EVENT
#define USB_DETECT_BY_REQUEST
+#endif
#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
#define INCLUDE_TIMEOUT_API
#define USB_DRIVER_CLOSE
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h
index 01934a0cc2..5494cf387a 100644
--- a/firmware/export/config/ipod6g.h
+++ b/firmware/export/config/ipod6g.h
@@ -248,14 +248,27 @@
#define USB_VENDOR_ID 0x05AC
#define USB_PRODUCT_ID 0x1261
#define USB_DEVBSS_ATTR __attribute__((aligned(32)))
+#define HAVE_BOOTLOADER_USB_MODE
+#ifdef BOOTLOADER
+#define USBPOWER_BTN_IGNORE (~0)
+#endif
#define USB_READ_BUFFER_SIZE (1024*24)
+/* Serial */
+#ifdef BOOTLOADER
+#if 0 /* Enable/disable LOGF_SERIAL for bootloader */
+#define HAVE_SERIAL
+#define ROCKBOX_HAS_LOGF
+#define LOGF_SERIAL
+#endif
+#else /* !BOOTLOADER */
#define HAVE_SERIAL
/* Disable iAP when LOGF_SERIAL is enabled to avoid conflicts */
#ifndef LOGF_SERIAL
#define IPOD_ACCESSORY_PROTOCOL
#endif
+#endif
/* Define this if you can switch on/off the accessory power supply */
#define HAVE_ACCESSORY_SUPPLY
diff --git a/firmware/target/arm/s5l8702/boot.lds b/firmware/target/arm/s5l8702/boot.lds
index 2885f77eda..61f23b9c22 100644
--- a/firmware/target/arm/s5l8702/boot.lds
+++ b/firmware/target/arm/s5l8702/boot.lds
@@ -1,5 +1,6 @@
#define ASM
#include "config.h"
+#include "cpu.h"
ENTRY(start)
#ifdef ROCKBOX_LITTLE_ENDIAN
@@ -10,13 +11,11 @@ OUTPUT_FORMAT(elf32-bigarm)
OUTPUT_ARCH(arm)
STARTUP(target/arm/s5l8702/crt0.o)
+#define MAX_LOADSIZE 8M /* reserved for loading Rockbox binary */
+
#ifdef IPOD_NANO2G
#define DRAMORIG 0x08000000 + ((MEMORYSIZE - 1) * 0x100000)
#define DRAMSIZE 0x00100000
-#else
-#define DRAMORIG 0x08000000
-#define DRAMSIZE (DRAM_SIZE - TTB_SIZE)
-#endif
#define IRAMORIG 0x22000000
#define IRAMSIZE 256K
@@ -26,17 +25,47 @@ MEMORY
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
}
-
#define LOAD_AREA IRAM
+#define VECT_AREA IRAM
+#define BSS_AREA DRAM
+
+#elif defined(IPOD_6G)
+MEMORY
+{
+ DRAM : ORIGIN = DRAM_ORIG, LENGTH = DRAM_SIZE
+ IRAM : ORIGIN = IRAM_ORIG, LENGTH = IRAM_SIZE
+
+ /* s5l8702 maps address 0 to ROM, IRAM or DRAM */
+ VECT_AREA : ORIGIN = 0, LENGTH = 1K
+
+ /* IRAM region where loaded IM3 body will be moved and executed,
+ preserving the loaded IM3 header (0x800 bytes) at IRAM1_ORIG */
+ MOVE_AREA : ORIGIN = IRAM1_ORIG + 0x800,
+ LENGTH = IRAM1_SIZE - 0x800
+
+ /* DRAM region for BSS */
+ BSS_AREA : ORIGIN = DRAM_ORIG + MAX_LOADSIZE,
+ LENGTH = DRAM_SIZE - MAX_LOADSIZE - TTB_SIZE
+}
+#define LOAD_AREA MOVE_AREA
+
+#else
+#error No target defined!
+#endif
+
SECTIONS
{
+ _dfuloadaddr = IRAM0_ORIG ;
+ _movestart = LOADADDR(.text) ;
+ _moveend = LOADADDR(.data) + SIZEOF(.data) ;
+
#ifdef NEEDS_INTVECT_COPYING
.intvect : {
_intvectstart = . ;
*(.intvect)
- _intvectend = _newstart ;
- } >IRAM AT> LOAD_AREA
+ _intvectend = _newstart ;
+ } >VECT_AREA AT> LOAD_AREA
_intvectcopy = LOADADDR(.intvect) ;
#endif
@@ -61,10 +90,9 @@ SECTIONS
*(.idata*)
*(.data*)
*(.ncdata*);
- . = ALIGN(0x4);
+ . = ALIGN(0x20); /* align move size */
_dataend = . ;
- } > IRAM AT> LOAD_AREA
- _datacopy = LOADADDR(.data) ;
+ } > LOAD_AREA
.stack (NOLOAD) :
{
@@ -80,7 +108,7 @@ SECTIONS
_fiqstackbegin = .;
. += 0x400;
_fiqstackend = .;
- } > IRAM
+ } > LOAD_AREA
.bss (NOLOAD) : {
_edata = .;
@@ -88,7 +116,7 @@ SECTIONS
*(.ibss*);
*(.ncbss*);
*(COMMON);
- . = ALIGN(0x4);
+ . = ALIGN(0x20); /* align bzero size */
_end = .;
- } > IRAM
+ } > BSS_AREA
}
diff --git a/firmware/target/arm/s5l8702/crt0.S b/firmware/target/arm/s5l8702/crt0.S
index 3d1ee2bdfd..915c3f680b 100644
--- a/firmware/target/arm/s5l8702/crt0.S
+++ b/firmware/target/arm/s5l8702/crt0.S
@@ -46,17 +46,20 @@ newstart2:
msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
#ifdef BOOTLOADER
- /* Relocate ourself to IRAM - we have been loaded to DRAM */
- mov r0, #0x08000000 /* source (DRAM) */
- mov r1, #0x22000000 /* dest (IRAM) */
- ldr r2, =_dataend
+ /* Relocate ourself to IRAM1 - we have been loaded to IRAM0 */
+ ldr r0, =_dfuloadaddr
+ ldr r1, =_movestart
+ ldr r2, =_moveend
1:
- cmp r2, r1
- ldrhi r3, [r0], #4
- strhi r3, [r1], #4
- bhi 1b
+ ldmia r0!, {r3-r10}
+ stmia r1!, {r3-r10}
+ cmp r1, r2
+ blt 1b
ldr pc, =start_loc /* jump to the relocated start_loc: */
+
+ .section .init.text,"ax",%progbits
+ .global start_loc
start_loc:
#endif
@@ -66,11 +69,11 @@ start_loc:
mcr p15, 0, r0, c1, c0, 0 /* disable caches and protection unit */
.cleancache:
- mrc p15, 0, r15,c7,c10,3
+ mrc p15, 0, r15, c7, c10, 3 /* test and clean dcache */
bne .cleancache
mov r0, #0
- mcr p15, 0, r0,c7,c10,4
- mcr p15, 0, r0,c7,c5,0
+ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */
+ mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */
/* reset VIC controller */
ldr r1, =0x38e00000
@@ -86,7 +89,15 @@ start_loc:
str r0, [r1,#0x14]
str r0, [r2,#0x14]
-#if !defined(BOOTLOADER)
+#if defined(BOOTLOADER)
+ /* SPI speed is limited when icache is not active. Not worth
+ * activating dcache, it is almost useless on pre-init stage
+ * and the TLB needs 16Kb in detriment of the bootloader.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #1<<12 /* enable icache */
+ mcr p15, 0, r0, c1, c0, 0
+#else
bl memory_init
/* Copy interrupt vectors to iram */
@@ -98,7 +109,6 @@ start_loc:
ldrhi r1, [r4], #4
strhi r1, [r2], #4
bhi 1b
-#endif
/* Initialise bss section to zero */
ldr r2, =_edata
@@ -109,7 +119,6 @@ start_loc:
strhi r4, [r2], #4
bhi 1b
-#ifndef BOOTLOADER
/* Copy icode and data to ram */
ldr r2, =_iramstart
ldr r3, =_iramend
@@ -159,3 +168,33 @@ start_loc:
bhi 1b
b main
+
+#ifdef BOOTLOADER
+ /* Initialise bss section to zero */
+ .global bss_init
+ .type bss_init, %function
+
+bss_init:
+ stmfd sp!, {r4-r9,lr}
+
+ ldr r0, =_edata
+ ldr r1, =_end
+ mov r2, #0
+ mov r3, #0
+ mov r4, #0
+ mov r5, #0
+ mov r6, #0
+ mov r7, #0
+ mov r8, #0
+ mov r9, #0
+ b 2f
+ .align 5 /* cache line size */
+1:
+ stmia r0!, {r2-r9}
+2:
+ cmp r0, r1
+ blt 1b
+
+ ldmpc regs=r4-r9
+ .ltorg
+#endif