From 5dfcf4abaa6f9af8e319f20ef0c23b5135d73d4c Mon Sep 17 00:00:00 2001 From: jethead71 Date: Sat, 15 Jan 2011 08:19:30 +0000 Subject: [PATCH] Bootloader USB mode for PP502x. Enable only on GoGear SA9200 for the time being. Add HAVE_BOOTLOADER_USB_MODE to config if BOOTLOADER is defined to enable it. Clean up some kernel stuff a little to support it. Mess up a bunch of other stuff (hopefully not too badly). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29053 a1c6a512-1295-4272-9138-f99709370657 --- bootloader/main-pp.c | 155 +++++++-- firmware/SOURCES | 6 +- firmware/export/config.h | 6 +- firmware/export/config/gigabeats.h | 4 + firmware/export/config/gogearsa9200.h | 7 +- firmware/export/kernel.h | 7 +- firmware/export/pp5020.h | 3 + firmware/export/sd.h | 4 + firmware/export/storage.h | 1 + firmware/export/usb.h | 3 + firmware/kernel.c | 36 +- firmware/target/arm/ata-sd-pp.c | 29 +- firmware/target/arm/ata-target.h | 4 + firmware/target/arm/crt0-pp502x-bl-usb.S | 362 +++++++++++++++++++++ firmware/target/arm/kernel-pp.c | 12 +- firmware/target/arm/philips/boot.lds | 203 ++++++++---- firmware/target/arm/philips/sa9200/button-sa9200.c | 4 + firmware/target/arm/philips/sa9200/button-target.h | 3 - firmware/target/arm/system-pp502x.c | 98 +++--- firmware/target/arm/system-target.h | 28 +- firmware/target/arm/tms320dm320/system-target.h | 9 + firmware/target/arm/usb-fw-pp5002.c | 8 +- firmware/target/arm/usb-fw-pp502x.c | 52 ++- firmware/target/arm/usb-target.h | 6 + firmware/usb.c | 2 +- firmware/usbstack/usb_storage.c | 4 +- 26 files changed, 869 insertions(+), 187 deletions(-) create mode 100644 firmware/target/arm/crt0-pp502x-bl-usb.S rewrite firmware/target/arm/philips/boot.lds (68%) diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c index d8ef64cdd..3670a7dc9 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 06dbf9d6e..d48d3c623 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 eca736dda..c77e67335 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 cf560aa35..3b3a717e2 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 2d777f197..23561e1b0 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 4656d87fb..cfc7a232a 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 5b5864f4e..073d33e49 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 c798f54e9..8e400bf88 100644 --- a/firmware/export/sd.h +++ b/firmware/export/sd.h @@ -25,6 +25,10 @@ #include #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 faceb2bb9..e9ac8b4cb 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 3e236bfb9..e192748e4 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 41d1d0068..4e629c550 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 914858e46..00437ea7a 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 12415c33e..779ebed07 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 000000000..c36059600 --- /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 + * + */ + .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 23610d2c6..2a0025417 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 dissimilarity index 68% index 0736bec96..0ea31024b 100644 --- a/firmware/target/arm/philips/boot.lds +++ b/firmware/target/arm/philips/boot.lds @@ -1,66 +1,137 @@ -#include "config.h" - -ENTRY(start) -OUTPUT_FORMAT(elf32-littlearm) -OUTPUT_ARCH(arm) -STARTUP(target/arm/crt0-pp-bl.o) - -#define DRAMSIZE (MEMORYSIZE * 0x100000) - -#define DRAMORIG 0x10000000 -#ifndef IRAMORIG -#define IRAMORIG 0x40000000 -#endif -#define IRAMSIZE 0x20000 -#define FLASHORIG 0x001f0000 -#define FLASHSIZE 2M - -MEMORY -{ - DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE - IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE -} - -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 -} +#include "config.h" + +ENTRY(start) +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +STARTUP(target/arm/crt0-pp502x-bl-usb.o) + +#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 +#define IRAMSIZE 0x20000 +#define FLASHORIG 0x001f0000 +#define FLASHSIZE 2M + +#define CACHEALIGN_SIZE 16 + +MEMORY +{ + DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE + IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE +} + +SECTIONS +{ + . = 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 1e92325c7..bef5be752 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 faed94320..7d060157c 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 c4bf81dc5..41b43ba24 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 3e3eab8f8..eb2a07f7d 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 1c197ce72..4e0a97f10 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 3ea9bd1a8..f9682161c 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 0b474c96b..8f754fd04 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 8e159617d..7342f2aaf 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 6309c1481..c8f011873 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 1ff3b1ec4..d8d6817ad 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; -- 2.11.4.GIT