summaryrefslogtreecommitdiff
path: root/utils/hwstub
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-12 19:46:04 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-12 19:46:04 +0200
commit11da9d23fe323ce452fcd04a10a0ddf78eaa63ea (patch)
tree7ab4d162b2a944214bb01d498d5a0400dec031a0 /utils/hwstub
parent3f4eeb850e91fd026a99f2b17bd7e0837f112bb5 (diff)
downloadrockbox-11da9d23fe323ce452fcd04a10a0ddf78eaa63ea.tar.gz
rockbox-11da9d23fe323ce452fcd04a10a0ddf78eaa63ea.zip
imxtools: move hwemul to its own directory
The hwemul is only partly imx specific: the stub is stmp specific but could be ported to other targets, the computer side and the protocol are mostly stmp independent (or should be). Change-Id: If88febffe591b0de86ea11cb740455ba20ddc401
Diffstat (limited to 'utils/hwstub')
-rw-r--r--utils/hwstub/hwemul_protocol.h127
-rw-r--r--utils/hwstub/lib/Makefile27
-rw-r--r--utils/hwstub/lib/hwemul.c175
-rw-r--r--utils/hwstub/lib/hwemul.h63
-rw-r--r--utils/hwstub/lib/hwemul_protocol.h1
-rw-r--r--utils/hwstub/stmp/Makefile92
-rw-r--r--utils/hwstub/stmp/config.h33
-rw-r--r--utils/hwstub/stmp/crt0.S17
-rw-r--r--utils/hwstub/stmp/format.c223
-rw-r--r--utils/hwstub/stmp/format.h29
-rw-r--r--utils/hwstub/stmp/hwemul.db31
-rw-r--r--utils/hwstub/stmp/hwemul.lds70
-rw-r--r--utils/hwstub/stmp/link.lds49
-rw-r--r--utils/hwstub/stmp/logf.c68
-rw-r--r--utils/hwstub/stmp/logf.h31
-rw-r--r--utils/hwstub/stmp/main.c1409
-rw-r--r--utils/hwstub/stmp/protocol.h1
-rw-r--r--utils/hwstub/stmp/stddef.h32
-rw-r--r--utils/hwstub/stmp/stdint.h38
-rw-r--r--utils/hwstub/stmp/string.c29
-rw-r--r--utils/hwstub/stmp/string.h30
-rw-r--r--utils/hwstub/stmp/system.h118
-rw-r--r--utils/hwstub/stmp/usb_ch9.h454
-rw-r--r--utils/hwstub/tools/Makefile22
-rw-r--r--utils/hwstub/tools/hwemul_tool.c558
25 files changed, 3727 insertions, 0 deletions
diff --git a/utils/hwstub/hwemul_protocol.h b/utils/hwstub/hwemul_protocol.h
new file mode 100644
index 0000000000..f11fd91352
--- /dev/null
+++ b/utils/hwstub/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/hwstub/lib/Makefile b/utils/hwstub/lib/Makefile
new file mode 100644
index 0000000000..7280fe8e38
--- /dev/null
+++ b/utils/hwstub/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/hwstub/lib/hwemul.c b/utils/hwstub/lib/hwemul.c
new file mode 100644
index 0000000000..3e2e6de38a
--- /dev/null
+++ b/utils/hwstub/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/hwstub/lib/hwemul.h b/utils/hwstub/lib/hwemul.h
new file mode 100644
index 0000000000..376ba65381
--- /dev/null
+++ b/utils/hwstub/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/hwstub/lib/hwemul_protocol.h b/utils/hwstub/lib/hwemul_protocol.h
new file mode 100644
index 0000000000..d3ffb6ce00
--- /dev/null
+++ b/utils/hwstub/lib/hwemul_protocol.h
@@ -0,0 +1 @@
#include "../hwemul_protocol.h"
diff --git a/utils/hwstub/stmp/Makefile b/utils/hwstub/stmp/Makefile
new file mode 100644
index 0000000000..ca61fe392d
--- /dev/null
+++ b/utils/hwstub/stmp/Makefile
@@ -0,0 +1,92 @@
1PREFIX?=arm-elf-eabi-
2CC=$(PREFIX)gcc
3LD=$(PREFIX)gcc
4AS=$(PREFIX)gcc
5OC=$(PREFIX)objcopy
6SBTOOLS=../../sbtools/
7CFLAGS=-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
8CFLAGS_3700=$(CFLAGS) -DHAVE_STMP3700
9ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
10ASFLAGS_3700=$(CFLAGS_3700) -D__ASSEMBLER__
11OCFLAGS=
12LINKER_FILE=hwemul.lds
13LDFLAGS=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul.map
14LDFLAGS_3700=-lgcc -Os -nostdlib -Tlink.lds -Wl,-Map,hwemul3700.map
15SRC_C=$(wildcard *.c)
16SRC_S=$(wildcard *.S)
17OBJ_C=$(SRC_C:.c=.o)
18OBJ_S=$(SRC_S:.S=.o)
19OBJ_C_3700=$(SRC_C:.c=.3700.o)
20OBJ_S_3700=$(SRC_S:.S=.3700.o)
21OBJ=$(OBJ_C) $(OBJ_S)
22OBJ_3700=$(OBJ_C_3700) $(OBJ_S_3700)
23OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
24OBJ_EXCEPT_CRT0_3700=$(filter-out crt0.3700.o,$(OBJ_3700))
25DEPS=$(OBJ:.o=.d)
26EXEC_ELF=hwemul.elf
27EXEC_SB=hwemul.sb
28EXEC_ELF_3700=hwemul3700.elf
29EXEC_SB_3700=hwemul3700.sb
30
31ELF2SB=$(SBTOOLS)/elftosb -d
32ELF2SB_CMD=-c hwemul.db
33ELF2SB_KEY=-z
34SBLOADER=$(SBTOOLS)/sbloader
35SBLOADER_CMD=0 $(EXEC_SB)
36SBLOADER_CMD_3700=0 $(EXEC_SB_3700)
37
38TOOLS=../../../../tools/
39SCRAMBLE=$(TOOLS)/scramble
40
41EXEC=$(EXEC_SB) $(EXEC_SB_3700) $(EXEC_ELF) $(EXEC_ELF_3700)
42
43all: $(EXEC)
44
45# pull in dependency info for *existing* .o files
46-include $(DEPS)
47
48%.3700.o: %.c
49 $(CC) $(CFLAGS_3700) -c -o $@ $<
50 $(CC) -MM $(CFLAGS_3700) $*.c > $*.d
51 @cp -f $*.d $*.d.tmp
52 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
53 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
54 @rm -f $*.d.tmp
55
56%.o: %.c
57 $(CC) $(CFLAGS) -c -o $@ $<
58 $(CC) -MM $(CFLAGS) $*.c > $*.d
59 @cp -f $*.d $*.d.tmp
60 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
61 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
62 @rm -f $*.d.tmp
63
64%.3700.o: %.S
65 $(AS) $(ASFLAGS_3700) -c -o $@ $<
66
67%.o: %.S
68 $(AS) $(ASFLAGS) -c -o $@ $<
69
70link.lds: $(LINKER_FILE)
71 $(CC) -E -x c - < $< | sed '/#/d' > $@
72
73$(EXEC_ELF): $(OBJ) link.lds
74 $(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
75
76$(EXEC_SB): $(EXEC_ELF)
77 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
78
79$(EXEC_ELF_3700): $(OBJ_3700) link.lds
80 $(LD) $(LDFLAGS_3700) -o $@ $(OBJ_EXCEPT_CRT0_3700)
81
82$(EXEC_SB_3700): $(EXEC_ELF_3700)
83 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
84
85sbload: $(EXEC_SB)
86 $(SBLOADER) $(SBLOADER_CMD)
87
88sbload3700: $(EXEC_SB_3700)
89 $(SBLOADER) $(SBLOADER_CMD_3700)
90
91clean:
92 rm -rf $(OBJ) $(OBJ_3700) $(DEPS) $(EXEC) *.map
diff --git a/utils/hwstub/stmp/config.h b/utils/hwstub/stmp/config.h
new file mode 100644
index 0000000000..6bd995e147
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/crt0.S b/utils/hwstub/stmp/crt0.S
new file mode 100644
index 0000000000..e2d4742d36
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/format.c b/utils/hwstub/stmp/format.c
new file mode 100644
index 0000000000..f5783159c0
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/format.h b/utils/hwstub/stmp/format.h
new file mode 100644
index 0000000000..a514c882ba
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/hwemul.db b/utils/hwstub/stmp/hwemul.db
new file mode 100644
index 0000000000..7a6f930f57
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/hwemul.lds b/utils/hwstub/stmp/hwemul.lds
new file mode 100644
index 0000000000..7e3ac747a2
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/link.lds b/utils/hwstub/stmp/link.lds
new file mode 100644
index 0000000000..97b259955f
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/logf.c b/utils/hwstub/stmp/logf.c
new file mode 100644
index 0000000000..3ccc5c5e9f
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/logf.h b/utils/hwstub/stmp/logf.h
new file mode 100644
index 0000000000..5aa882a630
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/main.c b/utils/hwstub/stmp/main.c
new file mode 100644
index 0000000000..09bb6c7714
--- /dev/null
+++ b/utils/hwstub/stmp/main.c
@@ -0,0 +1,1409 @@
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 * USB PHY
784 *
785 */
786/* USB Phy */
787#define HW_USBPHY_BASE 0x8007C000
788#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
789#define HW_USBPHY_PWD__ALL (7 << 10 | 0xf << 17)
790
791#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
792
793/**
794 *
795 * DCP
796 *
797 */
798#define HW_DCP_BASE 0x80028000
799
800#define HW_DCP_CTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x0))
801
802#define HW_DCP_STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x10))
803#define HW_DCP_STAT__IRQ(x) (1 << (x))
804
805#define HW_DCP_CHANNELCTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x20))
806#define HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(x) (1 << (x))
807
808#define HW_DCP_CH0CMDPTR (*(volatile unsigned long *)(HW_DCP_BASE + 0x100))
809
810#define HW_DCP_CH0SEMA (*(volatile unsigned long *)(HW_DCP_BASE + 0x110))
811#define HW_DCP_CH0SEMA__INCREMENT(x) (x)
812#define HW_DCP_CH0SEMA__VALUE_BP 16
813#define HW_DCP_CH0SEMA__VALUE_BM (0xff << 16)
814#define HW_DCP_CH0STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x120))
815
816#define HW_DCP_CTRL0__INTERRUPT_ENABLE (1 << 0)
817#define HW_DCP_CTRL0__DECR_SEMAPHORE (1 << 1)
818#define HW_DCP_CTRL0__ENABLE_MEMCOPY (1 << 4)
819#define HW_DCP_CTRL0__ENABLE_CIPHER (1 << 5)
820#define HW_DCP_CTRL0__ENABLE_HASH (1 << 6)
821#define HW_DCP_CTRL0__CIPHER_ENCRYPT (1 << 8)
822#define HW_DCP_CTRL0__CIPHER_INIT (1 << 9)
823#define HW_DCP_CTRL0__OTP_KEY (1 << 10)
824#define HW_DCP_CTRL0__HASH_INIT (1 << 12)
825#define HW_DCP_CTRL0__HASH_TERM (1 << 13)
826#define HW_DCP_CTRL0__HASH_OUTPUT (1 << 15)
827
828#define HW_DCP_CTRL1__CIPHER_SELECT_BP 0
829#define HW_DCP_CTRL1__CIPHER_SELECT_BM 0xf
830#define HW_DCP_CTRL1__CIPHER_SELECT__AES128 0
831#define HW_DCP_CTRL1__CIPHER_MODE_BP 4
832#define HW_DCP_CTRL1__CIPHER_MODE_BM 0xf0
833#define HW_DCP_CTRL1__CIPHER_MODE__CBC (1 << 4)
834#define HW_DCP_CTRL1__HASH_SELECT_BP 4
835#define HW_DCP_CTRL1__HASH_SELECT_BM 0xf00
836
837struct dcp_packet_t
838{
839 unsigned long next;
840 unsigned long ctrl0;
841 unsigned long ctrl1;
842 unsigned long src_buf;
843 unsigned long dst_buf;
844 unsigned long buf_sz;
845 unsigned long payload_ptr;
846 unsigned long status;
847} __attribute__((packed));
848
849/**
850 *
851 * Misc
852 *
853 */
854
855void memcpy(uint8_t *dst, const uint8_t *src, uint32_t length)
856{
857 for(uint32_t i = 0; i < length; i++)
858 dst[i] = src[i];
859}
860
861void memset(uint8_t *dst, uint8_t fill, uint32_t length)
862{
863 for(uint32_t i = 0; i < length; i++)
864 dst[i] = fill;
865}
866
867/**
868 *
869 * USB stack
870 *
871 */
872
873static struct usb_device_descriptor __attribute__((aligned(2)))
874 device_descriptor=
875{
876 .bLength = sizeof(struct usb_device_descriptor),
877 .bDescriptorType = USB_DT_DEVICE,
878 .bcdUSB = 0x0200,
879 .bDeviceClass = USB_CLASS_PER_INTERFACE,
880 .bDeviceSubClass = 0,
881 .bDeviceProtocol = 0,
882 .bMaxPacketSize0 = 64,
883 .idVendor = HWEMUL_USB_VID,
884 .idProduct = HWEMUL_USB_PID,
885 .bcdDevice = HWEMUL_VERSION_MAJOR << 8 | HWEMUL_VERSION_MINOR,
886 .iManufacturer = 1,
887 .iProduct = 2,
888 .iSerialNumber = 3,
889 .bNumConfigurations = 1
890};
891
892#define USB_MAX_CURRENT 200
893
894static struct usb_config_descriptor __attribute__((aligned(2)))
895 config_descriptor =
896{
897 .bLength = sizeof(struct usb_config_descriptor),
898 .bDescriptorType = USB_DT_CONFIG,
899 .wTotalLength = 0, /* will be filled in later */
900 .bNumInterfaces = 1,
901 .bConfigurationValue = 1,
902 .iConfiguration = 0,
903 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
904 .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */
905};
906
907/* main interface */
908static struct usb_interface_descriptor __attribute__((aligned(2)))
909 interface_descriptor =
910{
911 .bLength = sizeof(struct usb_interface_descriptor),
912 .bDescriptorType = USB_DT_INTERFACE,
913 .bInterfaceNumber = 0,
914 .bAlternateSetting = 0,
915 .bNumEndpoints = 3,
916 .bInterfaceClass = HWEMUL_CLASS,
917 .bInterfaceSubClass = HWEMUL_SUBCLASS,
918 .bInterfaceProtocol = HWEMUL_PROTOCOL,
919 .iInterface = 4
920};
921
922
923static struct usb_endpoint_descriptor __attribute__((aligned(2)))
924 endpoint_descriptor =
925{
926 .bLength = sizeof(struct usb_endpoint_descriptor),
927 .bDescriptorType = USB_DT_ENDPOINT,
928 .bEndpointAddress = 0,
929 .bmAttributes = USB_ENDPOINT_XFER_BULK,
930 .wMaxPacketSize = 0,
931 .bInterval = 0
932};
933
934static const struct usb_string_descriptor __attribute__((aligned(2)))
935 usb_string_iManufacturer =
936{
937 24,
938 USB_DT_STRING,
939 {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'}
940};
941
942static const struct usb_string_descriptor __attribute__((aligned(2)))
943 usb_string_iProduct =
944{
945 52,
946 USB_DT_STRING,
947 {'R', 'o', 'c', 'k', 'b', 'o', 'x', ' ',
948 'h', 'a', 'r', 'd', 'w', 'a', 'r', 'e', ' ',
949 'e', 'm', 'u', 'l', 'a', 't', 'e', 'r'}
950};
951
952static struct usb_string_descriptor __attribute__((aligned(2)))
953 usb_string_iSerial =
954{
955 84,
956 USB_DT_STRING,
957 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
958 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
959 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
960 '0', '0', '0', '0', '0', '0', '0', '0'}
961};
962
963static struct usb_string_descriptor __attribute__((aligned(2)))
964 usb_string_iInterface =
965{
966 28,
967 USB_DT_STRING,
968 {'A', 'c', 'i', 'd', ' ',
969 '0' + (HWEMUL_VERSION_MAJOR >> 4), '0' + (HWEMUL_VERSION_MAJOR & 0xf), '.',
970 '0' + (HWEMUL_VERSION_MINOR >> 4), '0' + (HWEMUL_VERSION_MINOR & 0xf), '.',
971 '0' + (HWEMUL_VERSION_REV >> 4), '0' + (HWEMUL_VERSION_REV & 0xf) }
972};
973
974/* this is stringid #0: languages supported */
975static const struct usb_string_descriptor __attribute__((aligned(2)))
976 lang_descriptor =
977{
978 4,
979 USB_DT_STRING,
980 {0x0409} /* LANGID US English */
981};
982
983#define USB_NUM_STRINGS 5
984
985static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
986{
987 &lang_descriptor,
988 &usb_string_iManufacturer,
989 &usb_string_iProduct,
990 &usb_string_iSerial,
991 &usb_string_iInterface
992};
993
994uint8_t *usb_buffer = oc_bufferstart;
995uint32_t usb_buffer_size = 0;
996
997#define EP_BULK 1
998#define EP_INT 2
999
1000static void set_config(void)
1001{
1002 usb_drv_configure_endpoint(EP_BULK, USB_ENDPOINT_XFER_BULK);
1003 usb_drv_configure_endpoint(EP_INT, USB_ENDPOINT_XFER_INT);
1004}
1005
1006static void handle_std_dev_desc(struct usb_ctrlrequest *req)
1007{
1008 int size;
1009 const void* ptr = NULL;
1010 unsigned index = req->wValue & 0xff;
1011
1012 switch(req->wValue >> 8)
1013 {
1014 case USB_DT_DEVICE:
1015 ptr = &device_descriptor;
1016 size = sizeof(struct usb_device_descriptor);
1017 break;
1018 case USB_DT_OTHER_SPEED_CONFIG:
1019 case USB_DT_CONFIG:
1020 {
1021 int max_packet_size;
1022
1023 /* config desc */
1024 if((req->wValue >> 8) ==USB_DT_CONFIG)
1025 {
1026 max_packet_size = (usb_drv_port_speed() ? 512 : 64);
1027 config_descriptor.bDescriptorType = USB_DT_CONFIG;
1028 }
1029 else
1030 {
1031 max_packet_size=(usb_drv_port_speed() ? 64 : 512);
1032 config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
1033 }
1034 size = sizeof(struct usb_config_descriptor);
1035
1036 /* interface */
1037 memcpy(usb_buffer + size, (void *)&interface_descriptor,
1038 sizeof(interface_descriptor));
1039 size += sizeof(interface_descriptor);
1040 /* endpoint 1: bulk out */
1041 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_OUT;
1042 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
1043 endpoint_descriptor.wMaxPacketSize = 512;
1044 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1045 sizeof(endpoint_descriptor));
1046 size += sizeof(endpoint_descriptor);
1047 /* endpoint 2: bulk in */
1048 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_IN;
1049 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
1050 endpoint_descriptor.wMaxPacketSize = 512;
1051 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1052 sizeof(endpoint_descriptor));
1053 size += sizeof(endpoint_descriptor);
1054 /* endpoint 3: int in */
1055 endpoint_descriptor.bEndpointAddress = EP_INT | USB_DIR_IN;
1056 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT;
1057 endpoint_descriptor.wMaxPacketSize = 1024;
1058 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
1059 sizeof(endpoint_descriptor));
1060 size += sizeof(endpoint_descriptor);
1061
1062 /* fix config descriptor */
1063 config_descriptor.bNumInterfaces = 1;
1064 config_descriptor.wTotalLength = size;
1065 memcpy(usb_buffer, (void *)&config_descriptor, sizeof(config_descriptor));
1066
1067 ptr = usb_buffer;
1068 break;
1069 }
1070 case USB_DT_STRING:
1071 if(index < USB_NUM_STRINGS)
1072 {
1073 size = usb_strings[index]->bLength;
1074 ptr = usb_strings[index];
1075 }
1076 else
1077 usb_drv_stall(EP_CONTROL, true, true);
1078 break;
1079 default:
1080 break;
1081 }
1082
1083 if(ptr)
1084 {
1085 int length = MIN(size, req->wLength);
1086
1087 if(ptr != usb_buffer)
1088 memcpy(usb_buffer, ptr, length);
1089
1090 usb_drv_send(EP_CONTROL, usb_buffer, length);
1091 usb_drv_recv(EP_CONTROL, NULL, 0);
1092 }
1093 else
1094 usb_drv_stall(EP_CONTROL, true, true);
1095}
1096
1097static void handle_std_dev_req(struct usb_ctrlrequest *req)
1098{
1099 switch(req->bRequest)
1100 {
1101 case USB_REQ_GET_CONFIGURATION:
1102 usb_buffer[0] = 1;
1103 usb_drv_send(EP_CONTROL, usb_buffer, 1);
1104 usb_drv_recv(EP_CONTROL, NULL, 0);
1105 break;
1106 case USB_REQ_SET_CONFIGURATION:
1107 usb_drv_send(EP_CONTROL, NULL, 0);
1108 set_config();
1109 break;
1110 case USB_REQ_GET_DESCRIPTOR:
1111 handle_std_dev_desc(req);
1112 break;
1113 case USB_REQ_SET_ADDRESS:
1114 usb_drv_send(EP_CONTROL, NULL, 0);
1115 usb_drv_set_address(req->wValue);
1116 break;
1117 case USB_REQ_GET_STATUS:
1118 usb_buffer[0] = 0;
1119 usb_buffer[1] = 0;
1120 usb_drv_send(EP_CONTROL, usb_buffer, 2);
1121 usb_drv_recv(EP_CONTROL, NULL, 0);
1122 break;
1123 default:
1124 usb_drv_stall(EP_CONTROL, true, true);
1125 }
1126}
1127
1128static void handle_std_req(struct usb_ctrlrequest *req)
1129{
1130 switch(req->bRequestType & USB_RECIP_MASK)
1131 {
1132 case USB_RECIP_DEVICE:
1133 return handle_std_dev_req(req);
1134 default:
1135 usb_drv_stall(EP_CONTROL, true, true);
1136 }
1137}
1138
1139struct usb_resp_info_version_t g_version =
1140{
1141 .major = HWEMUL_VERSION_MAJOR,
1142 .minor = HWEMUL_VERSION_MINOR,
1143 .revision = HWEMUL_VERSION_REV
1144};
1145
1146struct usb_resp_info_layout_t g_layout;
1147
1148struct usb_resp_info_stmp_t g_stmp;
1149
1150struct usb_resp_info_features_t g_features =
1151{
1152 .feature_mask = HWEMUL_FEATURE_LOG | HWEMUL_FEATURE_MEM |
1153 HWEMUL_FEATURE_CALL | HWEMUL_FEATURE_JUMP | HWEMUL_FEATURE_AES_OTP
1154};
1155
1156static void fill_layout_info(void)
1157{
1158 g_layout.oc_code_start = (uint32_t)oc_codestart;
1159 g_layout.oc_code_size = oc_codesize;
1160 g_layout.oc_stack_start = (uint32_t)oc_stackstart;
1161 g_layout.oc_stack_size = oc_stacksize;
1162 g_layout.oc_buffer_start = (uint32_t)oc_bufferstart;
1163 g_layout.oc_buffer_size = oc_buffersize;
1164}
1165
1166static void fill_stmp_info(void)
1167{
1168 g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
1169 g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
1170 g_stmp.is_supported = g_stmp.chipid == 0x3780 || g_stmp.chipid == 0x3700 ||
1171 g_stmp.chipid == 0x3b00;
1172}
1173
1174static void handle_get_info(struct usb_ctrlrequest *req)
1175{
1176 void *ptr = NULL;
1177 int size = 0;
1178 switch(req->wIndex)
1179 {
1180 case HWEMUL_INFO_VERSION:
1181 ptr = &g_version;
1182 size = sizeof(g_version);
1183 break;
1184 case HWEMUL_INFO_LAYOUT:
1185 fill_layout_info();
1186 ptr = &g_layout;
1187 size = sizeof(g_layout);
1188 break;
1189 case HWEMUL_INFO_STMP:
1190 fill_stmp_info();
1191 ptr = &g_stmp;
1192 size = sizeof(g_stmp);
1193 break;
1194 case HWEMUL_INFO_FEATURES:
1195 ptr = &g_features;
1196 size = sizeof(g_features);
1197 break;
1198 default:
1199 usb_drv_stall(EP_CONTROL, true, true);
1200 }
1201
1202 if(ptr)
1203 {
1204 int length = MIN(size, req->wLength);
1205
1206 if(ptr != usb_buffer)
1207 memcpy(usb_buffer, ptr, length);
1208 usb_drv_send(EP_CONTROL, usb_buffer, length);
1209 usb_drv_recv(EP_CONTROL, NULL, 0);
1210 }
1211}
1212
1213static void handle_get_log(struct usb_ctrlrequest *req)
1214{
1215 enable_logf(false);
1216 int length = logf_readback(usb_buffer, MIN(req->wLength, usb_buffer_size));
1217 usb_drv_send(EP_CONTROL, usb_buffer, length);
1218 usb_drv_recv(EP_CONTROL, NULL, 0);
1219 enable_logf(true);
1220}
1221
1222static void handle_rw_mem(struct usb_ctrlrequest *req)
1223{
1224 uint32_t addr = req->wValue | req->wIndex << 16;
1225 uint16_t length = req->wLength;
1226
1227 if(req->bRequestType & USB_DIR_IN)
1228 {
1229 memcpy(usb_buffer, (void *)addr, length);
1230 asm volatile("nop" : : : "memory");
1231 usb_drv_send(EP_CONTROL, usb_buffer, length);
1232 usb_drv_recv(EP_CONTROL, NULL, 0);
1233 }
1234 else
1235 {
1236 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
1237 asm volatile("nop" : : : "memory");
1238 if(size != length)
1239 usb_drv_stall(EP_CONTROL, true, true);
1240 else
1241 {
1242 memcpy((void *)addr, usb_buffer, length);
1243 usb_drv_send(EP_CONTROL, NULL, 0);
1244 }
1245 }
1246}
1247
1248static void handle_call_jump(struct usb_ctrlrequest *req)
1249{
1250 uint32_t addr = req->wValue | req->wIndex << 16;
1251
1252 if(req->bRequest == HWEMUL_CALL)
1253 ((void (*)(void))addr)();
1254 else
1255 asm volatile("bx %0\n" : : "r" (addr) : "memory");
1256}
1257
1258static void do_aes_otp(void *buffer, unsigned length, unsigned params)
1259{
1260 static struct dcp_packet_t dcp_packet;
1261
1262 bool encrypt = !!(params & HWEMUL_AES_OTP_ENCRYPT);
1263 /* reset DCP */
1264 __REG_SET(HW_DCP_CTRL) = 0x80000000;
1265 /* clear clock gate */
1266 __REG_CLR(HW_DCP_CTRL) = 0xc0000000;
1267 /* enable dma for channel 0 */
1268 __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(0);
1269 /* prepare packet */
1270 dcp_packet.next = 0;
1271
1272 dcp_packet.ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE |
1273 HW_DCP_CTRL0__DECR_SEMAPHORE | HW_DCP_CTRL0__CIPHER_INIT |
1274 HW_DCP_CTRL0__ENABLE_CIPHER | HW_DCP_CTRL0__OTP_KEY |
1275 (encrypt ? HW_DCP_CTRL0__CIPHER_ENCRYPT : 0);
1276 dcp_packet.ctrl1 = HW_DCP_CTRL1__CIPHER_SELECT__AES128 |
1277 HW_DCP_CTRL1__CIPHER_MODE__CBC;
1278 dcp_packet.src_buf = (unsigned long)buffer + 16;
1279 dcp_packet.dst_buf = (unsigned long)buffer + 16;
1280 dcp_packet.buf_sz = length - 16;
1281 dcp_packet.payload_ptr = (unsigned long)buffer;
1282 dcp_packet.status = 0;
1283
1284 asm volatile("":::"memory");
1285 /* kick */
1286 HW_DCP_CH0CMDPTR = (unsigned long)&dcp_packet;
1287 HW_DCP_CH0SEMA = HW_DCP_CH0SEMA__INCREMENT(1);
1288 /* wait */
1289 while(!(HW_DCP_STAT & HW_DCP_STAT__IRQ(0)));
1290
1291 usb_drv_send_nonblocking(EP_INT, buffer, length);
1292}
1293
1294static void handle_aes_otp(struct usb_ctrlrequest *req)
1295{
1296 uint16_t length = req->wLength;
1297
1298 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
1299 if(size != length)
1300 usb_drv_stall(EP_CONTROL, true, true);
1301 else
1302 usb_drv_send(EP_CONTROL, NULL, 0);
1303 do_aes_otp(usb_buffer, length, req->wValue);
1304}
1305
1306static void handle_class_dev_req(struct usb_ctrlrequest *req)
1307{
1308 switch(req->bRequest)
1309 {
1310 case HWEMUL_GET_INFO:
1311 handle_get_info(req);
1312 break;
1313 case HWEMUL_GET_LOG:
1314 handle_get_log(req);
1315 break;
1316 case HWEMUL_RW_MEM:
1317 handle_rw_mem(req);
1318 break;
1319 case HWEMUL_CALL:
1320 case HWEMUL_JUMP:
1321 handle_call_jump(req);
1322 break;
1323 case HWEMUL_AES_OTP:
1324 handle_aes_otp(req);
1325 break;
1326 default:
1327 usb_drv_stall(EP_CONTROL, true, true);
1328 }
1329}
1330
1331static void handle_class_req(struct usb_ctrlrequest *req)
1332{
1333 switch(req->bRequestType & USB_RECIP_MASK)
1334 {
1335 case USB_RECIP_DEVICE:
1336 return handle_class_dev_req(req);
1337 default:
1338 usb_drv_stall(EP_CONTROL, true, true);
1339 }
1340}
1341
1342/**
1343 *
1344 * Main
1345 *
1346 */
1347
1348void main(uint32_t arg)
1349{
1350 usb_buffer_size = oc_buffersize;
1351
1352 logf("hwemul %d.%d.%d\n", HWEMUL_VERSION_MAJOR, HWEMUL_VERSION_MINOR,
1353 HWEMUL_VERSION_REV);
1354 logf("argument: 0x%08x\n", arg);
1355
1356 /* we don't know if USB was connected or not. In USB recovery mode it will
1357 * but in other cases it might not be. In doubt, disconnect */
1358 REG_USBCMD &= ~USBCMD_RUN;
1359 /* enable USB PHY PLL */
1360 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
1361 /* power up USB PHY */
1362 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
1363 //__REG_CLR(HW_USBPHY_PWD) = HW_USBPHY_PWD__ALL;
1364 HW_USBPHY_PWD = 0;
1365 /* enable USB controller */
1366 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
1367 /* reset the controller */
1368 REG_USBCMD |= USBCMD_CTRL_RESET;
1369 while (REG_USBCMD & USBCMD_CTRL_RESET);
1370 /* put it in device mode */
1371 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
1372 /* reset address */
1373 REG_DEVICEADDR = 0;
1374 /* prepare qh array */
1375 qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1376 qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1377 qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1378 qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1379 /* setup qh */
1380 REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
1381 /* clear setup status */
1382 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1383 /* run! */
1384 REG_USBCMD |= USBCMD_RUN;
1385
1386 while(1)
1387 {
1388 /* wait for setup */
1389 while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0))
1390 ;
1391 /* clear setup status */
1392 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1393 /* check request */
1394 asm volatile("":::"memory");
1395 struct usb_ctrlrequest *req = (void *)&qh_array[0].setup_buffer[0];
1396
1397 switch(req->bRequestType & USB_TYPE_MASK)
1398 {
1399 case USB_TYPE_STANDARD:
1400 handle_std_req(req);
1401 break;
1402 case USB_TYPE_CLASS:
1403 handle_class_req(req);
1404 break;
1405 default:
1406 usb_drv_stall(EP_CONTROL, true, true);
1407 }
1408 }
1409}
diff --git a/utils/hwstub/stmp/protocol.h b/utils/hwstub/stmp/protocol.h
new file mode 100644
index 0000000000..d3ffb6ce00
--- /dev/null
+++ b/utils/hwstub/stmp/protocol.h
@@ -0,0 +1 @@
#include "../hwemul_protocol.h"
diff --git a/utils/hwstub/stmp/stddef.h b/utils/hwstub/stmp/stddef.h
new file mode 100644
index 0000000000..9d59d2913c
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/stdint.h b/utils/hwstub/stmp/stdint.h
new file mode 100644
index 0000000000..4fe3702c86
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/string.c b/utils/hwstub/stmp/string.c
new file mode 100644
index 0000000000..1f8c415a99
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/string.h b/utils/hwstub/stmp/string.h
new file mode 100644
index 0000000000..7ef460ea6e
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/system.h b/utils/hwstub/stmp/system.h
new file mode 100644
index 0000000000..c1babe7d87
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/stmp/usb_ch9.h b/utils/hwstub/stmp/usb_ch9.h
new file mode 100644
index 0000000000..09141b93bd
--- /dev/null
+++ b/utils/hwstub/stmp/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/hwstub/tools/Makefile b/utils/hwstub/tools/Makefile
new file mode 100644
index 0000000000..3466a4e776
--- /dev/null
+++ b/utils/hwstub/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` -lreadline
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) -o $@ $^ $(LDFLAGS)
18
19clean:
20 rm -rf $(OBJ) $(LIB)
21
22
diff --git a/utils/hwstub/tools/hwemul_tool.c b/utils/hwstub/tools/hwemul_tool.c
new file mode 100644
index 0000000000..d75cd7a957
--- /dev/null
+++ b/utils/hwstub/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#include <readline/readline.h>
28#include <readline/history.h>
29
30bool g_quiet = false;
31struct hwemul_device_t hwdev;
32struct hwemul_soc_t *cur_soc = NULL;
33
34void print_log(struct hwemul_device_t *hwdev)
35{
36 do
37 {
38 char buffer[128];
39 int length = hwemul_get_log(hwdev, buffer, sizeof(buffer) - 1);
40 if(length <= 0)
41 break;
42 buffer[length] = 0;
43 printf("%s", buffer);
44 }while(1);
45}
46
47int print_help()
48{
49 printf("Commands:\n");
50 printf(" help\t\tDisplay this help\n");
51 printf(" call <addr>\tCall address <addr>\n");
52 printf(" quit\t\tQuit this session\n");
53 printf(" read32 <addr>\tRead a 32-bit word at <addr>\n");
54 printf(" write32 <value> <addr>\tRead the 32-bit word <value> at <addr>\n");
55 printf(" read <regname>\tRead a register by name\n");
56 printf(" read <regname>.<field>\tRead a register field by name\n");
57 printf(" soc <socname>\tSelect the soc description to use\n");
58 printf(" write <value> <regname>\tWrite a register by name\n");
59 printf(" write <value <regname>.<field>\tWrite a register field by name\n");
60 printf(" NOTE: if the register is SCT variant, no read is performed.\n");
61 return 1;
62}
63
64int syntax_error(char *str)
65{
66 printf("Syntax error at '%s'. Type 'help' to get some help.\n", str);
67 return 1;
68}
69
70int parse_uint32(char *str, uint32_t *u)
71{
72 char *end;
73 *u = strtoul(str, &end, 0);
74 return *end == 0;
75}
76
77int do_call(uint32_t a)
78{
79 hwemul_call(&hwdev, a);
80 return 1;
81}
82
83int parse_call()
84{
85 char *arg = strtok(NULL, " ");
86 uint32_t addr;
87 if(arg && parse_uint32(arg, &addr))
88 return do_call(addr);
89 else
90 return syntax_error(arg);
91}
92
93int do_read32(uint32_t a)
94{
95 uint32_t val;
96 if(hwemul_rw_mem(&hwdev, 1, a, &val, sizeof(val)) == sizeof(val))
97 printf("%#x = %#x\n", a, val);
98 else
99 printf("read error at %#x\n", a);
100 return 1;
101}
102
103int parse_read32()
104{
105 char *arg = strtok(NULL, " ");
106 uint32_t addr;
107 if(arg && parse_uint32(arg, &addr))
108 return do_read32(addr);
109 else
110 return syntax_error(arg);
111}
112
113int do_write32(uint32_t val, uint32_t a)
114{
115 if(hwemul_rw_mem(&hwdev, 0, a, &val, sizeof(val)) == sizeof(val))
116 printf("data written\n");
117 else
118 printf("write error at %#x\n", a);
119 return 1;
120}
121
122int parse_write32()
123{
124 char *arg = strtok(NULL, " ");
125 uint32_t val;
126 if(!arg || !parse_uint32(arg, &val))
127 return syntax_error(arg);
128 uint32_t addr;
129 arg = strtok(NULL, " ");
130 if(arg && parse_uint32(arg, &addr))
131 return do_write32(val, addr);
132 else
133 return syntax_error(arg);
134}
135
136struct hwemul_soc_t *find_soc_by_name(const char *soc)
137{
138 struct hwemul_soc_list_t *list = hwemul_get_soc_list();
139 for(size_t i = 0; i < list->nr_socs; i++)
140 if(strcmp(soc, list->socs[i]->name) == 0)
141 return list->socs[i];
142 return NULL;
143}
144
145struct hwemul_soc_reg_t *find_reg_by_name(struct hwemul_soc_t *soc, const char *reg)
146{
147 for(size_t i = 0; i < soc->nr_regs; i++)
148 if(strcmp(reg, soc->regs_by_name[i]->name) == 0)
149 return soc->regs_by_name[i];
150 return NULL;
151}
152
153struct hwemul_soc_reg_field_t *find_field_by_name(struct hwemul_soc_reg_t *reg, const char *field)
154{
155 for(size_t i = 0; i < reg->nr_fields; i++)
156 if(strcmp(field, reg->fields_by_name[i]->name) == 0)
157 return reg->fields_by_name[i];
158 return NULL;
159}
160
161
162int do_read(char *regname)
163{
164 char *dot = strchr(regname, '.');
165 if(dot != NULL)
166 *dot++ = 0;
167 if(cur_soc == NULL)
168 {
169 printf("No soc selected!\n");
170 return 1;
171 }
172 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
173 if(reg == NULL)
174 {
175 printf("no reg '%s' found\n", regname);
176 return 1;
177 }
178 uint32_t val;
179 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &val, sizeof(val)) != sizeof(val))
180 {
181 printf("read error at %#x\n", reg->addr);
182 return 1;
183 }
184 if(dot)
185 {
186 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
187 if(field == NULL)
188 {
189 printf("no field '%s' found\n", dot);
190 return 1;
191 }
192 val >>= field->first_bit;
193 val &= (1 << (field->last_bit - field->first_bit + 1)) - 1;
194 printf("%s.%s = %#x\n", regname, dot, val);
195 }
196 else
197 printf("%s = %#x\n", regname, val);
198 return 1;
199}
200
201int parse_read()
202{
203 char *arg = strtok(NULL, " ");
204 if(arg)
205 return do_read(arg);
206 else
207 return syntax_error(arg);
208}
209
210int do_soc(char *soc)
211{
212 struct hwemul_soc_t *s = find_soc_by_name(soc);
213 if(s == NULL)
214 printf("no soc '%s' found\n", soc);
215 else
216 cur_soc = s;
217 return 1;
218}
219
220int parse_soc()
221{
222 char *arg = strtok(NULL, " ");
223 if(arg)
224 return do_soc(arg);
225 else
226 return syntax_error(arg);
227}
228
229int do_write(uint32_t val, char *regname)
230{
231 char *dot = strchr(regname, '.');
232 if(dot != NULL)
233 *dot++ = 0;
234 if(cur_soc == NULL)
235 {
236 printf("No soc selected!\n");
237 return 1;
238 }
239 struct hwemul_soc_reg_t *reg = find_reg_by_name(cur_soc, regname);
240 int is_sct = 0;
241 uint32_t addr_off = 0;
242 if(reg == NULL)
243 {
244 size_t len = strlen(regname);
245 /* try SCT variant */
246 if(strcmp(regname + len - 4, "_SET") == 0)
247 addr_off = 4;
248 else if(strcmp(regname + len - 4, "_CLR") == 0)
249 addr_off = 8;
250 else if(strcmp(regname + len - 4, "_TOG") == 0)
251 addr_off = 12;
252 else
253 {
254 printf("no reg '%s' found\n", regname);
255 return 1;
256 }
257 is_sct = 1;
258 regname[len - 4] = 0;
259 reg = find_reg_by_name(cur_soc, regname);
260 if(reg == NULL)
261 {
262 printf("no reg '%s' found\n", regname);
263 return 1;
264 }
265 }
266 if(dot)
267 {
268 struct hwemul_soc_reg_field_t *field = find_field_by_name(reg, dot);
269 if(field == NULL)
270 {
271 printf("no field '%s' found\n", dot);
272 return 1;
273 }
274 uint32_t actual_val = 0;
275 if(!is_sct)
276 {
277 if(hwemul_rw_mem(&hwdev, 1, reg->addr, &actual_val, sizeof(actual_val)) != sizeof(actual_val))
278 {
279 printf("read error at %#x\n", reg->addr);
280 return 1;
281 }
282 printf("read %#x at %#x\n", actual_val, reg->addr);
283 }
284 uint32_t mask = ((1 << (field->last_bit - field->first_bit + 1)) - 1) << field->first_bit;
285 printf("mask=%#x\n", mask);
286 val = (actual_val & ~mask) | ((val << field->first_bit) & mask);
287 }
288 printf("write %#x to %#x\n", val, reg->addr + addr_off);
289 if(hwemul_rw_mem(&hwdev, 0, reg->addr + addr_off, &val, sizeof(val)) != sizeof(val))
290 {
291 printf("write error at %#x\n", reg->addr);
292 return 1;
293 }
294 return 1;
295}
296
297int parse_write()
298{
299 char *arg = strtok(NULL, " ");
300 uint32_t val;
301 if(!arg || !parse_uint32(arg, &val))
302 return syntax_error(arg);
303 arg = strtok(NULL, " ");
304 if(arg)
305 return do_write(val, arg);
306 else
307 return syntax_error(arg);
308}
309
310int parse_command(char *cmd)
311{
312 if(strcmp(cmd, "help") == 0)
313 return print_help();
314 if(strcmp(cmd, "quit") == 0)
315 return 0;
316 if(strcmp(cmd, "call") == 0)
317 return parse_call();
318 if(strcmp(cmd, "read32") == 0)
319 return parse_read32();
320 if(strcmp(cmd, "write32") == 0)
321 return parse_write32();
322 if(strcmp(cmd, "read") == 0)
323 return parse_read();
324 if(strcmp(cmd, "soc") == 0)
325 return parse_soc();
326 if(strcmp(cmd, "write") == 0)
327 return parse_write();
328 return syntax_error(cmd);
329}
330
331void interactive_mode(void)
332{
333 rl_bind_key('\t', rl_complete);
334 while(1)
335 {
336 char *input = readline("> ");
337 if(!input)
338 break;
339 add_history(input);
340 int ret = parse_command(input);
341 free(input);
342 if(ret == 0)
343 break;
344 }
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
547 interactive_mode();
548
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}