diff options
Diffstat (limited to 'utils/hwstub/stub')
26 files changed, 2416 insertions, 0 deletions
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 @@ | |||
1 | main.c | ||
2 | crt0.S | ||
3 | logf.c | ||
4 | memcpy.S | ||
5 | memmove.S | ||
6 | memset.S | ||
7 | string.c | ||
8 | format.c | ||
9 | #ifdef CONFIG_STMP | ||
10 | usb_drv_arc.c | ||
11 | stmp/target.c | ||
12 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_CONFIG__ | ||
22 | #define __HWSTUB_CONFIG__ | ||
23 | |||
24 | #include "target-config.h" | ||
25 | |||
26 | #define STACK_SIZE 0x1000 | ||
27 | #define MAX_LOGF_SIZE 128 | ||
28 | |||
29 | #if defined(CPU_ARM) && defined(__ASSEMBLER__) | ||
30 | /* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */ | ||
31 | .macro ldmpc cond="", order="ia", regs | ||
32 | #if ARM_ARCH == 4 && defined(USE_THUMB) | ||
33 | ldm\cond\order sp!, { \regs, lr } | ||
34 | bx\cond lr | ||
35 | #else | ||
36 | ldm\cond\order sp!, { \regs, pc } | ||
37 | #endif | ||
38 | .endm | ||
39 | .macro ldrpc cond="" | ||
40 | #if ARM_ARCH == 4 && defined(USE_THUMB) | ||
41 | ldr\cond lr, [sp], #4 | ||
42 | bx\cond lr | ||
43 | #else | ||
44 | ldr\cond pc, [sp], #4 | ||
45 | #endif | ||
46 | .endm | ||
47 | #endif | ||
48 | |||
49 | #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 @@ | |||
1 | .section .text,"ax",%progbits | ||
2 | .code 32 | ||
3 | .align 0x04 | ||
4 | .global start | ||
5 | start: | ||
6 | msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ | ||
7 | ldr sp, =oc_stackend | ||
8 | /* clear bss */ | ||
9 | ldr r2, =bss_start | ||
10 | ldr r3, =bss_end | ||
11 | mov r4, #0 | ||
12 | 1: | ||
13 | cmp r3, r2 | ||
14 | strhi r4, [r2], #4 | ||
15 | bhi 1b | ||
16 | /* jump to C code */ | ||
17 | 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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Gary Czvitkovicz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #include <stdarg.h> | ||
24 | #include <limits.h> | ||
25 | #include "stddef.h" | ||
26 | #include "string.h" | ||
27 | #include "format.h" | ||
28 | |||
29 | static const char hexdigit[] = "0123456789ABCDEF"; | ||
30 | |||
31 | void vuprintf( | ||
32 | /* call 'push()' for each output letter */ | ||
33 | int (*push)(void *userp, unsigned char data), | ||
34 | void *userp, | ||
35 | const char *fmt, | ||
36 | va_list ap) | ||
37 | { | ||
38 | char *str; | ||
39 | char tmpbuf[12], pad; | ||
40 | int ch, width, val, sign, precision; | ||
41 | long lval, lsign; | ||
42 | unsigned int uval; | ||
43 | unsigned long ulval; | ||
44 | size_t uszval; | ||
45 | ssize_t szval, szsign; | ||
46 | bool ok = true; | ||
47 | |||
48 | tmpbuf[sizeof tmpbuf - 1] = '\0'; | ||
49 | |||
50 | while ((ch = *fmt++) != '\0' && ok) | ||
51 | { | ||
52 | if (ch == '%') | ||
53 | { | ||
54 | ch = *fmt++; | ||
55 | pad = ' '; | ||
56 | if (ch == '0') | ||
57 | pad = '0'; | ||
58 | |||
59 | width = 0; | ||
60 | while (ch >= '0' && ch <= '9') | ||
61 | { | ||
62 | width = 10*width + ch - '0'; | ||
63 | ch = *fmt++; | ||
64 | } | ||
65 | |||
66 | precision = 0; | ||
67 | if(ch == '.') | ||
68 | { | ||
69 | ch = *fmt++; | ||
70 | while (ch >= '0' && ch <= '9') | ||
71 | { | ||
72 | precision = 10*precision + ch - '0'; | ||
73 | ch = *fmt++; | ||
74 | } | ||
75 | } else { | ||
76 | precision = INT_MAX; | ||
77 | } | ||
78 | |||
79 | str = tmpbuf + sizeof tmpbuf - 1; | ||
80 | switch (ch) | ||
81 | { | ||
82 | case 'c': | ||
83 | *--str = va_arg (ap, int); | ||
84 | break; | ||
85 | |||
86 | case 's': | ||
87 | str = va_arg (ap, char*); | ||
88 | break; | ||
89 | |||
90 | case 'd': | ||
91 | val = sign = va_arg (ap, int); | ||
92 | if (val < 0) | ||
93 | val = -val; | ||
94 | do | ||
95 | { | ||
96 | *--str = (val % 10) + '0'; | ||
97 | val /= 10; | ||
98 | } | ||
99 | while (val > 0); | ||
100 | if (sign < 0) | ||
101 | *--str = '-'; | ||
102 | break; | ||
103 | |||
104 | case 'u': | ||
105 | uval = va_arg(ap, unsigned int); | ||
106 | do | ||
107 | { | ||
108 | *--str = (uval % 10) + '0'; | ||
109 | uval /= 10; | ||
110 | } | ||
111 | while (uval > 0); | ||
112 | break; | ||
113 | |||
114 | case 'x': | ||
115 | case 'X': | ||
116 | pad='0'; | ||
117 | uval = va_arg (ap, int); | ||
118 | do | ||
119 | { | ||
120 | *--str = hexdigit[uval & 0xf]; | ||
121 | uval >>= 4; | ||
122 | } | ||
123 | while (uval); | ||
124 | break; | ||
125 | |||
126 | case 'l': | ||
127 | ch = *fmt++; | ||
128 | switch(ch) { | ||
129 | case 'x': | ||
130 | case 'X': | ||
131 | pad='0'; | ||
132 | ulval = va_arg (ap, long); | ||
133 | do | ||
134 | { | ||
135 | *--str = hexdigit[ulval & 0xf]; | ||
136 | ulval >>= 4; | ||
137 | } | ||
138 | while (ulval); | ||
139 | break; | ||
140 | case 'd': | ||
141 | lval = lsign = va_arg (ap, long); | ||
142 | if (lval < 0) | ||
143 | lval = -lval; | ||
144 | do | ||
145 | { | ||
146 | *--str = (lval % 10) + '0'; | ||
147 | lval /= 10; | ||
148 | } | ||
149 | while (lval > 0); | ||
150 | if (lsign < 0) | ||
151 | *--str = '-'; | ||
152 | break; | ||
153 | |||
154 | case 'u': | ||
155 | ulval = va_arg(ap, unsigned long); | ||
156 | do | ||
157 | { | ||
158 | *--str = (ulval % 10) + '0'; | ||
159 | ulval /= 10; | ||
160 | } | ||
161 | while (ulval > 0); | ||
162 | break; | ||
163 | |||
164 | default: | ||
165 | *--str = 'l'; | ||
166 | *--str = ch; | ||
167 | } | ||
168 | |||
169 | break; | ||
170 | |||
171 | case 'z': | ||
172 | ch = *fmt++; | ||
173 | switch(ch) { | ||
174 | case 'd': | ||
175 | szval = szsign = va_arg (ap, ssize_t); | ||
176 | if (szval < 0) | ||
177 | szval = -szval; | ||
178 | do | ||
179 | { | ||
180 | *--str = (szval % 10) + '0'; | ||
181 | szval /= 10; | ||
182 | } | ||
183 | while (szval > 0); | ||
184 | if (szsign < 0) | ||
185 | *--str = '-'; | ||
186 | break; | ||
187 | |||
188 | case 'u': | ||
189 | uszval = va_arg(ap, size_t); | ||
190 | do | ||
191 | { | ||
192 | *--str = (uszval % 10) + '0'; | ||
193 | uszval /= 10; | ||
194 | } | ||
195 | while (uszval > 0); | ||
196 | break; | ||
197 | |||
198 | default: | ||
199 | *--str = 'z'; | ||
200 | *--str = ch; | ||
201 | } | ||
202 | |||
203 | break; | ||
204 | |||
205 | default: | ||
206 | *--str = ch; | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | if (width > 0) | ||
211 | { | ||
212 | width -= strlen (str); | ||
213 | while (width-- > 0 && ok) | ||
214 | ok=push(userp, pad); | ||
215 | } | ||
216 | while (*str != '\0' && ok && precision--) | ||
217 | ok=push(userp, *str++); | ||
218 | } | ||
219 | else | ||
220 | ok=push(userp, ch); | ||
221 | } | ||
222 | } | ||
223 | |||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_FORMAT__ | ||
22 | #define __HWSTUB_FORMAT__ | ||
23 | |||
24 | #include <stdarg.h> | ||
25 | |||
26 | void vuprintf(int (*push)(void *userp, unsigned char data), | ||
27 | void *userp, const char *fmt, va_list ap); | ||
28 | |||
29 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | |||
23 | ENTRY(start) | ||
24 | OUTPUT_FORMAT(elf32-littlearm) | ||
25 | OUTPUT_ARCH(arm) | ||
26 | STARTUP(crt0.o) | ||
27 | |||
28 | #define IRAM_END_ADDR (IRAM_ORIG + IRAM_SIZE) | ||
29 | |||
30 | MEMORY | ||
31 | { | ||
32 | OCRAM : ORIGIN = IRAM_ORIG, LENGTH = IRAM_SIZE | ||
33 | } | ||
34 | |||
35 | SECTIONS | ||
36 | { | ||
37 | .octext : | ||
38 | { | ||
39 | oc_codestart = .; | ||
40 | *(.text*) | ||
41 | *(.icode*) | ||
42 | *(.data*) | ||
43 | *(.rodata*) | ||
44 | } > OCRAM | ||
45 | |||
46 | .bss (NOLOAD) : | ||
47 | { | ||
48 | bss_start = .; | ||
49 | *(.bss) | ||
50 | bss_end = .; | ||
51 | } > OCRAM | ||
52 | |||
53 | .stack (NOLOAD) : | ||
54 | { | ||
55 | oc_codeend = .; | ||
56 | oc_stackstart = .; | ||
57 | . += STACK_SIZE; | ||
58 | oc_stackend = .; | ||
59 | oc_bufferstart = .; | ||
60 | } > OCRAM | ||
61 | |||
62 | .ocend IRAM_END_ADDR (NOLOAD) : | ||
63 | { | ||
64 | oc_bufferend = .; | ||
65 | } > OCRAM | ||
66 | |||
67 | /DISCARD/ : | ||
68 | { | ||
69 | *(.eh_frame) | ||
70 | } | ||
71 | } | ||
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 @@ | |||
1 | INCLUDES+=-I$(ROOT_DIR) | ||
2 | LINKER_FILE=$(ROOT_DIR)/hwstub.lds | ||
3 | TMP_LDS=$(BUILD_DIR)/link.lds | ||
4 | TMP_MAP=$(BUILD_DIR)/hwstub.map | ||
5 | CFLAGS=$(GCCOPTS) $(DEFINES) -W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init $(INCLUDES) | ||
6 | ASFLAGS=$(CFLAGS) -D__ASSEMBLER__ | ||
7 | LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP) $(INCLUDES) -L$(BUILD_DIR) | ||
8 | |||
9 | SRC:=$(shell cat $(ROOT_DIR)/SOURCES | $(CC) $(INCLUDES) \ | ||
10 | $(DEFINES) -E -P -include "config.h" - 2>/dev/null \ | ||
11 | | grep -v "^\#") | ||
12 | SRC:=$(foreach src,$(SRC),$(BUILD_DIR)/$(src)) | ||
13 | OBJ=$(SRC:.c=.o) | ||
14 | OBJ:=$(OBJ:.S=.o) | ||
15 | OBJ_EXCEPT_CRT0=$(filter-out $(BUILD_DIR)/crt0.o,$(OBJ)) | ||
16 | EXEC_ELF=$(BUILD_DIR)/hwstub.elf | ||
17 | DEPS=$(foreach obj,$(OBJ),$(obj).d) | ||
18 | |||
19 | EXEC=$(EXEC_ELF) | ||
20 | |||
21 | SILENT?=@ | ||
22 | PRINTS=$(SILENT)$(call info,$(1)) | ||
23 | |||
24 | all: $(EXEC) | ||
25 | |||
26 | # pull in dependency info for *existing* .o files | ||
27 | -include $(DEPS) | ||
28 | |||
29 | $(BUILD_DIR)/%.o: $(ROOT_DIR)/%.c | ||
30 | $(SILENT)mkdir -p $(dir $@) | ||
31 | $(call PRINTS,CC $(<F)) | ||
32 | $(SILENT)$(CC) $(CFLAGS) -c -o $@ $< | ||
33 | $(SILENT)$(CC) -MM $(CFLAGS) $< -MT $@ > $@.d | ||
34 | |||
35 | $(BUILD_DIR)/%.o: $(ROOT_DIR)/%.S | ||
36 | $(call PRINTS,AS $(<F)) | ||
37 | $(SILENT)mkdir -p $(dir $@) | ||
38 | $(SILENT)$(AS) $(ASFLAGS) -c -o $@ $< | ||
39 | |||
40 | $(TMP_LDS): $(LINKER_FILE) | ||
41 | $(call PRINTS,PP $(<F)) | ||
42 | $(SILENT)$(CC) $(CFLAGS) -E -x c - < $< | sed '/#/d' > $@ | ||
43 | |||
44 | $(EXEC_ELF): $(OBJ) $(TMP_LDS) | ||
45 | $(call PRINTS,LD $(@F)) | ||
46 | $(SILENT)$(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0) | ||
47 | |||
48 | clean: | ||
49 | $(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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | #include "logf.h" | ||
23 | #include "format.h" | ||
24 | #include "string.h" | ||
25 | #include "memory.h" | ||
26 | |||
27 | static unsigned char logfbuffer[MAX_LOGF_SIZE]; | ||
28 | static int logfread = 0; | ||
29 | static int logfwrite = 0; | ||
30 | static int logfen = true; | ||
31 | |||
32 | void enable_logf(bool en) | ||
33 | { | ||
34 | logfen = en; | ||
35 | } | ||
36 | |||
37 | static int logf_push(void *userp, unsigned char c) | ||
38 | { | ||
39 | (void)userp; | ||
40 | |||
41 | logfbuffer[logfwrite++] = c; | ||
42 | if(logfwrite == MAX_LOGF_SIZE) | ||
43 | logfwrite = 0; | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | void logf(const char *fmt, ...) | ||
48 | { | ||
49 | if(!logfen) return; | ||
50 | va_list ap; | ||
51 | va_start(ap, fmt); | ||
52 | vuprintf(logf_push, NULL, fmt, ap); | ||
53 | va_end(ap); | ||
54 | } | ||
55 | |||
56 | size_t logf_readback(char *buf, size_t max_size) | ||
57 | { | ||
58 | if(logfread == logfwrite) | ||
59 | return 0; | ||
60 | if(logfread < logfwrite) | ||
61 | max_size = MIN(max_size, (size_t)(logfwrite - logfread)); | ||
62 | else | ||
63 | max_size = MIN(max_size, (size_t)(MAX_LOGF_SIZE - logfread)); | ||
64 | memcpy(buf, &logfbuffer[logfread], max_size); | ||
65 | logfread += max_size; | ||
66 | if(logfread == MAX_LOGF_SIZE) | ||
67 | logfread = 0; | ||
68 | return max_size; | ||
69 | } | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_LOGF__ | ||
22 | #define __HWSTUB_LOGF__ | ||
23 | |||
24 | #include "stddef.h" | ||
25 | #include <stdarg.h> | ||
26 | |||
27 | void enable_logf(bool en); | ||
28 | void logf(const char *fmt, ...); | ||
29 | size_t logf_readback(char *buf, size_t max_size); | ||
30 | |||
31 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Free Software Foundation, Inc. | ||
11 | * This file was originally part of the GNU C Library | ||
12 | * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre) | ||
13 | * Adapted for Rockbox by Daniel Ankers | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #include "config.h" | ||
26 | |||
27 | /* | ||
28 | * Endian independent macros for shifting bytes within registers. | ||
29 | */ | ||
30 | #ifndef __ARMEB__ | ||
31 | #define pull lsr | ||
32 | #define push lsl | ||
33 | #else | ||
34 | #define pull lsl | ||
35 | #define push lsr | ||
36 | #endif | ||
37 | |||
38 | /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ | ||
39 | |||
40 | .section .icode,"ax",%progbits | ||
41 | |||
42 | .align 2 | ||
43 | .global memcpy | ||
44 | .type memcpy,%function | ||
45 | |||
46 | memcpy: | ||
47 | stmfd sp!, {r0, r4, lr} | ||
48 | |||
49 | subs r2, r2, #4 | ||
50 | blt 8f | ||
51 | ands ip, r0, #3 | ||
52 | bne 9f | ||
53 | ands ip, r1, #3 | ||
54 | bne 10f | ||
55 | |||
56 | 1: subs r2, r2, #(28) | ||
57 | stmfd sp!, {r5 - r8} | ||
58 | blt 5f | ||
59 | |||
60 | 2: | ||
61 | 3: | ||
62 | 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
63 | subs r2, r2, #32 | ||
64 | stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
65 | bge 3b | ||
66 | |||
67 | 5: ands ip, r2, #28 | ||
68 | rsb ip, ip, #32 | ||
69 | addne pc, pc, ip @ C is always clear here | ||
70 | b 7f | ||
71 | 6: nop | ||
72 | ldr r3, [r1], #4 | ||
73 | ldr r4, [r1], #4 | ||
74 | ldr r5, [r1], #4 | ||
75 | ldr r6, [r1], #4 | ||
76 | ldr r7, [r1], #4 | ||
77 | ldr r8, [r1], #4 | ||
78 | ldr lr, [r1], #4 | ||
79 | |||
80 | add pc, pc, ip | ||
81 | nop | ||
82 | nop | ||
83 | str r3, [r0], #4 | ||
84 | str r4, [r0], #4 | ||
85 | str r5, [r0], #4 | ||
86 | str r6, [r0], #4 | ||
87 | str r7, [r0], #4 | ||
88 | str r8, [r0], #4 | ||
89 | str lr, [r0], #4 | ||
90 | |||
91 | 7: ldmfd sp!, {r5 - r8} | ||
92 | |||
93 | 8: movs r2, r2, lsl #31 | ||
94 | ldrneb r3, [r1], #1 | ||
95 | ldrcsb r4, [r1], #1 | ||
96 | ldrcsb ip, [r1] | ||
97 | strneb r3, [r0], #1 | ||
98 | strcsb r4, [r0], #1 | ||
99 | strcsb ip, [r0] | ||
100 | |||
101 | ldmpc regs="r0, r4" | ||
102 | |||
103 | 9: rsb ip, ip, #4 | ||
104 | cmp ip, #2 | ||
105 | ldrgtb r3, [r1], #1 | ||
106 | ldrgeb r4, [r1], #1 | ||
107 | ldrb lr, [r1], #1 | ||
108 | strgtb r3, [r0], #1 | ||
109 | strgeb r4, [r0], #1 | ||
110 | subs r2, r2, ip | ||
111 | strb lr, [r0], #1 | ||
112 | blt 8b | ||
113 | ands ip, r1, #3 | ||
114 | beq 1b | ||
115 | |||
116 | 10: bic r1, r1, #3 | ||
117 | cmp ip, #2 | ||
118 | ldr lr, [r1], #4 | ||
119 | beq 17f | ||
120 | bgt 18f | ||
121 | |||
122 | |||
123 | .macro forward_copy_shift pull push | ||
124 | |||
125 | subs r2, r2, #28 | ||
126 | blt 14f | ||
127 | |||
128 | 11: stmfd sp!, {r5 - r9} | ||
129 | |||
130 | 12: | ||
131 | 13: ldmia r1!, {r4, r5, r6, r7} | ||
132 | mov r3, lr, pull #\pull | ||
133 | subs r2, r2, #32 | ||
134 | ldmia r1!, {r8, r9, ip, lr} | ||
135 | orr r3, r3, r4, push #\push | ||
136 | mov r4, r4, pull #\pull | ||
137 | orr r4, r4, r5, push #\push | ||
138 | mov r5, r5, pull #\pull | ||
139 | orr r5, r5, r6, push #\push | ||
140 | mov r6, r6, pull #\pull | ||
141 | orr r6, r6, r7, push #\push | ||
142 | mov r7, r7, pull #\pull | ||
143 | orr r7, r7, r8, push #\push | ||
144 | mov r8, r8, pull #\pull | ||
145 | orr r8, r8, r9, push #\push | ||
146 | mov r9, r9, pull #\pull | ||
147 | orr r9, r9, ip, push #\push | ||
148 | mov ip, ip, pull #\pull | ||
149 | orr ip, ip, lr, push #\push | ||
150 | stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip} | ||
151 | bge 12b | ||
152 | |||
153 | ldmfd sp!, {r5 - r9} | ||
154 | |||
155 | 14: ands ip, r2, #28 | ||
156 | beq 16f | ||
157 | |||
158 | 15: mov r3, lr, pull #\pull | ||
159 | ldr lr, [r1], #4 | ||
160 | subs ip, ip, #4 | ||
161 | orr r3, r3, lr, push #\push | ||
162 | str r3, [r0], #4 | ||
163 | bgt 15b | ||
164 | |||
165 | 16: sub r1, r1, #(\push / 8) | ||
166 | b 8b | ||
167 | |||
168 | .endm | ||
169 | |||
170 | |||
171 | forward_copy_shift pull=8 push=24 | ||
172 | |||
173 | 17: forward_copy_shift pull=16 push=16 | ||
174 | |||
175 | 18: forward_copy_shift pull=24 push=8 | ||
176 | |||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Free Software Foundation, Inc. | ||
11 | * This file was originally part of the GNU C Library | ||
12 | * Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre) | ||
13 | * Adapted for Rockbox by Daniel Ankers | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #include "config.h" | ||
26 | |||
27 | /* | ||
28 | * Endian independent macros for shifting bytes within registers. | ||
29 | */ | ||
30 | #ifndef __ARMEB__ | ||
31 | #define pull lsr | ||
32 | #define push lsl | ||
33 | #else | ||
34 | #define pull lsl | ||
35 | #define push lsr | ||
36 | #endif | ||
37 | |||
38 | .text | ||
39 | |||
40 | /* | ||
41 | * Prototype: void *memmove(void *dest, const void *src, size_t n); | ||
42 | * | ||
43 | * Note: | ||
44 | * | ||
45 | * If the memory regions don't overlap, we simply branch to memcpy which is | ||
46 | * normally a bit faster. Otherwise the copy is done going downwards. | ||
47 | */ | ||
48 | |||
49 | .section .icode,"ax",%progbits | ||
50 | |||
51 | .align 2 | ||
52 | .global memmove | ||
53 | .type memmove,%function | ||
54 | |||
55 | memmove: | ||
56 | |||
57 | subs ip, r0, r1 | ||
58 | cmphi r2, ip | ||
59 | bls memcpy | ||
60 | |||
61 | stmfd sp!, {r0, r4, lr} | ||
62 | add r1, r1, r2 | ||
63 | add r0, r0, r2 | ||
64 | subs r2, r2, #4 | ||
65 | blt 8f | ||
66 | ands ip, r0, #3 | ||
67 | bne 9f | ||
68 | ands ip, r1, #3 | ||
69 | bne 10f | ||
70 | |||
71 | 1: subs r2, r2, #(28) | ||
72 | stmfd sp!, {r5 - r8} | ||
73 | blt 5f | ||
74 | |||
75 | 2: | ||
76 | 3: | ||
77 | 4: ldmdb r1!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
78 | subs r2, r2, #32 | ||
79 | stmdb r0!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
80 | bge 3b | ||
81 | |||
82 | 5: ands ip, r2, #28 | ||
83 | rsb ip, ip, #32 | ||
84 | addne pc, pc, ip @ C is always clear here | ||
85 | b 7f | ||
86 | 6: nop | ||
87 | ldr r3, [r1, #-4]! | ||
88 | ldr r4, [r1, #-4]! | ||
89 | ldr r5, [r1, #-4]! | ||
90 | ldr r6, [r1, #-4]! | ||
91 | ldr r7, [r1, #-4]! | ||
92 | ldr r8, [r1, #-4]! | ||
93 | ldr lr, [r1, #-4]! | ||
94 | |||
95 | add pc, pc, ip | ||
96 | nop | ||
97 | nop | ||
98 | str r3, [r0, #-4]! | ||
99 | str r4, [r0, #-4]! | ||
100 | str r5, [r0, #-4]! | ||
101 | str r6, [r0, #-4]! | ||
102 | str r7, [r0, #-4]! | ||
103 | str r8, [r0, #-4]! | ||
104 | str lr, [r0, #-4]! | ||
105 | |||
106 | 7: ldmfd sp!, {r5 - r8} | ||
107 | |||
108 | 8: movs r2, r2, lsl #31 | ||
109 | ldrneb r3, [r1, #-1]! | ||
110 | ldrcsb r4, [r1, #-1]! | ||
111 | ldrcsb ip, [r1, #-1] | ||
112 | strneb r3, [r0, #-1]! | ||
113 | strcsb r4, [r0, #-1]! | ||
114 | strcsb ip, [r0, #-1] | ||
115 | ldmpc regs="r0, r4" | ||
116 | |||
117 | 9: cmp ip, #2 | ||
118 | ldrgtb r3, [r1, #-1]! | ||
119 | ldrgeb r4, [r1, #-1]! | ||
120 | ldrb lr, [r1, #-1]! | ||
121 | strgtb r3, [r0, #-1]! | ||
122 | strgeb r4, [r0, #-1]! | ||
123 | subs r2, r2, ip | ||
124 | strb lr, [r0, #-1]! | ||
125 | blt 8b | ||
126 | ands ip, r1, #3 | ||
127 | beq 1b | ||
128 | |||
129 | 10: bic r1, r1, #3 | ||
130 | cmp ip, #2 | ||
131 | ldr r3, [r1, #0] | ||
132 | beq 17f | ||
133 | blt 18f | ||
134 | |||
135 | |||
136 | .macro backward_copy_shift push pull | ||
137 | |||
138 | subs r2, r2, #28 | ||
139 | blt 14f | ||
140 | |||
141 | 11: stmfd sp!, {r5 - r9} | ||
142 | |||
143 | 12: | ||
144 | 13: ldmdb r1!, {r7, r8, r9, ip} | ||
145 | mov lr, r3, push #\push | ||
146 | subs r2, r2, #32 | ||
147 | ldmdb r1!, {r3, r4, r5, r6} | ||
148 | orr lr, lr, ip, pull #\pull | ||
149 | mov ip, ip, push #\push | ||
150 | orr ip, ip, r9, pull #\pull | ||
151 | mov r9, r9, push #\push | ||
152 | orr r9, r9, r8, pull #\pull | ||
153 | mov r8, r8, push #\push | ||
154 | orr r8, r8, r7, pull #\pull | ||
155 | mov r7, r7, push #\push | ||
156 | orr r7, r7, r6, pull #\pull | ||
157 | mov r6, r6, push #\push | ||
158 | orr r6, r6, r5, pull #\pull | ||
159 | mov r5, r5, push #\push | ||
160 | orr r5, r5, r4, pull #\pull | ||
161 | mov r4, r4, push #\push | ||
162 | orr r4, r4, r3, pull #\pull | ||
163 | stmdb r0!, {r4 - r9, ip, lr} | ||
164 | bge 12b | ||
165 | |||
166 | ldmfd sp!, {r5 - r9} | ||
167 | |||
168 | 14: ands ip, r2, #28 | ||
169 | beq 16f | ||
170 | |||
171 | 15: mov lr, r3, push #\push | ||
172 | ldr r3, [r1, #-4]! | ||
173 | subs ip, ip, #4 | ||
174 | orr lr, lr, r3, pull #\pull | ||
175 | str lr, [r0, #-4]! | ||
176 | bgt 15b | ||
177 | |||
178 | 16: add r1, r1, #(\pull / 8) | ||
179 | b 8b | ||
180 | |||
181 | .endm | ||
182 | |||
183 | |||
184 | backward_copy_shift push=8 pull=24 | ||
185 | |||
186 | 17: backward_copy_shift push=16 pull=16 | ||
187 | |||
188 | 18: backward_copy_shift push=24 pull=8 | ||
189 | |||
190 | |||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_MEMORY__ | ||
22 | #define __HWSTUB_MEMORY__ | ||
23 | |||
24 | #include "stddef.h" | ||
25 | |||
26 | void memset(void *dst, int c, size_t n); | ||
27 | void memcpy(void *dst, const void *src, size_t n); | ||
28 | void memmove(void *dst, const void *src, size_t n); | ||
29 | |||
30 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 by Thom Johansen | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | |||
23 | .section .icode,"ax",%progbits | ||
24 | |||
25 | .align 2 | ||
26 | |||
27 | /* The following code is based on code found in Linux kernel version 2.6.15.3 | ||
28 | * linux/arch/arm/lib/memset.S | ||
29 | * | ||
30 | * Copyright (C) 1995-2000 Russell King | ||
31 | */ | ||
32 | |||
33 | /* This code will align a pointer for memset, if needed */ | ||
34 | 1: cmp r2, #4 @ 1 do we have enough | ||
35 | blt 5f @ 1 bytes to align with? | ||
36 | cmp r3, #2 @ 1 | ||
37 | strgtb r1, [r0, #-1]! @ 1 | ||
38 | strgeb r1, [r0, #-1]! @ 1 | ||
39 | strb r1, [r0, #-1]! @ 1 | ||
40 | sub r2, r2, r3 @ 1 r2 = r2 - r3 | ||
41 | b 2f | ||
42 | |||
43 | .global memset | ||
44 | .type memset,%function | ||
45 | memset: | ||
46 | add r0, r0, r2 @ we'll write backwards in memory | ||
47 | ands r3, r0, #3 @ 1 unaligned? | ||
48 | bne 1b @ 1 | ||
49 | 2: | ||
50 | /* | ||
51 | * we know that the pointer in r0 is aligned to a word boundary. | ||
52 | */ | ||
53 | orr r1, r1, r1, lsl #8 | ||
54 | orr r1, r1, r1, lsl #16 | ||
55 | mov r3, r1 | ||
56 | cmp r2, #16 | ||
57 | blt 5f | ||
58 | /* | ||
59 | * We need an extra register for this loop - save the return address and | ||
60 | * use the LR | ||
61 | */ | ||
62 | str lr, [sp, #-4]! | ||
63 | mov ip, r1 | ||
64 | mov lr, r1 | ||
65 | |||
66 | 3: subs r2, r2, #64 | ||
67 | stmgedb r0!, {r1, r3, ip, lr} @ 64 bytes at a time. | ||
68 | stmgedb r0!, {r1, r3, ip, lr} | ||
69 | stmgedb r0!, {r1, r3, ip, lr} | ||
70 | stmgedb r0!, {r1, r3, ip, lr} | ||
71 | bgt 3b | ||
72 | ldrpc cond=eq @ Now <64 bytes to go. | ||
73 | /* | ||
74 | * No need to correct the count; we're only testing bits from now on | ||
75 | */ | ||
76 | tst r2, #32 | ||
77 | stmnedb r0!, {r1, r3, ip, lr} | ||
78 | stmnedb r0!, {r1, r3, ip, lr} | ||
79 | tst r2, #16 | ||
80 | stmnedb r0!, {r1, r3, ip, lr} | ||
81 | ldr lr, [sp], #4 | ||
82 | |||
83 | 5: tst r2, #8 | ||
84 | stmnedb r0!, {r1, r3} | ||
85 | tst r2, #4 | ||
86 | strne r1, [r0, #-4]! | ||
87 | /* | ||
88 | * When we get here, we've got less than 4 bytes to zero. We | ||
89 | * may have an unaligned pointer as well. | ||
90 | */ | ||
91 | 6: tst r2, #2 | ||
92 | strneb r1, [r0, #-1]! | ||
93 | strneb r1, [r0, #-1]! | ||
94 | tst r2, #1 | ||
95 | strneb r1, [r0, #-1]! | ||
96 | bx lr | ||
97 | .end: | ||
98 | .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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_STDDEF__ | ||
22 | #define __HWSTUB_STDDEF__ | ||
23 | |||
24 | #include "stdint.h" | ||
25 | |||
26 | typedef uint32_t size_t; | ||
27 | typedef int32_t ssize_t; | ||
28 | |||
29 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
30 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
31 | |||
32 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Dave Chapman | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef __STDINT_H__ | ||
23 | #define __STDINT_H__ | ||
24 | |||
25 | typedef signed char int8_t; | ||
26 | typedef unsigned char uint8_t; | ||
27 | typedef short int16_t; | ||
28 | typedef unsigned short uint16_t; | ||
29 | typedef long int32_t; | ||
30 | typedef unsigned long uint32_t; | ||
31 | typedef unsigned long long uint64_t; | ||
32 | typedef uint32_t intptr_t; | ||
33 | typedef char bool; | ||
34 | |||
35 | #define true 1 | ||
36 | #define false 0 | ||
37 | |||
38 | #define NULL (void *)0 | ||
39 | |||
40 | #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 @@ | |||
1 | # | ||
2 | # common | ||
3 | # | ||
4 | CC=arm-elf-eabi-gcc | ||
5 | LD=arm-elf-eabi-gcc | ||
6 | AS=arm-elf-eabi-gcc | ||
7 | OC=arm-elf-eabi-objcopy | ||
8 | DEFINES= | ||
9 | INCLUDES=-I$(CURDIR) | ||
10 | GCCOPTS=-mcpu=arm926ej-s | ||
11 | BUILD_DIR=$(CURDIR)/build/ | ||
12 | ROOT_DIR=$(CURDIR)/.. | ||
13 | |||
14 | 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 @@ | |||
1 | #define CONFIG_STMP | ||
2 | #define IRAM_ORIG 0 | ||
3 | #define IRAM_SIZE 0x8000 | ||
4 | #define DRAM_ORIG 0x40000000 | ||
5 | #define DRAM_SIZE (MEMORYSIZE * 0x100000) | ||
6 | #define CPU_ARM | ||
7 | #define ARM_ARCH 5 | ||
8 | #define USB_BASE 0x80080000 | ||
9 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "stddef.h" | ||
22 | #include "target.h" | ||
23 | #include "system.h" | ||
24 | #include "logf.h" | ||
25 | |||
26 | #define __REG_SET(reg) (*((volatile uint32_t *)(® + 1))) | ||
27 | #define __REG_CLR(reg) (*((volatile uint32_t *)(® + 2))) | ||
28 | #define __REG_TOG(reg) (*((volatile uint32_t *)(® + 3))) | ||
29 | |||
30 | #define __BLOCK_SFTRST (1 << 31) | ||
31 | #define __BLOCK_CLKGATE (1 << 30) | ||
32 | |||
33 | #define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP) | ||
34 | #define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP) | ||
35 | #define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP) | ||
36 | |||
37 | /** | ||
38 | * | ||
39 | * Global | ||
40 | * | ||
41 | */ | ||
42 | |||
43 | enum stmp_family_t | ||
44 | { | ||
45 | UNKNOWN, | ||
46 | STMP3600, | ||
47 | STMP3700, | ||
48 | STMP3770, | ||
49 | STMP3780 | ||
50 | }; | ||
51 | |||
52 | enum stmp_family_t g_stmp_family = UNKNOWN; | ||
53 | |||
54 | /** | ||
55 | * | ||
56 | * Clkctrl | ||
57 | * | ||
58 | */ | ||
59 | |||
60 | #define HW_CLKCTRL_BASE 0x80040000 | ||
61 | |||
62 | #define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0)) | ||
63 | #define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */ | ||
64 | #define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16) | ||
65 | #define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18) | ||
66 | |||
67 | #define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10)) | ||
68 | #define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31) | ||
69 | |||
70 | /* STMP3600 only */ | ||
71 | #define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20)) | ||
72 | #define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0 | ||
73 | #define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff | ||
74 | #define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30) | ||
75 | |||
76 | /* STMP3600 */ | ||
77 | #define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30)) | ||
78 | |||
79 | /* STMP3600 only */ | ||
80 | #define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40)) | ||
81 | #define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0 | ||
82 | #define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff | ||
83 | |||
84 | /* STMP3600 only */ | ||
85 | #define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70)) | ||
86 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30) | ||
87 | #define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31) | ||
88 | |||
89 | /** | ||
90 | * | ||
91 | * Digctl | ||
92 | * | ||
93 | */ | ||
94 | |||
95 | /* Digital control */ | ||
96 | #define HW_DIGCTL_BASE 0x8001C000 | ||
97 | #define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0)) | ||
98 | #define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2) | ||
99 | |||
100 | #define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0)) | ||
101 | |||
102 | #define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310)) | ||
103 | #define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16 | ||
104 | #define HW_DIGCTL_CHIPID__PRODUCT_CODE_BM 0xffff0000 | ||
105 | #define HW_DIGCTL_CHIPID__REVISION_BP 0 | ||
106 | #define HW_DIGCTL_CHIPID__REVISION_BM 0xff | ||
107 | |||
108 | #define HZ 1000000 | ||
109 | |||
110 | /** | ||
111 | * | ||
112 | * USB PHY | ||
113 | * | ||
114 | */ | ||
115 | /* USB Phy */ | ||
116 | #define HW_USBPHY_BASE 0x8007C000 | ||
117 | #define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0)) | ||
118 | |||
119 | #define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30)) | ||
120 | |||
121 | void target_init(void) | ||
122 | { | ||
123 | /* detect family */ | ||
124 | uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); | ||
125 | if(product_code >= 0x3600 && product_code < 0x3700) | ||
126 | { | ||
127 | logf("identified STMP3600 family\n"); | ||
128 | g_stmp_family = STMP3600; | ||
129 | } | ||
130 | else if(product_code == 0x3700) | ||
131 | { | ||
132 | logf("identified STMP3700 family\n"); | ||
133 | g_stmp_family = STMP3700; | ||
134 | } | ||
135 | else if(product_code == 0x37b0) | ||
136 | { | ||
137 | logf("identified STMP3770 family\n"); | ||
138 | g_stmp_family = STMP3770; | ||
139 | } | ||
140 | else if(product_code == 0x3780) | ||
141 | { | ||
142 | logf("identified STMP3780 family\n"); | ||
143 | g_stmp_family = STMP3780; | ||
144 | } | ||
145 | else | ||
146 | logf("cannot identify family: 0x%x\n", product_code); | ||
147 | |||
148 | if(g_stmp_family == STMP3600) | ||
149 | { | ||
150 | /* CPU clock is always derived from PLL, if we switch to PLL, cpu will | ||
151 | * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed | ||
152 | * (1.2MHz) for a safe transition */ | ||
153 | HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400; | ||
154 | /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the | ||
155 | * switch so lower XBUS too */ | ||
156 | HW_CLKCTRL_XBUSCLKCTRL = 20; | ||
157 | /* Power PLL */ | ||
158 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; | ||
159 | HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480; | ||
160 | /* Wait lock */ | ||
161 | while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK)); | ||
162 | /* Switch to PLL source */ | ||
163 | __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS; | ||
164 | /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */ | ||
165 | HW_CLKCTRL_CPUCLKCTRL = 7; | ||
166 | HW_CLKCTRL_HBUSCLKCTRL = 7; | ||
167 | HW_CLKCTRL_XBUSCLKCTRL = 1; | ||
168 | __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE; | ||
169 | __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE; | ||
170 | } | ||
171 | else | ||
172 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER; | ||
173 | /* enable USB PHY PLL */ | ||
174 | __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS; | ||
175 | /* power up USB PHY */ | ||
176 | __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST; | ||
177 | HW_USBPHY_PWD = 0; | ||
178 | /* enable USB controller */ | ||
179 | __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE; | ||
180 | } | ||
181 | |||
182 | static struct usb_resp_info_stmp_t g_stmp; | ||
183 | static struct usb_resp_info_target_t g_target = | ||
184 | { | ||
185 | .id = HWSTUB_TARGET_STMP, | ||
186 | .name = "STMP3600 / STMP3700 / STMP3780 (i.MX233)" | ||
187 | }; | ||
188 | |||
189 | int target_get_info(int info, void **buffer) | ||
190 | { | ||
191 | if(info == HWSTUB_INFO_STMP) | ||
192 | { | ||
193 | g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE); | ||
194 | g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION); | ||
195 | g_stmp.is_supported = g_stmp_family != 0; | ||
196 | *buffer = &g_stmp; | ||
197 | return sizeof(g_stmp); | ||
198 | } | ||
199 | else | ||
200 | return -1; | ||
201 | } | ||
202 | |||
203 | void target_exit(void) | ||
204 | { | ||
205 | } | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "string.h" | ||
22 | |||
23 | size_t strlen(const char *s) | ||
24 | { | ||
25 | size_t len = 0; | ||
26 | while(*s++) | ||
27 | len++; | ||
28 | return len; | ||
29 | } | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_STRING__ | ||
22 | #define __HWSTUB_STRING__ | ||
23 | |||
24 | #include "stddef.h" | ||
25 | |||
26 | size_t strlen(const char *s); | ||
27 | |||
28 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __HWSTUB_SYSTEM__ | ||
22 | #define __HWSTUB_SYSTEM__ | ||
23 | |||
24 | #define IRQ_ENABLED 0x00 | ||
25 | #define IRQ_DISABLED 0x80 | ||
26 | #define IRQ_STATUS 0x80 | ||
27 | #define FIQ_ENABLED 0x00 | ||
28 | #define FIQ_DISABLED 0x40 | ||
29 | #define FIQ_STATUS 0x40 | ||
30 | #define IRQ_FIQ_ENABLED 0x00 | ||
31 | #define IRQ_FIQ_DISABLED 0xc0 | ||
32 | #define IRQ_FIQ_STATUS 0xc0 | ||
33 | #define HIGHEST_IRQ_LEVEL IRQ_DISABLED | ||
34 | |||
35 | #define set_irq_level(status) \ | ||
36 | set_interrupt_status((status), IRQ_STATUS) | ||
37 | #define set_fiq_status(status) \ | ||
38 | set_interrupt_status((status), FIQ_STATUS) | ||
39 | |||
40 | #define disable_irq_save() \ | ||
41 | disable_interrupt_save(IRQ_STATUS) | ||
42 | #define disable_fiq_save() \ | ||
43 | disable_interrupt_save(FIQ_STATUS) | ||
44 | |||
45 | #define restore_irq(cpsr) \ | ||
46 | restore_interrupt(cpsr) | ||
47 | #define restore_fiq(cpsr) \ | ||
48 | restore_interrupt(cpsr) | ||
49 | |||
50 | #define disable_irq() \ | ||
51 | disable_interrupt(IRQ_STATUS) | ||
52 | #define enable_irq() \ | ||
53 | enable_interrupt(IRQ_STATUS) | ||
54 | #define disable_fiq() \ | ||
55 | disable_interrupt(FIQ_STATUS) | ||
56 | #define enable_fiq() \ | ||
57 | enable_interrupt(FIQ_STATUS) | ||
58 | |||
59 | static inline int set_interrupt_status(int status, int mask) | ||
60 | { | ||
61 | unsigned long cpsr; | ||
62 | int oldstatus; | ||
63 | /* Read the old levels and set the new ones */ | ||
64 | asm volatile ( | ||
65 | "mrs %1, cpsr \n" | ||
66 | "bic %0, %1, %[mask] \n" | ||
67 | "orr %0, %0, %2 \n" | ||
68 | "msr cpsr_c, %0 \n" | ||
69 | : "=&r,r"(cpsr), "=&r,r"(oldstatus) | ||
70 | : "r,i"(status & mask), [mask]"i,i"(mask)); | ||
71 | |||
72 | return oldstatus; | ||
73 | } | ||
74 | |||
75 | static inline void restore_interrupt(int cpsr) | ||
76 | { | ||
77 | /* Set cpsr_c from value returned by disable_interrupt_save | ||
78 | * or set_interrupt_status */ | ||
79 | asm volatile ("msr cpsr_c, %0" : : "r"(cpsr)); | ||
80 | } | ||
81 | |||
82 | static inline void enable_interrupt(int mask) | ||
83 | { | ||
84 | /* Clear I and/or F disable bit */ | ||
85 | int tmp; | ||
86 | asm volatile ( | ||
87 | "mrs %0, cpsr \n" | ||
88 | "bic %0, %0, %1 \n" | ||
89 | "msr cpsr_c, %0 \n" | ||
90 | : "=&r"(tmp) : "i"(mask)); | ||
91 | } | ||
92 | |||
93 | static inline void disable_interrupt(int mask) | ||
94 | { | ||
95 | /* Set I and/or F disable bit */ | ||
96 | int tmp; | ||
97 | asm volatile ( | ||
98 | "mrs %0, cpsr \n" | ||
99 | "orr %0, %0, %1 \n" | ||
100 | "msr cpsr_c, %0 \n" | ||
101 | : "=&r"(tmp) : "i"(mask)); | ||
102 | } | ||
103 | |||
104 | static inline int disable_interrupt_save(int mask) | ||
105 | { | ||
106 | /* Set I and/or F disable bit and return old cpsr value */ | ||
107 | int cpsr, tmp; | ||
108 | asm volatile ( | ||
109 | "mrs %1, cpsr \n" | ||
110 | "orr %0, %1, %2 \n" | ||
111 | "msr cpsr_c, %0 \n" | ||
112 | : "=&r"(tmp), "=&r"(cpsr) | ||
113 | : "i"(mask)); | ||
114 | return cpsr; | ||
115 | } | ||
116 | |||
117 | #endif /* __HWSTUB_SYSTEM__ */ | ||
118 | |||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef __TARGET_H__ | ||
22 | #define __TARGET_H__ | ||
23 | |||
24 | #include "protocol.h" | ||
25 | |||
26 | void target_init(void); | ||
27 | void target_exit(void); | ||
28 | /* return actual size or -1 if error */ | ||
29 | int target_get_info(int info, void **buffer); | ||
30 | |||
31 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) by Linux Kernel Developers | ||
11 | * | ||
12 | * Based on code from the Linux Kernel | ||
13 | * available at http://www.kernel.org | ||
14 | * Original file: <kernel>/include/linux/usb/ch9.h | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License | ||
18 | * as published by the Free Software Foundation; either version 2 | ||
19 | * of the License, or (at your option) any later version. | ||
20 | * | ||
21 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
22 | * KIND, either express or implied. | ||
23 | * | ||
24 | ****************************************************************************/ | ||
25 | |||
26 | /* | ||
27 | * This file holds USB constants and structures that are needed for | ||
28 | * USB device APIs. These are used by the USB device model, which is | ||
29 | * defined in chapter 9 of the USB 2.0 specification and in the | ||
30 | * Wireless USB 1.0 (spread around). Linux has several APIs in C that | ||
31 | * need these: | ||
32 | * | ||
33 | * - the master/host side Linux-USB kernel driver API; | ||
34 | * - the "usbfs" user space API; and | ||
35 | * - the Linux "gadget" slave/device/peripheral side driver API. | ||
36 | * | ||
37 | * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems | ||
38 | * act either as a USB master/host or as a USB slave/device. That means | ||
39 | * the master and slave side APIs benefit from working well together. | ||
40 | * | ||
41 | * There's also "Wireless USB", using low power short range radios for | ||
42 | * peripheral interconnection but otherwise building on the USB framework. | ||
43 | * | ||
44 | * Note all descriptors are declared '__attribute__((packed))' so that: | ||
45 | * | ||
46 | * [a] they never get padded, either internally (USB spec writers | ||
47 | * probably handled that) or externally; | ||
48 | * | ||
49 | * [b] so that accessing bigger-than-a-bytes fields will never | ||
50 | * generate bus errors on any platform, even when the location of | ||
51 | * its descriptor inside a bundle isn't "naturally aligned", and | ||
52 | * | ||
53 | * [c] for consistency, removing all doubt even when it appears to | ||
54 | * someone that the two other points are non-issues for that | ||
55 | * particular descriptor type. | ||
56 | */ | ||
57 | |||
58 | #ifndef _CH9_H_ | ||
59 | #define _CH9_H_ | ||
60 | |||
61 | #include "stdint.h" | ||
62 | |||
63 | /*-------------------------------------------------------------------------*/ | ||
64 | |||
65 | /* CONTROL REQUEST SUPPORT */ | ||
66 | |||
67 | /* | ||
68 | * USB directions | ||
69 | * | ||
70 | * This bit flag is used in endpoint descriptors' bEndpointAddress field. | ||
71 | * It's also one of three fields in control requests bRequestType. | ||
72 | */ | ||
73 | #define USB_DIR_OUT 0 /* to device */ | ||
74 | #define USB_DIR_IN 0x80 /* to host */ | ||
75 | |||
76 | /* | ||
77 | * USB types, the second of three bRequestType fields | ||
78 | */ | ||
79 | #define USB_TYPE_MASK (0x03 << 5) | ||
80 | #define USB_TYPE_STANDARD (0x00 << 5) | ||
81 | #define USB_TYPE_CLASS (0x01 << 5) | ||
82 | #define USB_TYPE_VENDOR (0x02 << 5) | ||
83 | #define USB_TYPE_RESERVED (0x03 << 5) | ||
84 | |||
85 | /* | ||
86 | * USB recipients, the third of three bRequestType fields | ||
87 | */ | ||
88 | #define USB_RECIP_MASK 0x1f | ||
89 | #define USB_RECIP_DEVICE 0x00 | ||
90 | #define USB_RECIP_INTERFACE 0x01 | ||
91 | #define USB_RECIP_ENDPOINT 0x02 | ||
92 | #define USB_RECIP_OTHER 0x03 | ||
93 | |||
94 | /* | ||
95 | * Standard requests, for the bRequest field of a SETUP packet. | ||
96 | * | ||
97 | * These are qualified by the bRequestType field, so that for example | ||
98 | * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved | ||
99 | * by a GET_STATUS request. | ||
100 | */ | ||
101 | #define USB_REQ_GET_STATUS 0x00 | ||
102 | #define USB_REQ_CLEAR_FEATURE 0x01 | ||
103 | #define USB_REQ_SET_FEATURE 0x03 | ||
104 | #define USB_REQ_SET_ADDRESS 0x05 | ||
105 | #define USB_REQ_GET_DESCRIPTOR 0x06 | ||
106 | #define USB_REQ_SET_DESCRIPTOR 0x07 | ||
107 | #define USB_REQ_GET_CONFIGURATION 0x08 | ||
108 | #define USB_REQ_SET_CONFIGURATION 0x09 | ||
109 | #define USB_REQ_GET_INTERFACE 0x0A | ||
110 | #define USB_REQ_SET_INTERFACE 0x0B | ||
111 | #define USB_REQ_SYNCH_FRAME 0x0C | ||
112 | /* | ||
113 | * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and | ||
114 | * are read as a bit array returned by USB_REQ_GET_STATUS. (So there | ||
115 | * are at most sixteen features of each type.) Hubs may also support a | ||
116 | * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. | ||
117 | */ | ||
118 | #define USB_DEVICE_SELF_POWERED 0 /* (read only) */ | ||
119 | #define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ | ||
120 | #define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ | ||
121 | #define USB_DEVICE_BATTERY 2 /* (wireless) */ | ||
122 | #define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ | ||
123 | #define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ | ||
124 | #define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ | ||
125 | #define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ | ||
126 | #define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ | ||
127 | |||
128 | #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ | ||
129 | |||
130 | |||
131 | /** | ||
132 | * struct usb_ctrlrequest - SETUP data for a USB device control request | ||
133 | * @bRequestType: matches the USB bmRequestType field | ||
134 | * @bRequest: matches the USB bRequest field | ||
135 | * @wValue: matches the USB wValue field (le16 byte order) | ||
136 | * @wIndex: matches the USB wIndex field (le16 byte order) | ||
137 | * @wLength: matches the USB wLength field (le16 byte order) | ||
138 | * | ||
139 | * This structure is used to send control requests to a USB device. It matches | ||
140 | * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the | ||
141 | * USB spec for a fuller description of the different fields, and what they are | ||
142 | * used for. | ||
143 | * | ||
144 | * Note that the driver for any interface can issue control requests. | ||
145 | * For most devices, interfaces don't coordinate with each other, so | ||
146 | * such requests may be made at any time. | ||
147 | */ | ||
148 | struct usb_ctrlrequest { | ||
149 | uint8_t bRequestType; | ||
150 | uint8_t bRequest; | ||
151 | uint16_t wValue; | ||
152 | uint16_t wIndex; | ||
153 | uint16_t wLength; | ||
154 | } __attribute__ ((packed)); | ||
155 | |||
156 | /*-------------------------------------------------------------------------*/ | ||
157 | |||
158 | /* | ||
159 | * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or | ||
160 | * (rarely) accepted by SET_DESCRIPTOR. | ||
161 | * | ||
162 | * Note that all multi-byte values here are encoded in little endian | ||
163 | * byte order "on the wire". But when exposed through Linux-USB APIs, | ||
164 | * they've been converted to cpu byte order. | ||
165 | */ | ||
166 | |||
167 | /* | ||
168 | * Descriptor types ... USB 2.0 spec table 9.5 | ||
169 | */ | ||
170 | #define USB_DT_DEVICE 0x01 | ||
171 | #define USB_DT_CONFIG 0x02 | ||
172 | #define USB_DT_STRING 0x03 | ||
173 | #define USB_DT_INTERFACE 0x04 | ||
174 | #define USB_DT_ENDPOINT 0x05 | ||
175 | #define USB_DT_DEVICE_QUALIFIER 0x06 | ||
176 | #define USB_DT_OTHER_SPEED_CONFIG 0x07 | ||
177 | #define USB_DT_INTERFACE_POWER 0x08 | ||
178 | /* these are from a minor usb 2.0 revision (ECN) */ | ||
179 | #define USB_DT_OTG 0x09 | ||
180 | #define USB_DT_DEBUG 0x0a | ||
181 | #define USB_DT_INTERFACE_ASSOCIATION 0x0b | ||
182 | /* these are from the Wireless USB spec */ | ||
183 | #define USB_DT_SECURITY 0x0c | ||
184 | #define USB_DT_KEY 0x0d | ||
185 | #define USB_DT_ENCRYPTION_TYPE 0x0e | ||
186 | #define USB_DT_BOS 0x0f | ||
187 | #define USB_DT_DEVICE_CAPABILITY 0x10 | ||
188 | #define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 | ||
189 | #define USB_DT_WIRE_ADAPTER 0x21 | ||
190 | #define USB_DT_RPIPE 0x22 | ||
191 | #define USB_DT_CS_RADIO_CONTROL 0x23 | ||
192 | |||
193 | /* Conventional codes for class-specific descriptors. The convention is | ||
194 | * defined in the USB "Common Class" Spec (3.11). Individual class specs | ||
195 | * are authoritative for their usage, not the "common class" writeup. | ||
196 | */ | ||
197 | #define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) | ||
198 | #define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) | ||
199 | #define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) | ||
200 | #define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) | ||
201 | #define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) | ||
202 | |||
203 | /* All standard descriptors have these 2 fields at the beginning */ | ||
204 | struct usb_descriptor_header { | ||
205 | uint8_t bLength; | ||
206 | uint8_t bDescriptorType; | ||
207 | } __attribute__ ((packed)); | ||
208 | |||
209 | |||
210 | /*-------------------------------------------------------------------------*/ | ||
211 | |||
212 | /* USB_DT_DEVICE: Device descriptor */ | ||
213 | struct usb_device_descriptor { | ||
214 | uint8_t bLength; | ||
215 | uint8_t bDescriptorType; | ||
216 | |||
217 | uint16_t bcdUSB; | ||
218 | uint8_t bDeviceClass; | ||
219 | uint8_t bDeviceSubClass; | ||
220 | uint8_t bDeviceProtocol; | ||
221 | uint8_t bMaxPacketSize0; | ||
222 | uint16_t idVendor; | ||
223 | uint16_t idProduct; | ||
224 | uint16_t bcdDevice; | ||
225 | uint8_t iManufacturer; | ||
226 | uint8_t iProduct; | ||
227 | uint8_t iSerialNumber; | ||
228 | uint8_t bNumConfigurations; | ||
229 | } __attribute__ ((packed)); | ||
230 | |||
231 | #define USB_DT_DEVICE_SIZE 18 | ||
232 | |||
233 | |||
234 | /* | ||
235 | * Device and/or Interface Class codes | ||
236 | * as found in bDeviceClass or bInterfaceClass | ||
237 | * and defined by www.usb.org documents | ||
238 | */ | ||
239 | #define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ | ||
240 | #define USB_CLASS_AUDIO 1 | ||
241 | #define USB_CLASS_COMM 2 | ||
242 | #define USB_CLASS_HID 3 | ||
243 | #define USB_CLASS_PHYSICAL 5 | ||
244 | #define USB_CLASS_STILL_IMAGE 6 | ||
245 | #define USB_CLASS_PRINTER 7 | ||
246 | #define USB_CLASS_MASS_STORAGE 8 | ||
247 | #define USB_CLASS_HUB 9 | ||
248 | #define USB_CLASS_CDC_DATA 0x0a | ||
249 | #define USB_CLASS_CSCID 0x0b /* chip+ smart card */ | ||
250 | #define USB_CLASS_CONTENT_SEC 0x0d /* content security */ | ||
251 | #define USB_CLASS_VIDEO 0x0e | ||
252 | #define USB_CLASS_WIRELESS_CONTROLLER 0xe0 | ||
253 | #define USB_CLASS_MISC 0xef | ||
254 | #define USB_CLASS_APP_SPEC 0xfe | ||
255 | #define USB_CLASS_VENDOR_SPEC 0xff | ||
256 | |||
257 | /*-------------------------------------------------------------------------*/ | ||
258 | |||
259 | /* USB_DT_CONFIG: Configuration descriptor information. | ||
260 | * | ||
261 | * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the | ||
262 | * descriptor type is different. Highspeed-capable devices can look | ||
263 | * different depending on what speed they're currently running. Only | ||
264 | * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG | ||
265 | * descriptors. | ||
266 | */ | ||
267 | struct usb_config_descriptor { | ||
268 | uint8_t bLength; | ||
269 | uint8_t bDescriptorType; | ||
270 | |||
271 | uint16_t wTotalLength; | ||
272 | uint8_t bNumInterfaces; | ||
273 | uint8_t bConfigurationValue; | ||
274 | uint8_t iConfiguration; | ||
275 | uint8_t bmAttributes; | ||
276 | uint8_t bMaxPower; | ||
277 | } __attribute__ ((packed)); | ||
278 | |||
279 | #define USB_DT_CONFIG_SIZE 9 | ||
280 | |||
281 | /* from config descriptor bmAttributes */ | ||
282 | #define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ | ||
283 | #define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ | ||
284 | #define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ | ||
285 | #define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ | ||
286 | |||
287 | /*-------------------------------------------------------------------------*/ | ||
288 | |||
289 | /* USB_DT_STRING: String descriptor */ | ||
290 | struct usb_string_descriptor { | ||
291 | uint8_t bLength; | ||
292 | uint8_t bDescriptorType; | ||
293 | |||
294 | uint16_t wString[]; /* UTF-16LE encoded */ | ||
295 | } __attribute__ ((packed)); | ||
296 | |||
297 | /* note that "string" zero is special, it holds language codes that | ||
298 | * the device supports, not Unicode characters. | ||
299 | */ | ||
300 | |||
301 | /*-------------------------------------------------------------------------*/ | ||
302 | |||
303 | /* USB_DT_INTERFACE: Interface descriptor */ | ||
304 | struct usb_interface_descriptor { | ||
305 | uint8_t bLength; | ||
306 | uint8_t bDescriptorType; | ||
307 | |||
308 | uint8_t bInterfaceNumber; | ||
309 | uint8_t bAlternateSetting; | ||
310 | uint8_t bNumEndpoints; | ||
311 | uint8_t bInterfaceClass; | ||
312 | uint8_t bInterfaceSubClass; | ||
313 | uint8_t bInterfaceProtocol; | ||
314 | uint8_t iInterface; | ||
315 | } __attribute__ ((packed)); | ||
316 | |||
317 | #define USB_DT_INTERFACE_SIZE 9 | ||
318 | |||
319 | /*-------------------------------------------------------------------------*/ | ||
320 | |||
321 | /* USB_DT_ENDPOINT: Endpoint descriptor */ | ||
322 | struct usb_endpoint_descriptor { | ||
323 | uint8_t bLength; | ||
324 | uint8_t bDescriptorType; | ||
325 | |||
326 | uint8_t bEndpointAddress; | ||
327 | uint8_t bmAttributes; | ||
328 | uint16_t wMaxPacketSize; | ||
329 | uint8_t bInterval; | ||
330 | } __attribute__ ((packed)); | ||
331 | |||
332 | #define USB_DT_ENDPOINT_SIZE 7 | ||
333 | #define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ | ||
334 | |||
335 | |||
336 | /* | ||
337 | * Endpoints | ||
338 | */ | ||
339 | #define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ | ||
340 | #define USB_ENDPOINT_DIR_MASK 0x80 | ||
341 | |||
342 | #define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ | ||
343 | #define USB_ENDPOINT_XFER_CONTROL 0 | ||
344 | #define USB_ENDPOINT_XFER_ISOC 1 | ||
345 | #define USB_ENDPOINT_XFER_BULK 2 | ||
346 | #define USB_ENDPOINT_XFER_INT 3 | ||
347 | #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 | ||
348 | |||
349 | |||
350 | /*-------------------------------------------------------------------------*/ | ||
351 | |||
352 | /* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ | ||
353 | struct usb_qualifier_descriptor { | ||
354 | uint8_t bLength; | ||
355 | uint8_t bDescriptorType; | ||
356 | |||
357 | uint16_t bcdUSB; | ||
358 | uint8_t bDeviceClass; | ||
359 | uint8_t bDeviceSubClass; | ||
360 | uint8_t bDeviceProtocol; | ||
361 | uint8_t bMaxPacketSize0; | ||
362 | uint8_t bNumConfigurations; | ||
363 | uint8_t bRESERVED; | ||
364 | } __attribute__ ((packed)); | ||
365 | |||
366 | |||
367 | /*-------------------------------------------------------------------------*/ | ||
368 | |||
369 | /* USB_DT_OTG (from OTG 1.0a supplement) */ | ||
370 | struct usb_otg_descriptor { | ||
371 | uint8_t bLength; | ||
372 | uint8_t bDescriptorType; | ||
373 | |||
374 | uint8_t bmAttributes; /* support for HNP, SRP, etc */ | ||
375 | } __attribute__ ((packed)); | ||
376 | |||
377 | /* from usb_otg_descriptor.bmAttributes */ | ||
378 | #define USB_OTG_SRP (1 << 0) | ||
379 | #define USB_OTG_HNP (1 << 1) /* swap host/device roles */ | ||
380 | |||
381 | /*-------------------------------------------------------------------------*/ | ||
382 | |||
383 | /* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ | ||
384 | struct usb_debug_descriptor { | ||
385 | uint8_t bLength; | ||
386 | uint8_t bDescriptorType; | ||
387 | |||
388 | /* bulk endpoints with 8 byte maxpacket */ | ||
389 | uint8_t bDebugInEndpoint; | ||
390 | uint8_t bDebugOutEndpoint; | ||
391 | } __attribute__((packed)); | ||
392 | |||
393 | /*-------------------------------------------------------------------------*/ | ||
394 | /* USB 2.0 defines three speeds, here's how Linux identifies them */ | ||
395 | |||
396 | enum usb_device_speed { | ||
397 | USB_SPEED_UNKNOWN = 0, /* enumerating */ | ||
398 | USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ | ||
399 | USB_SPEED_HIGH, /* usb 2.0 */ | ||
400 | USB_SPEED_VARIABLE, /* wireless (usb 2.5) */ | ||
401 | }; | ||
402 | |||
403 | enum usb_device_state { | ||
404 | /* NOTATTACHED isn't in the USB spec, and this state acts | ||
405 | * the same as ATTACHED ... but it's clearer this way. | ||
406 | */ | ||
407 | USB_STATE_NOTATTACHED = 0, | ||
408 | |||
409 | /* chapter 9 and authentication (wireless) device states */ | ||
410 | USB_STATE_ATTACHED, | ||
411 | USB_STATE_POWERED, /* wired */ | ||
412 | USB_STATE_UNAUTHENTICATED, /* auth */ | ||
413 | USB_STATE_RECONNECTING, /* auth */ | ||
414 | USB_STATE_DEFAULT, /* limited function */ | ||
415 | USB_STATE_ADDRESS, | ||
416 | USB_STATE_CONFIGURED, /* most functions */ | ||
417 | |||
418 | USB_STATE_SUSPENDED | ||
419 | |||
420 | /* NOTE: there are actually four different SUSPENDED | ||
421 | * states, returning to POWERED, DEFAULT, ADDRESS, or | ||
422 | * CONFIGURED respectively when SOF tokens flow again. | ||
423 | * At this level there's no difference between L1 and L2 | ||
424 | * suspend states. (L2 being original USB 1.1 suspend.) | ||
425 | */ | ||
426 | }; | ||
427 | |||
428 | /** | ||
429 | * struct usb_string - wraps a C string and its USB id | ||
430 | * @id:the (nonzero) ID for this string | ||
431 | * @s:the string, in UTF-8 encoding | ||
432 | * | ||
433 | * If you're using usb_gadget_get_string(), use this to wrap a string | ||
434 | * together with its ID. | ||
435 | */ | ||
436 | struct usb_string { | ||
437 | uint8_t id; | ||
438 | const char* s; | ||
439 | }; | ||
440 | |||
441 | /** | ||
442 | * struct usb_gadget_strings - a set of USB strings in a given language | ||
443 | * @language:identifies the strings' language (0x0409 for en-us) | ||
444 | * @strings:array of strings with their ids | ||
445 | * | ||
446 | * If you're using usb_gadget_get_string(), use this to wrap all the | ||
447 | * strings for a given language. | ||
448 | */ | ||
449 | struct usb_gadget_strings { | ||
450 | uint16_t language; /* 0x0409 for en-us */ | ||
451 | struct usb_string* strings; | ||
452 | }; | ||
453 | |||
454 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Björn Stenberg | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef _USB_DRV_H | ||
22 | #define _USB_DRV_H | ||
23 | |||
24 | #include "usb_ch9.h" | ||
25 | |||
26 | #define EP_CONTROL 0 | ||
27 | |||
28 | #define DIR_OUT 0 | ||
29 | #define DIR_IN 1 | ||
30 | |||
31 | #define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT) | ||
32 | #define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK) | ||
33 | |||
34 | void usb_drv_init(void); | ||
35 | void usb_drv_exit(void); | ||
36 | void usb_drv_stall(int endpoint, bool stall,bool in); | ||
37 | int usb_drv_send(int endpoint, void* ptr, int length); | ||
38 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length); | ||
39 | int usb_drv_recv(int endpoint, void* ptr, int length);// blocking ! | ||
40 | int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length); | ||
41 | int usb_drv_recv_setup(struct usb_ctrlrequest *req); | ||
42 | void usb_drv_set_address(int address); | ||
43 | int usb_drv_port_speed(void); | ||
44 | void usb_drv_configure_endpoint(int ep_num, int type); | ||
45 | |||
46 | #endif /* _USB_DRV_H */ | ||
47 | |||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Driver for ARC USBOTG Device Controller | ||
11 | * | ||
12 | * Copyright (C) 2007 by Björn Stenberg | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version 2 | ||
17 | * of the License, or (at your option) any later version. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | #include "usb_drv.h" | ||
24 | #include "config.h" | ||
25 | #include "memory.h" | ||
26 | |||
27 | #define MAX_PKT_SIZE 1024 | ||
28 | #define MAX_PKT_SIZE_EP0 64 | ||
29 | |||
30 | /* USB device mode registers (Little Endian) */ | ||
31 | #define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140)) | ||
32 | #define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154)) | ||
33 | #define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158)) | ||
34 | #define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184)) | ||
35 | #define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8)) | ||
36 | #define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac)) | ||
37 | #define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0)) | ||
38 | #define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8)) | ||
39 | #define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc)) | ||
40 | #define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0)) | ||
41 | #define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4)) | ||
42 | #define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8)) | ||
43 | #define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_))) | ||
44 | |||
45 | /* USB CMD Register Bit Masks */ | ||
46 | #define USBCMD_RUN (0x00000001) | ||
47 | #define USBCMD_CTRL_RESET (0x00000002) | ||
48 | #define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010) | ||
49 | #define USBCMD_ASYNC_SCHEDULE_EN (0x00000020) | ||
50 | #define USBCMD_INT_AA_DOORBELL (0x00000040) | ||
51 | #define USBCMD_ASP (0x00000300) | ||
52 | #define USBCMD_ASYNC_SCH_PARK_EN (0x00000800) | ||
53 | #define USBCMD_SUTW (0x00002000) | ||
54 | #define USBCMD_ATDTW (0x00004000) | ||
55 | #define USBCMD_ITC (0x00FF0000) | ||
56 | |||
57 | /* Device Address bit masks */ | ||
58 | #define USBDEVICEADDRESS_MASK (0xFE000000) | ||
59 | #define USBDEVICEADDRESS_BIT_POS (25) | ||
60 | |||
61 | /* Endpoint Setup Status bit masks */ | ||
62 | #define EPSETUP_STATUS_EP0 (0x00000001) | ||
63 | |||
64 | /* PORTSCX Register Bit Masks */ | ||
65 | #define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001) | ||
66 | #define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002) | ||
67 | #define PORTSCX_PORT_ENABLE (0x00000004) | ||
68 | #define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008) | ||
69 | #define PORTSCX_OVER_CURRENT_ACT (0x00000010) | ||
70 | #define PORTSCX_OVER_CURRENT_CHG (0x00000020) | ||
71 | #define PORTSCX_PORT_FORCE_RESUME (0x00000040) | ||
72 | #define PORTSCX_PORT_SUSPEND (0x00000080) | ||
73 | #define PORTSCX_PORT_RESET (0x00000100) | ||
74 | #define PORTSCX_LINE_STATUS_BITS (0x00000C00) | ||
75 | #define PORTSCX_PORT_POWER (0x00001000) | ||
76 | #define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000) | ||
77 | #define PORTSCX_PORT_TEST_CTRL (0x000F0000) | ||
78 | #define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000) | ||
79 | #define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000) | ||
80 | #define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000) | ||
81 | #define PORTSCX_PHY_LOW_POWER_SPD (0x00800000) | ||
82 | #define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000) | ||
83 | #define PORTSCX_PORT_SPEED_MASK (0x0C000000) | ||
84 | #define PORTSCX_PORT_WIDTH (0x10000000) | ||
85 | #define PORTSCX_PHY_TYPE_SEL (0xC0000000) | ||
86 | |||
87 | /* bit 11-10 are line status */ | ||
88 | #define PORTSCX_LINE_STATUS_SE0 (0x00000000) | ||
89 | #define PORTSCX_LINE_STATUS_JSTATE (0x00000400) | ||
90 | #define PORTSCX_LINE_STATUS_KSTATE (0x00000800) | ||
91 | #define PORTSCX_LINE_STATUS_UNDEF (0x00000C00) | ||
92 | #define PORTSCX_LINE_STATUS_BIT_POS (10) | ||
93 | |||
94 | /* bit 15-14 are port indicator control */ | ||
95 | #define PORTSCX_PIC_OFF (0x00000000) | ||
96 | #define PORTSCX_PIC_AMBER (0x00004000) | ||
97 | #define PORTSCX_PIC_GREEN (0x00008000) | ||
98 | #define PORTSCX_PIC_UNDEF (0x0000C000) | ||
99 | #define PORTSCX_PIC_BIT_POS (14) | ||
100 | |||
101 | /* bit 19-16 are port test control */ | ||
102 | #define PORTSCX_PTC_DISABLE (0x00000000) | ||
103 | #define PORTSCX_PTC_JSTATE (0x00010000) | ||
104 | #define PORTSCX_PTC_KSTATE (0x00020000) | ||
105 | #define PORTSCX_PTC_SE0NAK (0x00030000) | ||
106 | #define PORTSCX_PTC_PACKET (0x00040000) | ||
107 | #define PORTSCX_PTC_FORCE_EN (0x00050000) | ||
108 | #define PORTSCX_PTC_BIT_POS (16) | ||
109 | |||
110 | /* bit 27-26 are port speed */ | ||
111 | #define PORTSCX_PORT_SPEED_FULL (0x00000000) | ||
112 | #define PORTSCX_PORT_SPEED_LOW (0x04000000) | ||
113 | #define PORTSCX_PORT_SPEED_HIGH (0x08000000) | ||
114 | #define PORTSCX_PORT_SPEED_UNDEF (0x0C000000) | ||
115 | #define PORTSCX_SPEED_BIT_POS (26) | ||
116 | |||
117 | /* bit 28 is parallel transceiver width for UTMI interface */ | ||
118 | #define PORTSCX_PTW (0x10000000) | ||
119 | #define PORTSCX_PTW_8BIT (0x00000000) | ||
120 | #define PORTSCX_PTW_16BIT (0x10000000) | ||
121 | |||
122 | /* bit 31-30 are port transceiver select */ | ||
123 | #define PORTSCX_PTS_UTMI (0x00000000) | ||
124 | #define PORTSCX_PTS_CLASSIC (0x40000000) | ||
125 | #define PORTSCX_PTS_ULPI (0x80000000) | ||
126 | #define PORTSCX_PTS_FSLS (0xC0000000) | ||
127 | #define PORTSCX_PTS_BIT_POS (30) | ||
128 | |||
129 | /* USB MODE Register Bit Masks */ | ||
130 | #define USBMODE_CTRL_MODE_IDLE (0x00000000) | ||
131 | #define USBMODE_CTRL_MODE_DEVICE (0x00000002) | ||
132 | #define USBMODE_CTRL_MODE_HOST (0x00000003) | ||
133 | #define USBMODE_CTRL_MODE_RSV (0x00000001) | ||
134 | #define USBMODE_SETUP_LOCK_OFF (0x00000008) | ||
135 | #define USBMODE_STREAM_DISABLE (0x00000010) | ||
136 | |||
137 | /* ENDPOINTCTRLx Register Bit Masks */ | ||
138 | #define EPCTRL_TX_ENABLE (0x00800000) | ||
139 | #define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */ | ||
140 | #define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */ | ||
141 | #define EPCTRL_TX_TYPE (0x000C0000) | ||
142 | #define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */ | ||
143 | #define EPCTRL_TX_EP_STALL (0x00010000) | ||
144 | #define EPCTRL_RX_ENABLE (0x00000080) | ||
145 | #define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */ | ||
146 | #define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */ | ||
147 | #define EPCTRL_RX_TYPE (0x0000000C) | ||
148 | #define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */ | ||
149 | #define EPCTRL_RX_EP_STALL (0x00000001) | ||
150 | |||
151 | /* bit 19-18 and 3-2 are endpoint type */ | ||
152 | #define EPCTRL_TX_EP_TYPE_SHIFT (18) | ||
153 | #define EPCTRL_RX_EP_TYPE_SHIFT (2) | ||
154 | |||
155 | #define QH_MULT_POS (30) | ||
156 | #define QH_ZLT_SEL (0x20000000) | ||
157 | #define QH_MAX_PKT_LEN_POS (16) | ||
158 | #define QH_IOS (0x00008000) | ||
159 | #define QH_NEXT_TERMINATE (0x00000001) | ||
160 | #define QH_IOC (0x00008000) | ||
161 | #define QH_MULTO (0x00000C00) | ||
162 | #define QH_STATUS_HALT (0x00000040) | ||
163 | #define QH_STATUS_ACTIVE (0x00000080) | ||
164 | #define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF) | ||
165 | #define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0) | ||
166 | #define EP_QUEUE_FRINDEX_MASK (0x000007FF) | ||
167 | #define EP_MAX_LENGTH_TRANSFER (0x4000) | ||
168 | |||
169 | #define DTD_NEXT_TERMINATE (0x00000001) | ||
170 | #define DTD_IOC (0x00008000) | ||
171 | #define DTD_STATUS_ACTIVE (0x00000080) | ||
172 | #define DTD_STATUS_HALTED (0x00000040) | ||
173 | #define DTD_STATUS_DATA_BUFF_ERR (0x00000020) | ||
174 | #define DTD_STATUS_TRANSACTION_ERR (0x00000008) | ||
175 | #define DTD_RESERVED_FIELDS (0x80007300) | ||
176 | #define DTD_ADDR_MASK (0xFFFFFFE0) | ||
177 | #define DTD_PACKET_SIZE (0x7FFF0000) | ||
178 | #define DTD_LENGTH_BIT_POS (16) | ||
179 | #define DTD_ERROR_MASK (DTD_STATUS_HALTED | \ | ||
180 | DTD_STATUS_DATA_BUFF_ERR | \ | ||
181 | DTD_STATUS_TRANSACTION_ERR) | ||
182 | /*-------------------------------------------------------------------------*/ | ||
183 | /* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */ | ||
184 | struct transfer_descriptor { | ||
185 | unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set | ||
186 | indicate invalid */ | ||
187 | unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15), | ||
188 | MultO(11-10), STS (7-0) */ | ||
189 | unsigned int buff_ptr0; /* Buffer pointer Page 0 */ | ||
190 | unsigned int buff_ptr1; /* Buffer pointer Page 1 */ | ||
191 | unsigned int buff_ptr2; /* Buffer pointer Page 2 */ | ||
192 | unsigned int buff_ptr3; /* Buffer pointer Page 3 */ | ||
193 | unsigned int buff_ptr4; /* Buffer pointer Page 4 */ | ||
194 | unsigned int reserved; | ||
195 | } __attribute__ ((packed)); | ||
196 | |||
197 | static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2] | ||
198 | __attribute__((aligned(32))); | ||
199 | |||
200 | /* manual: 32.13.1 Endpoint Queue Head (dQH) */ | ||
201 | struct queue_head { | ||
202 | unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len | ||
203 | and IOS(15) */ | ||
204 | unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */ | ||
205 | struct transfer_descriptor dtd; /* dTD overlay */ | ||
206 | unsigned int setup_buffer[2]; /* Setup data 8 bytes */ | ||
207 | unsigned int reserved; /* for software use, pointer to the first TD */ | ||
208 | unsigned int status; /* for software use, status of chain in progress */ | ||
209 | unsigned int length; /* for software use, transfered bytes of chain in progress */ | ||
210 | unsigned int wait; /* for softwate use, indicates if the transfer is blocking */ | ||
211 | } __attribute__((packed)); | ||
212 | |||
213 | static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] __attribute__((aligned(2048))); | ||
214 | |||
215 | static const unsigned int pipe2mask[] = { | ||
216 | 0x01, 0x010000, | ||
217 | 0x02, 0x020000, | ||
218 | 0x04, 0x040000, | ||
219 | 0x08, 0x080000, | ||
220 | 0x10, 0x100000, | ||
221 | }; | ||
222 | |||
223 | /* return transfered size if wait=true */ | ||
224 | static int prime_transfer(int ep_num, void *ptr, int len, bool send, bool wait) | ||
225 | { | ||
226 | int pipe = ep_num * 2 + (send ? 1 : 0); | ||
227 | unsigned mask = pipe2mask[pipe]; | ||
228 | struct transfer_descriptor *td = &td_array[pipe]; | ||
229 | struct queue_head* qh = &qh_array[pipe]; | ||
230 | |||
231 | /* prepare TD */ | ||
232 | td->next_td_ptr = DTD_NEXT_TERMINATE; | ||
233 | td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE; | ||
234 | td->buff_ptr0 = (unsigned int)ptr; | ||
235 | td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000; | ||
236 | td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000; | ||
237 | td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000; | ||
238 | td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000; | ||
239 | td->reserved = 0; | ||
240 | /* prime */ | ||
241 | qh->dtd.next_td_ptr = (unsigned int)td; | ||
242 | qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); | ||
243 | REG_ENDPTPRIME |= mask; | ||
244 | /* wait for priming to be taken into account */ | ||
245 | while(!(REG_ENDPTSTATUS & mask)); | ||
246 | /* wait for completion */ | ||
247 | if(wait) | ||
248 | { | ||
249 | while(!(REG_ENDPTCOMPLETE & mask)); | ||
250 | REG_ENDPTCOMPLETE = mask; | ||
251 | /* memory barrier */ | ||
252 | asm volatile("":::"memory"); | ||
253 | /* return transfered size */ | ||
254 | return len - (td->size_ioc_sts >> DTD_LENGTH_BIT_POS); | ||
255 | } | ||
256 | else | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | void usb_drv_set_address(int address) | ||
261 | { | ||
262 | REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS; | ||
263 | } | ||
264 | |||
265 | /* endpoints */ | ||
266 | |||
267 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) | ||
268 | { | ||
269 | return prime_transfer(EP_NUM(endpoint), ptr, length, true, false); | ||
270 | } | ||
271 | |||
272 | int usb_drv_send(int endpoint, void* ptr, int length) | ||
273 | { | ||
274 | return prime_transfer(EP_NUM(endpoint), ptr, length, true, true); | ||
275 | } | ||
276 | |||
277 | int usb_drv_recv(int endpoint, void* ptr, int length) | ||
278 | { | ||
279 | return prime_transfer(EP_NUM(endpoint), ptr, length, false, true); | ||
280 | } | ||
281 | |||
282 | int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length) | ||
283 | { | ||
284 | return prime_transfer(EP_NUM(endpoint), ptr, length, false, false); | ||
285 | } | ||
286 | |||
287 | int usb_drv_port_speed(void) | ||
288 | { | ||
289 | return (REG_PORTSC1 & 0x08000000) ? 1 : 0; | ||
290 | } | ||
291 | |||
292 | void usb_drv_stall(int endpoint, bool stall, bool in) | ||
293 | { | ||
294 | int ep_num = EP_NUM(endpoint); | ||
295 | |||
296 | if(in) | ||
297 | { | ||
298 | if(stall) | ||
299 | REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL; | ||
300 | else | ||
301 | REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL; | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | if (stall) | ||
306 | REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL; | ||
307 | else | ||
308 | REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | void usb_drv_configure_endpoint(int ep_num, int type) | ||
313 | { | ||
314 | REG_ENDPTCTRL(ep_num) = | ||
315 | EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | | ||
316 | EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | | ||
317 | (type << EPCTRL_RX_EP_TYPE_SHIFT) | | ||
318 | (type << EPCTRL_TX_EP_TYPE_SHIFT); | ||
319 | } | ||
320 | |||
321 | void usb_drv_init(void) | ||
322 | { | ||
323 | /* we don't know if USB was connected or not. In USB recovery mode it will | ||
324 | * but in other cases it might not be. In doubt, disconnect */ | ||
325 | REG_USBCMD &= ~USBCMD_RUN; | ||
326 | /* reset the controller */ | ||
327 | REG_USBCMD |= USBCMD_CTRL_RESET; | ||
328 | while (REG_USBCMD & USBCMD_CTRL_RESET); | ||
329 | /* put it in device mode */ | ||
330 | REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; | ||
331 | /* reset address */ | ||
332 | REG_DEVICEADDR = 0; | ||
333 | /* prepare qh array */ | ||
334 | qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16; | ||
335 | qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16; | ||
336 | qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16; | ||
337 | qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16; | ||
338 | /* setup qh */ | ||
339 | REG_ENDPOINTLISTADDR = (unsigned int)qh_array; | ||
340 | /* clear setup status */ | ||
341 | REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0; | ||
342 | /* run! */ | ||
343 | REG_USBCMD |= USBCMD_RUN; | ||
344 | } | ||
345 | |||
346 | void usb_drv_exit(void) | ||
347 | { | ||
348 | REG_USBCMD &= ~USBCMD_RUN; | ||
349 | REG_USBCMD |= USBCMD_CTRL_RESET; | ||
350 | } | ||
351 | |||
352 | int usb_drv_recv_setup(struct usb_ctrlrequest *req) | ||
353 | { | ||
354 | /* wait for setup */ | ||
355 | while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0)) | ||
356 | ; | ||
357 | /* clear setup status */ | ||
358 | REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0; | ||
359 | /* check request */ | ||
360 | asm volatile("":::"memory"); | ||
361 | /* copy */ | ||
362 | memcpy(req, (void *)&qh_array[0].setup_buffer[0], sizeof(struct usb_ctrlrequest)); | ||
363 | return 0; | ||
364 | } | ||