From 140783ef66eef379feedcfef5403c5729d38936a Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sat, 13 Jul 2013 17:35:53 +0200 Subject: hwstub: split target specific code from the common part Completely rewrite the Mafile, properly put the usb driver in its own file and the target specific files in a subdirectory. Change-Id: Iaeee0128e021d5dad76b4d6035a63e33e2d946c1 --- utils/hwstub/stub/SOURCES | 12 + utils/hwstub/stub/config.h | 49 ++++ utils/hwstub/stub/crt0.S | 17 ++ utils/hwstub/stub/format.c | 223 ++++++++++++++++ utils/hwstub/stub/format.h | 29 +++ utils/hwstub/stub/hwstub.lds | 71 ++++++ utils/hwstub/stub/hwstub.make | 49 ++++ utils/hwstub/stub/logf.c | 69 +++++ utils/hwstub/stub/logf.h | 31 +++ utils/hwstub/stub/memcpy.S | 176 +++++++++++++ utils/hwstub/stub/memmove.S | 190 ++++++++++++++ utils/hwstub/stub/memory.h | 30 +++ utils/hwstub/stub/memset.S | 98 +++++++ utils/hwstub/stub/protocol.h | 1 + utils/hwstub/stub/stddef.h | 32 +++ utils/hwstub/stub/stdint.h | 40 +++ utils/hwstub/stub/stmp/Makefile | 14 + utils/hwstub/stub/stmp/target-config.h | 9 + utils/hwstub/stub/stmp/target.c | 205 +++++++++++++++ utils/hwstub/stub/string.c | 29 +++ utils/hwstub/stub/string.h | 28 ++ utils/hwstub/stub/system.h | 118 +++++++++ utils/hwstub/stub/target.h | 31 +++ utils/hwstub/stub/usb_ch9.h | 454 +++++++++++++++++++++++++++++++++ utils/hwstub/stub/usb_drv.h | 47 ++++ utils/hwstub/stub/usb_drv_arc.c | 364 ++++++++++++++++++++++++++ 26 files changed, 2416 insertions(+) create mode 100644 utils/hwstub/stub/SOURCES create mode 100644 utils/hwstub/stub/config.h create mode 100644 utils/hwstub/stub/crt0.S create mode 100644 utils/hwstub/stub/format.c create mode 100644 utils/hwstub/stub/format.h create mode 100644 utils/hwstub/stub/hwstub.lds create mode 100644 utils/hwstub/stub/hwstub.make create mode 100644 utils/hwstub/stub/logf.c create mode 100644 utils/hwstub/stub/logf.h create mode 100644 utils/hwstub/stub/memcpy.S create mode 100644 utils/hwstub/stub/memmove.S create mode 100644 utils/hwstub/stub/memory.h create mode 100644 utils/hwstub/stub/memset.S create mode 100644 utils/hwstub/stub/protocol.h create mode 100644 utils/hwstub/stub/stddef.h create mode 100644 utils/hwstub/stub/stdint.h create mode 100644 utils/hwstub/stub/stmp/Makefile create mode 100644 utils/hwstub/stub/stmp/target-config.h create mode 100644 utils/hwstub/stub/stmp/target.c create mode 100644 utils/hwstub/stub/string.c create mode 100644 utils/hwstub/stub/string.h create mode 100644 utils/hwstub/stub/system.h create mode 100644 utils/hwstub/stub/target.h create mode 100644 utils/hwstub/stub/usb_ch9.h create mode 100644 utils/hwstub/stub/usb_drv.h create mode 100644 utils/hwstub/stub/usb_drv_arc.c (limited to 'utils/hwstub/stub') diff --git a/utils/hwstub/stub/SOURCES b/utils/hwstub/stub/SOURCES new file mode 100644 index 0000000000..bfb847c21b --- /dev/null +++ b/utils/hwstub/stub/SOURCES @@ -0,0 +1,12 @@ +main.c +crt0.S +logf.c +memcpy.S +memmove.S +memset.S +string.c +format.c +#ifdef CONFIG_STMP +usb_drv_arc.c +stmp/target.c +#endif diff --git a/utils/hwstub/stub/config.h b/utils/hwstub/stub/config.h new file mode 100644 index 0000000000..3cd2deeeb3 --- /dev/null +++ b/utils/hwstub/stub/config.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_CONFIG__ +#define __HWSTUB_CONFIG__ + +#include "target-config.h" + +#define STACK_SIZE 0x1000 +#define MAX_LOGF_SIZE 128 + +#if defined(CPU_ARM) && defined(__ASSEMBLER__) +/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */ +.macro ldmpc cond="", order="ia", regs +#if ARM_ARCH == 4 && defined(USE_THUMB) + ldm\cond\order sp!, { \regs, lr } + bx\cond lr +#else + ldm\cond\order sp!, { \regs, pc } +#endif +.endm +.macro ldrpc cond="" +#if ARM_ARCH == 4 && defined(USE_THUMB) + ldr\cond lr, [sp], #4 + bx\cond lr +#else + ldr\cond pc, [sp], #4 +#endif +.endm +#endif + +#endif /* __HWSTUB_CONFIG__ */ diff --git a/utils/hwstub/stub/crt0.S b/utils/hwstub/stub/crt0.S new file mode 100644 index 0000000000..e2d4742d36 --- /dev/null +++ b/utils/hwstub/stub/crt0.S @@ -0,0 +1,17 @@ +.section .text,"ax",%progbits +.code 32 +.align 0x04 +.global start +start: + msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ + ldr sp, =oc_stackend + /* clear bss */ + ldr r2, =bss_start + ldr r3, =bss_end + mov r4, #0 +1: + cmp r3, r2 + strhi r4, [r2], #4 + bhi 1b + /* jump to C code */ + b main diff --git a/utils/hwstub/stub/format.c b/utils/hwstub/stub/format.c new file mode 100644 index 0000000000..f5783159c0 --- /dev/null +++ b/utils/hwstub/stub/format.c @@ -0,0 +1,223 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 by Gary Czvitkovicz + * + * 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 +#include +#include "stddef.h" +#include "string.h" +#include "format.h" + +static const char hexdigit[] = "0123456789ABCDEF"; + +void vuprintf( + /* call 'push()' for each output letter */ + int (*push)(void *userp, unsigned char data), + void *userp, + const char *fmt, + va_list ap) +{ + char *str; + char tmpbuf[12], pad; + int ch, width, val, sign, precision; + long lval, lsign; + unsigned int uval; + unsigned long ulval; + size_t uszval; + ssize_t szval, szsign; + bool ok = true; + + tmpbuf[sizeof tmpbuf - 1] = '\0'; + + while ((ch = *fmt++) != '\0' && ok) + { + if (ch == '%') + { + ch = *fmt++; + pad = ' '; + if (ch == '0') + pad = '0'; + + width = 0; + while (ch >= '0' && ch <= '9') + { + width = 10*width + ch - '0'; + ch = *fmt++; + } + + precision = 0; + if(ch == '.') + { + ch = *fmt++; + while (ch >= '0' && ch <= '9') + { + precision = 10*precision + ch - '0'; + ch = *fmt++; + } + } else { + precision = INT_MAX; + } + + str = tmpbuf + sizeof tmpbuf - 1; + switch (ch) + { + case 'c': + *--str = va_arg (ap, int); + break; + + case 's': + str = va_arg (ap, char*); + break; + + case 'd': + val = sign = va_arg (ap, int); + if (val < 0) + val = -val; + do + { + *--str = (val % 10) + '0'; + val /= 10; + } + while (val > 0); + if (sign < 0) + *--str = '-'; + break; + + case 'u': + uval = va_arg(ap, unsigned int); + do + { + *--str = (uval % 10) + '0'; + uval /= 10; + } + while (uval > 0); + break; + + case 'x': + case 'X': + pad='0'; + uval = va_arg (ap, int); + do + { + *--str = hexdigit[uval & 0xf]; + uval >>= 4; + } + while (uval); + break; + + case 'l': + ch = *fmt++; + switch(ch) { + case 'x': + case 'X': + pad='0'; + ulval = va_arg (ap, long); + do + { + *--str = hexdigit[ulval & 0xf]; + ulval >>= 4; + } + while (ulval); + break; + case 'd': + lval = lsign = va_arg (ap, long); + if (lval < 0) + lval = -lval; + do + { + *--str = (lval % 10) + '0'; + lval /= 10; + } + while (lval > 0); + if (lsign < 0) + *--str = '-'; + break; + + case 'u': + ulval = va_arg(ap, unsigned long); + do + { + *--str = (ulval % 10) + '0'; + ulval /= 10; + } + while (ulval > 0); + break; + + default: + *--str = 'l'; + *--str = ch; + } + + break; + + case 'z': + ch = *fmt++; + switch(ch) { + case 'd': + szval = szsign = va_arg (ap, ssize_t); + if (szval < 0) + szval = -szval; + do + { + *--str = (szval % 10) + '0'; + szval /= 10; + } + while (szval > 0); + if (szsign < 0) + *--str = '-'; + break; + + case 'u': + uszval = va_arg(ap, size_t); + do + { + *--str = (uszval % 10) + '0'; + uszval /= 10; + } + while (uszval > 0); + break; + + default: + *--str = 'z'; + *--str = ch; + } + + break; + + default: + *--str = ch; + break; + } + + if (width > 0) + { + width -= strlen (str); + while (width-- > 0 && ok) + ok=push(userp, pad); + } + while (*str != '\0' && ok && precision--) + ok=push(userp, *str++); + } + else + ok=push(userp, ch); + } +} + diff --git a/utils/hwstub/stub/format.h b/utils/hwstub/stub/format.h new file mode 100644 index 0000000000..2ad4229f1e --- /dev/null +++ b/utils/hwstub/stub/format.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_FORMAT__ +#define __HWSTUB_FORMAT__ + +#include + +void vuprintf(int (*push)(void *userp, unsigned char data), + void *userp, const char *fmt, va_list ap); + +#endif /* __HWSTUB_FORMAT__ */ diff --git a/utils/hwstub/stub/hwstub.lds b/utils/hwstub/stub/hwstub.lds new file mode 100644 index 0000000000..61504a3e75 --- /dev/null +++ b/utils/hwstub/stub/hwstub.lds @@ -0,0 +1,71 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" + +ENTRY(start) +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +STARTUP(crt0.o) + +#define IRAM_END_ADDR (IRAM_ORIG + IRAM_SIZE) + +MEMORY +{ + OCRAM : ORIGIN = IRAM_ORIG, LENGTH = IRAM_SIZE +} + +SECTIONS +{ + .octext : + { + oc_codestart = .; + *(.text*) + *(.icode*) + *(.data*) + *(.rodata*) + } > OCRAM + + .bss (NOLOAD) : + { + bss_start = .; + *(.bss) + bss_end = .; + } > OCRAM + + .stack (NOLOAD) : + { + oc_codeend = .; + oc_stackstart = .; + . += STACK_SIZE; + oc_stackend = .; + oc_bufferstart = .; + } > OCRAM + + .ocend IRAM_END_ADDR (NOLOAD) : + { + oc_bufferend = .; + } > OCRAM + + /DISCARD/ : + { + *(.eh_frame) + } +} diff --git a/utils/hwstub/stub/hwstub.make b/utils/hwstub/stub/hwstub.make new file mode 100644 index 0000000000..b46a2736ef --- /dev/null +++ b/utils/hwstub/stub/hwstub.make @@ -0,0 +1,49 @@ +INCLUDES+=-I$(ROOT_DIR) +LINKER_FILE=$(ROOT_DIR)/hwstub.lds +TMP_LDS=$(BUILD_DIR)/link.lds +TMP_MAP=$(BUILD_DIR)/hwstub.map +CFLAGS=$(GCCOPTS) $(DEFINES) -W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init $(INCLUDES) +ASFLAGS=$(CFLAGS) -D__ASSEMBLER__ +LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP) $(INCLUDES) -L$(BUILD_DIR) + +SRC:=$(shell cat $(ROOT_DIR)/SOURCES | $(CC) $(INCLUDES) \ + $(DEFINES) -E -P -include "config.h" - 2>/dev/null \ + | grep -v "^\#") +SRC:=$(foreach src,$(SRC),$(BUILD_DIR)/$(src)) +OBJ=$(SRC:.c=.o) +OBJ:=$(OBJ:.S=.o) +OBJ_EXCEPT_CRT0=$(filter-out $(BUILD_DIR)/crt0.o,$(OBJ)) +EXEC_ELF=$(BUILD_DIR)/hwstub.elf +DEPS=$(foreach obj,$(OBJ),$(obj).d) + +EXEC=$(EXEC_ELF) + +SILENT?=@ +PRINTS=$(SILENT)$(call info,$(1)) + +all: $(EXEC) + +# pull in dependency info for *existing* .o files +-include $(DEPS) + +$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.c + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CC $( $@.d + +$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.S + $(call PRINTS,AS $( $@ + +$(EXEC_ELF): $(OBJ) $(TMP_LDS) + $(call PRINTS,LD $(@F)) + $(SILENT)$(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0) + +clean: + $(SILENT)rm -rf $(OBJ) $(DEPS) $(EXEC) $(TMP_LDS) $(TMP_MAP) diff --git a/utils/hwstub/stub/logf.c b/utils/hwstub/stub/logf.c new file mode 100644 index 0000000000..623ddb1c6c --- /dev/null +++ b/utils/hwstub/stub/logf.c @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "logf.h" +#include "format.h" +#include "string.h" +#include "memory.h" + +static unsigned char logfbuffer[MAX_LOGF_SIZE]; +static int logfread = 0; +static int logfwrite = 0; +static int logfen = true; + +void enable_logf(bool en) +{ + logfen = en; +} + +static int logf_push(void *userp, unsigned char c) +{ + (void)userp; + + logfbuffer[logfwrite++] = c; + if(logfwrite == MAX_LOGF_SIZE) + logfwrite = 0; + return true; +} + +void logf(const char *fmt, ...) +{ + if(!logfen) return; + va_list ap; + va_start(ap, fmt); + vuprintf(logf_push, NULL, fmt, ap); + va_end(ap); +} + +size_t logf_readback(char *buf, size_t max_size) +{ + if(logfread == logfwrite) + return 0; + if(logfread < logfwrite) + max_size = MIN(max_size, (size_t)(logfwrite - logfread)); + else + max_size = MIN(max_size, (size_t)(MAX_LOGF_SIZE - logfread)); + memcpy(buf, &logfbuffer[logfread], max_size); + logfread += max_size; + if(logfread == MAX_LOGF_SIZE) + logfread = 0; + return max_size; +} diff --git a/utils/hwstub/stub/logf.h b/utils/hwstub/stub/logf.h new file mode 100644 index 0000000000..48c8c2c9b9 --- /dev/null +++ b/utils/hwstub/stub/logf.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_LOGF__ +#define __HWSTUB_LOGF__ + +#include "stddef.h" +#include + +void enable_logf(bool en); +void logf(const char *fmt, ...); +size_t logf_readback(char *buf, size_t max_size); + +#endif /* __HWSTUB_LOGF__ */ diff --git a/utils/hwstub/stub/memcpy.S b/utils/hwstub/stub/memcpy.S new file mode 100644 index 0000000000..2a55fb5656 --- /dev/null +++ b/utils/hwstub/stub/memcpy.S @@ -0,0 +1,176 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Free Software Foundation, Inc. + * This file was originally part of the GNU C Library + * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre) + * Adapted for Rockbox by Daniel Ankers + * + * 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" + +/* + * Endian independent macros for shifting bytes within registers. + */ +#ifndef __ARMEB__ +#define pull lsr +#define push lsl +#else +#define pull lsl +#define push lsr +#endif + +/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ + + .section .icode,"ax",%progbits + + .align 2 + .global memcpy + .type memcpy,%function + +memcpy: + stmfd sp!, {r0, r4, lr} + + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + +2: +3: +4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} + bge 3b + +5: ands ip, r2, #28 + rsb ip, ip, #32 + addne pc, pc, ip @ C is always clear here + b 7f +6: nop + ldr r3, [r1], #4 + ldr r4, [r1], #4 + ldr r5, [r1], #4 + ldr r6, [r1], #4 + ldr r7, [r1], #4 + ldr r8, [r1], #4 + ldr lr, [r1], #4 + + add pc, pc, ip + nop + nop + str r3, [r0], #4 + str r4, [r0], #4 + str r5, [r0], #4 + str r6, [r0], #4 + str r7, [r0], #4 + str r8, [r0], #4 + str lr, [r0], #4 + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldrneb r3, [r1], #1 + ldrcsb r4, [r1], #1 + ldrcsb ip, [r1] + strneb r3, [r0], #1 + strcsb r4, [r0], #1 + strcsb ip, [r0] + + ldmpc regs="r0, r4" + +9: rsb ip, ip, #4 + cmp ip, #2 + ldrgtb r3, [r1], #1 + ldrgeb r4, [r1], #1 + ldrb lr, [r1], #1 + strgtb r3, [r0], #1 + strgeb r4, [r0], #1 + subs r2, r2, ip + strb lr, [r0], #1 + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr lr, [r1], #4 + beq 17f + bgt 18f + + + .macro forward_copy_shift pull push + + subs r2, r2, #28 + blt 14f + +11: stmfd sp!, {r5 - r9} + +12: +13: ldmia r1!, {r4, r5, r6, r7} + mov r3, lr, pull #\pull + subs r2, r2, #32 + ldmia r1!, {r8, r9, ip, lr} + orr r3, r3, r4, push #\push + mov r4, r4, pull #\pull + orr r4, r4, r5, push #\push + mov r5, r5, pull #\pull + orr r5, r5, r6, push #\push + mov r6, r6, pull #\pull + orr r6, r6, r7, push #\push + mov r7, r7, pull #\pull + orr r7, r7, r8, push #\push + mov r8, r8, pull #\pull + orr r8, r8, r9, push #\push + mov r9, r9, pull #\pull + orr r9, r9, ip, push #\push + mov ip, ip, pull #\pull + orr ip, ip, lr, push #\push + stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip} + bge 12b + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov r3, lr, pull #\pull + ldr lr, [r1], #4 + subs ip, ip, #4 + orr r3, r3, lr, push #\push + str r3, [r0], #4 + bgt 15b + +16: sub r1, r1, #(\push / 8) + b 8b + + .endm + + + forward_copy_shift pull=8 push=24 + +17: forward_copy_shift pull=16 push=16 + +18: forward_copy_shift pull=24 push=8 + diff --git a/utils/hwstub/stub/memmove.S b/utils/hwstub/stub/memmove.S new file mode 100644 index 0000000000..d8cab048be --- /dev/null +++ b/utils/hwstub/stub/memmove.S @@ -0,0 +1,190 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Free Software Foundation, Inc. + * This file was originally part of the GNU C Library + * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre) + * Adapted for Rockbox by Daniel Ankers + * + * 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" + +/* + * Endian independent macros for shifting bytes within registers. + */ +#ifndef __ARMEB__ +#define pull lsr +#define push lsl +#else +#define pull lsl +#define push lsr +#endif + + .text + +/* + * Prototype: void *memmove(void *dest, const void *src, size_t n); + * + * Note: + * + * If the memory regions don't overlap, we simply branch to memcpy which is + * normally a bit faster. Otherwise the copy is done going downwards. + */ + + .section .icode,"ax",%progbits + + .align 2 + .global memmove + .type memmove,%function + +memmove: + + subs ip, r0, r1 + cmphi r2, ip + bls memcpy + + stmfd sp!, {r0, r4, lr} + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt 8f + ands ip, r0, #3 + bne 9f + ands ip, r1, #3 + bne 10f + +1: subs r2, r2, #(28) + stmfd sp!, {r5 - r8} + blt 5f + +2: +3: +4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} + subs r2, r2, #32 + stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} + bge 3b + +5: ands ip, r2, #28 + rsb ip, ip, #32 + addne pc, pc, ip @ C is always clear here + b 7f +6: nop + ldr r3, [r1, #-4]! + ldr r4, [r1, #-4]! + ldr r5, [r1, #-4]! + ldr r6, [r1, #-4]! + ldr r7, [r1, #-4]! + ldr r8, [r1, #-4]! + ldr lr, [r1, #-4]! + + add pc, pc, ip + nop + nop + str r3, [r0, #-4]! + str r4, [r0, #-4]! + str r5, [r0, #-4]! + str r6, [r0, #-4]! + str r7, [r0, #-4]! + str r8, [r0, #-4]! + str lr, [r0, #-4]! + +7: ldmfd sp!, {r5 - r8} + +8: movs r2, r2, lsl #31 + ldrneb r3, [r1, #-1]! + ldrcsb r4, [r1, #-1]! + ldrcsb ip, [r1, #-1] + strneb r3, [r0, #-1]! + strcsb r4, [r0, #-1]! + strcsb ip, [r0, #-1] + ldmpc regs="r0, r4" + +9: cmp ip, #2 + ldrgtb r3, [r1, #-1]! + ldrgeb r4, [r1, #-1]! + ldrb lr, [r1, #-1]! + strgtb r3, [r0, #-1]! + strgeb r4, [r0, #-1]! + subs r2, r2, ip + strb lr, [r0, #-1]! + blt 8b + ands ip, r1, #3 + beq 1b + +10: bic r1, r1, #3 + cmp ip, #2 + ldr r3, [r1, #0] + beq 17f + blt 18f + + + .macro backward_copy_shift push pull + + subs r2, r2, #28 + blt 14f + +11: stmfd sp!, {r5 - r9} + +12: +13: ldmdb r1!, {r7, r8, r9, ip} + mov lr, r3, push #\push + subs r2, r2, #32 + ldmdb r1!, {r3, r4, r5, r6} + orr lr, lr, ip, pull #\pull + mov ip, ip, push #\push + orr ip, ip, r9, pull #\pull + mov r9, r9, push #\push + orr r9, r9, r8, pull #\pull + mov r8, r8, push #\push + orr r8, r8, r7, pull #\pull + mov r7, r7, push #\push + orr r7, r7, r6, pull #\pull + mov r6, r6, push #\push + orr r6, r6, r5, pull #\pull + mov r5, r5, push #\push + orr r5, r5, r4, pull #\pull + mov r4, r4, push #\push + orr r4, r4, r3, pull #\pull + stmdb r0!, {r4 - r9, ip, lr} + bge 12b + + ldmfd sp!, {r5 - r9} + +14: ands ip, r2, #28 + beq 16f + +15: mov lr, r3, push #\push + ldr r3, [r1, #-4]! + subs ip, ip, #4 + orr lr, lr, r3, pull #\pull + str lr, [r0, #-4]! + bgt 15b + +16: add r1, r1, #(\pull / 8) + b 8b + + .endm + + + backward_copy_shift push=8 pull=24 + +17: backward_copy_shift push=16 pull=16 + +18: backward_copy_shift push=24 pull=8 + + diff --git a/utils/hwstub/stub/memory.h b/utils/hwstub/stub/memory.h new file mode 100644 index 0000000000..206ed8604a --- /dev/null +++ b/utils/hwstub/stub/memory.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_MEMORY__ +#define __HWSTUB_MEMORY__ + +#include "stddef.h" + +void memset(void *dst, int c, size_t n); +void memcpy(void *dst, const void *src, size_t n); +void memmove(void *dst, const void *src, size_t n); + +#endif /* __HWSTUB_MEMORY__ */ \ No newline at end of file diff --git a/utils/hwstub/stub/memset.S b/utils/hwstub/stub/memset.S new file mode 100644 index 0000000000..682da874ce --- /dev/null +++ b/utils/hwstub/stub/memset.S @@ -0,0 +1,98 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Thom Johansen + * + * 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" + + .section .icode,"ax",%progbits + + .align 2 + +/* The following code is based on code found in Linux kernel version 2.6.15.3 + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-2000 Russell King + */ + +/* This code will align a pointer for memset, if needed */ +1: cmp r2, #4 @ 1 do we have enough + blt 5f @ 1 bytes to align with? + cmp r3, #2 @ 1 + strgtb r1, [r0, #-1]! @ 1 + strgeb r1, [r0, #-1]! @ 1 + strb r1, [r0, #-1]! @ 1 + sub r2, r2, r3 @ 1 r2 = r2 - r3 + b 2f + + .global memset + .type memset,%function +memset: + add r0, r0, r2 @ we'll write backwards in memory + ands r3, r0, #3 @ 1 unaligned? + bne 1b @ 1 +2: +/* + * we know that the pointer in r0 is aligned to a word boundary. + */ + orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + mov r3, r1 + cmp r2, #16 + blt 5f +/* + * We need an extra register for this loop - save the return address and + * use the LR + */ + str lr, [sp, #-4]! + mov ip, r1 + mov lr, r1 + +3: subs r2, r2, #64 + stmgedb r0!, {r1, r3, ip, lr} @ 64 bytes at a time. + stmgedb r0!, {r1, r3, ip, lr} + stmgedb r0!, {r1, r3, ip, lr} + stmgedb r0!, {r1, r3, ip, lr} + bgt 3b + ldrpc cond=eq @ Now <64 bytes to go. +/* + * No need to correct the count; we're only testing bits from now on + */ + tst r2, #32 + stmnedb r0!, {r1, r3, ip, lr} + stmnedb r0!, {r1, r3, ip, lr} + tst r2, #16 + stmnedb r0!, {r1, r3, ip, lr} + ldr lr, [sp], #4 + +5: tst r2, #8 + stmnedb r0!, {r1, r3} + tst r2, #4 + strne r1, [r0, #-4]! +/* + * When we get here, we've got less than 4 bytes to zero. We + * may have an unaligned pointer as well. + */ +6: tst r2, #2 + strneb r1, [r0, #-1]! + strneb r1, [r0, #-1]! + tst r2, #1 + strneb r1, [r0, #-1]! + bx lr +.end: + .size memset,.end-memset diff --git a/utils/hwstub/stub/protocol.h b/utils/hwstub/stub/protocol.h new file mode 100644 index 0000000000..35510fa9b2 --- /dev/null +++ b/utils/hwstub/stub/protocol.h @@ -0,0 +1 @@ +#include "../hwstub_protocol.h" diff --git a/utils/hwstub/stub/stddef.h b/utils/hwstub/stub/stddef.h new file mode 100644 index 0000000000..9bfd767750 --- /dev/null +++ b/utils/hwstub/stub/stddef.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_STDDEF__ +#define __HWSTUB_STDDEF__ + +#include "stdint.h" + +typedef uint32_t size_t; +typedef int32_t ssize_t; + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#endif /* __HWSTUB_STDDEF__ */ diff --git a/utils/hwstub/stub/stdint.h b/utils/hwstub/stub/stdint.h new file mode 100644 index 0000000000..393ff3fffd --- /dev/null +++ b/utils/hwstub/stub/stdint.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * __________ __ ___. + * 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. + * + ****************************************************************************/ + +#ifndef __STDINT_H__ +#define __STDINT_H__ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; +typedef uint32_t intptr_t; +typedef char bool; + +#define true 1 +#define false 0 + +#define NULL (void *)0 + +#endif /* __STDINT_H__ */ diff --git a/utils/hwstub/stub/stmp/Makefile b/utils/hwstub/stub/stmp/Makefile new file mode 100644 index 0000000000..14e6d0fbba --- /dev/null +++ b/utils/hwstub/stub/stmp/Makefile @@ -0,0 +1,14 @@ +# +# common +# +CC=arm-elf-eabi-gcc +LD=arm-elf-eabi-gcc +AS=arm-elf-eabi-gcc +OC=arm-elf-eabi-objcopy +DEFINES= +INCLUDES=-I$(CURDIR) +GCCOPTS=-mcpu=arm926ej-s +BUILD_DIR=$(CURDIR)/build/ +ROOT_DIR=$(CURDIR)/.. + +include ../hwstub.make \ No newline at end of file diff --git a/utils/hwstub/stub/stmp/target-config.h b/utils/hwstub/stub/stmp/target-config.h new file mode 100644 index 0000000000..aba2cf564b --- /dev/null +++ b/utils/hwstub/stub/stmp/target-config.h @@ -0,0 +1,9 @@ +#define CONFIG_STMP +#define IRAM_ORIG 0 +#define IRAM_SIZE 0x8000 +#define DRAM_ORIG 0x40000000 +#define DRAM_SIZE (MEMORYSIZE * 0x100000) +#define CPU_ARM +#define ARM_ARCH 5 +#define USB_BASE 0x80080000 +#define USB_NUM_ENDPOINTS 2 \ No newline at end of file diff --git a/utils/hwstub/stub/stmp/target.c b/utils/hwstub/stub/stmp/target.c new file mode 100644 index 0000000000..60411f908e --- /dev/null +++ b/utils/hwstub/stub/stmp/target.c @@ -0,0 +1,205 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "stddef.h" +#include "target.h" +#include "system.h" +#include "logf.h" + +#define __REG_SET(reg) (*((volatile uint32_t *)(® + 1))) +#define __REG_CLR(reg) (*((volatile uint32_t *)(® + 2))) +#define __REG_TOG(reg) (*((volatile uint32_t *)(® + 3))) + +#define __BLOCK_SFTRST (1 << 31) +#define __BLOCK_CLKGATE (1 << 30) + +#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP) +#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP) +#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP) + +/** + * + * Global + * + */ + +enum stmp_family_t +{ + UNKNOWN, + STMP3600, + STMP3700, + STMP3770, + STMP3780 +}; + +enum stmp_family_t g_stmp_family = UNKNOWN; + +/** + * + * Clkctrl + * + */ + +#define HW_CLKCTRL_BASE 0x80040000 + +#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0)) +#define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */ +#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16) +#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18) + +#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10)) +#define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31) + +/* STMP3600 only */ +#define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20)) +#define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0 +#define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff +#define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30) + +/* STMP3600 */ +#define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30)) + +/* STMP3600 only */ +#define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40)) +#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0 +#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff + +/* STMP3600 only */ +#define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70)) +#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30) +#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31) + +/** + * + * Digctl + * + */ + +/* Digital control */ +#define HW_DIGCTL_BASE 0x8001C000 +#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0)) +#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2) + +#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) + +#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310)) +#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16 +#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BM 0xffff0000 +#define HW_DIGCTL_CHIPID__REVISION_BP 0 +#define HW_DIGCTL_CHIPID__REVISION_BM 0xff + +#define HZ 1000000 + +/** + * + * USB PHY + * + */ +/* USB Phy */ +#define HW_USBPHY_BASE 0x8007C000 +#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0)) + +#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30)) + +void target_init(void) +{ + /* detect family */ + uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); + if(product_code >= 0x3600 && product_code < 0x3700) + { + logf("identified STMP3600 family\n"); + g_stmp_family = STMP3600; + } + else if(product_code == 0x3700) + { + logf("identified STMP3700 family\n"); + g_stmp_family = STMP3700; + } + else if(product_code == 0x37b0) + { + logf("identified STMP3770 family\n"); + g_stmp_family = STMP3770; + } + else if(product_code == 0x3780) + { + logf("identified STMP3780 family\n"); + g_stmp_family = STMP3780; + } + else + logf("cannot identify family: 0x%x\n", product_code); + + if(g_stmp_family == STMP3600) + { + /* CPU clock is always derived from PLL, if we switch to PLL, cpu will + * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed + * (1.2MHz) for a safe transition */ + HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400; + /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the + * switch so lower XBUS too */ + HW_CLKCTRL_XBUSCLKCTRL = 20; + /* Power PLL */ + __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; + HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480; + /* Wait lock */ + while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK)); + /* Switch to PLL source */ + __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS; + /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */ + HW_CLKCTRL_CPUCLKCTRL = 7; + HW_CLKCTRL_HBUSCLKCTRL = 7; + HW_CLKCTRL_XBUSCLKCTRL = 1; + __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE; + __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE; + } + else + __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; + /* enable USB PHY PLL */ + __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; + /* power up USB PHY */ + __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; + HW_USBPHY_PWD = 0; + /* enable USB controller */ + __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; +} + +static struct usb_resp_info_stmp_t g_stmp; +static struct usb_resp_info_target_t g_target = +{ + .id = HWSTUB_TARGET_STMP, + .name = "STMP3600 / STMP3700 / STMP3780 (i.MX233)" +}; + +int target_get_info(int info, void **buffer) +{ + if(info == HWSTUB_INFO_STMP) + { + g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); + g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION); + g_stmp.is_supported = g_stmp_family != 0; + *buffer = &g_stmp; + return sizeof(g_stmp); + } + else + return -1; +} + +void target_exit(void) +{ +} diff --git a/utils/hwstub/stub/string.c b/utils/hwstub/stub/string.c new file mode 100644 index 0000000000..1f8c415a99 --- /dev/null +++ b/utils/hwstub/stub/string.c @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "string.h" + +size_t strlen(const char *s) +{ + size_t len = 0; + while(*s++) + len++; + return len; +} diff --git a/utils/hwstub/stub/string.h b/utils/hwstub/stub/string.h new file mode 100644 index 0000000000..ae352fe50e --- /dev/null +++ b/utils/hwstub/stub/string.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_STRING__ +#define __HWSTUB_STRING__ + +#include "stddef.h" + +size_t strlen(const char *s); + +#endif /* __HWSTUB_STRING__ */ diff --git a/utils/hwstub/stub/system.h b/utils/hwstub/stub/system.h new file mode 100644 index 0000000000..e5aea12051 --- /dev/null +++ b/utils/hwstub/stub/system.h @@ -0,0 +1,118 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __HWSTUB_SYSTEM__ +#define __HWSTUB_SYSTEM__ + +#define IRQ_ENABLED 0x00 +#define IRQ_DISABLED 0x80 +#define IRQ_STATUS 0x80 +#define FIQ_ENABLED 0x00 +#define FIQ_DISABLED 0x40 +#define FIQ_STATUS 0x40 +#define IRQ_FIQ_ENABLED 0x00 +#define IRQ_FIQ_DISABLED 0xc0 +#define IRQ_FIQ_STATUS 0xc0 +#define HIGHEST_IRQ_LEVEL IRQ_DISABLED + +#define set_irq_level(status) \ + set_interrupt_status((status), IRQ_STATUS) +#define set_fiq_status(status) \ + set_interrupt_status((status), FIQ_STATUS) + +#define disable_irq_save() \ + disable_interrupt_save(IRQ_STATUS) +#define disable_fiq_save() \ + disable_interrupt_save(FIQ_STATUS) + +#define restore_irq(cpsr) \ + restore_interrupt(cpsr) +#define restore_fiq(cpsr) \ + restore_interrupt(cpsr) + +#define disable_irq() \ + disable_interrupt(IRQ_STATUS) +#define enable_irq() \ + enable_interrupt(IRQ_STATUS) +#define disable_fiq() \ + disable_interrupt(FIQ_STATUS) +#define enable_fiq() \ + enable_interrupt(FIQ_STATUS) + +static inline int set_interrupt_status(int status, int mask) +{ + unsigned long cpsr; + int oldstatus; + /* Read the old levels and set the new ones */ + asm volatile ( + "mrs %1, cpsr \n" + "bic %0, %1, %[mask] \n" + "orr %0, %0, %2 \n" + "msr cpsr_c, %0 \n" + : "=&r,r"(cpsr), "=&r,r"(oldstatus) + : "r,i"(status & mask), [mask]"i,i"(mask)); + + return oldstatus; +} + +static inline void restore_interrupt(int cpsr) +{ + /* Set cpsr_c from value returned by disable_interrupt_save + * or set_interrupt_status */ + asm volatile ("msr cpsr_c, %0" : : "r"(cpsr)); +} + +static inline void enable_interrupt(int mask) +{ + /* Clear I and/or F disable bit */ + int tmp; + asm volatile ( + "mrs %0, cpsr \n" + "bic %0, %0, %1 \n" + "msr cpsr_c, %0 \n" + : "=&r"(tmp) : "i"(mask)); +} + +static inline void disable_interrupt(int mask) +{ + /* Set I and/or F disable bit */ + int tmp; + asm volatile ( + "mrs %0, cpsr \n" + "orr %0, %0, %1 \n" + "msr cpsr_c, %0 \n" + : "=&r"(tmp) : "i"(mask)); +} + +static inline int disable_interrupt_save(int mask) +{ + /* Set I and/or F disable bit and return old cpsr value */ + int cpsr, tmp; + asm volatile ( + "mrs %1, cpsr \n" + "orr %0, %1, %2 \n" + "msr cpsr_c, %0 \n" + : "=&r"(tmp), "=&r"(cpsr) + : "i"(mask)); + return cpsr; +} + +#endif /* __HWSTUB_SYSTEM__ */ + diff --git a/utils/hwstub/stub/target.h b/utils/hwstub/stub/target.h new file mode 100644 index 0000000000..3f1551c72d --- /dev/null +++ b/utils/hwstub/stub/target.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2013 by Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __TARGET_H__ +#define __TARGET_H__ + +#include "protocol.h" + +void target_init(void); +void target_exit(void); +/* return actual size or -1 if error */ +int target_get_info(int info, void **buffer); + +#endif /* __TARGET_H__ */ diff --git a/utils/hwstub/stub/usb_ch9.h b/utils/hwstub/stub/usb_ch9.h new file mode 100644 index 0000000000..09141b93bd --- /dev/null +++ b/utils/hwstub/stub/usb_ch9.h @@ -0,0 +1,454 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) by Linux Kernel Developers + * + * Based on code from the Linux Kernel + * available at http://www.kernel.org + * Original file: /include/linux/usb/ch9.h + * + * 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. + * + ****************************************************************************/ + +/* + * This file holds USB constants and structures that are needed for + * USB device APIs. These are used by the USB device model, which is + * defined in chapter 9 of the USB 2.0 specification and in the + * Wireless USB 1.0 (spread around). Linux has several APIs in C that + * need these: + * + * - the master/host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - the Linux "gadget" slave/device/peripheral side driver API. + * + * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems + * act either as a USB master/host or as a USB slave/device. That means + * the master and slave side APIs benefit from working well together. + * + * There's also "Wireless USB", using low power short range radios for + * peripheral interconnection but otherwise building on the USB framework. + * + * Note all descriptors are declared '__attribute__((packed))' so that: + * + * [a] they never get padded, either internally (USB spec writers + * probably handled that) or externally; + * + * [b] so that accessing bigger-than-a-bytes fields will never + * generate bus errors on any platform, even when the location of + * its descriptor inside a bundle isn't "naturally aligned", and + * + * [c] for consistency, removing all doubt even when it appears to + * someone that the two other points are non-issues for that + * particular descriptor type. + */ + +#ifndef _CH9_H_ +#define _CH9_H_ + +#include "stdint.h" + +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C +/* + * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and + * are read as a bit array returned by USB_REQ_GET_STATUS. (So there + * are at most sixteen features of each type.) Hubs may also support a + * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. + */ +#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ +#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ +#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ +#define USB_DEVICE_BATTERY 2 /* (wireless) */ +#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ +#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ +#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ +#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ +#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ + +#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + + +/** + * struct usb_ctrlrequest - SETUP data for a USB device control request + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (le16 byte order) + * @wIndex: matches the USB wIndex field (le16 byte order) + * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. + */ +struct usb_ctrlrequest { + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or + * (rarely) accepted by SET_DESCRIPTOR. + * + * Note that all multi-byte values here are encoded in little endian + * byte order "on the wire". But when exposed through Linux-USB APIs, + * they've been converted to cpu byte order. + */ + +/* + * Descriptor types ... USB 2.0 spec table 9.5 + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 +/* these are from a minor usb 2.0 revision (ECN) */ +#define USB_DT_OTG 0x09 +#define USB_DT_DEBUG 0x0a +#define USB_DT_INTERFACE_ASSOCIATION 0x0b +/* these are from the Wireless USB spec */ +#define USB_DT_SECURITY 0x0c +#define USB_DT_KEY 0x0d +#define USB_DT_ENCRYPTION_TYPE 0x0e +#define USB_DT_BOS 0x0f +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_DT_WIRE_ADAPTER 0x21 +#define USB_DT_RPIPE 0x22 +#define USB_DT_CS_RADIO_CONTROL 0x23 + +/* Conventional codes for class-specific descriptors. The convention is + * defined in the USB "Common Class" Spec (3.11). Individual class specs + * are authoritative for their usage, not the "common class" writeup. + */ +#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) +#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) +#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) +#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) +#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) + +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + uint8_t bLength; + uint8_t bDescriptorType; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE: Device descriptor */ +struct usb_device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} __attribute__ ((packed)); + +#define USB_DT_DEVICE_SIZE 18 + + +/* + * Device and/or Interface Class codes + * as found in bDeviceClass or bInterfaceClass + * and defined by www.usb.org documents + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG + * descriptors. + */ +struct usb_config_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} __attribute__ ((packed)); + +#define USB_DT_CONFIG_SIZE 9 + +/* from config descriptor bmAttributes */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ +#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_STRING: String descriptor */ +struct usb_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t wString[]; /* UTF-16LE encoded */ +} __attribute__ ((packed)); + +/* note that "string" zero is special, it holds language codes that + * the device supports, not Unicode characters. + */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE: Interface descriptor */ +struct usb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} __attribute__ ((packed)); + +#define USB_DT_INTERFACE_SIZE 9 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +struct usb_endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} __attribute__ ((packed)); + +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_qualifier_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bRESERVED; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_OTG (from OTG 1.0a supplement) */ +struct usb_otg_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + uint8_t bmAttributes; /* support for HNP, SRP, etc */ +} __attribute__ ((packed)); + +/* from usb_otg_descriptor.bmAttributes */ +#define USB_OTG_SRP (1 << 0) +#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ +struct usb_debug_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + + /* bulk endpoints with 8 byte maxpacket */ + uint8_t bDebugInEndpoint; + uint8_t bDebugOutEndpoint; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ +/* USB 2.0 defines three speeds, here's how Linux identifies them */ + +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ +}; + +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* chapter 9 and authentication (wireless) device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, /* wired */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_RECONNECTING, /* auth */ + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + * At this level there's no difference between L1 and L2 + * suspend states. (L2 being original USB 1.1 suspend.) + */ +}; + +/** + * struct usb_string - wraps a C string and its USB id + * @id:the (nonzero) ID for this string + * @s:the string, in UTF-8 encoding + * + * If you're using usb_gadget_get_string(), use this to wrap a string + * together with its ID. + */ +struct usb_string { + uint8_t id; + const char* s; +}; + +/** + * struct usb_gadget_strings - a set of USB strings in a given language + * @language:identifies the strings' language (0x0409 for en-us) + * @strings:array of strings with their ids + * + * If you're using usb_gadget_get_string(), use this to wrap all the + * strings for a given language. + */ +struct usb_gadget_strings { + uint16_t language; /* 0x0409 for en-us */ + struct usb_string* strings; +}; + +#endif /*_CH9_H_*/ diff --git a/utils/hwstub/stub/usb_drv.h b/utils/hwstub/stub/usb_drv.h new file mode 100644 index 0000000000..00f22d8e1a --- /dev/null +++ b/utils/hwstub/stub/usb_drv.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by Björn Stenberg + * + * 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. + * + ****************************************************************************/ +#ifndef _USB_DRV_H +#define _USB_DRV_H + +#include "usb_ch9.h" + +#define EP_CONTROL 0 + +#define DIR_OUT 0 +#define DIR_IN 1 + +#define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT) +#define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK) + +void usb_drv_init(void); +void usb_drv_exit(void); +void usb_drv_stall(int endpoint, bool stall,bool in); +int usb_drv_send(int endpoint, void* ptr, int length); +int usb_drv_send_nonblocking(int endpoint, void* ptr, int length); +int usb_drv_recv(int endpoint, void* ptr, int length);// blocking ! +int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length); +int usb_drv_recv_setup(struct usb_ctrlrequest *req); +void usb_drv_set_address(int address); +int usb_drv_port_speed(void); +void usb_drv_configure_endpoint(int ep_num, int type); + +#endif /* _USB_DRV_H */ + diff --git a/utils/hwstub/stub/usb_drv_arc.c b/utils/hwstub/stub/usb_drv_arc.c new file mode 100644 index 0000000000..32275b6adb --- /dev/null +++ b/utils/hwstub/stub/usb_drv_arc.c @@ -0,0 +1,364 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Driver for ARC USBOTG Device Controller + * + * Copyright (C) 2007 by Björn Stenberg + * + * 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 "usb_drv.h" +#include "config.h" +#include "memory.h" + +#define MAX_PKT_SIZE 1024 +#define MAX_PKT_SIZE_EP0 64 + +/* USB device mode registers (Little Endian) */ +#define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140)) +#define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154)) +#define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158)) +#define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184)) +#define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8)) +#define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac)) +#define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0)) +#define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8)) +#define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc)) +#define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0)) +#define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4)) +#define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8)) +#define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_))) + +/* USB CMD Register Bit Masks */ +#define USBCMD_RUN (0x00000001) +#define USBCMD_CTRL_RESET (0x00000002) +#define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010) +#define USBCMD_ASYNC_SCHEDULE_EN (0x00000020) +#define USBCMD_INT_AA_DOORBELL (0x00000040) +#define USBCMD_ASP (0x00000300) +#define USBCMD_ASYNC_SCH_PARK_EN (0x00000800) +#define USBCMD_SUTW (0x00002000) +#define USBCMD_ATDTW (0x00004000) +#define USBCMD_ITC (0x00FF0000) + +/* Device Address bit masks */ +#define USBDEVICEADDRESS_MASK (0xFE000000) +#define USBDEVICEADDRESS_BIT_POS (25) + +/* Endpoint Setup Status bit masks */ +#define EPSETUP_STATUS_EP0 (0x00000001) + +/* PORTSCX Register Bit Masks */ +#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001) +#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002) +#define PORTSCX_PORT_ENABLE (0x00000004) +#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008) +#define PORTSCX_OVER_CURRENT_ACT (0x00000010) +#define PORTSCX_OVER_CURRENT_CHG (0x00000020) +#define PORTSCX_PORT_FORCE_RESUME (0x00000040) +#define PORTSCX_PORT_SUSPEND (0x00000080) +#define PORTSCX_PORT_RESET (0x00000100) +#define PORTSCX_LINE_STATUS_BITS (0x00000C00) +#define PORTSCX_PORT_POWER (0x00001000) +#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000) +#define PORTSCX_PORT_TEST_CTRL (0x000F0000) +#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000) +#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000) +#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000) +#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000) +#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000) +#define PORTSCX_PORT_SPEED_MASK (0x0C000000) +#define PORTSCX_PORT_WIDTH (0x10000000) +#define PORTSCX_PHY_TYPE_SEL (0xC0000000) + +/* bit 11-10 are line status */ +#define PORTSCX_LINE_STATUS_SE0 (0x00000000) +#define PORTSCX_LINE_STATUS_JSTATE (0x00000400) +#define PORTSCX_LINE_STATUS_KSTATE (0x00000800) +#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00) +#define PORTSCX_LINE_STATUS_BIT_POS (10) + +/* bit 15-14 are port indicator control */ +#define PORTSCX_PIC_OFF (0x00000000) +#define PORTSCX_PIC_AMBER (0x00004000) +#define PORTSCX_PIC_GREEN (0x00008000) +#define PORTSCX_PIC_UNDEF (0x0000C000) +#define PORTSCX_PIC_BIT_POS (14) + +/* bit 19-16 are port test control */ +#define PORTSCX_PTC_DISABLE (0x00000000) +#define PORTSCX_PTC_JSTATE (0x00010000) +#define PORTSCX_PTC_KSTATE (0x00020000) +#define PORTSCX_PTC_SE0NAK (0x00030000) +#define PORTSCX_PTC_PACKET (0x00040000) +#define PORTSCX_PTC_FORCE_EN (0x00050000) +#define PORTSCX_PTC_BIT_POS (16) + +/* bit 27-26 are port speed */ +#define PORTSCX_PORT_SPEED_FULL (0x00000000) +#define PORTSCX_PORT_SPEED_LOW (0x04000000) +#define PORTSCX_PORT_SPEED_HIGH (0x08000000) +#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000) +#define PORTSCX_SPEED_BIT_POS (26) + +/* bit 28 is parallel transceiver width for UTMI interface */ +#define PORTSCX_PTW (0x10000000) +#define PORTSCX_PTW_8BIT (0x00000000) +#define PORTSCX_PTW_16BIT (0x10000000) + +/* bit 31-30 are port transceiver select */ +#define PORTSCX_PTS_UTMI (0x00000000) +#define PORTSCX_PTS_CLASSIC (0x40000000) +#define PORTSCX_PTS_ULPI (0x80000000) +#define PORTSCX_PTS_FSLS (0xC0000000) +#define PORTSCX_PTS_BIT_POS (30) + +/* USB MODE Register Bit Masks */ +#define USBMODE_CTRL_MODE_IDLE (0x00000000) +#define USBMODE_CTRL_MODE_DEVICE (0x00000002) +#define USBMODE_CTRL_MODE_HOST (0x00000003) +#define USBMODE_CTRL_MODE_RSV (0x00000001) +#define USBMODE_SETUP_LOCK_OFF (0x00000008) +#define USBMODE_STREAM_DISABLE (0x00000010) + +/* ENDPOINTCTRLx Register Bit Masks */ +#define EPCTRL_TX_ENABLE (0x00800000) +#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */ +#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */ +#define EPCTRL_TX_TYPE (0x000C0000) +#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */ +#define EPCTRL_TX_EP_STALL (0x00010000) +#define EPCTRL_RX_ENABLE (0x00000080) +#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */ +#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */ +#define EPCTRL_RX_TYPE (0x0000000C) +#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */ +#define EPCTRL_RX_EP_STALL (0x00000001) + +/* bit 19-18 and 3-2 are endpoint type */ +#define EPCTRL_TX_EP_TYPE_SHIFT (18) +#define EPCTRL_RX_EP_TYPE_SHIFT (2) + +#define QH_MULT_POS (30) +#define QH_ZLT_SEL (0x20000000) +#define QH_MAX_PKT_LEN_POS (16) +#define QH_IOS (0x00008000) +#define QH_NEXT_TERMINATE (0x00000001) +#define QH_IOC (0x00008000) +#define QH_MULTO (0x00000C00) +#define QH_STATUS_HALT (0x00000040) +#define QH_STATUS_ACTIVE (0x00000080) +#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF) +#define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0) +#define EP_QUEUE_FRINDEX_MASK (0x000007FF) +#define EP_MAX_LENGTH_TRANSFER (0x4000) + +#define DTD_NEXT_TERMINATE (0x00000001) +#define DTD_IOC (0x00008000) +#define DTD_STATUS_ACTIVE (0x00000080) +#define DTD_STATUS_HALTED (0x00000040) +#define DTD_STATUS_DATA_BUFF_ERR (0x00000020) +#define DTD_STATUS_TRANSACTION_ERR (0x00000008) +#define DTD_RESERVED_FIELDS (0x80007300) +#define DTD_ADDR_MASK (0xFFFFFFE0) +#define DTD_PACKET_SIZE (0x7FFF0000) +#define DTD_LENGTH_BIT_POS (16) +#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \ + DTD_STATUS_DATA_BUFF_ERR | \ + DTD_STATUS_TRANSACTION_ERR) +/*-------------------------------------------------------------------------*/ +/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */ +struct transfer_descriptor { + unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set + indicate invalid */ + unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15), + MultO(11-10), STS (7-0) */ + unsigned int buff_ptr0; /* Buffer pointer Page 0 */ + unsigned int buff_ptr1; /* Buffer pointer Page 1 */ + unsigned int buff_ptr2; /* Buffer pointer Page 2 */ + unsigned int buff_ptr3; /* Buffer pointer Page 3 */ + unsigned int buff_ptr4; /* Buffer pointer Page 4 */ + unsigned int reserved; +} __attribute__ ((packed)); + +static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2] + __attribute__((aligned(32))); + +/* manual: 32.13.1 Endpoint Queue Head (dQH) */ +struct queue_head { + unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len + and IOS(15) */ + unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */ + struct transfer_descriptor dtd; /* dTD overlay */ + unsigned int setup_buffer[2]; /* Setup data 8 bytes */ + unsigned int reserved; /* for software use, pointer to the first TD */ + unsigned int status; /* for software use, status of chain in progress */ + unsigned int length; /* for software use, transfered bytes of chain in progress */ + unsigned int wait; /* for softwate use, indicates if the transfer is blocking */ +} __attribute__((packed)); + +static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] __attribute__((aligned(2048))); + +static const unsigned int pipe2mask[] = { + 0x01, 0x010000, + 0x02, 0x020000, + 0x04, 0x040000, + 0x08, 0x080000, + 0x10, 0x100000, +}; + +/* return transfered size if wait=true */ +static int prime_transfer(int ep_num, void *ptr, int len, bool send, bool wait) +{ + int pipe = ep_num * 2 + (send ? 1 : 0); + unsigned mask = pipe2mask[pipe]; + struct transfer_descriptor *td = &td_array[pipe]; + struct queue_head* qh = &qh_array[pipe]; + + /* prepare TD */ + td->next_td_ptr = DTD_NEXT_TERMINATE; + td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE; + td->buff_ptr0 = (unsigned int)ptr; + td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000; + td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000; + td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000; + td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000; + td->reserved = 0; + /* prime */ + qh->dtd.next_td_ptr = (unsigned int)td; + qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); + REG_ENDPTPRIME |= mask; + /* wait for priming to be taken into account */ + while(!(REG_ENDPTSTATUS & mask)); + /* wait for completion */ + if(wait) + { + while(!(REG_ENDPTCOMPLETE & mask)); + REG_ENDPTCOMPLETE = mask; + /* memory barrier */ + asm volatile("":::"memory"); + /* return transfered size */ + return len - (td->size_ioc_sts >> DTD_LENGTH_BIT_POS); + } + else + return 0; +} + +void usb_drv_set_address(int address) +{ + REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS; +} + +/* endpoints */ + +int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) +{ + return prime_transfer(EP_NUM(endpoint), ptr, length, true, false); +} + +int usb_drv_send(int endpoint, void* ptr, int length) +{ + return prime_transfer(EP_NUM(endpoint), ptr, length, true, true); +} + +int usb_drv_recv(int endpoint, void* ptr, int length) +{ + return prime_transfer(EP_NUM(endpoint), ptr, length, false, true); +} + +int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length) +{ + return prime_transfer(EP_NUM(endpoint), ptr, length, false, false); +} + +int usb_drv_port_speed(void) +{ + return (REG_PORTSC1 & 0x08000000) ? 1 : 0; +} + +void usb_drv_stall(int endpoint, bool stall, bool in) +{ + int ep_num = EP_NUM(endpoint); + + if(in) + { + if(stall) + REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL; + else + REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL; + } + else + { + if (stall) + REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL; + else + REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL; + } +} + +void usb_drv_configure_endpoint(int ep_num, int type) +{ + REG_ENDPTCTRL(ep_num) = + EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | + EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | + (type << EPCTRL_RX_EP_TYPE_SHIFT) | + (type << EPCTRL_TX_EP_TYPE_SHIFT); +} + +void usb_drv_init(void) +{ + /* we don't know if USB was connected or not. In USB recovery mode it will + * but in other cases it might not be. In doubt, disconnect */ + REG_USBCMD &= ~USBCMD_RUN; + /* reset the controller */ + REG_USBCMD |= USBCMD_CTRL_RESET; + while (REG_USBCMD & USBCMD_CTRL_RESET); + /* put it in device mode */ + REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; + /* reset address */ + REG_DEVICEADDR = 0; + /* prepare qh array */ + qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16; + qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16; + qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16; + qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16; + /* setup qh */ + REG_ENDPOINTLISTADDR = (unsigned int)qh_array; + /* clear setup status */ + REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0; + /* run! */ + REG_USBCMD |= USBCMD_RUN; +} + +void usb_drv_exit(void) +{ + REG_USBCMD &= ~USBCMD_RUN; + REG_USBCMD |= USBCMD_CTRL_RESET; +} + +int usb_drv_recv_setup(struct usb_ctrlrequest *req) +{ + /* wait for setup */ + while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) + ; + /* clear setup status */ + REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0; + /* check request */ + asm volatile("":::"memory"); + /* copy */ + memcpy(req, (void *)&qh_array[0].setup_buffer[0], sizeof(struct usb_ctrlrequest)); + return 0; +} -- cgit v1.2.3