summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-11-14 12:51:51 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-11-14 12:51:51 +0100
commitf44d95630c1629627b99a2ccf06b434d23027bb3 (patch)
treeb93bef2c03028e0af42e840a6e5944eead2c082b
parentec2153f2dd265129c69c690f9c6c19b61ba9bf18 (diff)
downloadrockbox-f44d95630c1629627b99a2ccf06b434d23027bb3.tar.gz
rockbox-f44d95630c1629627b99a2ccf06b434d23027bb3.zip
imxtools: introduce hwemul
The hwemul tool is a small binary blob running on the device that can received commands over USB. It is mainly intended to be loaded using the recory mode and allows to read/write registers, memory, use the OTP device, ... The tool is split into three parts: dev/ contains the actual blob (which handles both imx233 and stmp3700), lib/ contains the communication library and can also use the register description produced by the regtools/ to ease register by name, tools/ contains an interactive tool to send commands to the device when running the blob. Change-Id: Ie8cb32e987f825d8ed750d48071e43415b4dacb3
-rw-r--r--utils/imxtools/hwemul/dev/Makefile91
-rw-r--r--utils/imxtools/hwemul/dev/config.h33
-rw-r--r--utils/imxtools/hwemul/dev/crt0.S17
-rw-r--r--utils/imxtools/hwemul/dev/format.c223
-rw-r--r--utils/imxtools/hwemul/dev/format.h29
-rw-r--r--utils/imxtools/hwemul/dev/hwemul.db31
-rw-r--r--utils/imxtools/hwemul/dev/hwemul.lds70
-rw-r--r--utils/imxtools/hwemul/dev/link.lds49
-rw-r--r--utils/imxtools/hwemul/dev/logf.c68
-rw-r--r--utils/imxtools/hwemul/dev/logf.h31
-rw-r--r--utils/imxtools/hwemul/dev/main.c1512
-rw-r--r--utils/imxtools/hwemul/dev/protocol.h1
-rw-r--r--utils/imxtools/hwemul/dev/stddef.h32
-rw-r--r--utils/imxtools/hwemul/dev/stdint.h38
-rw-r--r--utils/imxtools/hwemul/dev/string.c29
-rw-r--r--utils/imxtools/hwemul/dev/string.h30
-rw-r--r--utils/imxtools/hwemul/dev/system.h118
-rw-r--r--utils/imxtools/hwemul/dev/usb_ch9.h454
-rw-r--r--utils/imxtools/hwemul/hwemul_protocol.h127
-rw-r--r--utils/imxtools/hwemul/lib/Makefile27
-rw-r--r--utils/imxtools/hwemul/lib/hwemul.c175
-rw-r--r--utils/imxtools/hwemul/lib/hwemul.h63
-rw-r--r--utils/imxtools/hwemul/lib/hwemul_protocol.h1
-rw-r--r--utils/imxtools/hwemul/tools/Makefile22
-rwxr-xr-xutils/imxtools/hwemul/tools/hwemul_toolbin0 -> 1354604 bytes
-rw-r--r--utils/imxtools/hwemul/tools/hwemul_tool.c558
26 files changed, 3829 insertions, 0 deletions
diff --git a/utils/imxtools/hwemul/dev/Makefile b/utils/imxtools/hwemul/dev/Makefile
new file mode 100644
index 0000000000..9bae1df21b
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/Makefile
@@ -0,0 +1,91 @@
1CC=arm-elf-eabi-gcc
2LD=arm-elf-eabi-gcc
3AS=arm-elf-eabi-gcc
4OC=arm-elf-eabi-objcopy
5SBTOOLS=../../sbtools/
6CFLAGS=-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -mcpu=arm926ej-s -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init -ffunction-sections
7CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700
8ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
9ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__
10OCFLAGS=
11LINKER_FILE=hwemul.lds
12LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map
13LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map
14SRC_C=$(wildcard *.c)
15SRC_S=$(wildcard *.S)
16OBJ_C=$(SRC_C:.c=.o)
17OBJ_S=$(SRC_S:.S=.o)
18OBJ_C_3700=$(SRC_C:.c=.3700.o)
19OBJ_S_3700=$(SRC_S:.S=.3700.o)
20OBJ=$(OBJ_C) $(OBJ_S)
21OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700)
22OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
23OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700))
24DEPS=$(OBJ:.o=.d)
25EXEC_ELF=hwemul.elf
26EXEC_SB=hwemul.sb
27EXEC_ELF_3700=hwemul3700.elf
28EXEC_SB_3700=hwemul3700.sb
29
30ELF2SB=$(SBTOOLS)/elftosb -d
31ELF2SB_CMD=-c hwemul.db
32ELF2SB_KEY=-z
33SBLOADER=$(SBTOOLS)/sbloader
34SBLOADER_CMD=0 $(EXEC_SB)
35SBLOADER_CMD_3700=0 $(EXEC_SB_3700)
36
37TOOLS=../../../../tools/
38SCRAMBLE=$(TOOLS)/scramble
39
40EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700)
41
42all: $(EXEC)
43
44# pull in dependency info for *existing* .o files
45-include $(DEPS)
46
47%.3700.o: %.c
48 $(CC) $(CFLAGS_3700) -c -o $@ $<
49 $(CC) -MM $(CFLAGS_3700) $*.c > $*.d
50 @cp -f $*.d $*.d.tmp
51 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
52 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
53 @rm -f $*.d.tmp
54
55%.o: %.c
56 $(CC) $(CFLAGS) -c -o $@ $<
57 $(CC) -MM $(CFLAGS) $*.c > $*.d
58 @cp -f $*.d $*.d.tmp
59 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
60 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
61 @rm -f $*.d.tmp
62
63%.3700.o: %.S
64 $(AS) $(ASFLAGS_3700) -c -o $@ $<
65
66%.o: %.S
67 $(AS) $(ASFLAGS) -c -o $@ $<
68
69link.lds: $(LINKER_FILE)
70 $(CC) -E -x c - < $< | sed '/#/d' > $@
71
72$(EXEC_ELF): $(OBJ) link.lds
73 $(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
74
75$(EXEC_SB): $(EXEC_ELF)
76 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
77
78$(EXEC_ELF_3700): $(OBJ_3700) link.lds
79 $(LD) $(LDFLAGS_3700) -o $@ $(OBJ_EXCEPT_CRT0_3700)
80
81$(EXEC_SB_3700): $(EXEC_ELF_3700)
82 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
83
84sbload: $(EXEC_SB)
85 $(SBLOADER) $(SBLOADER_CMD)
86
87sbload3700: $(EXEC_SB_3700)
88 $(SBLOADER) $(SBLOADER_CMD_3700)
89
90clean:
91 rm -rf $(OBJ) $(OBJ_3700) $(DEPS) $(EXEC) *.map
diff --git a/utils/imxtools/hwemul/dev/config.h b/utils/imxtools/hwemul/dev/config.h
new file mode 100644
index 0000000000..6bd995e147
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/config.h
@@ -0,0 +1,33 @@
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 __HWEMUL_CONFIG__
22#define __HWEMUL_CONFIG__
23
24#define MEMORYSIZE 0
25#define STACK_SIZE 0x1000
26#define MAX_LOGF_SIZE 128
27
28#define IRAM_ORIG 0
29#define IRAM_SIZE 0x8000
30#define DRAM_ORIG 0x40000000
31#define DRAM_SIZE (MEMORYSIZE * 0x100000)
32
33#endif /* __HWEMUL_CONFIG__ */
diff --git a/utils/imxtools/hwemul/dev/crt0.S b/utils/imxtools/hwemul/dev/crt0.S
new file mode 100644
index 0000000000..e2d4742d36
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/crt0.S
@@ -0,0 +1,17 @@
1.section .text,"ax",%progbits
2.code 32
3.align 0x04
4.global start
5start:
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
121:
13 cmp r3, r2
14 strhi r4, [r2], #4
15 bhi 1b
16 /* jump to C code */
17 b main
diff --git a/utils/imxtools/hwemul/dev/format.c b/utils/imxtools/hwemul/dev/format.c
new file mode 100644
index 0000000000..f5783159c0
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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
29static const char hexdigit[] = "0123456789ABCDEF";
30
31void 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/imxtools/hwemul/dev/format.h b/utils/imxtools/hwemul/dev/format.h
new file mode 100644
index 0000000000..a514c882ba
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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 __HWEMUL_FORMAT__
22#define __HWEMUL_FORMAT__
23
24#include <stdarg.h>
25
26void vuprintf(int (*push)(void *userp, unsigned char data),
27 void *userp, const char *fmt, va_list ap);
28
29#endif /* __HWEMUL_FORMAT__ */
diff --git a/utils/imxtools/hwemul/dev/hwemul.db b/utils/imxtools/hwemul/dev/hwemul.db
new file mode 100644
index 0000000000..7a6f930f57
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/hwemul.db
@@ -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 ****************************************************************************/
21sources
22{
23 hwemul = "hwemul.elf";
24}
25
26section(0)
27{
28 load hwemul;
29 jump hwemul(1);
30}
31
diff --git a/utils/imxtools/hwemul/dev/hwemul.lds b/utils/imxtools/hwemul/dev/hwemul.lds
new file mode 100644
index 0000000000..7e3ac747a2
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/hwemul.lds
@@ -0,0 +1,70 @@
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
23ENTRY(start)
24OUTPUT_FORMAT(elf32-littlearm)
25OUTPUT_ARCH(arm)
26STARTUP(crt0.o)
27
28#define IRAM_END_ADDR (IRAM_ORIG + IRAM_SIZE)
29
30MEMORY
31{
32 OCRAM : ORIGIN = IRAM_ORIG, LENGTH = IRAM_SIZE
33}
34
35SECTIONS
36{
37 .octext :
38 {
39 oc_codestart = .;
40 *(.text*)
41 *(.data*)
42 *(.rodata*)
43 } > OCRAM
44
45 .bss (NOLOAD) :
46 {
47 bss_start = .;
48 *(.bss)
49 bss_end = .;
50 } > OCRAM
51
52 .stack (NOLOAD) :
53 {
54 oc_codeend = .;
55 oc_stackstart = .;
56 . += STACK_SIZE;
57 oc_stackend = .;
58 oc_bufferstart = .;
59 } > OCRAM
60
61 .ocend IRAM_END_ADDR (NOLOAD) :
62 {
63 oc_bufferend = .;
64 } > OCRAM
65
66 /DISCARD/ :
67 {
68 *(.eh_frame)
69 }
70}
diff --git a/utils/imxtools/hwemul/dev/link.lds b/utils/imxtools/hwemul/dev/link.lds
new file mode 100644
index 0000000000..97b259955f
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/link.lds
@@ -0,0 +1,49 @@
1
2ENTRY(start)
3OUTPUT_FORMAT(elf32-littlearm)
4OUTPUT_ARCH(arm)
5STARTUP(crt0.o)
6
7
8
9MEMORY
10{
11 OCRAM : ORIGIN = 0, LENGTH = 0x8000
12}
13
14SECTIONS
15{
16 .octext :
17 {
18 oc_codestart = .;
19 *(.text*)
20 *(.data*)
21 *(.rodata*)
22 } > OCRAM
23
24 .bss (NOLOAD) :
25 {
26 bss_start = .;
27 *(.bss)
28 bss_end = .;
29 } > OCRAM
30
31 .stack (NOLOAD) :
32 {
33 oc_codeend = .;
34 oc_stackstart = .;
35 . += 0x1000;
36 oc_stackend = .;
37 oc_bufferstart = .;
38 } > OCRAM
39
40 .ocend (0 + 0x8000) (NOLOAD) :
41 {
42 oc_bufferend = .;
43 } > OCRAM
44
45 /DISCARD/ :
46 {
47 *(.eh_frame)
48 }
49}
diff --git a/utils/imxtools/hwemul/dev/logf.c b/utils/imxtools/hwemul/dev/logf.c
new file mode 100644
index 0000000000..3ccc5c5e9f
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/logf.c
@@ -0,0 +1,68 @@
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
26static unsigned char logfbuffer[MAX_LOGF_SIZE];
27static int logfread = 0;
28static int logfwrite = 0;
29static int logfen = true;
30
31void enable_logf(bool en)
32{
33 logfen = en;
34}
35
36static int logf_push(void *userp, unsigned char c)
37{
38 (void)userp;
39
40 logfbuffer[logfwrite++] = c;
41 if(logfwrite == MAX_LOGF_SIZE)
42 logfwrite = 0;
43 return true;
44}
45
46void logf(const char *fmt, ...)
47{
48 if(!logfen) return;
49 va_list ap;
50 va_start(ap, fmt);
51 vuprintf(logf_push, NULL, fmt, ap);
52 va_end(ap);
53}
54
55size_t logf_readback(char *buf, size_t max_size)
56{
57 if(logfread == logfwrite)
58 return 0;
59 if(logfread < logfwrite)
60 max_size = MIN(max_size, (size_t)(logfwrite - logfread));
61 else
62 max_size = MIN(max_size, (size_t)(MAX_LOGF_SIZE - logfread));
63 memcpy(buf, &logfbuffer[logfread], max_size);
64 logfread += max_size;
65 if(logfread == MAX_LOGF_SIZE)
66 logfread = 0;
67 return max_size;
68}
diff --git a/utils/imxtools/hwemul/dev/logf.h b/utils/imxtools/hwemul/dev/logf.h
new file mode 100644
index 0000000000..5aa882a630
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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 __HWEMUL_LOGF__
22#define __HWEMUL_LOGF__
23
24#include "stddef.h"
25#include <stdarg.h>
26
27void enable_logf(bool en);
28void logf(const char *fmt, ...);
29size_t logf_readback(char *buf, size_t max_size);
30
31#endif /* __HWEMUL_LOGF__ */
diff --git a/utils/imxtools/hwemul/dev/main.c b/utils/imxtools/hwemul/dev/main.c
new file mode 100644
index 0000000000..3a4d8620c0
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/main.c
@@ -0,0 +1,1512 @@
1#include "stddef.h"
2#include "protocol.h"
3#include "logf.h"
4#include "usb_ch9.h"
5
6extern unsigned char oc_codestart[];
7extern unsigned char oc_codeend[];
8extern unsigned char oc_stackstart[];
9extern unsigned char oc_stackend[];
10extern unsigned char oc_bufferstart[];
11extern unsigned char oc_bufferend[];
12
13#define oc_codesize ((size_t)(oc_codeend - oc_codestart))
14#define oc_stacksize ((size_t)(oc_stackend - oc_stackstart))
15#define oc_buffersize ((size_t)(oc_bufferend - oc_bufferstart))
16
17/**
18 *
19 * Common
20 *
21 */
22#define MIN(a,b) ((a) < (b) ? (a) : (b))
23
24#define __REG_SET(reg) (*((volatile uint32_t *)(&reg + 1)))
25#define __REG_CLR(reg) (*((volatile uint32_t *)(&reg + 2)))
26#define __REG_TOG(reg) (*((volatile uint32_t *)(&reg + 3)))
27
28#define __BLOCK_SFTRST (1 << 31)
29#define __BLOCK_CLKGATE (1 << 30)
30
31#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
32#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
33#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
34
35/**
36 *
37 * Pin control
38 *
39 */
40
41#define HW_PINCTRL_BASE 0x80018000
42
43#define HW_PINCTRL_CTRL (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x0))
44#define HW_PINCTRL_MUXSEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x100 + (i) * 0x10))
45#define HW_PINCTRL_DRIVE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x200 + (i) * 0x10))
46#ifdef HAVE_STMP3700
47#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x300 + (i) * 0x10))
48#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
49#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
50#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
51#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
52#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
53#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
54#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
55#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
56#else
57#define HW_PINCTRL_PULL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x400 + (i) * 0x10))
58#define HW_PINCTRL_DOUT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x500 + (i) * 0x10))
59#define HW_PINCTRL_DIN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x600 + (i) * 0x10))
60#define HW_PINCTRL_DOE(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x700 + (i) * 0x10))
61#define HW_PINCTRL_PIN2IRQ(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x800 + (i) * 0x10))
62#define HW_PINCTRL_IRQEN(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0x900 + (i) * 0x10))
63#define HW_PINCTRL_IRQLEVEL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xa00 + (i) * 0x10))
64#define HW_PINCTRL_IRQPOL(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xb00 + (i) * 0x10))
65#define HW_PINCTRL_IRQSTAT(i) (*(volatile uint32_t *)(HW_PINCTRL_BASE + 0xc00 + (i) * 0x10))
66#endif
67
68#define PINCTRL_FUNCTION_MAIN 0
69#define PINCTRL_FUNCTION_ALT1 1
70#define PINCTRL_FUNCTION_ALT2 2
71#define PINCTRL_FUNCTION_GPIO 3
72
73#define PINCTRL_DRIVE_4mA 0
74#define PINCTRL_DRIVE_8mA 1
75#define PINCTRL_DRIVE_12mA 2
76#define PINCTRL_DRIVE_16mA 3 /* not available on all pins */
77
78typedef void (*pin_irq_cb_t)(int bank, int pin);
79
80static inline void imx233_pinctrl_init(void)
81{
82 __REG_CLR(HW_PINCTRL_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
83}
84
85static inline void imx233_set_pin_drive_strength(unsigned bank, unsigned pin, unsigned strength)
86{
87 __REG_CLR(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = 3 << (4 * (pin % 8));
88 __REG_SET(HW_PINCTRL_DRIVE(4 * bank + pin / 8)) = strength << (4 * (pin % 8));
89}
90
91static inline void imx233_enable_gpio_output(unsigned bank, unsigned pin, bool enable)
92{
93 if(enable)
94 __REG_SET(HW_PINCTRL_DOE(bank)) = 1 << pin;
95 else
96 __REG_CLR(HW_PINCTRL_DOE(bank)) = 1 << pin;
97}
98
99static inline void imx233_enable_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool enable)
100{
101 if(enable)
102 __REG_SET(HW_PINCTRL_DOE(bank)) = pin_mask;
103 else
104 __REG_CLR(HW_PINCTRL_DOE(bank)) = pin_mask;
105}
106
107static inline void imx233_set_gpio_output(unsigned bank, unsigned pin, bool value)
108{
109 if(value)
110 __REG_SET(HW_PINCTRL_DOUT(bank)) = 1 << pin;
111 else
112 __REG_CLR(HW_PINCTRL_DOUT(bank)) = 1 << pin;
113}
114
115static inline void imx233_set_gpio_output_mask(unsigned bank, uint32_t pin_mask, bool value)
116{
117 if(value)
118 __REG_SET(HW_PINCTRL_DOUT(bank)) = pin_mask;
119 else
120 __REG_CLR(HW_PINCTRL_DOUT(bank)) = pin_mask;
121}
122
123static inline uint32_t imx233_get_gpio_input_mask(unsigned bank, uint32_t pin_mask)
124{
125 return HW_PINCTRL_DIN(bank) & pin_mask;
126}
127
128static inline void imx233_set_pin_function(unsigned bank, unsigned pin, unsigned function)
129{
130 __REG_CLR(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = 3 << (2 * (pin % 16));
131 __REG_SET(HW_PINCTRL_MUXSEL(2 * bank + pin / 16)) = function << (2 * (pin % 16));
132}
133
134static inline void imx233_enable_pin_pullup(unsigned bank, unsigned pin, bool enable)
135{
136 if(enable)
137 __REG_SET(HW_PINCTRL_PULL(bank)) = 1 << pin;
138 else
139 __REG_CLR(HW_PINCTRL_PULL(bank)) = 1 << pin;
140}
141
142static inline void imx233_enable_pin_pullup_mask(unsigned bank, uint32_t pin_msk, bool enable)
143{
144 if(enable)
145 __REG_SET(HW_PINCTRL_PULL(bank)) = pin_msk;
146 else
147 __REG_CLR(HW_PINCTRL_PULL(bank)) = pin_msk;
148}
149
150/**
151 *
152 * USB subsystem
153 *
154 */
155
156#define USB_BASE 0x80080000
157#define USB_NUM_ENDPOINTS 2
158#define MAX_PKT_SIZE 1024
159#define MAX_PKT_SIZE_EP0 64
160
161/* USB device mode registers (Little Endian) */
162#define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140))
163#define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154))
164#define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158))
165#define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184))
166#define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8))
167#define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac))
168#define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0))
169#define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8))
170#define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc))
171#define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0))
172#define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4))
173#define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8))
174#define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_)))
175
176/* USB CMD Register Bit Masks */
177#define USBCMD_RUN (0x00000001)
178#define USBCMD_CTRL_RESET (0x00000002)
179#define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010)
180#define USBCMD_ASYNC_SCHEDULE_EN (0x00000020)
181#define USBCMD_INT_AA_DOORBELL (0x00000040)
182#define USBCMD_ASP (0x00000300)
183#define USBCMD_ASYNC_SCH_PARK_EN (0x00000800)
184#define USBCMD_SUTW (0x00002000)
185#define USBCMD_ATDTW (0x00004000)
186#define USBCMD_ITC (0x00FF0000)
187
188/* Device Address bit masks */
189#define USBDEVICEADDRESS_MASK (0xFE000000)
190#define USBDEVICEADDRESS_BIT_POS (25)
191
192/* Endpoint Setup Status bit masks */
193#define EPSETUP_STATUS_EP0 (0x00000001)
194
195/* PORTSCX Register Bit Masks */
196#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001)
197#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002)
198#define PORTSCX_PORT_ENABLE (0x00000004)
199#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008)
200#define PORTSCX_OVER_CURRENT_ACT (0x00000010)
201#define PORTSCX_OVER_CURRENT_CHG (0x00000020)
202#define PORTSCX_PORT_FORCE_RESUME (0x00000040)
203#define PORTSCX_PORT_SUSPEND (0x00000080)
204#define PORTSCX_PORT_RESET (0x00000100)
205#define PORTSCX_LINE_STATUS_BITS (0x00000C00)
206#define PORTSCX_PORT_POWER (0x00001000)
207#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000)
208#define PORTSCX_PORT_TEST_CTRL (0x000F0000)
209#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000)
210#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000)
211#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000)
212#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000)
213#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000)
214#define PORTSCX_PORT_SPEED_MASK (0x0C000000)
215#define PORTSCX_PORT_WIDTH (0x10000000)
216#define PORTSCX_PHY_TYPE_SEL (0xC0000000)
217
218/* bit 11-10 are line status */
219#define PORTSCX_LINE_STATUS_SE0 (0x00000000)
220#define PORTSCX_LINE_STATUS_JSTATE (0x00000400)
221#define PORTSCX_LINE_STATUS_KSTATE (0x00000800)
222#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00)
223#define PORTSCX_LINE_STATUS_BIT_POS (10)
224
225/* bit 15-14 are port indicator control */
226#define PORTSCX_PIC_OFF (0x00000000)
227#define PORTSCX_PIC_AMBER (0x00004000)
228#define PORTSCX_PIC_GREEN (0x00008000)
229#define PORTSCX_PIC_UNDEF (0x0000C000)
230#define PORTSCX_PIC_BIT_POS (14)
231
232/* bit 19-16 are port test control */
233#define PORTSCX_PTC_DISABLE (0x00000000)
234#define PORTSCX_PTC_JSTATE (0x00010000)
235#define PORTSCX_PTC_KSTATE (0x00020000)
236#define PORTSCX_PTC_SE0NAK (0x00030000)
237#define PORTSCX_PTC_PACKET (0x00040000)
238#define PORTSCX_PTC_FORCE_EN (0x00050000)
239#define PORTSCX_PTC_BIT_POS (16)
240
241/* bit 27-26 are port speed */
242#define PORTSCX_PORT_SPEED_FULL (0x00000000)
243#define PORTSCX_PORT_SPEED_LOW (0x04000000)
244#define PORTSCX_PORT_SPEED_HIGH (0x08000000)
245#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000)
246#define PORTSCX_SPEED_BIT_POS (26)
247
248/* bit 28 is parallel transceiver width for UTMI interface */
249#define PORTSCX_PTW (0x10000000)
250#define PORTSCX_PTW_8BIT (0x00000000)
251#define PORTSCX_PTW_16BIT (0x10000000)
252
253/* bit 31-30 are port transceiver select */
254#define PORTSCX_PTS_UTMI (0x00000000)
255#define PORTSCX_PTS_CLASSIC (0x40000000)
256#define PORTSCX_PTS_ULPI (0x80000000)
257#define PORTSCX_PTS_FSLS (0xC0000000)
258#define PORTSCX_PTS_BIT_POS (30)
259
260/* USB MODE Register Bit Masks */
261#define USBMODE_CTRL_MODE_IDLE (0x00000000)
262#define USBMODE_CTRL_MODE_DEVICE (0x00000002)
263#define USBMODE_CTRL_MODE_HOST (0x00000003)
264#define USBMODE_CTRL_MODE_RSV (0x00000001)
265#define USBMODE_SETUP_LOCK_OFF (0x00000008)
266#define USBMODE_STREAM_DISABLE (0x00000010)
267
268/* ENDPOINTCTRLx Register Bit Masks */
269#define EPCTRL_TX_ENABLE (0x00800000)
270#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */
271#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */
272#define EPCTRL_TX_TYPE (0x000C0000)
273#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */
274#define EPCTRL_TX_EP_STALL (0x00010000)
275#define EPCTRL_RX_ENABLE (0x00000080)
276#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */
277#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */
278#define EPCTRL_RX_TYPE (0x0000000C)
279#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */
280#define EPCTRL_RX_EP_STALL (0x00000001)
281
282/* bit 19-18 and 3-2 are endpoint type */
283#define EPCTRL_TX_EP_TYPE_SHIFT (18)
284#define EPCTRL_RX_EP_TYPE_SHIFT (2)
285
286#define QH_MULT_POS (30)
287#define QH_ZLT_SEL (0x20000000)
288#define QH_MAX_PKT_LEN_POS (16)
289#define QH_IOS (0x00008000)
290#define QH_NEXT_TERMINATE (0x00000001)
291#define QH_IOC (0x00008000)
292#define QH_MULTO (0x00000C00)
293#define QH_STATUS_HALT (0x00000040)
294#define QH_STATUS_ACTIVE (0x00000080)
295#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
296#define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0)
297#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
298#define EP_MAX_LENGTH_TRANSFER (0x4000)
299
300#define DTD_NEXT_TERMINATE (0x00000001)
301#define DTD_IOC (0x00008000)
302#define DTD_STATUS_ACTIVE (0x00000080)
303#define DTD_STATUS_HALTED (0x00000040)
304#define DTD_STATUS_DATA_BUFF_ERR (0x00000020)
305#define DTD_STATUS_TRANSACTION_ERR (0x00000008)
306#define DTD_RESERVED_FIELDS (0x80007300)
307#define DTD_ADDR_MASK (0xFFFFFFE0)
308#define DTD_PACKET_SIZE (0x7FFF0000)
309#define DTD_LENGTH_BIT_POS (16)
310#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \
311 DTD_STATUS_DATA_BUFF_ERR | \
312 DTD_STATUS_TRANSACTION_ERR)
313/*-------------------------------------------------------------------------*/
314/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */
315struct transfer_descriptor {
316 unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set
317 indicate invalid */
318 unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15),
319 MultO(11-10), STS (7-0) */
320 unsigned int buff_ptr0; /* Buffer pointer Page 0 */
321 unsigned int buff_ptr1; /* Buffer pointer Page 1 */
322 unsigned int buff_ptr2; /* Buffer pointer Page 2 */
323 unsigned int buff_ptr3; /* Buffer pointer Page 3 */
324 unsigned int buff_ptr4; /* Buffer pointer Page 4 */
325 unsigned int reserved;
326} __attribute__ ((packed));
327
328static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2]
329 __attribute__((aligned(32)));
330
331/* manual: 32.13.1 Endpoint Queue Head (dQH) */
332struct queue_head {
333 unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len
334 and IOS(15) */
335 unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */
336 struct transfer_descriptor dtd; /* dTD overlay */
337 unsigned int setup_buffer[2]; /* Setup data 8 bytes */
338 unsigned int reserved; /* for software use, pointer to the first TD */
339 unsigned int status; /* for software use, status of chain in progress */
340 unsigned int length; /* for software use, transfered bytes of chain in progress */
341 unsigned int wait; /* for softwate use, indicates if the transfer is blocking */
342} __attribute__((packed));
343
344static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] __attribute__((aligned(2048)));
345
346static const unsigned int pipe2mask[] = {
347 0x01, 0x010000,
348 0x02, 0x020000,
349 0x04, 0x040000,
350 0x08, 0x080000,
351 0x10, 0x100000,
352};
353
354/* return transfered size if wait=true */
355static int prime_transfer(int ep_num, void *ptr, int len, bool send, bool wait)
356{
357 int pipe = ep_num * 2 + (send ? 1 : 0);
358 unsigned mask = pipe2mask[pipe];
359 struct transfer_descriptor *td = &td_array[pipe];
360 struct queue_head* qh = &qh_array[pipe];
361
362 /* prepare TD */
363 td->next_td_ptr = DTD_NEXT_TERMINATE;
364 td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE;
365 td->buff_ptr0 = (unsigned int)ptr;
366 td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
367 td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
368 td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
369 td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
370 td->reserved = 0;
371 /* prime */
372 qh->dtd.next_td_ptr = (unsigned int)td;
373 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
374 REG_ENDPTPRIME |= mask;
375 /* wait for priming to be taken into account */
376 while(!(REG_ENDPTSTATUS & mask));
377 /* wait for completion */
378 if(wait)
379 {
380 while(!(REG_ENDPTCOMPLETE & mask));
381 REG_ENDPTCOMPLETE = mask;
382 /* memory barrier */
383 asm volatile("":::"memory");
384 /* return transfered size */
385 return len - (td->size_ioc_sts >> DTD_LENGTH_BIT_POS);
386 }
387 else
388 return 0;
389}
390
391void usb_drv_set_address(int address)
392{
393 REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS;
394}
395
396/* endpoints */
397#define EP_CONTROL 0
398
399#define DIR_OUT 0
400#define DIR_IN 1
401
402#define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT)
403#define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK)
404
405static int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
406{
407 return prime_transfer(EP_NUM(endpoint), ptr, length, true, false);
408}
409
410static int usb_drv_send(int endpoint, void* ptr, int length)
411{
412 return prime_transfer(EP_NUM(endpoint), ptr, length, true, true);
413}
414
415static int usb_drv_recv(int endpoint, void* ptr, int length)
416{
417 return prime_transfer(EP_NUM(endpoint), ptr, length, false, true);
418}
419
420static int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length)
421{
422 return prime_transfer(EP_NUM(endpoint), ptr, length, false, false);
423}
424
425static int usb_drv_port_speed(void)
426{
427 return (REG_PORTSC1 & 0x08000000) ? 1 : 0;
428}
429
430static void usb_drv_stall(int endpoint, bool stall, bool in)
431{
432 int ep_num = EP_NUM(endpoint);
433
434 if(in)
435 {
436 if(stall)
437 REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL;
438 else
439 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL;
440 }
441 else
442 {
443 if (stall)
444 REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL;
445 else
446 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL;
447 }
448}
449
450static void usb_drv_configure_endpoint(int ep_num, int type)
451{
452 REG_ENDPTCTRL(ep_num) =
453 EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE |
454 EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE |
455 (type << EPCTRL_RX_EP_TYPE_SHIFT) |
456 (type << EPCTRL_TX_EP_TYPE_SHIFT);
457}
458
459/**
460 *
461 * Clock control
462 *
463 **/
464#define __CLK_CLKGATE (1 << 31)
465#define __CLK_BUSY (1 << 29)
466
467#define HW_CLKCTRL_BASE 0x80040000
468
469#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
470#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16)
471#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18)
472#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BP 20
473#define HW_CLKCTRL_PLLCTRL0__DIV_SEL_BM (3 << 20)
474
475#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
476
477#define HW_CLKCTRL_CPU (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
478#define HW_CLKCTRL_CPU__DIV_CPU_BP 0
479#define HW_CLKCTRL_CPU__DIV_CPU_BM 0x3f
480#define HW_CLKCTRL_CPU__INTERRUPT_WAIT (1 << 12)
481#define HW_CLKCTRL_CPU__DIV_XTAL_BP 16
482#define HW_CLKCTRL_CPU__DIV_XTAL_BM (0x3ff << 16)
483#define HW_CLKCTRL_CPU__DIV_XTAL_FRAC_EN (1 << 26)
484#define HW_CLKCTRL_CPU__BUSY_REF_CPU (1 << 28)
485
486#define HW_CLKCTRL_HBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
487#define HW_CLKCTRL_HBUS__DIV_BP 0
488#define HW_CLKCTRL_HBUS__DIV_BM 0x1f
489#define HW_CLKCTRL_HBUS__DIV_FRAC_EN (1 << 5)
490#define HW_CLKCTRL_HBUS__SLOW_DIV_BP 16
491#define HW_CLKCTRL_HBUS__SLOW_DIV_BM (0x7 << 16)
492#define HW_CLKCTRL_HBUS__AUTO_SLOW_MODE (1 << 20)
493
494#define HW_CLKCTRL_XBUS (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
495#define HW_CLKCTRL_XBUS__DIV_BP 0
496#define HW_CLKCTRL_XBUS__DIV_BM 0x3ff
497#define HW_CLKCTRL_XBUS__BUSY (1 << 31)
498
499#define HW_CLKCTRL_XTAL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x50))
500#define HW_CLKCTRL_XTAL__TIMROT_CLK32K_GATE (1 << 26)
501#define HW_CLKCTRL_XTAL__DRI_CLK24M_GATE (1 << 28)
502#define HW_CLKCTRL_XTAL__PWM_CLK24M_GATE (1 << 29)
503#define HW_CLKCTRL_XTAL__FILT_CLK24M_GATE (1 << 30)
504
505#define HW_CLKCTRL_PIX (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x60))
506#define HW_CLKCTRL_PIX__DIV_BP 0
507#define HW_CLKCTRL_PIX__DIV_BM 0xfff
508
509#define HW_CLKCTRL_SSP (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
510#define HW_CLKCTRL_SSP__DIV_BP 0
511#define HW_CLKCTRL_SSP__DIV_BM 0x1ff
512
513#define HW_CLKCTRL_EMI (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xa0))
514#define HW_CLKCTRL_EMI__DIV_EMI_BP 0
515#define HW_CLKCTRL_EMI__DIV_EMI_BM 0x3f
516#define HW_CLKCTRL_EMI__DIV_XTAL_BP 8
517#define HW_CLKCTRL_EMI__DIV_XTAL_BM (0xf << 8)
518#define HW_CLKCTRL_EMI__BUSY_REF_EMI (1 << 28)
519#define HW_CLKCTRL_EMI__SYNC_MODE_EN (1 << 30)
520#define HW_CLKCTRL_EMI__CLKGATE (1 << 31)
521
522#ifdef HAVE_STMP3770
523#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xe0))
524#else
525#define HW_CLKCTRL_CLKSEQ (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x110))
526#endif
527#define HW_CLKCTRL_CLKSEQ__BYPASS_PIX (1 << 1)
528#define HW_CLKCTRL_CLKSEQ__BYPASS_SSP (1 << 5)
529#define HW_CLKCTRL_CLKSEQ__BYPASS_EMI (1 << 6)
530#define HW_CLKCTRL_CLKSEQ__BYPASS_CPU (1 << 7)
531
532#ifdef HAVE_STMP3770
533#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xd0))
534#else
535#define HW_CLKCTRL_FRAC (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0xf0))
536#endif
537#define HW_CLKCTRL_FRAC_CPU (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf0))
538#define HW_CLKCTRL_FRAC_EMI (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf1))
539#define HW_CLKCTRL_FRAC_PIX (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf2))
540#define HW_CLKCTRL_FRAC_IO (*(volatile uint8_t *)(HW_CLKCTRL_BASE + 0xf3))
541#define HW_CLKCTRL_FRAC_XX__XXDIV_BM 0x3f
542#define HW_CLKCTRL_FRAC_XX__XX_STABLE (1 << 6)
543#define HW_CLKCTRL_FRAC_XX__CLKGATEXX (1 << 7)
544
545#define HW_CLKCTRL_RESET (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x120))
546#define HW_CLKCTRL_RESET_CHIP 0x2
547#define HW_CLKCTRL_RESET_DIG 0x1
548
549/**
550 *
551 * DMA
552 *
553 */
554
555/********
556 * APHB *
557 ********/
558
559#define HW_APBH_BASE 0x80004000
560
561/* APHB channels */
562#define HW_APBH_SSP(ssp) ssp
563
564#define HW_APBH_CTRL0 (*(volatile uint32_t *)(HW_APBH_BASE + 0x0))
565#define HW_APBH_CTRL0__FREEZE_CHANNEL(i) (1 << (i))
566#define HW_APBH_CTRL0__CLKGATE_CHANNEL(i) (1 << ((i) + 8))
567#define HW_APBH_CTRL0__RESET_CHANNEL(i) (1 << ((i) + 16))
568#define HW_APBH_CTRL0__APB_BURST4_EN (1 << 28)
569#define HW_APBH_CTRL0__APB_BURST8_EN (1 << 29)
570
571#define HW_APBH_CTRL1 (*(volatile uint32_t *)(HW_APBH_BASE + 0x10))
572#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
573#define HW_APBH_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
574
575#define HW_APBH_CTRL2 (*(volatile uint32_t *)(HW_APBH_BASE + 0x20))
576#define HW_APBH_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
577#define HW_APBH_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
578
579#define HW_APBH_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x40 + 0x70 * (i)))
580
581#define HW_APBH_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x50 + 0x70 * (i)))
582
583#define HW_APBH_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x60 + 0x70 * (i)))
584
585#define HW_APBH_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x70 + 0x70 * (i)))
586
587#define HW_APBH_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x80 + 0x70 * (i)))
588
589#define HW_APBH_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0x90 + 0x70 * (i)))
590
591#define HW_APBH_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBH_BASE + 0xa0 + 0x70 * (i)))
592#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BP 0
593#define HW_APBH_CHx_DEBUG2__AHB_BYTES_BM 0xffff
594#define HW_APBH_CHx_DEBUG2__APB_BYTES_BP 16
595#define HW_APBH_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
596
597/********
598 * APHX *
599 ********/
600
601/* APHX channels */
602#define HW_APBX_AUDIO_ADC 0
603#define HW_APBX_AUDIO_DAC 1
604#define HW_APBX_I2C 3
605
606#define HW_APBX_BASE 0x80024000
607
608#define HW_APBX_CTRL0 (*(volatile uint32_t *)(HW_APBX_BASE + 0x0))
609
610#define HW_APBX_CTRL1 (*(volatile uint32_t *)(HW_APBX_BASE + 0x10))
611#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ(i) (1 << (i))
612#define HW_APBX_CTRL1__CHx_CMDCMPLT_IRQ_EN(i) (1 << ((i) + 16))
613
614#define HW_APBX_CTRL2 (*(volatile uint32_t *)(HW_APBX_BASE + 0x20))
615#define HW_APBX_CTRL2__CHx_ERROR_IRQ(i) (1 << (i))
616#define HW_APBX_CTRL2__CHx_ERROR_STATUS(i) (1 << ((i) + 16))
617
618#define HW_APBX_CHANNEL_CTRL (*(volatile uint32_t *)(HW_APBX_BASE + 0x30))
619#define HW_APBX_CHANNEL_CTRL__FREEZE_CHANNEL(i) (1 << (i))
620#define HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(i) (1 << ((i) + 16))
621
622#define HW_APBX_CHx_CURCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x100 + (i) * 0x70))
623
624#define HW_APBX_CHx_NXTCMDAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x110 + (i) * 0x70))
625
626#define HW_APBX_CHx_CMD(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x120 + (i) * 0x70))
627
628#define HW_APBX_CHx_BAR(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x130 + (i) * 0x70))
629
630#define HW_APBX_CHx_SEMA(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x140 + (i) * 0x70))
631
632#define HW_APBX_CHx_DEBUG1(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x150 + (i) * 0x70))
633
634#define HW_APBX_CHx_DEBUG2(i) (*(volatile uint32_t *)(HW_APBX_BASE + 0x160 + (i) * 0x70))
635#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BP 0
636#define HW_APBX_CHx_DEBUG2__AHB_BYTES_BM 0xffff
637#define HW_APBX_CHx_DEBUG2__APB_BYTES_BP 16
638#define HW_APBX_CHx_DEBUG2__APB_BYTES_BM 0xffff0000
639
640/**********
641 * COMMON *
642 **********/
643
644struct apb_dma_command_t
645{
646 struct apb_dma_command_t *next;
647 uint32_t cmd;
648 void *buffer;
649 /* PIO words follow */
650};
651
652#define APBH_DMA_CHANNEL(i) i
653#define APBX_DMA_CHANNEL(i) ((i) | 0x10)
654#define APB_IS_APBX_CHANNEL(x) ((x) & 0x10)
655#define APB_GET_DMA_CHANNEL(x) ((x) & 0xf)
656
657#define APB_SSP(ssp) APBH_DMA_CHANNEL(HW_APBH_SSP(ssp))
658#define APB_AUDIO_ADC APBX_DMA_CHANNEL(HW_APBX_AUDIO_ADC)
659#define APB_AUDIO_DAC APBX_DMA_CHANNEL(HW_APBX_AUDIO_DAC)
660#define APB_I2C APBX_DMA_CHANNEL(HW_APBX_I2C)
661
662#define HW_APB_CHx_CMD__COMMAND_BM 0x3
663#define HW_APB_CHx_CMD__COMMAND__NO_XFER 0
664#define HW_APB_CHx_CMD__COMMAND__WRITE 1
665#define HW_APB_CHx_CMD__COMMAND__READ 2
666#define HW_APB_CHx_CMD__COMMAND__SENSE 3
667#define HW_APB_CHx_CMD__CHAIN (1 << 2)
668#define HW_APB_CHx_CMD__IRQONCMPLT (1 << 3)
669/* those two are only available on APHB */
670#define HW_APBH_CHx_CMD__NANDLOCK (1 << 4)
671#define HW_APBH_CHx_CMD__NANDWAIT4READY (1 << 5)
672#define HW_APB_CHx_CMD__SEMAPHORE (1 << 6)
673#define HW_APB_CHx_CMD__WAIT4ENDCMD (1 << 7)
674/* An errata advise not to use it */
675//#define HW_APB_CHx_CMD__HALTONTERMINATE (1 << 8)
676#define HW_APB_CHx_CMD__CMDWORDS_BM 0xf000
677#define HW_APB_CHx_CMD__CMDWORDS_BP 12
678#define HW_APB_CHx_CMD__XFER_COUNT_BM 0xffff0000
679#define HW_APB_CHx_CMD__XFER_COUNT_BP 16
680/* For software use */
681#define HW_APB_CHx_CMD__UNUSED_BP 8
682#define HW_APB_CHx_CMD__UNUSED_BM (0xf << 8)
683#define HW_APB_CHx_CMD__UNUSED_MAGIC (0xa << 8)
684
685#define HW_APB_CHx_SEMA__PHORE_BM 0xff0000
686#define HW_APB_CHx_SEMA__PHORE_BP 16
687
688/* A single descriptor cannot transfer more than 2^16 bytes */
689#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16)
690
691static void imx233_dma_init(void)
692{
693 __REG_CLR(HW_APBH_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
694 __REG_CLR(HW_APBX_CTRL0) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
695}
696
697static void imx233_dma_reset_channel(unsigned chan)
698{
699 volatile uint32_t *ptr;
700 uint32_t bm;
701 if(APB_IS_APBX_CHANNEL(chan))
702 {
703 ptr = &HW_APBX_CHANNEL_CTRL;
704 bm = HW_APBX_CHANNEL_CTRL__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
705 }
706 else
707 {
708 ptr = &HW_APBH_CTRL0;
709 bm = HW_APBH_CTRL0__RESET_CHANNEL(APB_GET_DMA_CHANNEL(chan));
710 }
711 __REG_SET(*ptr) = bm;
712 /* wait for end of reset */
713 while(*ptr & bm)
714 ;
715}
716
717static void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd)
718{
719 if(APB_IS_APBX_CHANNEL(chan))
720 {
721 HW_APBX_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
722 HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
723 }
724 else
725 {
726 HW_APBH_CHx_NXTCMDAR(APB_GET_DMA_CHANNEL(chan)) = (uint32_t)cmd;
727 HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan)) = 1;
728 }
729}
730
731static void imx233_dma_wait_completion(unsigned chan)
732{
733 volatile uint32_t *sema;
734 if(APB_IS_APBX_CHANNEL(chan))
735 sema = &HW_APBX_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
736 else
737 sema = &HW_APBH_CHx_SEMA(APB_GET_DMA_CHANNEL(chan));
738
739 while(*sema & HW_APB_CHx_SEMA__PHORE_BM)
740 ;
741}
742
743/**
744 *
745 * Digctl
746 *
747 */
748
749/* Digital control */
750#define HW_DIGCTL_BASE 0x8001C000
751#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
752#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
753
754#define HW_DIGCTL_HCLKCOUNT (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x20))
755
756#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
757
758#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
759#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16
760#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BM 0xffff0000
761#define HW_DIGCTL_CHIPID__REVISION_BP 0
762#define HW_DIGCTL_CHIPID__REVISION_BM 0xff
763
764static bool imx233_us_elapsed(uint32_t ref, unsigned us_delay)
765{
766 uint32_t cur = HW_DIGCTL_MICROSECONDS;
767 if(ref + us_delay <= ref)
768 return !(cur > ref) && !(cur < (ref + us_delay));
769 else
770 return (cur < ref) || cur >= (ref + us_delay);
771}
772
773static void udelay(unsigned us)
774{
775 uint32_t ref = HW_DIGCTL_MICROSECONDS;
776 while(!imx233_us_elapsed(ref, us));
777}
778
779#define HZ 1000000
780
781/**
782 *
783 * PWM
784 *
785 */
786
787#define HW_PWM_BASE 0x80064000
788
789#define HW_PWM_CTRL (*(volatile uint32_t *)(HW_PWM_BASE + 0x0))
790#define HW_PWM_CTRL__PWMx_ENABLE(x) (1 << (x))
791
792#define HW_PWM_ACTIVEx(x) (*(volatile uint32_t *)(HW_PWM_BASE + 0x10 + (x) * 0x20))
793#define HW_PWM_ACTIVEx__ACTIVE_BP 0
794#define HW_PWM_ACTIVEx__ACTIVE_BM 0xffff
795#define HW_PWM_ACTIVEx__INACTIVE_BP 16
796#define HW_PWM_ACTIVEx__INACTIVE_BM 0xffff0000
797
798#define HW_PWM_PERIODx(x) (*(volatile uint32_t *)(HW_PWM_BASE + 0x20 + (x) * 0x20))
799#define HW_PWM_PERIODx__PERIOD_BP 0
800#define HW_PWM_PERIODx__PERIOD_BM 0xffff
801#define HW_PWM_PERIODx__ACTIVE_STATE_BP 16
802#define HW_PWM_PERIODx__ACTIVE_STATE_BM (0x3 << 16)
803#define HW_PWM_PERIODx__INACTIVE_STATE_BP 18
804#define HW_PWM_PERIODx__INACTIVE_STATE_BM (0x3 << 18)
805#define HW_PWM_PERIODx__CDIV_BP 20
806#define HW_PWM_PERIODx__CDIV_BM (0x7 << 20)
807#define HW_PWM_PERIODx__CDIV__DIV_1 0
808#define HW_PWM_PERIODx__CDIV__DIV_2 1
809#define HW_PWM_PERIODx__CDIV__DIV_4 2
810#define HW_PWM_PERIODx__CDIV__DIV_8 3
811#define HW_PWM_PERIODx__CDIV__DIV_16 4
812#define HW_PWM_PERIODx__CDIV__DIV_64 5
813#define HW_PWM_PERIODx__CDIV__DIV_256 6
814#define HW_PWM_PERIODx__CDIV__DIV_1024 7
815
816#define HW_PWM_PERIODx__STATE__HI_Z 0
817#define HW_PWM_PERIODx__STATE__LOW 2
818#define HW_PWM_PERIODx__STATE__HIGH 3
819
820#define IMX233_PWM_PIN_BANK(channel) 2
821#define IMX233_PWM_PIN(channel) (0 + (channel))
822
823static void imx233_pwm_init(void)
824{
825 //__REG_SET(HW_PWM_CTRL) = __BLOCK_SFTRST;
826 __REG_CLR(HW_PWM_CTRL) = __BLOCK_SFTRST | __BLOCK_CLKGATE;
827 while(HW_PWM_CTRL & __BLOCK_CLKGATE);
828 __REG_CLR(HW_CLKCTRL_XTAL) = HW_CLKCTRL_XTAL__PWM_CLK24M_GATE;
829}
830
831static bool imx233_pwm_is_channel_enable(int channel)
832{
833 return HW_PWM_CTRL & HW_PWM_CTRL__PWMx_ENABLE(channel);
834}
835
836static void imx233_pwm_enable_channel(int channel, bool enable)
837{
838 if(enable)
839 __REG_SET(HW_PWM_CTRL) = HW_PWM_CTRL__PWMx_ENABLE(channel);
840 else
841 __REG_CLR(HW_PWM_CTRL) = HW_PWM_CTRL__PWMx_ENABLE(channel);
842}
843
844static void imx233_pwm_setup_channel(int channel, int period, int cdiv, int active,
845 int active_state, int inactive, int inactive_state)
846{
847 /* stop */
848 bool enable = imx233_pwm_is_channel_enable(channel);
849 if(enable)
850 imx233_pwm_enable_channel(channel, false);
851 /* setup pin */
852 imx233_set_pin_function(IMX233_PWM_PIN_BANK(channel), IMX233_PWM_PIN(channel),
853 PINCTRL_FUNCTION_MAIN);
854 imx233_set_pin_drive_strength(IMX233_PWM_PIN_BANK(channel), IMX233_PWM_PIN(channel),
855 PINCTRL_DRIVE_4mA);
856 /* watch the order ! active THEN period */
857 HW_PWM_ACTIVEx(channel) = active << HW_PWM_ACTIVEx__ACTIVE_BP |
858 inactive << HW_PWM_ACTIVEx__INACTIVE_BP;
859 HW_PWM_PERIODx(channel) = period | active_state << HW_PWM_PERIODx__ACTIVE_STATE_BP |
860 inactive_state << HW_PWM_PERIODx__INACTIVE_STATE_BP |
861 cdiv << HW_PWM_PERIODx__CDIV_BP;
862 /* restore */
863 imx233_pwm_enable_channel(channel, enable);
864}
865
866/**
867 *
868 * USB PHY
869 *
870 */
871/* USB Phy */
872#define HW_USBPHY_BASE 0x8007C000
873#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
874#define HW_USBPHY_PWD__ALL (7 << 10 | 0xf << 17)
875
876#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
877
878/**
879 *
880 * DCP
881 *
882 */
883#define HW_DCP_BASE 0x80028000
884
885#define HW_DCP_CTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x0))
886
887#define HW_DCP_STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x10))
888#define HW_DCP_STAT__IRQ(x) (1 << (x))
889
890#define HW_DCP_CHANNELCTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x20))
891#define HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(x) (1 << (x))
892
893#define HW_DCP_CH0CMDPTR (*(volatile unsigned long *)(HW_DCP_BASE + 0x100))
894
895#define HW_DCP_CH0SEMA (*(volatile unsigned long *)(HW_DCP_BASE + 0x110))
896#define HW_DCP_CH0SEMA__INCREMENT(x) (x)
897#define HW_DCP_CH0SEMA__VALUE_BP 16
898#define HW_DCP_CH0SEMA__VALUE_BM (0xff << 16)
899#define HW_DCP_CH0STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x120))
900
901#define HW_DCP_CTRL0__INTERRUPT_ENABLE (1 << 0)
902#define HW_DCP_CTRL0__DECR_SEMAPHORE (1 << 1)
903#define HW_DCP_CTRL0__ENABLE_MEMCOPY (1 << 4)
904#define HW_DCP_CTRL0__ENABLE_CIPHER (1 << 5)
905#define HW_DCP_CTRL0__ENABLE_HASH (1 << 6)
906#define HW_DCP_CTRL0__CIPHER_ENCRYPT (1 << 8)
907#define HW_DCP_CTRL0__CIPHER_INIT (1 << 9)
908#define HW_DCP_CTRL0__OTP_KEY (1 << 10)
909#define HW_DCP_CTRL0__HASH_INIT (1 << 12)
910#define HW_DCP_CTRL0__HASH_TERM (1 << 13)
911#define HW_DCP_CTRL0__HASH_OUTPUT (1 << 15)
912
913#define HW_DCP_CTRL1__CIPHER_SELECT_BP 0
914#define HW_DCP_CTRL1__CIPHER_SELECT_BM 0xf
915#define HW_DCP_CTRL1__CIPHER_SELECT__AES128 0
916#define HW_DCP_CTRL1__CIPHER_MODE_BP 4
917#define HW_DCP_CTRL1__CIPHER_MODE_BM 0xf0
918#define HW_DCP_CTRL1__CIPHER_MODE__CBC (1 << 4)
919#define HW_DCP_CTRL1__HASH_SELECT_BP 4
920#define HW_DCP_CTRL1__HASH_SELECT_BM 0xf00
921
922struct dcp_packet_t
923{
924 unsigned long next;
925 unsigned long ctrl0;
926 unsigned long ctrl1;
927 unsigned long src_buf;
928 unsigned long dst_buf;
929 unsigned long buf_sz;
930 unsigned long payload_ptr;
931 unsigned long status;
932} __attribute__((packed));
933
934/**
935 *
936 * Misc
937 *
938 */
939
940void memcpy(uint8_t *dst, const uint8_t *src, uint32_t length)
941{
942 for(uint32_t i = 0; i < length; i++)
943 dst[i] = src[i];
944}
945
946void memset(uint8_t *dst, uint8_t fill, uint32_t length)
947{
948 for(uint32_t i = 0; i < length; i++)
949 dst[i] = fill;
950}
951
952/**
953 *
954 * USB stack
955 *
956 */
957
958static struct usb_device_descriptor __attribute__((aligned(2)))
959 device_descriptor=
960{
961 .bLength = sizeof(struct usb_device_descriptor),
962 .bDescriptorType = USB_DT_DEVICE,
963 .bcdUSB = 0x0200,
964 .bDeviceClass = USB_CLASS_PER_INTERFACE,
965 .bDeviceSubClass = 0,
966 .bDeviceProtocol = 0,
967 .bMaxPacketSize0 = 64,
968 .idVendor = HWEMUL_USB_VID,
969 .idProduct = HWEMUL_USB_PID,
970 .bcdDevice = HWEMUL_VERSION_MAJOR << 8 | HWEMUL_VERSION_MINOR,
971 .iManufacturer = 1,
972 .iProduct = 2,
973 .iSerialNumber = 3,
974 .bNumConfigurations = 1
975};
976
977#define USB_MAX_CURRENT 200
978
979static struct usb_config_descriptor __attribute__((aligned(2)))
980 config_descriptor =
981{
982 .bLength = sizeof(struct usb_config_descriptor),
983 .bDescriptorType = USB_DT_CONFIG,
984 .wTotalLength = 0, /* will be filled in later */
985 .bNumInterfaces = 1,
986 .bConfigurationValue = 1,
987 .iConfiguration = 0,
988 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
989 .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */
990};
991
992/* main interface */
993static struct usb_interface_descriptor __attribute__((aligned(2)))
994 interface_descriptor =
995{
996 .bLength = sizeof(struct usb_interface_descriptor),
997 .bDescriptorType = USB_DT_INTERFACE,
998 .bInterfaceNumber = 0,
999 .bAlternateSetting = 0,
1000 .bNumEndpoints = 3,
1001 .bInterfaceClass = HWEMUL_CLASS,
1002 .bInterfaceSubClass = HWEMUL_SUBCLASS,
1003 .bInterfaceProtocol = HWEMUL_PROTOCOL,
1004 .iInterface = 4
1005};
1006
1007
1008static struct usb_endpoint_descriptor __attribute__((aligned(2)))
1009 endpoint_descriptor =
1010{
1011 .bLength = sizeof(struct usb_endpoint_descriptor),
1012 .bDescriptorType = USB_DT_ENDPOINT,
1013 .bEndpointAddress = 0,
1014 .bmAttributes = USB_ENDPOINT_XFER_BULK,
1015 .wMaxPacketSize = 0,
1016 .bInterval = 0
1017};
1018
1019static const struct usb_string_descriptor __attribute__((aligned(2)))
1020 usb_string_iManufacturer =
1021{
1022 24,
1023 USB_DT_STRING,
1024 {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'}
1025};
1026
1027static const struct usb_string_descriptor __attribute__((aligned(2)))
1028 usb_string_iProduct =
1029{
1030 52,
1031 USB_DT_STRING,
1032 {'R', 'o', 'c', 'k', 'b', 'o', 'x', ' ',
1033 'h', 'a', 'r', 'd', 'w', 'a', 'r', 'e', ' ',
1034 'e', 'm', 'u', 'l', 'a', 't', 'e', 'r'}
1035};
1036
1037static struct usb_string_descriptor __attribute__((aligned(2)))
1038 usb_string_iSerial =
1039{
1040 84,
1041 USB_DT_STRING,
1042 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1043 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1044 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
1045 '0', '0', '0', '0', '0', '0', '0', '0'}
1046};
1047
1048static struct usb_string_descriptor __attribute__((aligned(2)))
1049 usb_string_iInterface =
1050{
1051 28,
1052 USB_DT_STRING,
1053 {'A', 'c', 'i', 'd', ' ',
1054 '0' + (HWEMUL_VERSION_MAJOR >> 4), '0' + (HWEMUL_VERSION_MAJOR & 0xf), '.',
1055 '0' + (HWEMUL_VERSION_MINOR >> 4), '0' + (HWEMUL_VERSION_MINOR & 0xf), '.',
1056 '0' + (HWEMUL_VERSION_REV >> 4), '0' + (HWEMUL_VERSION_REV & 0xf) }
1057};
1058
1059/* this is stringid #0: languages supported */
1060static const struct usb_string_descriptor __attribute__((aligned(2)))
1061 lang_descriptor =
1062{
1063 4,
1064 USB_DT_STRING,
1065 {0x0409} /* LANGID US English */
1066};
1067
1068#define USB_NUM_STRINGS 5
1069
1070static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
1071{
1072 &lang_descriptor,
1073 &usb_string_iManufacturer,
1074 &usb_string_iProduct,
1075 &usb_string_iSerial,
1076 &usb_string_iInterface
1077};
1078
1079uint8_t *usb_buffer = oc_bufferstart;
1080uint32_t usb_buffer_size = 0;
1081
1082#define EP_BULK 1
1083#define EP_INT 2
1084
1085static void set_config(void)
1086{
1087 usb_drv_configure_endpoint(EP_BULK, USB_ENDPOINT_XFER_BULK);
1088 usb_drv_configure_endpoint(EP_INT, USB_ENDPOINT_XFER_INT);
1089}
1090
1091static void handle_std_dev_desc(struct usb_ctrlrequest *req)
1092{
1093 int size;
1094 const void* ptr = NULL;
1095 unsigned index = req->wValue & 0xff;
1096
1097 switch(req->wValue >> 8)
1098 {
1099 case USB_DT_DEVICE:
1100 ptr = &device_descriptor;
1101 size = sizeof(struct usb_device_descriptor);
1102 break;
1103 case USB_DT_OTHER_SPEED_CONFIG:
1104 case USB_DT_CONFIG:
1105 {
1106 int max_packet_size;
1107
1108 /* config desc */
1109 if((req->wValue >> 8) ==USB_DT_CONFIG)
1110 {
1111 max_packet_size = (usb_drv_port_speed() ? 512 : 64);
1112 config_descriptor.bDescriptorType = USB_DT_CONFIG;
1113 }
1114 else
1115 {
1116 max_packet_size=(usb_drv_port_speed() ? 64 : 512);
1117 config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
1118 }
1119 size = sizeof(struct usb_config_descriptor);
1120
1121 /* interface */
1122 memcpy(usb_buffer + size, (void *)&interface_descriptor,
1123 sizeof(interface_descriptor));
1124 size += sizeof(interface_descriptor);
1125 /* endpoint 1: bulk out */
1126 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_OUT;
1127 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
1128 endpoint_descriptor.wMaxPacketSize = 512;
1129 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1130 sizeof(endpoint_descriptor));
1131 size += sizeof(endpoint_descriptor);
1132 /* endpoint 2: bulk in */
1133 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_IN;
1134 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
1135 endpoint_descriptor.wMaxPacketSize = 512;
1136 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1137 sizeof(endpoint_descriptor));
1138 size += sizeof(endpoint_descriptor);
1139 /* endpoint 3: int in */
1140 endpoint_descriptor.bEndpointAddress = EP_INT | USB_DIR_IN;
1141 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT;
1142 endpoint_descriptor.wMaxPacketSize = 1024;
1143 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1144 sizeof(endpoint_descriptor));
1145 size += sizeof(endpoint_descriptor);
1146
1147 /* fix config descriptor */
1148 config_descriptor.bNumInterfaces = 1;
1149 config_descriptor.wTotalLength = size;
1150 memcpy(usb_buffer, (void *)&config_descriptor, sizeof(config_descriptor));
1151
1152 ptr = usb_buffer;
1153 break;
1154 }
1155 case USB_DT_STRING:
1156 if(index < USB_NUM_STRINGS)
1157 {
1158 size = usb_strings[index]->bLength;
1159 ptr = usb_strings[index];
1160 }
1161 else
1162 usb_drv_stall(EP_CONTROL, true, true);
1163 break;
1164 default:
1165 break;
1166 }
1167
1168 if(ptr)
1169 {
1170 int length = MIN(size, req->wLength);
1171
1172 if(ptr != usb_buffer)
1173 memcpy(usb_buffer, ptr, length);
1174
1175 usb_drv_send(EP_CONTROL, usb_buffer, length);
1176 usb_drv_recv(EP_CONTROL, NULL, 0);
1177 }
1178 else
1179 usb_drv_stall(EP_CONTROL, true, true);
1180}
1181
1182static void handle_std_dev_req(struct usb_ctrlrequest *req)
1183{
1184 switch(req->bRequest)
1185 {
1186 case USB_REQ_GET_CONFIGURATION:
1187 usb_buffer[0] = 1;
1188 usb_drv_send(EP_CONTROL, usb_buffer, 1);
1189 usb_drv_recv(EP_CONTROL, NULL, 0);
1190 break;
1191 case USB_REQ_SET_CONFIGURATION:
1192 usb_drv_send(EP_CONTROL, NULL, 0);
1193 set_config();
1194 break;
1195 case USB_REQ_GET_DESCRIPTOR:
1196 handle_std_dev_desc(req);
1197 break;
1198 case USB_REQ_SET_ADDRESS:
1199 usb_drv_send(EP_CONTROL, NULL, 0);
1200 usb_drv_set_address(req->wValue);
1201 break;
1202 case USB_REQ_GET_STATUS:
1203 usb_buffer[0] = 0;
1204 usb_buffer[1] = 0;
1205 usb_drv_send(EP_CONTROL, usb_buffer, 2);
1206 usb_drv_recv(EP_CONTROL, NULL, 0);
1207 break;
1208 default:
1209 usb_drv_stall(EP_CONTROL, true, true);
1210 }
1211}
1212
1213static void handle_std_req(struct usb_ctrlrequest *req)
1214{
1215 switch(req->bRequestType & USB_RECIP_MASK)
1216 {
1217 case USB_RECIP_DEVICE:
1218 return handle_std_dev_req(req);
1219 default:
1220 usb_drv_stall(EP_CONTROL, true, true);
1221 }
1222}
1223
1224struct usb_resp_info_version_t g_version =
1225{
1226 .major = HWEMUL_VERSION_MAJOR,
1227 .minor = HWEMUL_VERSION_MINOR,
1228 .revision = HWEMUL_VERSION_REV
1229};
1230
1231struct usb_resp_info_layout_t g_layout;
1232
1233struct usb_resp_info_stmp_t g_stmp;
1234
1235struct usb_resp_info_features_t g_features =
1236{
1237 .feature_mask = HWEMUL_FEATURE_LOG | HWEMUL_FEATURE_MEM |
1238 HWEMUL_FEATURE_CALL | HWEMUL_FEATURE_JUMP | HWEMUL_FEATURE_AES_OTP
1239};
1240
1241static void fill_layout_info(void)
1242{
1243 g_layout.oc_code_start = (uint32_t)oc_codestart;
1244 g_layout.oc_code_size = oc_codesize;
1245 g_layout.oc_stack_start = (uint32_t)oc_stackstart;
1246 g_layout.oc_stack_size = oc_stacksize;
1247 g_layout.oc_buffer_start = (uint32_t)oc_bufferstart;
1248 g_layout.oc_buffer_size = oc_buffersize;
1249}
1250
1251static void fill_stmp_info(void)
1252{
1253 g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
1254 g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
1255 g_stmp.is_supported = g_stmp.chipid == 0x3780 || g_stmp.chipid == 0x3700 ||
1256 g_stmp.chipid == 0x3b00;
1257}
1258
1259static void handle_get_info(struct usb_ctrlrequest *req)
1260{
1261 void *ptr = NULL;
1262 int size = 0;
1263 switch(req->wIndex)
1264 {
1265 case HWEMUL_INFO_VERSION:
1266 ptr = &g_version;
1267 size = sizeof(g_version);
1268 break;
1269 case HWEMUL_INFO_LAYOUT:
1270 fill_layout_info();
1271 ptr = &g_layout;
1272 size = sizeof(g_layout);
1273 break;
1274 case HWEMUL_INFO_STMP:
1275 fill_stmp_info();
1276 ptr = &g_stmp;
1277 size = sizeof(g_stmp);
1278 break;
1279 case HWEMUL_INFO_FEATURES:
1280 ptr = &g_features;
1281 size = sizeof(g_features);
1282 break;
1283 default:
1284 usb_drv_stall(EP_CONTROL, true, true);
1285 }
1286
1287 if(ptr)
1288 {
1289 int length = MIN(size, req->wLength);
1290
1291 if(ptr != usb_buffer)
1292 memcpy(usb_buffer, ptr, length);
1293 usb_drv_send(EP_CONTROL, usb_buffer, length);
1294 usb_drv_recv(EP_CONTROL, NULL, 0);
1295 }
1296}
1297
1298static void handle_get_log(struct usb_ctrlrequest *req)
1299{
1300 enable_logf(false);
1301 int length = logf_readback(usb_buffer, MIN(req->wLength, usb_buffer_size));
1302 usb_drv_send(EP_CONTROL, usb_buffer, length);
1303 usb_drv_recv(EP_CONTROL, NULL, 0);
1304 enable_logf(true);
1305}
1306
1307static void handle_rw_mem(struct usb_ctrlrequest *req)
1308{
1309 uint32_t addr = req->wValue | req->wIndex << 16;
1310 uint16_t length = req->wLength;
1311
1312 if(req->bRequestType & USB_DIR_IN)
1313 {
1314 memcpy(usb_buffer, (void *)addr, length);
1315 asm volatile("nop" : : : "memory");
1316 usb_drv_send(EP_CONTROL, usb_buffer, length);
1317 usb_drv_recv(EP_CONTROL, NULL, 0);
1318 }
1319 else
1320 {
1321 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
1322 asm volatile("nop" : : : "memory");
1323 if(size != length)
1324 usb_drv_stall(EP_CONTROL, true, true);
1325 else
1326 {
1327 memcpy((void *)addr, usb_buffer, length);
1328 usb_drv_send(EP_CONTROL, NULL, 0);
1329 }
1330 }
1331}
1332
1333static void handle_call_jump(struct usb_ctrlrequest *req)
1334{
1335 uint32_t addr = req->wValue | req->wIndex << 16;
1336
1337 if(req->bRequest == HWEMUL_CALL)
1338 ((void (*)(void))addr)();
1339 else
1340 asm volatile("bx %0\n" : : "r" (addr) : "memory");
1341}
1342
1343static void do_aes_otp(void *buffer, unsigned length, unsigned params)
1344{
1345 static struct dcp_packet_t dcp_packet;
1346
1347 bool encrypt = !!(params & HWEMUL_AES_OTP_ENCRYPT);
1348 /* reset DCP */
1349 __REG_SET(HW_DCP_CTRL) = 0x80000000;
1350 /* clear clock gate */
1351 __REG_CLR(HW_DCP_CTRL) = 0xc0000000;
1352 /* enable dma for channel 0 */
1353 __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(0);
1354 /* prepare packet */
1355 dcp_packet.next = 0;
1356
1357 dcp_packet.ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE |
1358 HW_DCP_CTRL0__DECR_SEMAPHORE | HW_DCP_CTRL0__CIPHER_INIT |
1359 HW_DCP_CTRL0__ENABLE_CIPHER | HW_DCP_CTRL0__OTP_KEY |
1360 (encrypt ? HW_DCP_CTRL0__CIPHER_ENCRYPT : 0);
1361 dcp_packet.ctrl1 = HW_DCP_CTRL1__CIPHER_SELECT__AES128 |
1362 HW_DCP_CTRL1__CIPHER_MODE__CBC;
1363 dcp_packet.src_buf = (unsigned long)buffer + 16;
1364 dcp_packet.dst_buf = (unsigned long)buffer + 16;
1365 dcp_packet.buf_sz = length - 16;
1366 dcp_packet.payload_ptr = (unsigned long)buffer;
1367 dcp_packet.status = 0;
1368
1369 asm volatile("":::"memory");
1370 /* kick */
1371 HW_DCP_CH0CMDPTR = (unsigned long)&dcp_packet;
1372 HW_DCP_CH0SEMA = HW_DCP_CH0SEMA__INCREMENT(1);
1373 /* wait */
1374 while(!(HW_DCP_STAT & HW_DCP_STAT__IRQ(0)));
1375
1376 usb_drv_send_nonblocking(EP_INT, buffer, length);
1377}
1378
1379static void handle_aes_otp(struct usb_ctrlrequest *req)
1380{
1381 uint16_t length = req->wLength;
1382
1383 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
1384 if(size != length)
1385 usb_drv_stall(EP_CONTROL, true, true);
1386 else
1387 usb_drv_send(EP_CONTROL, NULL, 0);
1388 do_aes_otp(usb_buffer, length, req->wValue);
1389}
1390
1391static void handle_class_dev_req(struct usb_ctrlrequest *req)
1392{
1393 switch(req->bRequest)
1394 {
1395 case HWEMUL_GET_INFO:
1396 handle_get_info(req);
1397 break;
1398 case HWEMUL_GET_LOG:
1399 handle_get_log(req);
1400 break;
1401 case HWEMUL_RW_MEM:
1402 handle_rw_mem(req);
1403 break;
1404 case HWEMUL_CALL:
1405 case HWEMUL_JUMP:
1406 handle_call_jump(req);
1407 break;
1408 case HWEMUL_AES_OTP:
1409 handle_aes_otp(req);
1410 break;
1411 default:
1412 usb_drv_stall(EP_CONTROL, true, true);
1413 }
1414}
1415
1416static void handle_class_req(struct usb_ctrlrequest *req)
1417{
1418 switch(req->bRequestType & USB_RECIP_MASK)
1419 {
1420 case USB_RECIP_DEVICE:
1421 return handle_class_dev_req(req);
1422 default:
1423 usb_drv_stall(EP_CONTROL, true, true);
1424 }
1425}
1426
1427/**
1428 *
1429 * Main
1430 *
1431 */
1432
1433static void flash_pwm(int chan, int v1, int v2)
1434{
1435 imx233_pwm_setup_channel(chan, 500, HW_PWM_PERIODx__CDIV__DIV_256,
1436 v1, HW_PWM_PERIODx__STATE__HIGH,
1437 v2, HW_PWM_PERIODx__STATE__LOW);
1438}
1439
1440void main(uint32_t arg)
1441{
1442 usb_buffer_size = oc_buffersize;
1443
1444 logf("hwemul %d.%d.%d\n", HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR,
1445 HWEMUL_VERSION_REV);
1446 logf("argument: 0x%08x\n", arg);
1447
1448 imx233_pwm_init();
1449
1450 flash_pwm(2, 0, 500);
1451 flash_pwm(4, 0, 0);
1452
1453 udelay(HZ / 2);
1454
1455 /* we don't know if USB was connected or not. In USB recovery mode it will
1456 * but in other cases it might not be. In doubt, disconnect */
1457 REG_USBCMD &= ~USBCMD_RUN;
1458 /* enable USB PHY PLL */
1459 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
1460 /* power up USB PHY */
1461 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
1462 //__REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
1463 HW_USBPHY_PWD = 0;
1464 /* enable USB controller */
1465 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
1466 /* reset the controller */
1467 REG_USBCMD |= USBCMD_CTRL_RESET;
1468 while (REG_USBCMD & USBCMD_CTRL_RESET);
1469 /* put it in device mode */
1470 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
1471 /* reset address */
1472 REG_DEVICEADDR = 0;
1473 /* prepare qh array */
1474 qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1475 qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1476 qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1477 qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1478 qh_array[5].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1479 /* setup qh */
1480 REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
1481 /* clear setup status */
1482 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1483 /* run! */
1484 REG_USBCMD |= USBCMD_RUN;
1485 /* infinite loop */
1486 flash_pwm(2, 0, 0);
1487 flash_pwm(4, 0, 500);
1488
1489 while(1)
1490 {
1491 /* wait for setup */
1492 while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0))
1493 ;
1494 /* clear setup status */
1495 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1496 /* check request */
1497 asm volatile("":::"memory");
1498 struct usb_ctrlrequest *req = (void *)&qh_array[0].setup_buffer[0];
1499
1500 switch(req->bRequestType & USB_TYPE_MASK)
1501 {
1502 case USB_TYPE_STANDARD:
1503 handle_std_req(req);
1504 break;
1505 case USB_TYPE_CLASS:
1506 handle_class_req(req);
1507 break;
1508 default:
1509 usb_drv_stall(EP_CONTROL, true, true);
1510 }
1511 }
1512}
diff --git a/utils/imxtools/hwemul/dev/protocol.h b/utils/imxtools/hwemul/dev/protocol.h
new file mode 100644
index 0000000000..d3ffb6ce00
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/protocol.h
@@ -0,0 +1 @@
#include "../hwemul_protocol.h"
diff --git a/utils/imxtools/hwemul/dev/stddef.h b/utils/imxtools/hwemul/dev/stddef.h
new file mode 100644
index 0000000000..9d59d2913c
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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 __HWEMUL_STDDEF__
22#define __HWEMUL_STDDEF__
23
24#include "stdint.h"
25
26typedef uint32_t size_t;
27typedef 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 /* __HWEMUL_STDDEF__ */
diff --git a/utils/imxtools/hwemul/dev/stdint.h b/utils/imxtools/hwemul/dev/stdint.h
new file mode 100644
index 0000000000..4fe3702c86
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/stdint.h
@@ -0,0 +1,38 @@
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
25typedef signed char int8_t;
26typedef unsigned char uint8_t;
27typedef short int16_t;
28typedef unsigned short uint16_t;
29typedef long int32_t;
30typedef unsigned long uint32_t;
31typedef char bool;
32
33#define true 1
34#define false 0
35
36#define NULL (void *)0
37
38#endif /* __STDINT_H__ */
diff --git a/utils/imxtools/hwemul/dev/string.c b/utils/imxtools/hwemul/dev/string.c
new file mode 100644
index 0000000000..1f8c415a99
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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
23size_t strlen(const char *s)
24{
25 size_t len = 0;
26 while(*s++)
27 len++;
28 return len;
29}
diff --git a/utils/imxtools/hwemul/dev/string.h b/utils/imxtools/hwemul/dev/string.h
new file mode 100644
index 0000000000..7ef460ea6e
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/string.h
@@ -0,0 +1,30 @@
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 __HWEMUL_STRING__
22#define __HWEMUL_STRING__
23
24#include "stddef.h"
25
26void memset(void *dst, int c, size_t n);
27void memcpy(void *dst, const void *src, size_t n);
28size_t strlen(const char *s);
29
30#endif /* __HWEMUL_STRING__ */
diff --git a/utils/imxtools/hwemul/dev/system.h b/utils/imxtools/hwemul/dev/system.h
new file mode 100644
index 0000000000..c1babe7d87
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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 __HWEMUL_SYSTEM__
22#define __HWEMUL_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
59static 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
75static 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
82static 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
93static 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
104static 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 /* __HWEMUL_SYSTEM__ */
118
diff --git a/utils/imxtools/hwemul/dev/usb_ch9.h b/utils/imxtools/hwemul/dev/usb_ch9.h
new file mode 100644
index 0000000000..09141b93bd
--- /dev/null
+++ b/utils/imxtools/hwemul/dev/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 */
148struct 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 */
204struct usb_descriptor_header {
205 uint8_t bLength;
206 uint8_t bDescriptorType;
207} __attribute__ ((packed));
208
209
210/*-------------------------------------------------------------------------*/
211
212/* USB_DT_DEVICE: Device descriptor */
213struct 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 */
267struct 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 */
290struct 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 */
304struct 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 */
322struct 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 */
353struct 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) */
370struct 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 */
384struct 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
396enum 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
403enum 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 */
436struct 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 */
449struct 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/imxtools/hwemul/hwemul_protocol.h b/utils/imxtools/hwemul/hwemul_protocol.h
new file mode 100644
index 0000000000..f11fd91352
--- /dev/null
+++ b/utils/imxtools/hwemul/hwemul_protocol.h
@@ -0,0 +1,127 @@
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 __HWEMUL_PROTOCOL__
22#define __HWEMUL_PROTOCOL__
23
24#define HWEMUL_CLASS 0xfe
25#define HWEMUL_SUBCLASS 0xac
26#define HWEMUL_PROTOCOL 0x1d
27
28#define HWEMUL_VERSION_MAJOR 2
29#define HWEMUL_VERSION_MINOR 8
30#define HWEMUL_VERSION_REV 2
31
32#define HWEMUL_USB_VID 0xfee1
33#define HWEMUL_USB_PID 0xdead
34
35/**
36 * Control commands
37 *
38 * These commands are sent to the device, using the standard bRequest field
39 * of the SETUP packet. This is to take advantage of both wIndex and wValue
40 * although it would have been more correct to send them to the interface.
41 */
42
43/* list of commands */
44#define HWEMUL_GET_INFO 0 /* mandatory */
45#define HWEMUL_GET_LOG 1 /* optional */
46#define HWEMUL_RW_MEM 2 /* optional */
47#define HWEMUL_CALL 3 /* optional */
48#define HWEMUL_JUMP 4 /* optional */
49#define HWEMUL_AES_OTP 5 /* optional */
50
51/**
52 * HWEMUL_GET_INFO: get some information about an aspect of the device.
53 * The wIndex field of the SETUP specifies which information to get. */
54
55/* list of possible information */
56#define HWEMUL_INFO_VERSION 0
57#define HWEMUL_INFO_LAYOUT 1
58#define HWEMUL_INFO_STMP 2
59#define HWEMUL_INFO_FEATURES 3
60
61struct usb_resp_info_version_t
62{
63 uint8_t major;
64 uint8_t minor;
65 uint8_t revision;
66} __attribute__((packed));
67
68struct usb_resp_info_layout_t
69{
70 /* describe the range of memory used by the running code */
71 uint32_t oc_code_start;
72 uint32_t oc_code_size;
73 /* describe the range of memory used by the stack */
74 uint32_t oc_stack_start;
75 uint32_t oc_stack_size;
76 /* describe the range of memory available as a buffer */
77 uint32_t oc_buffer_start;
78 uint32_t oc_buffer_size;
79} __attribute__((packed));
80
81struct usb_resp_info_stmp_t
82{
83 uint16_t chipid; /* 0x3780 for STMP3780 for example */
84 uint8_t rev; /* 0=TA1 on STMP3780 for example */
85 uint8_t is_supported; /* 1 if the chip is supported */
86} __attribute__((packed));
87
88/* list of possible features */
89#define HWEMUL_FEATURE_LOG (1 << 0)
90#define HWEMUL_FEATURE_MEM (1 << 1)
91#define HWEMUL_FEATURE_CALL (1 << 2)
92#define HWEMUL_FEATURE_JUMP (1 << 2)
93#define HWEMUL_FEATURE_AES_OTP (1 << 3)
94
95struct usb_resp_info_features_t
96{
97 uint32_t feature_mask;
98};
99
100/**
101 * HWEMUL_GET_LOG: only if has HWEMUL_FEATURE_LOG.
102 * The log is returned as part of the control transfer.
103 */
104
105/**
106 * HWEMUL_RW_MEM: only if has HWEMUL_FEATURE_MEM.
107 * The 32-bit address is split into two parts.
108 * The low 16-bit are stored in wValue and the upper
109 * 16-bit are stored in wIndex. Depending on the transfer direction,
110 * the transfer is either a read or a write. */
111
112/**
113 * HWEMUL_x: only if has HWEMUL_FEATURE_x where x=CALL or JUMP.
114 * The 32-bit address is split into two parts.
115 * The low 16-bit are stored in wValue and the upper
116 * 16-bit are stored in wIndex. Depending on the transfer direction,
117 * the transfer is either a read or a write. */
118
119/**
120 * HWEMUL_AES_OTP: only if has HWEMUL_FEATURE_AES_OTP.
121 * The control transfer contains the data to be en/decrypted and the data
122 * is sent back on the interrupt endpoint. The first 16-bytes of the data
123 * are interpreted as the IV. The output format is the same.
124 * The wValue field contains the parameters of the process. */
125#define HWEMUL_AES_OTP_ENCRYPT (1 << 0)
126
127#endif /* __HWEMUL_PROTOCOL__ */
diff --git a/utils/imxtools/hwemul/lib/Makefile b/utils/imxtools/hwemul/lib/Makefile
new file mode 100644
index 0000000000..7280fe8e38
--- /dev/null
+++ b/utils/imxtools/hwemul/lib/Makefile
@@ -0,0 +1,27 @@
1CC=gcc
2AR=ar
3CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC
4LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC
5LIB=libhwemul.a
6REGTOOLS=../../regtools
7DESC=$(REGTOOLS)/desc
8HWEMULGEN=$(REGTOOLS)/hwemulgen
9HWEMULSOC_PREFIX=hwemul_soc
10SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c
11OBJ=$(SRC:.c=.o)
12
13all: $(LIB) $(EXEC)
14
15$(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h:
16 $(HWEMULGEN) $(DESC)/*.xml $(HWEMULSOC_PREFIX)
17
18%.o: %.c $(HWEMULSOC_PREFIX).h
19 $(CC) $(CFLAGS) -c -o $@ $<
20
21$(LIB): $(OBJ)
22 $(AR) rcs $@ $^
23
24clean:
25 rm -rf $(OBJ) $(LIB) $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h
26
27
diff --git a/utils/imxtools/hwemul/lib/hwemul.c b/utils/imxtools/hwemul/lib/hwemul.c
new file mode 100644
index 0000000000..3e2e6de38a
--- /dev/null
+++ b/utils/imxtools/hwemul/lib/hwemul.c
@@ -0,0 +1,175 @@
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 "hwemul.h"
22#include "hwemul_soc.h"
23
24#ifndef MIN
25#define MIN(a,b) ((a) < (b) ? (a) : (b))
26#endif
27
28/* requires then ->handle field only */
29int hwemul_probe(struct hwemul_device_t *dev)
30{
31 libusb_device *mydev = libusb_get_device(dev->handle);
32
33 int config_id;
34 libusb_get_configuration(dev->handle, &config_id);
35 struct libusb_config_descriptor *config;
36 libusb_get_active_config_descriptor(mydev, &config);
37
38 const struct libusb_endpoint_descriptor *endp = NULL;
39 int intf;
40 for(intf = 0; intf < config->bNumInterfaces; intf++)
41 {
42 if(config->interface[intf].num_altsetting != 1)
43 continue;
44 const struct libusb_interface_descriptor *interface =
45 &config->interface[intf].altsetting[0];
46 if(interface->bNumEndpoints != 3 ||
47 interface->bInterfaceClass != HWEMUL_CLASS ||
48 interface->bInterfaceSubClass != HWEMUL_SUBCLASS ||
49 interface->bInterfaceProtocol != HWEMUL_PROTOCOL)
50 continue;
51 dev->intf = intf;
52 dev->bulk_in = dev->bulk_out = dev->int_in = -1;
53 for(int ep = 0; ep < interface->bNumEndpoints; ep++)
54 {
55 endp = &interface->endpoint[ep];
56 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
57 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
58 dev->int_in = endp->bEndpointAddress;
59 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
60 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
61 dev->bulk_in = endp->bEndpointAddress;
62 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
63 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
64 dev->bulk_out = endp->bEndpointAddress;
65 }
66 if(dev->bulk_in == -1 || dev->bulk_out == -1 || dev->int_in == -1)
67 continue;
68 break;
69 }
70 if(intf == config->bNumInterfaces)
71 return 1;
72
73 return libusb_claim_interface(dev->handle, intf);
74}
75
76int hwemul_release(struct hwemul_device_t *dev)
77{
78 return libusb_release_interface(dev->handle, dev->intf);
79}
80
81int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz)
82{
83 return libusb_control_transfer(dev->handle,
84 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
85 HWEMUL_GET_INFO, 0, idx, info, sz, 1000);
86}
87
88int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz)
89{
90 return libusb_control_transfer(dev->handle,
91 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
92 HWEMUL_GET_LOG, 0, 0, buf, sz, 1000);
93}
94
95int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
96{
97 size_t tot_sz = 0;
98 while(sz)
99 {
100 uint16_t xfer = MIN(1 * 1024, sz);
101 int ret = libusb_control_transfer(dev->handle,
102 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
103 (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
104 HWEMUL_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
105 if(ret != xfer)
106 return ret;
107 sz -= xfer;
108 addr += xfer;
109 buf += xfer;
110 tot_sz += xfer;
111 }
112 return tot_sz;
113}
114
115int hwemul_call(struct hwemul_device_t *dev, uint32_t addr)
116{
117 return libusb_control_transfer(dev->handle,
118 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
119 LIBUSB_ENDPOINT_OUT, HWEMUL_CALL, addr & 0xffff, addr >> 16, NULL, 0,
120 1000);
121}
122
123int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr)
124{
125 return libusb_control_transfer(dev->handle,
126 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
127 LIBUSB_ENDPOINT_OUT, HWEMUL_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
128 1000);
129}
130
131const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
132{
133 switch(stmp->chipid)
134 {
135 case 0x3700: return "STMP 3700";
136 case 0x37b0: return "STMP 3770";
137 case 0x3780: return "STMP 3780 / i.MX233";
138 default: return "unknown";
139 }
140}
141
142const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
143{
144 switch(stmp->chipid)
145 {
146 case 0x37b0:
147 case 0x3780:
148 switch(stmp->rev)
149 {
150 case 0: return "TA1";
151 case 1: return "TA2";
152 case 2: return "TA3";
153 case 3: return "TA4";
154 default: return "unknown";
155 }
156 break;
157 default:
158 return "unknown";
159 }
160}
161
162int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param)
163{
164 int ret = libusb_control_transfer(dev->handle,
165 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
166 LIBUSB_ENDPOINT_OUT, HWEMUL_AES_OTP, param, 0, buf, sz,
167 1000);
168 if(ret <0 || (unsigned)ret != sz)
169 return -1;
170 int xfer;
171 ret = libusb_interrupt_transfer(dev->handle, dev->int_in, buf, sz, &xfer, 1000);
172 if(ret < 0 || (unsigned)xfer != sz)
173 return -1;
174 return ret;
175}
diff --git a/utils/imxtools/hwemul/lib/hwemul.h b/utils/imxtools/hwemul/lib/hwemul.h
new file mode 100644
index 0000000000..376ba65381
--- /dev/null
+++ b/utils/imxtools/hwemul/lib/hwemul.h
@@ -0,0 +1,63 @@
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 __HWEMUL__
22#define __HWEMUL__
23
24#include <libusb.h>
25#include "hwemul_protocol.h"
26#include "hwemul_soc.h"
27
28/**
29 *
30 * Low-Level interface
31 *
32 */
33
34struct hwemul_device_t
35{
36 libusb_device_handle *handle;
37 int intf;
38 int bulk_in;
39 int bulk_out;
40 int int_in;
41};
42
43/* Requires then ->handle field only. Returns 0 on success */
44int hwemul_probe(struct hwemul_device_t *dev);
45/* Returns 0 on success */
46int hwemul_release(struct hwemul_device_t *dev);
47
48/* Returns number of bytes filled */
49int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz);
50/* Returns number of bytes filled */
51int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz);
52/* Returns number of bytes written/read or <0 on error */
53int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
54/* Returns <0 on error */
55int hwemul_call(struct hwemul_device_t *dev, uint32_t addr);
56int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr);
57/* Returns <0 on error. The size must be a multiple of 16. */
58int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param);
59
60const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp);
61const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp);
62
63#endif /* __HWEMUL__ */ \ No newline at end of file
diff --git a/utils/imxtools/hwemul/lib/hwemul_protocol.h b/utils/imxtools/hwemul/lib/hwemul_protocol.h
new file mode 100644
index 0000000000..d3ffb6ce00
--- /dev/null
+++ b/utils/imxtools/hwemul/lib/hwemul_protocol.h
@@ -0,0 +1 @@
#include "../hwemul_protocol.h"
diff --git a/utils/imxtools/hwemul/tools/Makefile b/utils/imxtools/hwemul/tools/Makefile
new file mode 100644
index 0000000000..80a2f405bb
--- /dev/null
+++ b/utils/imxtools/hwemul/tools/Makefile
@@ -0,0 +1,22 @@
1CC=gcc
2AR=ar
3HWEMUL_LIB_DIR=../lib
4CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -I$(HWEMUL_LIB_DIR)
5LDFLAGS=`pkg-config --libs libusb-1.0`
6EXEC=hwemul_tool
7HWEMUL_LIB=$(HWEMUL_LIB_DIR)/libhwemul.a
8SRC=$(wildcard *.c)
9OBJ=$(SRC:.c=.o)
10
11all: $(EXEC)
12
13%.o: %.c
14 $(CC) $(CFLAGS) -c -o $@ $<
15
16hwemul_tool: hwemul_tool.o $(HWEMUL_LIB)
17 $(CC) $(LDFLAGS) -o $@ $^
18
19clean:
20 rm -rf $(OBJ) $(LIB)
21
22
diff --git a/utils/imxtools/hwemul/tools/hwemul_tool b/utils/imxtools/hwemul/tools/hwemul_tool
new file mode 100755
index 0000000000..1690385c6a
--- /dev/null
+++ b/utils/imxtools/hwemul/tools/hwemul_tool
Binary files differ
diff --git a/utils/imxtools/hwemul/tools/hwemul_tool.c b/utils/imxtools/hwemul/tools/hwemul_tool.c
new file mode 100644
index 0000000000..c6056edf96
--- /dev/null
+++ b/utils/imxtools/hwemul/tools/hwemul_tool.c
@@ -0,0 +1,558 @@
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 "hwemul.h"
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <getopt.h>
26#include <stdbool.h>
27
28bool g_quiet = false;
29struct hwemul_device_t hwdev;
30struct hwemul_soc_t *cur_soc = NULL;
31
32void print_log(struct hwemul_device_t *hwdev)
33{
34 do
35 {
36 char buffer[128];
37 int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
38 if(length <= 0)
39 break;
40 buffer[length] = 0;
41 printf("%s", buffer);
42 }while(1);
43}
44
45int print_help()
46{
47 printf("Commands:\n");
48 printf(" help\t\tDisplay this help\n");
49 printf(" call <addr>\tCall address <addr>\n");
50 printf(" quit\t\tQuit this session\n");
51 printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
52 printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
53 printf(" read <regname>\tRead a register by name\n");
54 printf(" read <regname>.<field>\tRead a register field by name\n");
55 printf(" soc <socname>\tSelect the soc description to use\n");
56 printf(" write <value> <regname>\tWrite a register by name\n");
57 printf(" write <value <regname>.<field>\tWrite a register field by name\n");
58 printf(" NOTE: if the register is SCT variant, no read is performed.\n");
59 return 1;
60}
61
62int syntax_error(char *str)
63{
64 printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
65 return 1;
66}
67
68int parse_uint32(char *str, uint32_t *u)
69{
70 char *end;
71 *u = strtoul(str, &end, 0);
72 return *end == 0;
73}
74
75int do_call(uint32_t a)
76{
77 hwemul_call(&hwdev, a);
78 return 1;
79}
80
81int parse_call()
82{
83 char *arg = strtok(NULL, " ");
84 uint32_t addr;
85 if(arg && parse_uint32(arg, &addr))
86 return do_call(addr);
87 else
88 return syntax_error(arg);
89}
90
91int do_read32(uint32_t a)
92{
93 uint32_t val;
94 if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
95 printf("%#x = %#x\n", a, val);
96 else
97 printf("read error at %#x\n", a);
98 return 1;
99}
100
101int parse_read32()
102{
103 char *arg = strtok(NULL, " ");
104 uint32_t addr;
105 if(arg && parse_uint32(arg, &addr))
106 return do_read32(addr);
107 else
108 return syntax_error(arg);
109}
110
111int do_write32(uint32_t val, uint32_t a)
112{
113 if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
114 printf("data written\n");
115 else
116 printf("write error at %#x\n", a);
117 return 1;
118}
119
120int parse_write32()
121{
122 char *arg = strtok(NULL, " ");
123 uint32_t val;
124 if(!arg || !parse_uint32(arg, &val))
125 return syntax_error(arg);
126 uint32_t addr;
127 arg = strtok(NULL, " ");
128 if(arg && parse_uint32(arg, &addr))
129 return do_write32(val, addr);
130 else
131 return syntax_error(arg);
132}
133
134struct hwemul_soc_t *find_soc_by_name(const char *soc)
135{
136 struct hwemul_soc_list_t *list = hwemul_get_soc_list();
137 for(size_t i = 0; i < list->nr_socs; i++)
138 if(strcmp(soc, list->socs[i]->name) == 0)
139 return list->socs[i];
140 return NULL;
141}
142
143struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
144{
145 for(size_t i = 0; i < soc->nr_regs; i++)
146 if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
147 return soc->regs_by_name[i];
148 return NULL;
149}
150
151struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
152{
153 for(size_t i = 0; i < reg->nr_fields; i++)
154 if(strcmp(field, reg->fields_by_name[i]->name) == 0)
155 return reg->fields_by_name[i];
156 return NULL;
157}
158
159
160int do_read(char *regname)
161{
162 char *dot = strchr(regname, '.');
163 if(dot != NULL)
164 *dot++ = 0;
165 if(cur_soc == NULL)
166 {
167 printf("No soc selected!\n");
168 return 1;
169 }
170 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
171 if(reg == NULL)
172 {
173 printf("no reg '%s' found\n", regname);
174 return 1;
175 }
176 uint32_t val;
177 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
178 {
179 printf("read error at %#x\n", reg->addr);
180 return 1;
181 }
182 if(dot)
183 {
184 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
185 if(field == NULL)
186 {
187 printf("no field '%s' found\n", dot);
188 return 1;
189 }
190 val >>= field->first_bit;
191 val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
192 printf("%s.%s = %#x\n", regname, dot, val);
193 }
194 else
195 printf("%s = %#x\n", regname, val);
196 return 1;
197}
198
199int parse_read()
200{
201 char *arg = strtok(NULL, " ");
202 if(arg)
203 return do_read(arg);
204 else
205 return syntax_error(arg);
206}
207
208int do_soc(char *soc)
209{
210 struct hwemul_soc_t *s = find_soc_by_name(soc);
211 if(s == NULL)
212 printf("no soc '%s' found\n", soc);
213 else
214 cur_soc = s;
215 return 1;
216}
217
218int parse_soc()
219{
220 char *arg = strtok(NULL, " ");
221 if(arg)
222 return do_soc(arg);
223 else
224 return syntax_error(arg);
225}
226
227int do_write(uint32_t val, char *regname)
228{
229 char *dot = strchr(regname, '.');
230 if(dot != NULL)
231 *dot++ = 0;
232 if(cur_soc == NULL)
233 {
234 printf("No soc selected!\n");
235 return 1;
236 }
237 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
238 int is_sct = 0;
239 uint32_t addr_off = 0;
240 if(reg == NULL)
241 {
242 size_t len = strlen(regname);
243 /* try SCT variant */
244 if(strcmp(regname + len - 4, "_SET") == 0)
245 addr_off = 4;
246 else if(strcmp(regname + len - 4, "_CLR") == 0)
247 addr_off = 8;
248 else if(strcmp(regname + len - 4, "_TOG") == 0)
249 addr_off = 12;
250 else
251 {
252 printf("no reg '%s' found\n", regname);
253 return 1;
254 }
255 is_sct = 1;
256 regname[len - 4] = 0;
257 reg = find_reg_by_name(cur_soc, regname);
258 if(reg == NULL)
259 {
260 printf("no reg '%s' found\n", regname);
261 return 1;
262 }
263 }
264 if(dot)
265 {
266 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
267 if(field == NULL)
268 {
269 printf("no field '%s' found\n", dot);
270 return 1;
271 }
272 uint32_t actual_val = 0;
273 if(!is_sct)
274 {
275 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
276 {
277 printf("read error at %#x\n", reg->addr);
278 return 1;
279 }
280 printf("read %#x at %#x\n", actual_val, reg->addr);
281 }
282 uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
283 printf("mask=%#x\n", mask);
284 val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
285 }
286 printf("write %#x to %#x\n", val, reg->addr + addr_off);
287 if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
288 {
289 printf("write error at %#x\n", reg->addr);
290 return 1;
291 }
292 return 1;
293}
294
295int parse_write()
296{
297 char *arg = strtok(NULL, " ");
298 uint32_t val;
299 if(!arg || !parse_uint32(arg, &val))
300 return syntax_error(arg);
301 arg = strtok(NULL, " ");
302 if(arg)
303 return do_write(val, arg);
304 else
305 return syntax_error(arg);
306}
307
308int parse_command(char *cmd)
309{
310 if(strcmp(cmd, "help") == 0)
311 return print_help();
312 if(strcmp(cmd, "quit") == 0)
313 return 0;
314 if(strcmp(cmd, "call") == 0)
315 return parse_call();
316 if(strcmp(cmd, "read32") == 0)
317 return parse_read32();
318 if(strcmp(cmd, "write32") == 0)
319 return parse_write32();
320 if(strcmp(cmd, "read") == 0)
321 return parse_read();
322 if(strcmp(cmd, "soc") == 0)
323 return parse_soc();
324 if(strcmp(cmd, "write") == 0)
325 return parse_write();
326 return syntax_error(cmd);
327}
328
329int do_command()
330{
331 char *line = NULL;
332 int size = 0;
333 getline(&line, &size, stdin);
334 char *end = strchr(line, '\n');
335 if(end)
336 *end = 0;
337 char *pch = strtok(line, " ");
338 int ret;
339 if(pch)
340 ret = parse_command(pch);
341 else
342 ret = print_help();
343 free(line);
344 return ret;
345}
346
347void usage(void)
348{
349 printf("hwemul_tool, compiled with hwemul %d.%d.%d\n",
350 HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR, HWEMUL_VERSION_REV);
351 printf("available soc descriptions:");
352 for(unsigned i = 0; i < hwemul_get_soc_list()->nr_socs; i++)
353 printf(" %s", hwemul_get_soc_list()->socs[i]->name);
354 printf("\n");
355 printf("usage: hwemul_tool [options]\n");
356 printf("options:\n");
357 printf(" --help/-?\tDisplay this help\n");
358 printf(" --quiet/-q\tQuiet non-command messages\n");
359 exit(1);
360}
361
362int main(int argc, char **argv)
363{
364 while(1)
365 {
366 static struct option long_options[] =
367 {
368 {"help", no_argument, 0, '?'},
369 {"quiet", no_argument, 0, 'q'},
370 {0, 0, 0, 0}
371 };
372
373 int c = getopt_long(argc, argv, "?q", long_options, NULL);
374 if(c == -1)
375 break;
376 switch(c)
377 {
378 case -1:
379 break;
380 case 'q':
381 g_quiet = true;
382 break;
383 case '?':
384 usage();
385 break;
386 default:
387 abort();
388 }
389 }
390
391 if(argc - optind != 0)
392 {
393 usage();
394 return 1;
395 }
396
397 libusb_context *ctx;
398 libusb_init(&ctx);
399 libusb_set_debug(ctx, 3);
400
401 if(!g_quiet)
402 printf("Looking for device %#04x:%#04x...\n", HWEMUL_USB_VID, HWEMUL_USB_PID);
403
404 libusb_device_handle *handle = libusb_open_device_with_vid_pid(ctx,
405 HWEMUL_USB_VID, HWEMUL_USB_PID);
406 if(handle == NULL)
407 {
408 printf("No device found\n");
409 return 1;
410 }
411
412 libusb_device *mydev = libusb_get_device(handle);
413 if(!g_quiet)
414 {
415 printf("device found at %d:%d\n",
416 libusb_get_bus_number(mydev),
417 libusb_get_device_address(mydev));
418 }
419 hwdev.handle = handle;
420 if(hwemul_probe(&hwdev))
421 {
422 printf("Cannot probe device!\n");
423 return 1;
424 }
425
426 struct usb_resp_info_version_t ver;
427 int ret = hwemul_get_info(&hwdev, HWEMUL_INFO_VERSION, &ver, sizeof(ver));
428 if(ret != sizeof(ver))
429 {
430 printf("Cannot get version!\n");
431 goto Lerr;
432 }
433 if(!g_quiet)
434 printf("Device version: %d.%d.%d\n", ver.major, ver.minor, ver.revision);
435
436 struct usb_resp_info_layout_t layout;
437 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_LAYOUT, &layout, sizeof(layout));
438 if(ret != sizeof(layout))
439 {
440 printf("Cannot get layout: %d\n", ret);
441 goto Lerr;
442 }
443 if(!g_quiet)
444 {
445 printf("Device layout:\n");
446 printf(" Code: 0x%x (0x%x)\n", layout.oc_code_start, layout.oc_code_size);
447 printf(" Stack: 0x%x (0x%x)\n", layout.oc_stack_start, layout.oc_stack_size);
448 printf(" Buffer: 0x%x (0x%x)\n", layout.oc_buffer_start, layout.oc_buffer_size);
449 }
450
451 struct usb_resp_info_features_t features;
452 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_FEATURES, &features, sizeof(features));
453 if(ret != sizeof(features))
454 {
455 printf("Cannot get features: %d\n", ret);
456 goto Lerr;
457 }
458 if(!g_quiet)
459 {
460 printf("Device features:");
461 if(features.feature_mask & HWEMUL_FEATURE_LOG)
462 printf(" log");
463 if(features.feature_mask & HWEMUL_FEATURE_MEM)
464 printf(" mem");
465 if(features.feature_mask & HWEMUL_FEATURE_CALL)
466 printf(" call");
467 if(features.feature_mask & HWEMUL_FEATURE_JUMP)
468 printf(" jump");
469 if(features.feature_mask & HWEMUL_FEATURE_AES_OTP)
470 printf(" aes_otp");
471 printf("\n");
472 }
473
474 struct usb_resp_info_stmp_t stmp;
475 ret = hwemul_get_info(&hwdev, HWEMUL_INFO_STMP, &stmp, sizeof(stmp));
476 if(ret != sizeof(stmp))
477 {
478 printf("Cannot get stmp: %d\n", ret);
479 goto Lerr;
480 }
481 if(!g_quiet)
482 {
483 printf("Device stmp:\n");
484 printf(" chip ID: %x (%s)\n", stmp.chipid,hwemul_get_product_string(&stmp));
485 printf(" revision: %d (%s)\n", stmp.rev, hwemul_get_rev_string(&stmp));
486 printf(" supported: %d\n", stmp.is_supported);
487 }
488
489 if(!g_quiet)
490 {
491 void *rom = malloc(64 * 1024);
492 ret = hwemul_rw_mem(&hwdev, 1, 0xc0000000, rom, 64 * 1024);
493 if(ret != 64 * 1024)
494 {
495 printf("Cannot read ROM: %d\n", ret);
496 goto Lerr;
497 }
498
499 printf("ROM successfully read!\n");
500 FILE *f = fopen("rom.bin", "wb");
501 fwrite(rom, 64 * 1024, 1, f);
502 fclose(f);
503 }
504
505 if(!g_quiet)
506 {
507 struct
508 {
509 uint8_t iv[16];
510 uint8_t data[16];
511 } __attribute__((packed)) dcp_test;
512
513 for(int i = 0; i < 16; i++)
514 dcp_test.iv[i] = rand();
515 for(int i = 0; i < 16; i++)
516 dcp_test.data[i] = rand();
517 printf("DCP\n");
518 printf(" IN\n");
519 printf(" IV:");
520 for(int i = 0; i < 16; i++)
521 printf(" %02x", dcp_test.iv[i]);
522 printf("\n");
523 printf(" IV:");
524 for(int i = 0; i < 16; i++)
525 printf(" %02x", dcp_test.data[i]);
526 printf("\n");
527
528 if(!hwemul_aes_otp(&hwdev, &dcp_test, sizeof(dcp_test), HWEMUL_AES_OTP_ENCRYPT))
529 {
530 printf(" OUT\n");
531 printf(" IV:");
532 for(int i = 0; i < 16; i++)
533 printf(" %02x", dcp_test.iv[i]);
534 printf("\n");
535 printf(" IV:");
536 for(int i = 0; i < 16; i++)
537 printf(" %02x", dcp_test.data[i]);
538 printf("\n");
539 }
540 else
541 printf("DCP error!\n");
542 }
543
544 if(!g_quiet)
545 printf("Starting interactive session. Type 'help' to get help.\n");
546 while(1)
547 if(!do_command())
548 break;
549 Lerr:
550 if(features.feature_mask & HWEMUL_FEATURE_LOG)
551 {
552 if(!g_quiet)
553 printf("Device log:\n");
554 print_log(&hwdev);
555 }
556 hwemul_release(&hwdev);
557 return 1;
558}