summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootloader/main-pp.c155
-rw-r--r--firmware/SOURCES6
-rw-r--r--firmware/export/config.h6
-rw-r--r--firmware/export/config/gigabeats.h4
-rw-r--r--firmware/export/config/gogearsa9200.h7
-rw-r--r--firmware/export/kernel.h7
-rw-r--r--firmware/export/pp5020.h3
-rw-r--r--firmware/export/sd.h4
-rw-r--r--firmware/export/storage.h1
-rw-r--r--firmware/export/usb.h3
-rw-r--r--firmware/kernel.c36
-rw-r--r--firmware/target/arm/ata-sd-pp.c29
-rw-r--r--firmware/target/arm/ata-target.h4
-rw-r--r--firmware/target/arm/crt0-pp502x-bl-usb.S362
-rw-r--r--firmware/target/arm/kernel-pp.c12
-rw-r--r--firmware/target/arm/philips/boot.lds159
-rw-r--r--firmware/target/arm/philips/sa9200/button-sa9200.c4
-rw-r--r--firmware/target/arm/philips/sa9200/button-target.h3
-rw-r--r--firmware/target/arm/system-pp502x.c98
-rw-r--r--firmware/target/arm/system-target.h28
-rw-r--r--firmware/target/arm/tms320dm320/system-target.h9
-rw-r--r--firmware/target/arm/usb-fw-pp5002.c8
-rw-r--r--firmware/target/arm/usb-fw-pp502x.c52
-rw-r--r--firmware/target/arm/usb-target.h6
-rw-r--r--firmware/usb.c2
-rw-r--r--firmware/usbstack/usb_storage.c4
26 files changed, 847 insertions, 165 deletions
diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c
index d8ef64cdd0..3670a7dc97 100644
--- a/bootloader/main-pp.c
+++ b/bootloader/main-pp.c
@@ -48,6 +48,7 @@
#include "usb.h"
#include "usb_drv.h"
#endif
+#include "usb-target.h"
#if defined(SAMSUNG_YH925)
/* this function (in lcd-yh925.c) resets the screen orientation for the OF
* for use with dualbooting */
@@ -451,8 +452,104 @@ int load_mi4_part(unsigned char* buf, struct partinfo* pinfo,
return EOK;
}
+#endif /* (CONFIG_STORAGE & STORAGE_SD) */
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+/* Return USB_HANDLED if session took place else return USB_EXTRACTED */
+static int handle_usb(int connect_timeout)
+{
+ static struct event_queue q SHAREDBSS_ATTR;
+ struct queue_event ev;
+ int usb = USB_EXTRACTED;
+ long end_tick = 0;
+
+ if (!usb_plugged())
+ return USB_EXTRACTED;
+
+ queue_init(&q, true);
+ usb_init();
+ usb_start_monitoring();
+
+ /* Switch to verbose mode if not in it so that the status updates
+ * are shown */
+
+ /* TODO: Should we forgo any messages except the connect? It might be a
+ * charger, not a USB host. */
+ verbose = true;
+
+ printf("USB: Connecting");
+
+ if (connect_timeout != TIMEOUT_BLOCK)
+ end_tick = current_tick + connect_timeout;
+
+ while (1)
+ {
+ /* Sleep no longer than 1/2s */
+ queue_wait_w_tmo(&q, &ev, HZ/2);
+
+ if (ev.id == SYS_USB_CONNECTED)
+ {
+ /* Got the message - wait for disconnect */
+ printf("Bootloader USB mode");
+
+ usb = USB_HANDLED;
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ usb_wait_for_disconnect(&q);
+ break;
+ }
+
+ if (connect_timeout != TIMEOUT_BLOCK &&
+ TIME_AFTER(current_tick, end_tick))
+ {
+ /* Timed out waiting for the connect */
+ printf("USB: Timed out");
+ break;
+ }
+
+ if (!usb_plugged())
+ break; /* Cable pulled */
+ }
+
+ usb_close();
+ queue_delete(&q);
+
+ return usb;
+}
+#else /* !HAVE_BOOTLOADER_USB_MODE */
+
+#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) \
+ || defined (SANSA_VIEW)
+/* Ignore cable state */
+static int handle_usb(int connect_timeout)
+{
+ return USB_EXTRACTED;
+ (void)connect_timeout;
+}
+#else
+/* Return USB_INSERTED if cable present */
+static int handle_usb(int connect_timeout)
+{
+ int usb_retry = 0;
+ int usb = USB_EXTRACTED;
+
+ usb_init();
+ while (usb_drv_powered() && usb_retry < 5 && usb != USB_INSERTED)
+ {
+ usb_retry++;
+ sleep(HZ/4);
+ usb = usb_detect();
+ }
+
+ if (usb != USB_INSERTED)
+ usb = USB_EXTRACTED;
+
+ return usb;
+ (void)connect_timeout;
+}
#endif
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+
void* main(void)
{
int i;
@@ -460,29 +557,33 @@ void* main(void)
int rc;
int num_partitions;
struct partinfo* pinfo;
-#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) \
- || defined (SANSA_VIEW)
-#if !defined(USE_ROCKBOX_USB)
- int usb_retry = 0;
-#endif
- bool usb = false;
-#else
+#if !(CONFIG_STORAGE & STORAGE_SD)
char buf[256];
unsigned short* identify_info;
#endif
+ int usb = USB_EXTRACTED;
chksum_crc32gentab ();
system_init();
kernel_init();
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ /* loader must service interrupts */
+ enable_interrupt(IRQ_FIQ_STATUS);
+#endif
+
lcd_init();
font_init();
show_logo();
adc_init();
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ button_init_device();
+#else
button_init();
+#endif
#if defined(SANSA_E200) || defined(PHILIPS_SA9200)
i2c_init();
_backlight_on();
@@ -506,20 +607,6 @@ void* main(void)
verbose = true;
}
-#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)
-#if !defined(USE_ROCKBOX_USB)
- usb_init();
- while (usb_drv_powered() && usb_retry < 5 && !usb)
- {
- usb_retry++;
- sleep(HZ/4);
- usb = (usb_detect() == USB_INSERTED);
- }
- if (usb)
- btn |= BOOTLOADER_BOOT_OF;
-#endif /* USE_ROCKBOX_USB */
-#endif
-
lcd_setfont(FONT_SYSFIXED);
printf("Rockbox boot loader");
@@ -560,6 +647,15 @@ void* main(void)
i, pinfo->type, pinfo->size / 2048);
}
+ /* Now that storage is initialized, check for USB connection */
+ if ((btn & BOOTLOADER_BOOT_OF) == 0)
+ {
+ usb_pin_init();
+ usb = handle_usb(HZ*2);
+ if (usb == USB_INSERTED)
+ btn |= BOOTLOADER_BOOT_OF;
+ }
+
/* Try loading Rockbox, if that fails, fall back to the OF */
if((btn & BOOTLOADER_BOOT_OF) == 0)
{
@@ -576,7 +672,7 @@ void* main(void)
sleep(5*HZ);
}
else
- return (void*)loadbuffer;
+ goto main_exit;
}
if(btn & BOOTLOADER_BOOT_OF)
@@ -601,7 +697,7 @@ void* main(void)
printf("Can't load from partition");
printf(strerror(rc));
} else {
- return (void*)loadbuffer;
+ goto main_exit;
}
} else {
printf("No hidden partition found.");
@@ -615,7 +711,7 @@ void* main(void)
printf("Can't load /System/OF.ebn");
printf(strerror(rc));
} else {
- return (void*)loadbuffer;
+ goto main_exit;
}
#endif
@@ -628,7 +724,7 @@ void* main(void)
#if defined(SAMSUNG_YH925)
lcd_reset();
#endif
- return (void*)loadbuffer;
+ goto main_exit;
}
printf("Trying /System/OF.bin");
@@ -640,10 +736,17 @@ void* main(void)
#if defined(SAMSUNG_YH925)
lcd_reset();
#endif
- return (void*)loadbuffer;
+ goto main_exit;
}
error(0, 0, true);
}
+
+main_exit:
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ storage_close();
+ system_prepare_fw_start();
+#endif
+
return (void*)loadbuffer;
}
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 06dbf9d6e8..d48d3c623a 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -508,8 +508,12 @@ target/arm/system-pp5002.c
target/arm/system-pp502x.c
#endif
#ifdef BOOTLOADER
-target/arm/crt0-pp-bl.S
+#ifdef HAVE_BOOTLOADER_USB_MODE
+target/arm/crt0-pp502x-bl-usb.S
#else
+target/arm/crt0-pp-bl.S
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+#else /* !BOOTLOADER */
target/arm/pcm-pp.c
target/arm/debug-pp.c
#if !defined(SANSA_E200) && !defined(SANSA_C200)
diff --git a/firmware/export/config.h b/firmware/export/config.h
index eca736ddae..c77e673351 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -693,7 +693,7 @@ Lyre prototype 1 */
#if (CONFIG_CODEC == SWCODEC)
#ifdef BOOTLOADER
-#if CONFIG_CPU == IMX31L
+#ifdef HAVE_BOOTLOADER_USB_MODE
/* Priority in bootloader is wanted */
#define HAVE_PRIORITY_SCHEDULING
#define USB_STATUS_BY_EVENT
@@ -964,8 +964,8 @@ Lyre prototype 1 */
#ifdef BOOTLOADER
/* enable usb storage for targets that do bootloader usb */
-#if (defined(TOSHIBA_GIGABEAT_S) || \
- (defined(CREATIVE_ZVx) || \
+#if defined(HAVE_BOOTLOADER_USB_MODE) || \
+ ((defined(CREATIVE_ZVx) || \
defined(CPU_TCC77X) || defined(CPU_TCC780X))) || \
(CONFIG_USBOTG == USBOTG_JZ4740) || defined(IPOD_NANO2G) || \
CONFIG_USBOTG == USBOTG_AS3525
diff --git a/firmware/export/config/gigabeats.h b/firmware/export/config/gigabeats.h
index cf560aa35f..3b3a717e20 100644
--- a/firmware/export/config/gigabeats.h
+++ b/firmware/export/config/gigabeats.h
@@ -217,6 +217,10 @@
#define USB_VENDOR_ID 0x0930
#define USB_PRODUCT_ID 0x0010
#define HAVE_USB_HID_MOUSE
+#ifdef BOOTLOADER
+/* enable bootloader USB mode - ONLY define when also BOOTLOADER */
+#define HAVE_BOOTLOADER_USB_MODE
+#endif
/* Define this if you have ATA power-off control */
#define HAVE_ATA_POWER_OFF
diff --git a/firmware/export/config/gogearsa9200.h b/firmware/export/config/gogearsa9200.h
index 2d777f1977..23561e1b08 100644
--- a/firmware/export/config/gogearsa9200.h
+++ b/firmware/export/config/gogearsa9200.h
@@ -172,10 +172,9 @@
#define USB_VENDOR_ID 0x0471
#define USB_PRODUCT_ID 0x014f
#define HAVE_USB_HID_MOUSE
-
-/* WARNING! Enable Rockbox USB mass storage. */
-#ifndef BOOTLOADER
-#define USE_ROCKBOX_USB
+#ifdef BOOTLOADER
+/* enable bootloader USB mode - ONLY define when also BOOTLOADER */
+#define HAVE_BOOTLOADER_USB_MODE
#endif
/* Define this if you have adjustable CPU frequency */
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h
index 4656d87fb2..cfc7a232ac 100644
--- a/firmware/export/kernel.h
+++ b/firmware/export/kernel.h
@@ -178,9 +178,10 @@ struct wakeup
/* global tick variable */
-#if defined(CPU_PP) && defined(BOOTLOADER)
-/* We don't enable interrupts in the iPod bootloader, so we need to fake
- the current_tick variable */
+#if defined(CPU_PP) && defined(BOOTLOADER) && \
+ !defined(HAVE_BOOTLOADER_USB_MODE)
+/* We don't enable interrupts in the PP bootloader unless USB mode is
+ enabled for it, so we need to fake the current_tick variable */
#define current_tick (signed)(USEC_TIMER/10000)
static inline void call_tick_tasks(void)
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 5b5864f4e1..073d33e494 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -224,6 +224,9 @@
#define CACHE_OP_FLUSH 0x0002
#define CACHE_OP_INVALIDATE 0x0004
+/* Local interrupt vector table (set CACHE_CTL_VECT_REMAP to enable) */
+#define INT_VECTOR_ENTRY(v) (*((volatile unsigned long *)(0x6000f100) + (v)))
+
/* GPIO Ports */
#define GPIO_BASE_ADDR 0x6000d000
#define GPIOA_ENABLE (*(volatile unsigned long *)(0x6000d000))
diff --git a/firmware/export/sd.h b/firmware/export/sd.h
index c798f54e9a..8e400bf88a 100644
--- a/firmware/export/sd.h
+++ b/firmware/export/sd.h
@@ -25,6 +25,10 @@
#include <stdbool.h>
#include "mv.h" /* for HAVE_MULTIDRIVE or not */
+#ifdef HAVE_BOOTLOADER_USB_MODE
+#define SD_DRIVER_CLOSE
+#endif
+
#define SD_BLOCK_SIZE 512 /* XXX : support other sizes ? */
struct storage_info;
diff --git a/firmware/export/storage.h b/firmware/export/storage.h
index faceb2bb96..e9ac8b4cb9 100644
--- a/firmware/export/storage.h
+++ b/firmware/export/storage.h
@@ -112,6 +112,7 @@ static inline void stub_storage_spindown(int timeout) { (void)timeout; }
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
#define storage_init() sd_init()
+ #define storage_close() sd_close()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 3e236bfb9f..e192748e4d 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -55,6 +55,9 @@ enum {
#if defined(HAVE_USB_CHARGING_ENABLE) && defined(HAVE_USBSTACK)
USB_CHARGER_UPDATE, /* Event */
#endif
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ USB_HANDLED, /* Bootloader status code */
+#endif
};
#ifdef HAVE_USB_POWER
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 41d1d00689..4e629c5504 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -48,10 +48,19 @@
#define KERNEL_ASSERT(exp, msg...) ({})
#endif
-#if !defined(CPU_PP) || !defined(BOOTLOADER)
+#if !defined(CPU_PP) || !defined(BOOTLOADER) || \
+ defined(HAVE_BOOTLOADER_USB_MODE)
volatile long current_tick SHAREDDATA_ATTR = 0;
#endif
+/* Unless otherwise defined, do nothing */
+#ifndef YIELD_KERNEL_HOOK
+#define YIELD_KERNEL_HOOK() false
+#endif
+#ifndef SLEEP_KERNEL_HOOK
+#define SLEEP_KERNEL_HOOK(ticks) false
+#endif
+
/* List of tick tasks - final element always NULL for termination */
void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
@@ -215,30 +224,25 @@ void timeout_register(struct timeout *tmo, timeout_cb_type callback,
****************************************************************************/
unsigned sleep(unsigned ticks)
{
-#if defined(CPU_PP) && defined(BOOTLOADER)
- unsigned stop = USEC_TIMER + ticks * (1000000/HZ);
- while (TIME_BEFORE(USEC_TIMER, stop))
- switch_thread();
-#elif defined(CREATIVE_ZVx) && defined(BOOTLOADER)
- /* hacky.. */
- long sleep_ticks = current_tick + ticks + 1;
- while (TIME_BEFORE(current_tick, sleep_ticks))
- switch_thread();
-#else
+ /* In certain situations, certain bootloaders in particular, a normal
+ * threading call is inappropriate. */
+ if (SLEEP_KERNEL_HOOK(ticks))
+ return 0; /* Handled */
+
disable_irq();
sleep_thread(ticks);
switch_thread();
-#endif
return 0;
}
void yield(void)
{
-#if ((defined(TATUNG_TPJ1022)) && defined(BOOTLOADER))
- /* Some targets don't like yielding in the bootloader */
-#else
+ /* In certain situations, certain bootloaders in particular, a normal
+ * threading call is inappropriate. */
+ if (YIELD_KERNEL_HOOK())
+ return; /* handled */
+
switch_thread();
-#endif
}
/****************************************************************************
diff --git a/firmware/target/arm/ata-sd-pp.c b/firmware/target/arm/ata-sd-pp.c
index 914858e464..00437ea7a7 100644
--- a/firmware/target/arm/ata-sd-pp.c
+++ b/firmware/target/arm/ata-sd-pp.c
@@ -154,6 +154,9 @@ static long last_disk_activity = -1;
/** static, private data **/
static bool initialized = false;
+static unsigned int sd_thread_id = 0;
+
+#define Q_CLOSE 1
static long next_yield = 0;
#define MIN_YIELD_PERIOD 1000
@@ -1106,7 +1109,9 @@ sd_write_error:
}
}
+#ifndef SD_DRIVER_CLOSE
static void sd_thread(void) NORETURN_ATTR;
+#endif
static void sd_thread(void)
{
struct queue_event ev;
@@ -1175,10 +1180,30 @@ static void sd_thread(void)
case SYS_USB_DISCONNECTED:
usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
break;
+
+#ifdef SD_DRIVER_CLOSE
+ case Q_CLOSE:
+ return;
+#endif
}
}
}
+#ifdef SD_DRIVER_CLOSE
+void sd_close(void)
+{
+ unsigned int thread_id = sd_thread_id;
+
+ if (thread_id == 0)
+ return;
+
+ sd_thread_id = 0;
+
+ queue_post(&sd_queue, Q_CLOSE, 0);
+ thread_wait(thread_id);
+}
+#endif /* SD_DRIVER_CLOSE */
+
void sd_enable(bool on)
{
if(on)
@@ -1241,8 +1266,8 @@ int sd_init(void)
ret = currcard->initialized;
queue_init(&sd_queue, true);
- create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
- sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
+ sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack),
+ 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
IF_COP(, CPU));
/* enable interupt for the mSD card */
diff --git a/firmware/target/arm/ata-target.h b/firmware/target/arm/ata-target.h
index 12415c33e8..779ebed070 100644
--- a/firmware/target/arm/ata-target.h
+++ b/firmware/target/arm/ata-target.h
@@ -21,6 +21,10 @@
#ifdef CPU_PP
+#ifdef HAVE_BOOTLOADER_USB_MODE
+#define ATA_DRIVER_CLOSE
+#endif
+
/* primary channel */
#define ATA_DATA (*((volatile unsigned short*)(IDE_BASE + 0x1e0)))
#define ATA_ERROR (*((volatile unsigned char*)(IDE_BASE + 0x1e4)))
diff --git a/firmware/target/arm/crt0-pp502x-bl-usb.S b/firmware/target/arm/crt0-pp502x-bl-usb.S
new file mode 100644
index 0000000000..c360596001
--- /dev/null
+++ b/firmware/target/arm/crt0-pp502x-bl-usb.S
@@ -0,0 +1,362 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Linus Nielsen Feltzing
+ * Copyright (C) 2010 by Michael Sevakis
+ *
+ * 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 "cpu.h"
+
+/* PortalPlayer bootloader and startup code based on startup.s from the iPodLinux
+ * loader
+ *
+ * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org)
+ * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org>
+ *
+ */
+ .equ PROC_ID, 0x60000000
+ .equ CPU_IDIS, 0x60004028
+ .equ CPU_CTRL, 0x60007000
+ .equ CPU_STATUS, 0x60007000
+ .equ COP_IDIS, 0x60004038
+ .equ COP_CTRL, 0x60007004
+ .equ COP_STATUS, 0x60007004
+ .equ CPU_SLEEPING,0x80000000
+ .equ COP_SLEEPING,0x80000000
+ .equ SLEEP, 0x80000000
+ .equ WAKE, 0x00000000
+ .equ MMAP_LOG, 0xf000f000 /* MMAP0 */
+ .equ MMAP_PHYS, 0xf000f004
+ .equ INT_VECT_TBL,0x6000f100
+ .equ CACHE_CTRL, 0x6000c000
+ .equ CACHE_ENAB, 0x1
+ .equ CACHE_OP_COMMIT_DISCARD, 0x1
+ .equ CACHE_OP_COMMIT , 0x0
+#if MEM > 32
+ .equ MMAP_MASK, 0x00003c00
+#else
+ .equ MMAP_MASK, 0x00003e00
+#endif
+ .equ MMAP_FLAGS, 0x00000f84
+
+/*
+ * Entry point
+ */
+ .section .init.text,"ax",%progbits
+ .global start
+start:
+ b newstart
+
+#ifdef IPOD_ARCH
+.align 8 /* starts at 0x100 */
+.global boot_table
+boot_table:
+ /* here comes the boot table, don't move its offset - preceding
+ code+data must stay <= 256 bytes */
+ .space 400
+#else /* !IPOD_ARCH */
+ /* (more than enough) space for exception vectors and mi4 magic */
+ .space 68*4
+#endif /* IPOD_ARCH */
+
+newstart:
+ msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
+ adr r4, start /* cache initial load address */
+
+ /* Copy startup stub to IRAM since we need to both move the bootloader's
+ * location, which could overlap itself, and setup the memory mapper. */
+ adr r0, start_stub_begin
+ mov r1, #0x40000000
+ adr r2, start_stub_end
+1:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r0, r2
+ blo 1b
+ mov pc, #0x40000000
+
+start_stub_begin:
+ ldr r0, =PROC_ID
+ ldrb r0, [r0]
+ cmp r0, #0x55
+ beq cpu
+
+cop:
+ mov r0, #CACHE_OP_COMMIT_DISCARD
+ bl cache_operation
+
+ ldr r1, =COP_CTRL
+ mov r0, #SLEEP
+
+ /* sleep us (co-processor) while bootloader is copied */
+ str r0, [r1]
+ nop
+ nop
+ nop
+
+ /* branch to final physical load address */
+ ldr r2, =1f
+ and r4, r4, #0xfc000000
+ add pc, r2, r4
+1:
+ /* wait for bootloader to finish */
+ str r0, [r1]
+ nop
+ nop
+ nop
+
+ /* branch to the address returned by main() */
+ adr r0, startup_loc
+ ldr pc, [r0]
+
+cpu:
+ /* wait for COP to sleep */
+ ldr r1, =COP_STATUS
+1:
+ ldr r0, [r1]
+ tst r0, #COP_SLEEPING
+ beq 1b
+
+ mov r0, #CACHE_OP_COMMIT_DISCARD
+ bl cache_operation
+
+ /* move bootloader to the correct load address if needed */
+ ldr r1, =_loadaddress
+ cmp r4, r1
+ ldrne r2, =_loadaddressend
+ movne r0, r4
+ sublo r3, r2, r1 /* size */
+ addlo r0, r0, r3 /* initial load end addr */
+1: /* lower to higher move - copy up */
+ cmphi r2, r1
+ ldrhi r3, [r0], #4
+ strhi r3, [r1], #4
+ bhi 1b
+1: /* higher to lower move - copy down */
+ cmplo r1, r2
+ ldrlo r3, [r0, #-4]!
+ strlo r3, [r2, #-4]!
+ blo 1b
+
+ mov r0, #CACHE_OP_COMMIT
+ bl cache_operation
+
+ and r4, r4, #0xfc000000
+
+ ldr r0, =MMAP_FLAGS
+ orr r0, r0, r4 /* adjust for execute address */
+ ldr r1, =MMAP_MASK
+ ldr r2, =MMAP_LOG
+ ldr r3, =MMAP_PHYS
+ str r1, [r2] /* MMAP_LOG = MMAP_MASK */
+ str r0, [r3] /* MMAP_PHYS = MMAP_FLAGS | SDRAM base addr */
+
+ /* wake the COP to jump it to the correct place */
+ ldr r1, =COP_CTRL
+ mov r0, #WAKE
+ str r0, [r1]
+
+ /* wait for COP to halt then loading may proceed */
+ ldr r1, =COP_STATUS
+1:
+ ldr r0, [r1]
+ tst r0, #COP_SLEEPING
+ beq 1b
+
+ ldr r0, =start_stub_end
+ add pc, r0, r4
+
+cache_operation: /* (bool commit_discard) */
+ ldr r2, =CACHE_CTRL
+ ldr r1, [r2]
+ tst r1, #CACHE_ENAB
+ bxeq lr
+ cmp r0, #CACHE_OP_COMMIT
+ ldr r0, =0xf000f044
+ ldr r1, [r0]
+ orrne r1, r1, #0x6
+ orreq r1, r1, #0x2
+ str r1, [r0]
+1:
+ ldr r1, [r2]
+ tst r1, #0x8000
+ bne 1b
+ bx lr
+ .ltorg /* constants used in stub come with us to IRAM */
+start_stub_end:
+ /* now executing from final physical address */
+
+ /* copy the vector addresses to the table */
+ ldr r0, =INT_VECT_TBL
+ adr r1, vectorsstart
+ adr r2, vectorsend
+1:
+ cmp r2, r1
+ ldrhi r3, [r1], #4
+ strhi r3, [r0], #4
+ bhi 1b
+
+ /* Copy the IRAM */
+ ldr r0, =_iramcopy
+ ldr r1, =_iramstart
+ ldr r2, =_iramend
+1:
+ cmp r2, r1
+ ldrhi r3, [r0], #4
+ strhi r3, [r1], #4
+ bhi 1b
+
+ mov r0, #0
+
+ /* Zero out IBSS */
+ ldr r1, =_iedata
+ ldr r2, =_iend
+1:
+ cmp r2, r1
+ strhi r0, [r1], #4
+ bhi 1b
+
+ /* Initialise bss/ncbss sections to zero */
+ ldr r1, =_edata
+ ldr r2, =_end
+1:
+ cmp r2, r1
+ strhi r0, [r1], #4
+ bhi 1b
+
+ /* Set up some stack and munge it with 0xdeadbeef */
+ ldr r0, =0xdeadbeef
+ ldr r1, =stackbegin
+ ldr sp, =stackend
+1:
+ cmp sp, r1
+ strhi r0, [r1], #4
+ bhi 1b
+
+ /* Set up stack for IRQ mode */
+ msr cpsr_c, #0xd2 /* IRQ/FIQ disabled */
+ ldr sp, =irq_stack
+ /* Let abort and undefined modes use IRQ stack */
+ msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */
+ ldr sp, =irq_stack
+ msr cpsr_c, #0xdb /* IRQ/FIQ disabled */
+ ldr sp, =irq_stack
+
+ /* Switch back to supervisor mode */
+ msr cpsr_c, #0xd3
+
+ /* execute the loader - this will load an image to 0x10000000 */
+ ldr r0, =main
+ mov lr, pc
+ bx r0
+
+ /* store actual startup location returned by main() */
+ ldr r1, =startup_loc
+ str r0, [r1]
+
+ /* write back anything loaded + startup_loc */
+ mov r0, #CACHE_OP_COMMIT
+ bl cache_operation
+
+ mov r0, #0
+
+ /* disable memory mapper */
+ ldr r1, =MMAP_LOG
+ ldr r2, =MMAP_PHYS
+ str r0, [r1]
+ str r0, [r2]
+
+ /* bring COP back to life */
+ ldr r1, =COP_CTRL
+ mov r0, #WAKE
+ str r0, [r1]
+
+ /* after this point, r0-r3 are reserved for OF magic */
+
+#if defined(SANSA_C200) || defined(PHILIPS_HDD1630)
+ /* Magic for loading the c200 OF */
+ ldr r0, =0xb00d10ad
+ mov r1, #0x700
+ ldr r2, =0xfff0
+ mov r3, #0x7
+#endif
+
+#if defined(PHILIPS_HDD6330)
+ /* Magic for loading the HDD6XX0 OF */
+ ldr r0, =0xb00d10ad
+ mov r1, #0x800
+ ldr r2, =0xfff0
+ mov r3, #0x7
+#endif
+
+ /* branch to the address returned by main() */
+ adr r4, startup_loc
+ ldr pc, [r4]
+
+startup_loc:
+ .word 0x00000000
+
+/* exception handlers: will be copied to local vector table */
+vectorsstart:
+ .word newstart
+ .word undef_instr_handler
+ .word software_int_handler
+ .word prefetch_abort_handler
+ .word data_abort_handler
+ .word reserved_handler
+ .word irq_handler
+ .word fiq_handler
+vectorsend:
+
+ .text
+
+/* All illegal exceptions call into UIE with exception address as first
+ parameter. This is calculated differently depending on which exception
+ we're in. Second parameter is exception number, used for a string lookup
+ in UIE.
+ */
+undef_instr_handler:
+ sub r0, lr, #4
+ mov r1, #0
+ b UIE
+
+/* We run supervisor mode most of the time, and should never see a software
+ exception being thrown. Perhaps make it illegal and call UIE?
+ */
+software_int_handler:
+reserved_handler:
+ movs pc, lr
+prefetch_abort_handler:
+ sub r0, lr, #4
+ mov r1, #1
+ b UIE
+
+data_abort_handler:
+ sub r0, lr, #8
+ mov r1, #2
+ b UIE
+
+/* should never happen in the bootloader */
+fiq_handler:
+ subs pc, lr, #4
+
+/* 256 words of IRQ stack */
+ .section .bss
+ .balign 16
+ .space 256*4
+irq_stack:
diff --git a/firmware/target/arm/kernel-pp.c b/firmware/target/arm/kernel-pp.c
index 23610d2c61..2a00254173 100644
--- a/firmware/target/arm/kernel-pp.c
+++ b/firmware/target/arm/kernel-pp.c
@@ -22,7 +22,7 @@
#include "system.h"
#include "kernel.h"
-#ifndef BOOTLOADER
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
void TIMER1(void)
{
/* Run through the list of tick tasks (using main core) */
@@ -42,7 +42,7 @@ void TIMER1(void)
/* Must be last function called init kernel/thread initialization */
void tick_start(unsigned int interval_in_ms)
{
-#ifndef BOOTLOADER
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
TIMER1_CFG = 0x0;
TIMER1_VAL;
/* enable timer */
@@ -54,3 +54,11 @@ void tick_start(unsigned int interval_in_ms)
(void)interval_in_ms;
#endif
}
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+void tick_stop(void)
+{
+ CPU_INT_DIS = TIMER1_MASK;
+ TIMER1_CFG = 0;
+}
+#endif
diff --git a/firmware/target/arm/philips/boot.lds b/firmware/target/arm/philips/boot.lds
index 0736bec96a..0ea31024bf 100644
--- a/firmware/target/arm/philips/boot.lds
+++ b/firmware/target/arm/philips/boot.lds
@@ -3,11 +3,12 @@
ENTRY(start)
OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
-STARTUP(target/arm/crt0-pp-bl.o)
+STARTUP(target/arm/crt0-pp502x-bl-usb.o)
-#define DRAMSIZE (MEMORYSIZE * 0x100000)
-
-#define DRAMORIG 0x10000000
+#define DRAMORIG 0x01000000 /* Load at 16 MB */
+#define DRAMSIZE 0x00100000 /* 1MB for bootloader */
+#define MEMEND (MEMORYSIZE*0x100000) /* From virtual mapping at 0 */
+#define NOCACHE_BASE 0x10000000
#ifndef IRAMORIG
#define IRAMORIG 0x40000000
#endif
@@ -15,6 +16,8 @@ STARTUP(target/arm/crt0-pp-bl.o)
#define FLASHORIG 0x001f0000
#define FLASHSIZE 2M
+#define CACHEALIGN_SIZE 16
+
MEMORY
{
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
@@ -23,44 +26,112 @@ MEMORY
SECTIONS
{
- . = IRAMORIG;
-
- .text : {
- *(.init.text)
- *(.text*)
- *(.glue_7)
- *(.glue_7t)
- } > IRAM
-
- .data : {
- *(.icode)
- *(.irodata)
- *(.idata)
- *(.data*)
- *(.ncdata*)
- *(.rodata*)
- _dataend = . ;
- } > IRAM
-
- .stack (NOLOAD) : {
- *(.stack)
- _stackbegin = .;
- stackbegin = .;
- . += 0x2000;
- _stackend = .;
- stackend = .;
- } > IRAM
-
- /* The bss section is too large for IRAM - we just move it 16MB into the
- DRAM */
-
- . = DRAMORIG;
- .bss . + (16*1024*1024) (NOLOAD) : {
- _edata = .;
- *(.bss*);
- *(.ibss);
- *(COMMON)
- *(.ncbss*);
- _end = .;
- } > DRAM
+ . = DRAMORIG;
+ _loadaddress = . + NOCACHE_BASE;
+
+ .text :
+ {
+ *(.init.text)
+ *(.text*)
+ *(.glue_7)
+ *(.glue_7t)
+ . = ALIGN(0x4);
+ } > DRAM
+
+ .rodata :
+ {
+ *(.rodata) /* problems without this, dunno why */
+ *(.rodata*)
+ *(.rodata.str1.1)
+ *(.rodata.str1.4)
+ . = ALIGN(0x4);
+ } > DRAM
+
+ .data :
+ {
+ *(.data*)
+ . = ALIGN(0x4);
+ } > DRAM
+
+ /* .ncdata section is placed at uncached physical alias address and is
+ * loaded at the proper cached virtual address - no copying is
+ * performed in the init code */
+ .ncdata . + NOCACHE_BASE :
+ {
+ . = ALIGN(CACHEALIGN_SIZE);
+ *(.ncdata*)
+ . = ALIGN(CACHEALIGN_SIZE);
+ } AT> DRAM
+
+ /DISCARD/ . - NOCACHE_BASE :
+ {
+ *(.eh_frame)
+ } > DRAM
+
+ _noloaddram = .;
+
+ .ibss IRAMORIG (NOLOAD) :
+ {
+ _iedata = .;
+ *(.qharray)
+ *(.ibss)
+ . = ALIGN(0x4);
+ _iend = .;
+ } > IRAM
+
+ .iram _iend :
+ {
+ _iramstart = .;
+ *(.icode)
+ *(.irodata)
+ *(.idata)
+ _iramend = .;
+ } > IRAM AT> DRAM
+
+ _iramcopy = LOADADDR(.iram);
+
+ .loadaddressend :
+ {
+ _loadaddressend = . + NOCACHE_BASE;
+ } AT> DRAM
+
+ .stack (NOLOAD) :
+ {
+ . = ALIGN(8);
+ *(.stack)
+ stackbegin = .;
+ . += 0x2000;
+ stackend = .;
+ } > IRAM
+
+ /* .bss and .ncbss are treated as a single section to use one init loop
+ * to zero them - note "_edata" and "_end" */
+ .bss _noloaddram (NOLOAD) :
+ {
+ _edata = .;
+ *(.bss*)
+ *(COMMON)
+ } > DRAM
+
+ .ncbss . + NOCACHE_BASE (NOLOAD) :
+ {
+ . = ALIGN(CACHEALIGN_SIZE);
+ *(.ncbss*)
+ . = ALIGN(CACHEALIGN_SIZE);
+ } AT> DRAM
+
+ /* This will be aligned by preceding alignments */
+ .endaddr . - NOCACHE_BASE (NOLOAD) :
+ {
+ _end = .;
+ } > DRAM
+
+ /* Reference to all DRAM after loaded bootloader image */
+ .freebuffer _end (NOLOAD) :
+ {
+ . = ALIGN(4);
+ freebuffer = .;
+ . = MEMEND-1;
+ freebufferend = .;
+ }
}
diff --git a/firmware/target/arm/philips/sa9200/button-sa9200.c b/firmware/target/arm/philips/sa9200/button-sa9200.c
index 1e92325c73..bef5be7522 100644
--- a/firmware/target/arm/philips/sa9200/button-sa9200.c
+++ b/firmware/target/arm/philips/sa9200/button-sa9200.c
@@ -119,6 +119,10 @@ void button_int(void)
void button_init_device(void)
{
}
+
+void button_int(void)
+{
+}
#endif /* BOOTLOADER */
bool button_hold(void)
diff --git a/firmware/target/arm/philips/sa9200/button-target.h b/firmware/target/arm/philips/sa9200/button-target.h
index faed943208..7d060157c6 100644
--- a/firmware/target/arm/philips/sa9200/button-target.h
+++ b/firmware/target/arm/philips/sa9200/button-target.h
@@ -34,10 +34,7 @@
bool button_hold(void);
void button_init_device(void);
int button_read_device(void);
-
-#ifndef BOOTLOADER
void button_int(void);
-#endif
/* Main unit's buttons */
#define BUTTON_POWER 0x00000001
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index c4bf81dc5a..41b43ba24d 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -33,7 +33,7 @@
#include "lcd-remote-target.h"
#endif
-#ifndef BOOTLOADER
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
extern void TIMER1(void);
extern void TIMER2(void);
extern void SERIAL0(void);
@@ -184,15 +184,33 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void)
TIMER2();
}
}
-#endif /* BOOTLOADER */
+#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */
-/* TODO: The following function has been lifted straight from IPL, and
- hence has a lot of numeric addresses used straight. I'd like to use
- #defines for these, but don't know what most of them are for or even what
- they should be named. Because of this I also have no way of knowing how
- to extend the funtions to do alternate cache configurations. */
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
+static void disable_all_interrupts(void)
+{
+ COP_HI_INT_DIS = -1;
+ CPU_HI_INT_DIS = -1;
+ HI_INT_FORCED_CLR = -1;
+
+ COP_INT_DIS = -1;
+ CPU_INT_DIS = -1;
+ INT_FORCED_CLR = -1;
+
+ GPIOA_INT_EN = 0;
+ GPIOB_INT_EN = 0;
+ GPIOC_INT_EN = 0;
+ GPIOD_INT_EN = 0;
+ GPIOE_INT_EN = 0;
+ GPIOF_INT_EN = 0;
+ GPIOG_INT_EN = 0;
+ GPIOH_INT_EN = 0;
+ GPIOI_INT_EN = 0;
+ GPIOJ_INT_EN = 0;
+ GPIOK_INT_EN = 0;
+ GPIOL_INT_EN = 0;
+}
-#ifndef BOOTLOADER
void ICODE_ATTR cpucache_commit(void)
{
if (CACHE_CTL & CACHE_CTL_ENABLE)
@@ -217,13 +235,17 @@ void cpucache_invalidate(void) __attribute__((alias("cpucache_commit_discard")))
static void init_cache(void)
{
-/* Initialising the cache in the iPod bootloader prevents Rockbox from starting */
+/* Initialising the cache in the iPod bootloader may prevent Rockbox from starting
+ * depending on the model */
/* cache init mode */
+ CACHE_CTL &= ~(CACHE_CTL_ENABLE | CACHE_CTL_RUN);
CACHE_CTL |= CACHE_CTL_INIT;
+#ifndef BOOTLOADER
/* what's this do? */
CACHE_PRIORITY |= CURRENT_CORE == CPU ? 0x10 : 0x20;
+#endif
/* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
* yes: 0x00000000 - 0x03ffffff
@@ -238,10 +260,11 @@ static void init_cache(void)
CACHE_CTL |= CACHE_CTL_INIT | CACHE_CTL_ENABLE | CACHE_CTL_RUN;
nop; nop; nop; nop;
}
-#endif /* !BOOTLOADER */
+#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE*/
/* We need this for Sansas since we boost the cpu in their bootloader */
-#if !defined(BOOTLOADER) || defined(SANSA_E200) || defined(SANSA_C200) || \
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE) || \
+ defined(SANSA_E200) || defined(SANSA_C200) || \
defined(PHILIPS_SA9200)
void scale_suspend_core(bool suspend) ICODE_ATTR;
void scale_suspend_core(bool suspend)
@@ -386,7 +409,8 @@ static void pp_set_cpu_frequency(long frequency)
corelock_unlock(&cpufreq_cl);
#endif
}
-#endif /* !BOOTLOADER || SANSA_E200 || SANSA_C200 || PHILIPS_SA9200 */
+#endif /* !BOOTLOADER || HAVE_BOOTLOADER_USB_MODE ||
+ SANSA_E200 || SANSA_C200 || PHILIPS_SA9200 */
void system_init(void)
{
@@ -494,27 +518,7 @@ void system_init(void)
MMAP_PHYS_DATA_MASK | MMAP_PHYS_CODE_MASK;
#endif
- /* disable all irqs */
- COP_HI_INT_DIS = -1;
- CPU_HI_INT_DIS = -1;
- HI_INT_FORCED_CLR = -1;
-
- COP_INT_DIS = -1;
- CPU_INT_DIS = -1;
- INT_FORCED_CLR = -1;
-
- GPIOA_INT_EN = 0;
- GPIOB_INT_EN = 0;
- GPIOC_INT_EN = 0;
- GPIOD_INT_EN = 0;
- GPIOE_INT_EN = 0;
- GPIOF_INT_EN = 0;
- GPIOG_INT_EN = 0;
- GPIOH_INT_EN = 0;
- GPIOI_INT_EN = 0;
- GPIOJ_INT_EN = 0;
- GPIOK_INT_EN = 0;
- GPIOL_INT_EN = 0;
+ disable_all_interrupts();
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#if NUM_CORES > 1
@@ -534,13 +538,23 @@ void system_init(void)
}
init_cache();
-#else /* BOOTLOADER */
- if (CURRENT_CORE == CPU)
- {
+
+#else /* !BOOTLOADER */
+ /* Only the CPU gets here in the bootloader */
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+ disable_all_interrupts();
+ init_cache();
+ /* Use the local vector map */
+ CACHE_CTL |= CACHE_CTL_VECT_REMAP;
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+
#if defined(SANSA_C200) || defined(SANSA_E200) || defined(PHILIPS_SA9200)
- pp_set_cpu_frequency(CPUFREQ_MAX);
+ pp_set_cpu_frequency(CPUFREQ_MAX);
#endif
- }
+ /* Else the frequency shot get changed upon USB connect -
+ * decide per-target */
+
#endif /* BOOTLOADER */
}
@@ -582,3 +596,11 @@ int system_memory_guard(int newmode)
(void)newmode;
return 0;
}
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+void system_prepare_fw_start(void)
+{
+ tick_stop();
+ disable_all_interrupts();
+}
+#endif
diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h
index 3e3eab8f8d..eb2a07f7d3 100644
--- a/firmware/target/arm/system-target.h
+++ b/firmware/target/arm/system-target.h
@@ -141,7 +141,7 @@ static inline void wake_core(int core)
}
#endif
-#ifdef BOOTLOADER
+#if defined(BOOTLOADER) && !defined(HAVE_BOOTLOADER_USB_MODE)
/* All addresses within rockbox are in IRAM in the bootloader so
are therefore uncached */
#define UNCACHED_ADDR(a) (a)
@@ -163,7 +163,7 @@ static inline void wake_core(int core)
#endif
/** cache functions **/
-#ifndef BOOTLOADER
+#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
#define HAVE_CPUCACHE_COMMIT_DISCARD
#define HAVE_CPUCACHE_COMMIT
/* deprecated alias */
@@ -175,6 +175,30 @@ static inline void wake_core(int core)
extern unsigned char probed_ramsize;
#endif
+
+#ifdef BOOTLOADER
+#if defined(TATUNG_TPJ1022)
+ /* Some targets don't like yielding in the bootloader - force
+ * yield() to return without a context switch. */
+#define YIELD_KERNEL_HOOK() true
+#endif
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+void tick_stop(void);
+void system_prepare_fw_start(void);
+
+#else /* !HAVE_BOOTLOADER_USB_MODE */
+
+ /* Busy "sleep" without a tick */
+#define SLEEP_KERNEL_HOOK(ticks) \
+ ({ unsigned _stop = USEC_TIMER + ((ticks) + 1) * (1000000/HZ); \
+ while (TIME_BEFORE(USEC_TIMER, _stop)) \
+ switch_thread(); \
+ true; })
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+
+#endif /* BOOTLOADER */
+
#endif /* CPU_PP */
#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/tms320dm320/system-target.h b/firmware/target/arm/tms320dm320/system-target.h
index 1c197ce72c..4e0a97f10e 100644
--- a/firmware/target/arm/tms320dm320/system-target.h
+++ b/firmware/target/arm/tms320dm320/system-target.h
@@ -34,4 +34,13 @@ void udelay(int usec);
void dm320_set_io (char pin_num, bool input, bool invert, bool irq, bool irqany,
bool chat, char func_num );
+#if defined(CREATIVE_ZVx) && defined(BOOTLOADER)
+#define SLEEP_KERNEL_HOOK(ticks) \
+ ({ \ /* hacky.. */
+ long _sleep_ticks = current_tick + ticks + 1; \
+ while (TIME_BEFORE(current_tick, _sleep_ticks)) \
+ switch_thread(); \
+ true; }) /* handled here */
+#endif
+
#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/usb-fw-pp5002.c b/firmware/target/arm/usb-fw-pp5002.c
index 3ea9bd1a89..f9682161c1 100644
--- a/firmware/target/arm/usb-fw-pp5002.c
+++ b/firmware/target/arm/usb-fw-pp5002.c
@@ -27,7 +27,7 @@
#include "usb.h"
#include "usb-target.h"
-void usb_init_device(void)
+void usb_pin_init(void)
{
/* TODO: add USB init for iPod 3rd gen */
@@ -38,6 +38,9 @@ void usb_init_device(void)
#endif
}
+/* No different for now */
+void usb_init_device(void) __attribute__((alias("usb_pin_init")));
+
void usb_enable(bool on)
{
/* This device specific code will eventually give way to proper USB
@@ -70,3 +73,6 @@ int usb_detect(void)
return USB_EXTRACTED;
}
+
+/* No different for now */
+void usb_plugged(void) __attribute__((alias("usb_detect")));
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c
index 0b474c96bf..8f754fd04b 100644
--- a/firmware/target/arm/usb-fw-pp502x.c
+++ b/firmware/target/arm/usb-fw-pp502x.c
@@ -106,6 +106,18 @@
#define USB_GPIO_INT_CLR GPIO_INT_CLR(USB_GPIO)
#define USB_GPIO_HI_INT_MASK GPIO_HI_INT_MASK(USB_GPIO)
+/* Enable raw status pin read only - not interrupt */
+void usb_pin_init(void)
+{
+ GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
+ GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
+#ifdef USB_FIREWIRE_HANDLING
+ /* GPIO C bit 1 is firewire detect */
+ GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
+ GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
+#endif
+}
+
void usb_init_device(void)
{
/* enable usb module */
@@ -140,12 +152,12 @@ void usb_init_device(void)
DEV_INIT2 &= ~INIT_USB;
#endif
- /* These set INV_LEV to the inserted level so it will fire if already
+ usb_pin_init();
+
+ /* These set INT_LEV to the inserted level so it will fire if already
* inserted at the time they are enabled. */
#ifdef USB_STATUS_BY_EVENT
GPIO_CLEAR_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
- GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
- GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, USB_GPIO_VAL, USB_GPIO_MASK);
USB_GPIO_INT_CLR = USB_GPIO_MASK;
GPIO_SET_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
@@ -154,23 +166,12 @@ void usb_init_device(void)
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x02);
- GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
- GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
GPIO_WRITE_BITWISE(GPIOC_INT_LEV, 0x00, 0x02);
GPIOC_INT_CLR = 0x02;
GPIO_SET_BITWISE(GPIOC_INT_EN, 0x02);
CPU_HI_INT_EN = GPIO0_MASK;
#endif
CPU_INT_EN = HI_MASK;
-#else
- /* No interrupt - setup pin read only (BOOTLOADER) */
- GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
- GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
-#ifdef USB_FIREWIRE_HANDLING
- /* GPIO C bit 1 is firewire detect */
- GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
- GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
-#endif
#endif /* USB_STATUS_BY_EVENT */
}
@@ -185,10 +186,12 @@ void usb_enable(bool on)
}
else {
usb_core_exit();
+#ifndef BOOTLOADER
/* Disable USB devices */
DEV_EN &=~ DEV_USB0;
DEV_EN &=~ DEV_USB1;
DEV_INIT2 &=~ INIT_USB;
+#endif
}
}
@@ -197,7 +200,7 @@ void usb_attach(void)
usb_drv_attach();
}
-static bool usb_pin_state(void)
+bool usb_plugged(void)
{
return (USB_GPIO_INPUT_VAL & USB_GPIO_MASK) == USB_GPIO_VAL;
}
@@ -226,12 +229,27 @@ void usb_insert_int(void)
* invalid bus reset when unplugging by checking the pin state. */
void usb_drv_usb_detect_event(void)
{
- if(usb_pin_state()) {
+ if(usb_plugged()) {
usb_status_event(USB_INSERTED);
}
}
#endif /* USB_STATUS_BY_EVENT */
+#ifdef HAVE_BOOTLOADER_USB_MODE
+/* Replacement function that returns all unused memory after the bootloader
+ * because the storage driver uses the audio buffer */
+extern unsigned char freebuffer[];
+extern unsigned char freebufferend[];
+unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
+{
+ if (buffer_size)
+ *buffer_size = freebufferend - freebuffer + 1;
+
+ return freebuffer;
+ (void)talk_buf;
+}
+#endif /* HAVE_BOOTLOADER_USB_MODE */
+
void usb_drv_int_enable(bool enable)
{
/* enable/disable USB IRQ in CPU */
@@ -249,7 +267,7 @@ int usb_detect(void)
#ifdef USB_STATUS_BY_EVENT
return usb_status;
#else
- return usb_pin_state() ? USB_INSERTED : USB_EXTRACTED;
+ return usb_plugged() ? USB_INSERTED : USB_EXTRACTED;
#endif
}
diff --git a/firmware/target/arm/usb-target.h b/firmware/target/arm/usb-target.h
index 8e159617d5..7342f2aafa 100644
--- a/firmware/target/arm/usb-target.h
+++ b/firmware/target/arm/usb-target.h
@@ -24,5 +24,11 @@
void usb_init_device(void);
void usb_insert_int(void);
void firewire_insert_int(void);
+void usb_pin_init(void); /* Init the GPIO input only */
+bool usb_plugged(void); /* Returns instantaneous state - always */
+
+#ifdef HAVE_BOOTLOADER_USB_MODE
+#define USB_DRIVER_CLOSE
+#endif
#endif
diff --git a/firmware/usb.c b/firmware/usb.c
index 6309c1481c..c8f0118730 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -46,7 +46,7 @@
/* Conditions under which we want the entire driver */
#if !defined(BOOTLOADER) || (CONFIG_CPU == SH7034) || \
- (defined(TOSHIBA_GIGABEAT_S) && defined(USE_ROCKBOX_USB) && defined(USB_ENABLE_STORAGE)) || \
+ (defined(HAVE_USBSTACK) && defined(HAVE_BOOTLOADER_USB_MODE)) || \
(defined(HAVE_USBSTACK) && (defined(CREATIVE_ZVx))) || \
(defined(HAVE_USBSTACK) && (defined(OLYMPUS_MROBE_500))) || \
(defined(HAVE_USBSTACK) && (defined(IPOD_NANO2G))) || \
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 1ff3b1ec4c..d8d6817ad2 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -451,8 +451,8 @@ void usb_storage_init_connection(void)
/* prime rx endpoint. We only need room for commands */
state = WAITING_FOR_COMMAND;
-#if CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
- defined(BOOTLOADER) || CONFIG_CPU == DM320
+#if (CONFIG_CPU == IMX31L || defined(CPU_TCC77X) || defined(CPU_TCC780X) || \
+ defined(BOOTLOADER) || CONFIG_CPU == DM320) && !defined(CPU_PP502x)
static unsigned char _cbw_buffer[MAX_CBW_SIZE]
USB_DEVBSS_ATTR __attribute__((aligned(32)));
cbw_buffer = (void *)_cbw_buffer;