summaryrefslogtreecommitdiff
path: root/utils/hwstub
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-07-13 17:35:53 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-07-13 17:47:01 +0200
commit140783ef66eef379feedcfef5403c5729d38936a (patch)
tree0185a6a6ef80ab134150454674a1d7e1333b8757 /utils/hwstub
parent3dd5e983db8d83113cc76ee0f5c02e158380606a (diff)
downloadrockbox-140783ef66eef379feedcfef5403c5729d38936a.tar.gz
rockbox-140783ef66eef379feedcfef5403c5729d38936a.zip
hwstub: split target specific code from the common part
Completely rewrite the Mafile, properly put the usb driver in its own file and the target specific files in a subdirectory. Change-Id: Iaeee0128e021d5dad76b4d6035a63e33e2d946c1
Diffstat (limited to 'utils/hwstub')
-rw-r--r--utils/hwstub/stmp/Makefile74
-rw-r--r--utils/hwstub/stmp/main.c1105
-rw-r--r--utils/hwstub/stub/SOURCES12
-rw-r--r--utils/hwstub/stub/config.h (renamed from utils/hwstub/stmp/config.h)11
-rw-r--r--utils/hwstub/stub/crt0.S (renamed from utils/hwstub/stmp/crt0.S)0
-rw-r--r--utils/hwstub/stub/format.c (renamed from utils/hwstub/stmp/format.c)0
-rw-r--r--utils/hwstub/stub/format.h (renamed from utils/hwstub/stmp/format.h)0
-rw-r--r--utils/hwstub/stub/hwstub.lds (renamed from utils/hwstub/stmp/hwstub.lds)0
-rw-r--r--utils/hwstub/stub/hwstub.make49
-rw-r--r--utils/hwstub/stub/logf.c (renamed from utils/hwstub/stmp/logf.c)1
-rw-r--r--utils/hwstub/stub/logf.h (renamed from utils/hwstub/stmp/logf.h)0
-rw-r--r--utils/hwstub/stub/memcpy.S (renamed from utils/hwstub/stmp/memcpy.S)0
-rw-r--r--utils/hwstub/stub/memmove.S (renamed from utils/hwstub/stmp/memmove.S)0
-rw-r--r--utils/hwstub/stub/memory.h30
-rw-r--r--utils/hwstub/stub/memset.S (renamed from utils/hwstub/stmp/memset.S)0
-rw-r--r--utils/hwstub/stub/protocol.h (renamed from utils/hwstub/stmp/protocol.h)0
-rw-r--r--utils/hwstub/stub/stddef.h (renamed from utils/hwstub/stmp/stddef.h)0
-rw-r--r--utils/hwstub/stub/stdint.h (renamed from utils/hwstub/stmp/stdint.h)2
-rw-r--r--utils/hwstub/stub/stmp/Makefile14
-rw-r--r--utils/hwstub/stub/stmp/target-config.h9
-rw-r--r--utils/hwstub/stub/stmp/target.c205
-rw-r--r--utils/hwstub/stub/string.c (renamed from utils/hwstub/stmp/string.c)0
-rw-r--r--utils/hwstub/stub/string.h (renamed from utils/hwstub/stmp/string.h)2
-rw-r--r--utils/hwstub/stub/system.h (renamed from utils/hwstub/stmp/system.h)0
-rw-r--r--utils/hwstub/stub/target.h (renamed from utils/hwstub/stmp/hwstub.db)20
-rw-r--r--utils/hwstub/stub/usb_ch9.h (renamed from utils/hwstub/stmp/usb_ch9.h)0
-rw-r--r--utils/hwstub/stub/usb_drv.h47
-rw-r--r--utils/hwstub/stub/usb_drv_arc.c364
28 files changed, 745 insertions, 1200 deletions
diff --git a/utils/hwstub/stmp/Makefile b/utils/hwstub/stmp/Makefile
deleted file mode 100644
index 4185dcbbc9..0000000000
--- a/utils/hwstub/stmp/Makefile
+++ /dev/null
@@ -1,74 +0,0 @@
1#
2# common
3#
4CC=arm-elf-eabi-gcc
5LD=arm-elf-eabi-gcc
6AS=arm-elf-eabi-gcc
7OC=arm-elf-eabi-objcopy
8CFLAGS=-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
9ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
10OCFLAGS=
11LINKER_FILE=hwstub.lds
12TMP_LDS=link.lds
13TMP_MAP=hwstub.map
14LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP)
15SRC_C=$(wildcard *.c)
16SRC_S=$(wildcard *.S)
17OBJ_C=$(SRC_C:.c=.o)
18OBJ_S=$(SRC_S:.S=.o)
19OBJ=$(OBJ_C) $(OBJ_S)
20OBJ_EXCEPT_CRT0=$(filter-out crt0.o,$(OBJ))
21DEPS=$(OBJ:.o=.d)
22EXEC_ELF=hwstub.elf
23
24#
25# image production
26#
27TOOLS=../../../tools
28SBTOOLS=../../imxtools/sbtools
29
30# sb (stmp37xx)
31EXEC_SB=hwstub.sb
32ELF2SB=$(SBTOOLS)/elftosb -d
33ELF2SB_CMD=-c hwstub.db
34ELF2SB_KEY?=-z
35
36# sb1 (stmp36xx)
37EXEC_SB1=hwstub.sb1
38ELF2SB1_CMD=-loadjump $(EXEC_ELF)
39ELF2SB1_KEY?=
40ELF2SB1=$(SBTOOLS)/elftosb1 -d
41
42EXEC=$(EXEC_ELF) $(EXEC_SB) $(EXEC_SB1)
43
44all: $(EXEC)
45
46# pull in dependency info for *existing* .o files
47-include $(DEPS)
48
49%.o: %.c
50 $(CC) $(CFLAGS) -c -o $@ $<
51 $(CC) -MM $(CFLAGS) $*.c > $*.d
52 @cp -f $*.d $*.d.tmp
53 @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
54 sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
55 @rm -f $*.d.tmp
56
57%.o: %.S
58 $(AS) $(ASFLAGS) -c -o $@ $<
59
60$(TMP_LDS): $(LINKER_FILE)
61 $(CC) -E -x c - < $< | sed '/#/d' > $@
62
63$(EXEC_ELF): $(OBJ) $(TMP_LDS)
64 $(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
65
66$(EXEC_SB): $(EXEC_ELF)
67 $(ELF2SB) $(ELF2SB_CMD) $(ELF2SB_KEY) -o $@
68
69$(EXEC_SB1): $(EXEC_ELF)
70 $(ELF2SB1) $(ELF2SB1_CMD) $(ELF2SB1_KEY) -o $@
71
72clean:
73 rm -rf $(OBJ) $(DEPS) $(EXEC) $(TMP_LDS) $(TMP_MAP)
74
diff --git a/utils/hwstub/stmp/main.c b/utils/hwstub/stmp/main.c
deleted file mode 100644
index 845f3842ea..0000000000
--- a/utils/hwstub/stmp/main.c
+++ /dev/null
@@ -1,1105 +0,0 @@
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 * Global
38 *
39 */
40
41enum stmp_family_t
42{
43 UNKNOWN,
44 STMP3600,
45 STMP3700,
46 STMP3770,
47 STMP3780
48};
49
50enum stmp_family_t g_stmp_family = UNKNOWN;
51
52/**
53 *
54 * USB subsystem
55 *
56 */
57
58#define USB_BASE 0x80080000
59#define USB_NUM_ENDPOINTS 2
60#define MAX_PKT_SIZE 1024
61#define MAX_PKT_SIZE_EP0 64
62
63/* USB device mode registers (Little Endian) */
64#define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140))
65#define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154))
66#define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158))
67#define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184))
68#define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8))
69#define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac))
70#define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0))
71#define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8))
72#define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc))
73#define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0))
74#define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4))
75#define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8))
76#define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_)))
77
78/* USB CMD Register Bit Masks */
79#define USBCMD_RUN (0x00000001)
80#define USBCMD_CTRL_RESET (0x00000002)
81#define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010)
82#define USBCMD_ASYNC_SCHEDULE_EN (0x00000020)
83#define USBCMD_INT_AA_DOORBELL (0x00000040)
84#define USBCMD_ASP (0x00000300)
85#define USBCMD_ASYNC_SCH_PARK_EN (0x00000800)
86#define USBCMD_SUTW (0x00002000)
87#define USBCMD_ATDTW (0x00004000)
88#define USBCMD_ITC (0x00FF0000)
89
90/* Device Address bit masks */
91#define USBDEVICEADDRESS_MASK (0xFE000000)
92#define USBDEVICEADDRESS_BIT_POS (25)
93
94/* Endpoint Setup Status bit masks */
95#define EPSETUP_STATUS_EP0 (0x00000001)
96
97/* PORTSCX Register Bit Masks */
98#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001)
99#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002)
100#define PORTSCX_PORT_ENABLE (0x00000004)
101#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008)
102#define PORTSCX_OVER_CURRENT_ACT (0x00000010)
103#define PORTSCX_OVER_CURRENT_CHG (0x00000020)
104#define PORTSCX_PORT_FORCE_RESUME (0x00000040)
105#define PORTSCX_PORT_SUSPEND (0x00000080)
106#define PORTSCX_PORT_RESET (0x00000100)
107#define PORTSCX_LINE_STATUS_BITS (0x00000C00)
108#define PORTSCX_PORT_POWER (0x00001000)
109#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000)
110#define PORTSCX_PORT_TEST_CTRL (0x000F0000)
111#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000)
112#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000)
113#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000)
114#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000)
115#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000)
116#define PORTSCX_PORT_SPEED_MASK (0x0C000000)
117#define PORTSCX_PORT_WIDTH (0x10000000)
118#define PORTSCX_PHY_TYPE_SEL (0xC0000000)
119
120/* bit 11-10 are line status */
121#define PORTSCX_LINE_STATUS_SE0 (0x00000000)
122#define PORTSCX_LINE_STATUS_JSTATE (0x00000400)
123#define PORTSCX_LINE_STATUS_KSTATE (0x00000800)
124#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00)
125#define PORTSCX_LINE_STATUS_BIT_POS (10)
126
127/* bit 15-14 are port indicator control */
128#define PORTSCX_PIC_OFF (0x00000000)
129#define PORTSCX_PIC_AMBER (0x00004000)
130#define PORTSCX_PIC_GREEN (0x00008000)
131#define PORTSCX_PIC_UNDEF (0x0000C000)
132#define PORTSCX_PIC_BIT_POS (14)
133
134/* bit 19-16 are port test control */
135#define PORTSCX_PTC_DISABLE (0x00000000)
136#define PORTSCX_PTC_JSTATE (0x00010000)
137#define PORTSCX_PTC_KSTATE (0x00020000)
138#define PORTSCX_PTC_SE0NAK (0x00030000)
139#define PORTSCX_PTC_PACKET (0x00040000)
140#define PORTSCX_PTC_FORCE_EN (0x00050000)
141#define PORTSCX_PTC_BIT_POS (16)
142
143/* bit 27-26 are port speed */
144#define PORTSCX_PORT_SPEED_FULL (0x00000000)
145#define PORTSCX_PORT_SPEED_LOW (0x04000000)
146#define PORTSCX_PORT_SPEED_HIGH (0x08000000)
147#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000)
148#define PORTSCX_SPEED_BIT_POS (26)
149
150/* bit 28 is parallel transceiver width for UTMI interface */
151#define PORTSCX_PTW (0x10000000)
152#define PORTSCX_PTW_8BIT (0x00000000)
153#define PORTSCX_PTW_16BIT (0x10000000)
154
155/* bit 31-30 are port transceiver select */
156#define PORTSCX_PTS_UTMI (0x00000000)
157#define PORTSCX_PTS_CLASSIC (0x40000000)
158#define PORTSCX_PTS_ULPI (0x80000000)
159#define PORTSCX_PTS_FSLS (0xC0000000)
160#define PORTSCX_PTS_BIT_POS (30)
161
162/* USB MODE Register Bit Masks */
163#define USBMODE_CTRL_MODE_IDLE (0x00000000)
164#define USBMODE_CTRL_MODE_DEVICE (0x00000002)
165#define USBMODE_CTRL_MODE_HOST (0x00000003)
166#define USBMODE_CTRL_MODE_RSV (0x00000001)
167#define USBMODE_SETUP_LOCK_OFF (0x00000008)
168#define USBMODE_STREAM_DISABLE (0x00000010)
169
170/* ENDPOINTCTRLx Register Bit Masks */
171#define EPCTRL_TX_ENABLE (0x00800000)
172#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */
173#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */
174#define EPCTRL_TX_TYPE (0x000C0000)
175#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */
176#define EPCTRL_TX_EP_STALL (0x00010000)
177#define EPCTRL_RX_ENABLE (0x00000080)
178#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */
179#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */
180#define EPCTRL_RX_TYPE (0x0000000C)
181#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */
182#define EPCTRL_RX_EP_STALL (0x00000001)
183
184/* bit 19-18 and 3-2 are endpoint type */
185#define EPCTRL_TX_EP_TYPE_SHIFT (18)
186#define EPCTRL_RX_EP_TYPE_SHIFT (2)
187
188#define QH_MULT_POS (30)
189#define QH_ZLT_SEL (0x20000000)
190#define QH_MAX_PKT_LEN_POS (16)
191#define QH_IOS (0x00008000)
192#define QH_NEXT_TERMINATE (0x00000001)
193#define QH_IOC (0x00008000)
194#define QH_MULTO (0x00000C00)
195#define QH_STATUS_HALT (0x00000040)
196#define QH_STATUS_ACTIVE (0x00000080)
197#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
198#define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0)
199#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
200#define EP_MAX_LENGTH_TRANSFER (0x4000)
201
202#define DTD_NEXT_TERMINATE (0x00000001)
203#define DTD_IOC (0x00008000)
204#define DTD_STATUS_ACTIVE (0x00000080)
205#define DTD_STATUS_HALTED (0x00000040)
206#define DTD_STATUS_DATA_BUFF_ERR (0x00000020)
207#define DTD_STATUS_TRANSACTION_ERR (0x00000008)
208#define DTD_RESERVED_FIELDS (0x80007300)
209#define DTD_ADDR_MASK (0xFFFFFFE0)
210#define DTD_PACKET_SIZE (0x7FFF0000)
211#define DTD_LENGTH_BIT_POS (16)
212#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \
213 DTD_STATUS_DATA_BUFF_ERR | \
214 DTD_STATUS_TRANSACTION_ERR)
215/*-------------------------------------------------------------------------*/
216/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */
217struct transfer_descriptor {
218 unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set
219 indicate invalid */
220 unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15),
221 MultO(11-10), STS (7-0) */
222 unsigned int buff_ptr0; /* Buffer pointer Page 0 */
223 unsigned int buff_ptr1; /* Buffer pointer Page 1 */
224 unsigned int buff_ptr2; /* Buffer pointer Page 2 */
225 unsigned int buff_ptr3; /* Buffer pointer Page 3 */
226 unsigned int buff_ptr4; /* Buffer pointer Page 4 */
227 unsigned int reserved;
228} __attribute__ ((packed));
229
230static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2]
231 __attribute__((aligned(32)));
232
233/* manual: 32.13.1 Endpoint Queue Head (dQH) */
234struct queue_head {
235 unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len
236 and IOS(15) */
237 unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */
238 struct transfer_descriptor dtd; /* dTD overlay */
239 unsigned int setup_buffer[2]; /* Setup data 8 bytes */
240 unsigned int reserved; /* for software use, pointer to the first TD */
241 unsigned int status; /* for software use, status of chain in progress */
242 unsigned int length; /* for software use, transfered bytes of chain in progress */
243 unsigned int wait; /* for softwate use, indicates if the transfer is blocking */
244} __attribute__((packed));
245
246static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] __attribute__((aligned(2048)));
247
248static const unsigned int pipe2mask[] = {
249 0x01, 0x010000,
250 0x02, 0x020000,
251 0x04, 0x040000,
252 0x08, 0x080000,
253 0x10, 0x100000,
254};
255
256/* return transfered size if wait=true */
257static int prime_transfer(int ep_num, void *ptr, int len, bool send, bool wait)
258{
259 int pipe = ep_num * 2 + (send ? 1 : 0);
260 unsigned mask = pipe2mask[pipe];
261 struct transfer_descriptor *td = &td_array[pipe];
262 struct queue_head* qh = &qh_array[pipe];
263
264 /* prepare TD */
265 td->next_td_ptr = DTD_NEXT_TERMINATE;
266 td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE;
267 td->buff_ptr0 = (unsigned int)ptr;
268 td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
269 td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
270 td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
271 td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
272 td->reserved = 0;
273 /* prime */
274 qh->dtd.next_td_ptr = (unsigned int)td;
275 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
276 REG_ENDPTPRIME |= mask;
277 /* wait for priming to be taken into account */
278 while(!(REG_ENDPTSTATUS & mask));
279 /* wait for completion */
280 if(wait)
281 {
282 while(!(REG_ENDPTCOMPLETE & mask));
283 REG_ENDPTCOMPLETE = mask;
284 /* memory barrier */
285 asm volatile("":::"memory");
286 /* return transfered size */
287 return len - (td->size_ioc_sts >> DTD_LENGTH_BIT_POS);
288 }
289 else
290 return 0;
291}
292
293void usb_drv_set_address(int address)
294{
295 REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS;
296}
297
298/* endpoints */
299#define EP_CONTROL 0
300
301#define DIR_OUT 0
302#define DIR_IN 1
303
304#define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT)
305#define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK)
306
307static int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
308{
309 return prime_transfer(EP_NUM(endpoint), ptr, length, true, false);
310}
311
312static int usb_drv_send(int endpoint, void* ptr, int length)
313{
314 return prime_transfer(EP_NUM(endpoint), ptr, length, true, true);
315}
316
317static int usb_drv_recv(int endpoint, void* ptr, int length)
318{
319 return prime_transfer(EP_NUM(endpoint), ptr, length, false, true);
320}
321
322static int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length)
323{
324 return prime_transfer(EP_NUM(endpoint), ptr, length, false, false);
325}
326
327static int usb_drv_port_speed(void)
328{
329 return (REG_PORTSC1 & 0x08000000) ? 1 : 0;
330}
331
332static void usb_drv_stall(int endpoint, bool stall, bool in)
333{
334 int ep_num = EP_NUM(endpoint);
335
336 if(in)
337 {
338 if(stall)
339 REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL;
340 else
341 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL;
342 }
343 else
344 {
345 if (stall)
346 REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL;
347 else
348 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL;
349 }
350}
351
352static void usb_drv_configure_endpoint(int ep_num, int type)
353{
354 REG_ENDPTCTRL(ep_num) =
355 EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE |
356 EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE |
357 (type << EPCTRL_RX_EP_TYPE_SHIFT) |
358 (type << EPCTRL_TX_EP_TYPE_SHIFT);
359}
360
361/**
362 *
363 * Clkctrl
364 *
365 */
366
367#define HW_CLKCTRL_BASE 0x80040000
368
369#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
370#define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */
371#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16)
372#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18)
373
374#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
375#define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31)
376
377/* STMP3600 only */
378#define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
379#define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0
380#define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff
381#define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30)
382
383/* STMP3600 */
384#define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
385
386/* STMP3600 only */
387#define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
388#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0
389#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff
390
391/* STMP3600 only */
392#define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
393#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30)
394#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31)
395
396/**
397 *
398 * Digctl
399 *
400 */
401
402/* Digital control */
403#define HW_DIGCTL_BASE 0x8001C000
404#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
405#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
406
407#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
408
409#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
410#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16
411#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BM 0xffff0000
412#define HW_DIGCTL_CHIPID__REVISION_BP 0
413#define HW_DIGCTL_CHIPID__REVISION_BM 0xff
414
415static bool imx233_us_elapsed(uint32_t ref, unsigned us_delay)
416{
417 uint32_t cur = HW_DIGCTL_MICROSECONDS;
418 if(ref + us_delay <= ref)
419 return !(cur > ref) && !(cur < (ref + us_delay));
420 else
421 return (cur < ref) || cur >= (ref + us_delay);
422}
423
424static void udelay(unsigned us)
425{
426 uint32_t ref = HW_DIGCTL_MICROSECONDS;
427 while(!imx233_us_elapsed(ref, us));
428}
429
430#define HZ 1000000
431
432/**
433 *
434 * USB PHY
435 *
436 */
437/* USB Phy */
438#define HW_USBPHY_BASE 0x8007C000
439#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
440
441#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
442
443/**
444 *
445 * DCP
446 *
447 */
448#define HW_DCP_BASE 0x80028000
449
450#define HW_DCP_CTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x0))
451
452#define HW_DCP_STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x10))
453#define HW_DCP_STAT__IRQ(x) (1 << (x))
454
455#define HW_DCP_CHANNELCTRL (*(volatile unsigned long *)(HW_DCP_BASE + 0x20))
456#define HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(x) (1 << (x))
457
458#define HW_DCP_CH0CMDPTR (*(volatile unsigned long *)(HW_DCP_BASE + 0x100))
459
460#define HW_DCP_CH0SEMA (*(volatile unsigned long *)(HW_DCP_BASE + 0x110))
461#define HW_DCP_CH0SEMA__INCREMENT(x) (x)
462#define HW_DCP_CH0SEMA__VALUE_BP 16
463#define HW_DCP_CH0SEMA__VALUE_BM (0xff << 16)
464#define HW_DCP_CH0STAT (*(volatile unsigned long *)(HW_DCP_BASE + 0x120))
465
466#define HW_DCP_CTRL0__INTERRUPT_ENABLE (1 << 0)
467#define HW_DCP_CTRL0__DECR_SEMAPHORE (1 << 1)
468#define HW_DCP_CTRL0__ENABLE_MEMCOPY (1 << 4)
469#define HW_DCP_CTRL0__ENABLE_CIPHER (1 << 5)
470#define HW_DCP_CTRL0__ENABLE_HASH (1 << 6)
471#define HW_DCP_CTRL0__CIPHER_ENCRYPT (1 << 8)
472#define HW_DCP_CTRL0__CIPHER_INIT (1 << 9)
473#define HW_DCP_CTRL0__OTP_KEY (1 << 10)
474#define HW_DCP_CTRL0__HASH_INIT (1 << 12)
475#define HW_DCP_CTRL0__HASH_TERM (1 << 13)
476#define HW_DCP_CTRL0__HASH_OUTPUT (1 << 15)
477
478#define HW_DCP_CTRL1__CIPHER_SELECT_BP 0
479#define HW_DCP_CTRL1__CIPHER_SELECT_BM 0xf
480#define HW_DCP_CTRL1__CIPHER_SELECT__AES128 0
481#define HW_DCP_CTRL1__CIPHER_MODE_BP 4
482#define HW_DCP_CTRL1__CIPHER_MODE_BM 0xf0
483#define HW_DCP_CTRL1__CIPHER_MODE__CBC (1 << 4)
484#define HW_DCP_CTRL1__HASH_SELECT_BP 4
485#define HW_DCP_CTRL1__HASH_SELECT_BM 0xf00
486
487struct dcp_packet_t
488{
489 unsigned long next;
490 unsigned long ctrl0;
491 unsigned long ctrl1;
492 unsigned long src_buf;
493 unsigned long dst_buf;
494 unsigned long buf_sz;
495 unsigned long payload_ptr;
496 unsigned long status;
497} __attribute__((packed));
498
499/**
500 *
501 * Misc
502 *
503 */
504
505void memcpy(void *dest, const void *src, size_t n);
506void memmove(void *dest, const void *src, size_t n);
507void memset(void *dst, int value, size_t n);
508
509/**
510 *
511 * USB stack
512 *
513 */
514
515static struct usb_device_descriptor __attribute__((aligned(2)))
516 device_descriptor=
517{
518 .bLength = sizeof(struct usb_device_descriptor),
519 .bDescriptorType = USB_DT_DEVICE,
520 .bcdUSB = 0x0200,
521 .bDeviceClass = USB_CLASS_PER_INTERFACE,
522 .bDeviceSubClass = 0,
523 .bDeviceProtocol = 0,
524 .bMaxPacketSize0 = 64,
525 .idVendor = HWSTUB_USB_VID,
526 .idProduct = HWSTUB_USB_PID,
527 .bcdDevice = HWSTUB_VERSION_MAJOR << 8 | HWSTUB_VERSION_MINOR,
528 .iManufacturer = 1,
529 .iProduct = 2,
530 .iSerialNumber = 3,
531 .bNumConfigurations = 1
532};
533
534#define USB_MAX_CURRENT 200
535
536static struct usb_config_descriptor __attribute__((aligned(2)))
537 config_descriptor =
538{
539 .bLength = sizeof(struct usb_config_descriptor),
540 .bDescriptorType = USB_DT_CONFIG,
541 .wTotalLength = 0, /* will be filled in later */
542 .bNumInterfaces = 1,
543 .bConfigurationValue = 1,
544 .iConfiguration = 0,
545 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
546 .bMaxPower = (USB_MAX_CURRENT + 1) / 2, /* In 2mA units */
547};
548
549/* main interface */
550static struct usb_interface_descriptor __attribute__((aligned(2)))
551 interface_descriptor =
552{
553 .bLength = sizeof(struct usb_interface_descriptor),
554 .bDescriptorType = USB_DT_INTERFACE,
555 .bInterfaceNumber = 0,
556 .bAlternateSetting = 0,
557 .bNumEndpoints = 3,
558 .bInterfaceClass = HWSTUB_CLASS,
559 .bInterfaceSubClass = HWSTUB_SUBCLASS,
560 .bInterfaceProtocol = HWSTUB_PROTOCOL,
561 .iInterface = 4
562};
563
564
565static struct usb_endpoint_descriptor __attribute__((aligned(2)))
566 endpoint_descriptor =
567{
568 .bLength = sizeof(struct usb_endpoint_descriptor),
569 .bDescriptorType = USB_DT_ENDPOINT,
570 .bEndpointAddress = 0,
571 .bmAttributes = USB_ENDPOINT_XFER_BULK,
572 .wMaxPacketSize = 0,
573 .bInterval = 0
574};
575
576static const struct usb_string_descriptor __attribute__((aligned(2)))
577 usb_string_iManufacturer =
578{
579 24,
580 USB_DT_STRING,
581 {'R', 'o', 'c', 'k', 'b', 'o', 'x', '.', 'o', 'r', 'g'}
582};
583
584static const struct usb_string_descriptor __attribute__((aligned(2)))
585 usb_string_iProduct =
586{
587 52,
588 USB_DT_STRING,
589 {'R', 'o', 'c', 'k', 'b', 'o', 'x', ' ',
590 'h', 'a', 'r', 'd', 'w', 'a', 'r', 'e', ' ',
591 'e', 'm', 'u', 'l', 'a', 't', 'e', 'r'}
592};
593
594static struct usb_string_descriptor __attribute__((aligned(2)))
595 usb_string_iSerial =
596{
597 84,
598 USB_DT_STRING,
599 {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
600 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
601 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
602 '0', '0', '0', '0', '0', '0', '0', '0'}
603};
604
605static struct usb_string_descriptor __attribute__((aligned(2)))
606 usb_string_iInterface =
607{
608 28,
609 USB_DT_STRING,
610 {'A', 'c', 'i', 'd', ' ',
611 '0' + (HWSTUB_VERSION_MAJOR >> 4), '0' + (HWSTUB_VERSION_MAJOR & 0xf), '.',
612 '0' + (HWSTUB_VERSION_MINOR >> 4), '0' + (HWSTUB_VERSION_MINOR & 0xf), '.',
613 '0' + (HWSTUB_VERSION_REV >> 4), '0' + (HWSTUB_VERSION_REV & 0xf) }
614};
615
616/* this is stringid #0: languages supported */
617static const struct usb_string_descriptor __attribute__((aligned(2)))
618 lang_descriptor =
619{
620 4,
621 USB_DT_STRING,
622 {0x0409} /* LANGID US English */
623};
624
625#define USB_NUM_STRINGS 5
626
627static const struct usb_string_descriptor* const usb_strings[USB_NUM_STRINGS] =
628{
629 &lang_descriptor,
630 &usb_string_iManufacturer,
631 &usb_string_iProduct,
632 &usb_string_iSerial,
633 &usb_string_iInterface
634};
635
636uint8_t *usb_buffer = oc_bufferstart;
637uint32_t usb_buffer_size = 0;
638
639#define EP_BULK 1
640#define EP_INT 2
641
642static void set_config(void)
643{
644 usb_drv_configure_endpoint(EP_BULK, USB_ENDPOINT_XFER_BULK);
645 usb_drv_configure_endpoint(EP_INT, USB_ENDPOINT_XFER_INT);
646}
647
648static void handle_std_dev_desc(struct usb_ctrlrequest *req)
649{
650 int size;
651 const void* ptr = NULL;
652 unsigned index = req->wValue & 0xff;
653
654 switch(req->wValue >> 8)
655 {
656 case USB_DT_DEVICE:
657 ptr = &device_descriptor;
658 size = sizeof(struct usb_device_descriptor);
659 break;
660 case USB_DT_OTHER_SPEED_CONFIG:
661 case USB_DT_CONFIG:
662 {
663 int max_packet_size;
664
665 /* config desc */
666 if((req->wValue >> 8) ==USB_DT_CONFIG)
667 {
668 max_packet_size = (usb_drv_port_speed() ? 512 : 64);
669 config_descriptor.bDescriptorType = USB_DT_CONFIG;
670 }
671 else
672 {
673 max_packet_size=(usb_drv_port_speed() ? 64 : 512);
674 config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
675 }
676 size = sizeof(struct usb_config_descriptor);
677
678 /* interface */
679 memcpy(usb_buffer + size, (void *)&interface_descriptor,
680 sizeof(interface_descriptor));
681 size += sizeof(interface_descriptor);
682 /* endpoint 1: bulk out */
683 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_OUT;
684 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
685 endpoint_descriptor.wMaxPacketSize = 512;
686 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
687 sizeof(endpoint_descriptor));
688 size += sizeof(endpoint_descriptor);
689 /* endpoint 2: bulk in */
690 endpoint_descriptor.bEndpointAddress = EP_BULK | USB_DIR_IN;
691 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_BULK;
692 endpoint_descriptor.wMaxPacketSize = 512;
693 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
694 sizeof(endpoint_descriptor));
695 size += sizeof(endpoint_descriptor);
696 /* endpoint 3: int in */
697 endpoint_descriptor.bEndpointAddress = EP_INT | USB_DIR_IN;
698 endpoint_descriptor.bmAttributes = USB_ENDPOINT_XFER_INT;
699 endpoint_descriptor.wMaxPacketSize = 1024;
700 memcpy(usb_buffer + size, (void *)&endpoint_descriptor,
701 sizeof(endpoint_descriptor));
702 size += sizeof(endpoint_descriptor);
703
704 /* fix config descriptor */
705 config_descriptor.bNumInterfaces = 1;
706 config_descriptor.wTotalLength = size;
707 memcpy(usb_buffer, (void *)&config_descriptor, sizeof(config_descriptor));
708
709 ptr = usb_buffer;
710 break;
711 }
712 case USB_DT_STRING:
713 if(index < USB_NUM_STRINGS)
714 {
715 size = usb_strings[index]->bLength;
716 ptr = usb_strings[index];
717 }
718 else
719 usb_drv_stall(EP_CONTROL, true, true);
720 break;
721 default:
722 break;
723 }
724
725 if(ptr)
726 {
727 int length = MIN(size, req->wLength);
728
729 if(ptr != usb_buffer)
730 memcpy(usb_buffer, ptr, length);
731
732 usb_drv_send(EP_CONTROL, usb_buffer, length);
733 usb_drv_recv(EP_CONTROL, NULL, 0);
734 }
735 else
736 usb_drv_stall(EP_CONTROL, true, true);
737}
738
739static void handle_std_dev_req(struct usb_ctrlrequest *req)
740{
741 switch(req->bRequest)
742 {
743 case USB_REQ_GET_CONFIGURATION:
744 usb_buffer[0] = 1;
745 usb_drv_send(EP_CONTROL, usb_buffer, 1);
746 usb_drv_recv(EP_CONTROL, NULL, 0);
747 break;
748 case USB_REQ_SET_CONFIGURATION:
749 usb_drv_send(EP_CONTROL, NULL, 0);
750 set_config();
751 break;
752 case USB_REQ_GET_DESCRIPTOR:
753 handle_std_dev_desc(req);
754 break;
755 case USB_REQ_SET_ADDRESS:
756 usb_drv_send(EP_CONTROL, NULL, 0);
757 usb_drv_set_address(req->wValue);
758 break;
759 case USB_REQ_GET_STATUS:
760 usb_buffer[0] = 0;
761 usb_buffer[1] = 0;
762 usb_drv_send(EP_CONTROL, usb_buffer, 2);
763 usb_drv_recv(EP_CONTROL, NULL, 0);
764 break;
765 default:
766 usb_drv_stall(EP_CONTROL, true, true);
767 }
768}
769
770static void handle_std_req(struct usb_ctrlrequest *req)
771{
772 switch(req->bRequestType & USB_RECIP_MASK)
773 {
774 case USB_RECIP_DEVICE:
775 return handle_std_dev_req(req);
776 default:
777 usb_drv_stall(EP_CONTROL, true, true);
778 }
779}
780
781struct usb_resp_info_version_t g_version =
782{
783 .major = HWSTUB_VERSION_MAJOR,
784 .minor = HWSTUB_VERSION_MINOR,
785 .revision = HWSTUB_VERSION_REV
786};
787
788struct usb_resp_info_layout_t g_layout;
789
790struct usb_resp_info_stmp_t g_stmp;
791
792struct usb_resp_info_features_t g_features =
793{
794 .feature_mask = HWSTUB_FEATURE_LOG | HWSTUB_FEATURE_MEM |
795 HWSTUB_FEATURE_CALL | HWSTUB_FEATURE_JUMP | HWSTUB_FEATURE_AES_OTP
796};
797
798static void fill_layout_info(void)
799{
800 g_layout.oc_code_start = (uint32_t)oc_codestart;
801 g_layout.oc_code_size = oc_codesize;
802 g_layout.oc_stack_start = (uint32_t)oc_stackstart;
803 g_layout.oc_stack_size = oc_stacksize;
804 g_layout.oc_buffer_start = (uint32_t)oc_bufferstart;
805 g_layout.oc_buffer_size = oc_buffersize;
806}
807
808static void fill_stmp_info(void)
809{
810 g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
811 g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
812 g_stmp.is_supported = g_stmp.chipid == 0x3780 || g_stmp.chipid == 0x3700 ||
813 g_stmp.chipid == 0x3b00;
814}
815
816static void handle_get_info(struct usb_ctrlrequest *req)
817{
818 void *ptr = NULL;
819 int size = 0;
820 switch(req->wIndex)
821 {
822 case HWSTUB_INFO_VERSION:
823 ptr = &g_version;
824 size = sizeof(g_version);
825 break;
826 case HWSTUB_INFO_LAYOUT:
827 fill_layout_info();
828 ptr = &g_layout;
829 size = sizeof(g_layout);
830 break;
831 case HWSTUB_INFO_STMP:
832 fill_stmp_info();
833 ptr = &g_stmp;
834 size = sizeof(g_stmp);
835 break;
836 case HWSTUB_INFO_FEATURES:
837 ptr = &g_features;
838 size = sizeof(g_features);
839 break;
840 default:
841 usb_drv_stall(EP_CONTROL, true, true);
842 }
843
844 if(ptr)
845 {
846 int length = MIN(size, req->wLength);
847
848 if(ptr != usb_buffer)
849 memcpy(usb_buffer, ptr, length);
850 usb_drv_send(EP_CONTROL, usb_buffer, length);
851 usb_drv_recv(EP_CONTROL, NULL, 0);
852 }
853}
854
855static void handle_get_log(struct usb_ctrlrequest *req)
856{
857 enable_logf(false);
858 int length = logf_readback(usb_buffer, MIN(req->wLength, usb_buffer_size));
859 usb_drv_send(EP_CONTROL, usb_buffer, length);
860 usb_drv_recv(EP_CONTROL, NULL, 0);
861 enable_logf(true);
862}
863
864static void handle_rw_mem(struct usb_ctrlrequest *req)
865{
866 uint32_t addr = req->wValue | req->wIndex << 16;
867 uint16_t length = req->wLength;
868
869 if(req->bRequestType & USB_DIR_IN)
870 {
871 memcpy(usb_buffer, (void *)addr, length);
872 asm volatile("nop" : : : "memory");
873 usb_drv_send(EP_CONTROL, usb_buffer, length);
874 usb_drv_recv(EP_CONTROL, NULL, 0);
875 }
876 else
877 {
878 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
879 asm volatile("nop" : : : "memory");
880 if(size != length)
881 usb_drv_stall(EP_CONTROL, true, true);
882 else
883 {
884 memcpy((void *)addr, usb_buffer, length);
885 usb_drv_send(EP_CONTROL, NULL, 0);
886 }
887 }
888}
889
890static void handle_call_jump(struct usb_ctrlrequest *req)
891{
892 uint32_t addr = req->wValue | req->wIndex << 16;
893
894 if(req->bRequest == HWSTUB_CALL)
895 ((void (*)(void))addr)();
896 else
897 {
898 /* disconnect to make sure usb/dma won't interfere */
899 REG_USBCMD &= ~USBCMD_RUN;
900 REG_USBCMD |= USBCMD_CTRL_RESET;
901 asm volatile("bx %0\n" : : "r" (addr) : "memory");
902 }
903}
904
905static void do_aes_otp(void *buffer, unsigned length, unsigned params)
906{
907 static struct dcp_packet_t dcp_packet;
908
909 bool encrypt = !!(params & HWSTUB_AES_OTP_ENCRYPT);
910 /* reset DCP */
911 __REG_SET(HW_DCP_CTRL) = 0x80000000;
912 /* clear clock gate */
913 __REG_CLR(HW_DCP_CTRL) = 0xc0000000;
914 /* enable dma for channel 0 */
915 __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(0);
916 /* prepare packet */
917 dcp_packet.next = 0;
918
919 dcp_packet.ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE |
920 HW_DCP_CTRL0__DECR_SEMAPHORE | HW_DCP_CTRL0__CIPHER_INIT |
921 HW_DCP_CTRL0__ENABLE_CIPHER | HW_DCP_CTRL0__OTP_KEY |
922 (encrypt ? HW_DCP_CTRL0__CIPHER_ENCRYPT : 0);
923 dcp_packet.ctrl1 = HW_DCP_CTRL1__CIPHER_SELECT__AES128 |
924 HW_DCP_CTRL1__CIPHER_MODE__CBC;
925 dcp_packet.src_buf = (unsigned long)buffer + 16;
926 dcp_packet.dst_buf = (unsigned long)buffer + 16;
927 dcp_packet.buf_sz = length - 16;
928 dcp_packet.payload_ptr = (unsigned long)buffer;
929 dcp_packet.status = 0;
930
931 asm volatile("":::"memory");
932 /* kick */
933 HW_DCP_CH0CMDPTR = (unsigned long)&dcp_packet;
934 HW_DCP_CH0SEMA = HW_DCP_CH0SEMA__INCREMENT(1);
935 /* wait */
936 while(!(HW_DCP_STAT & HW_DCP_STAT__IRQ(0)));
937
938 usb_drv_send_nonblocking(EP_INT, buffer, length);
939}
940
941static void handle_aes_otp(struct usb_ctrlrequest *req)
942{
943 uint16_t length = req->wLength;
944
945 int size = usb_drv_recv(EP_CONTROL, usb_buffer, length);
946 if(size != length)
947 usb_drv_stall(EP_CONTROL, true, true);
948 else
949 usb_drv_send(EP_CONTROL, NULL, 0);
950 do_aes_otp(usb_buffer, length, req->wValue);
951}
952
953static void handle_class_dev_req(struct usb_ctrlrequest *req)
954{
955 switch(req->bRequest)
956 {
957 case HWSTUB_GET_INFO:
958 handle_get_info(req);
959 break;
960 case HWSTUB_GET_LOG:
961 handle_get_log(req);
962 break;
963 case HWSTUB_RW_MEM:
964 handle_rw_mem(req);
965 break;
966 case HWSTUB_CALL:
967 case HWSTUB_JUMP:
968 handle_call_jump(req);
969 break;
970 case HWSTUB_AES_OTP:
971 handle_aes_otp(req);
972 break;
973 default:
974 usb_drv_stall(EP_CONTROL, true, true);
975 }
976}
977
978static void handle_class_req(struct usb_ctrlrequest *req)
979{
980 switch(req->bRequestType & USB_RECIP_MASK)
981 {
982 case USB_RECIP_DEVICE:
983 return handle_class_dev_req(req);
984 default:
985 usb_drv_stall(EP_CONTROL, true, true);
986 }
987}
988
989/**
990 *
991 * Main
992 *
993 */
994
995void main(uint32_t arg)
996{
997 usb_buffer_size = oc_buffersize;
998
999 logf("hwstub %d.%d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR,
1000 HWSTUB_VERSION_REV);
1001 logf("argument: 0x%08x\n", arg);
1002
1003 /* detect family */
1004 uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
1005 if(product_code >= 0x3600 && product_code < 0x3700)
1006 {
1007 logf("identified STMP3600 family\n");
1008 g_stmp_family = STMP3600;
1009 }
1010 else if(product_code == 0x3700)
1011 {
1012 logf("identified STMP3700 family\n");
1013 g_stmp_family = STMP3700;
1014 }
1015 else if(product_code == 0x37b0)
1016 {
1017 logf("identified STMP3770 family\n");
1018 g_stmp_family = STMP3770;
1019 }
1020 else if(product_code == 0x3780)
1021 {
1022 logf("identified STMP3780 family\n");
1023 g_stmp_family = STMP3780;
1024 }
1025 else
1026 logf("cannot identify family: 0x%x\n", product_code);
1027
1028 /* we don't know if USB was connected or not. In USB recovery mode it will
1029 * but in other cases it might not be. In doubt, disconnect */
1030 REG_USBCMD &= ~USBCMD_RUN;
1031 if(g_stmp_family == STMP3600)
1032 {
1033 /* CPU clock is always derived from PLL, if we switch to PLL, cpu will
1034 * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed
1035 * (1.2MHz) for a safe transition */
1036 HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400;
1037 /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the
1038 * switch so lower XBUS too */
1039 HW_CLKCTRL_XBUSCLKCTRL = 20;
1040 /* Power PLL */
1041 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
1042 HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480;
1043 /* Wait lock */
1044 while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK));
1045 /* Switch to PLL source */
1046 __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS;
1047 /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */
1048 HW_CLKCTRL_CPUCLKCTRL = 7;
1049 HW_CLKCTRL_HBUSCLKCTRL = 7;
1050 HW_CLKCTRL_XBUSCLKCTRL = 1;
1051 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE;
1052 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE;
1053 }
1054 else
1055 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
1056 /* enable USB PHY PLL */
1057 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
1058 /* power up USB PHY */
1059 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
1060 HW_USBPHY_PWD = 0;
1061 /* enable USB controller */
1062 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
1063 /* reset the controller */
1064 REG_USBCMD |= USBCMD_CTRL_RESET;
1065 while (REG_USBCMD & USBCMD_CTRL_RESET);
1066 /* put it in device mode */
1067 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
1068 /* reset address */
1069 REG_DEVICEADDR = 0;
1070 /* prepare qh array */
1071 qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1072 qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
1073 qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1074 qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
1075 /* setup qh */
1076 REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
1077 /* clear setup status */
1078 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1079 /* run! */
1080 REG_USBCMD |= USBCMD_RUN;
1081
1082 while(1)
1083 {
1084 /* wait for setup */
1085 while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0))
1086 ;
1087 /* clear setup status */
1088 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
1089 /* check request */
1090 asm volatile("":::"memory");
1091 struct usb_ctrlrequest *req = (void *)&qh_array[0].setup_buffer[0];
1092
1093 switch(req->bRequestType & USB_TYPE_MASK)
1094 {
1095 case USB_TYPE_STANDARD:
1096 handle_std_req(req);
1097 break;
1098 case USB_TYPE_CLASS:
1099 handle_class_req(req);
1100 break;
1101 default:
1102 usb_drv_stall(EP_CONTROL, true, true);
1103 }
1104 }
1105}
diff --git a/utils/hwstub/stub/SOURCES b/utils/hwstub/stub/SOURCES
new file mode 100644
index 0000000000..bfb847c21b
--- /dev/null
+++ b/utils/hwstub/stub/SOURCES
@@ -0,0 +1,12 @@
1main.c
2crt0.S
3logf.c
4memcpy.S
5memmove.S
6memset.S
7string.c
8format.c
9#ifdef CONFIG_STMP
10usb_drv_arc.c
11stmp/target.c
12#endif
diff --git a/utils/hwstub/stmp/config.h b/utils/hwstub/stub/config.h
index 9d6de07f33..3cd2deeeb3 100644
--- a/utils/hwstub/stmp/config.h
+++ b/utils/hwstub/stub/config.h
@@ -21,18 +21,11 @@
21#ifndef __HWSTUB_CONFIG__ 21#ifndef __HWSTUB_CONFIG__
22#define __HWSTUB_CONFIG__ 22#define __HWSTUB_CONFIG__
23 23
24#define MEMORYSIZE 0 24#include "target-config.h"
25
25#define STACK_SIZE 0x1000 26#define STACK_SIZE 0x1000
26#define MAX_LOGF_SIZE 128 27#define MAX_LOGF_SIZE 128
27 28
28#define IRAM_ORIG 0
29#define IRAM_SIZE 0x8000
30#define DRAM_ORIG 0x40000000
31#define DRAM_SIZE (MEMORYSIZE * 0x100000)
32
33#define CPU_ARM
34#define ARM_ARCH 5
35
36#if defined(CPU_ARM) && defined(__ASSEMBLER__) 29#if defined(CPU_ARM) && defined(__ASSEMBLER__)
37/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */ 30/* ARMv4T doesn't switch the T bit when popping pc directly, we must use BX */
38.macro ldmpc cond="", order="ia", regs 31.macro ldmpc cond="", order="ia", regs
diff --git a/utils/hwstub/stmp/crt0.S b/utils/hwstub/stub/crt0.S
index e2d4742d36..e2d4742d36 100644
--- a/utils/hwstub/stmp/crt0.S
+++ b/utils/hwstub/stub/crt0.S
diff --git a/utils/hwstub/stmp/format.c b/utils/hwstub/stub/format.c
index f5783159c0..f5783159c0 100644
--- a/utils/hwstub/stmp/format.c
+++ b/utils/hwstub/stub/format.c
diff --git a/utils/hwstub/stmp/format.h b/utils/hwstub/stub/format.h
index 2ad4229f1e..2ad4229f1e 100644
--- a/utils/hwstub/stmp/format.h
+++ b/utils/hwstub/stub/format.h
diff --git a/utils/hwstub/stmp/hwstub.lds b/utils/hwstub/stub/hwstub.lds
index 61504a3e75..61504a3e75 100644
--- a/utils/hwstub/stmp/hwstub.lds
+++ b/utils/hwstub/stub/hwstub.lds
diff --git a/utils/hwstub/stub/hwstub.make b/utils/hwstub/stub/hwstub.make
new file mode 100644
index 0000000000..b46a2736ef
--- /dev/null
+++ b/utils/hwstub/stub/hwstub.make
@@ -0,0 +1,49 @@
1INCLUDES+=-I$(ROOT_DIR)
2LINKER_FILE=$(ROOT_DIR)/hwstub.lds
3TMP_LDS=$(BUILD_DIR)/link.lds
4TMP_MAP=$(BUILD_DIR)/hwstub.map
5CFLAGS=$(GCCOPTS) $(DEFINES) -W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe -std=gnu99 -fomit-frame-pointer -Wno-pointer-sign -Wno-override-init $(INCLUDES)
6ASFLAGS=$(CFLAGS) -D__ASSEMBLER__
7LDFLAGS=-lgcc -Os -nostdlib -T$(TMP_LDS) -Wl,-Map,$(TMP_MAP) $(INCLUDES) -L$(BUILD_DIR)
8
9SRC:=$(shell cat $(ROOT_DIR)/SOURCES | $(CC) $(INCLUDES) \
10 $(DEFINES) -E -P -include "config.h" - 2>/dev/null \
11 | grep -v "^\#")
12SRC:=$(foreach src,$(SRC),$(BUILD_DIR)/$(src))
13OBJ=$(SRC:.c=.o)
14OBJ:=$(OBJ:.S=.o)
15OBJ_EXCEPT_CRT0=$(filter-out $(BUILD_DIR)/crt0.o,$(OBJ))
16EXEC_ELF=$(BUILD_DIR)/hwstub.elf
17DEPS=$(foreach obj,$(OBJ),$(obj).d)
18
19EXEC=$(EXEC_ELF)
20
21SILENT?=@
22PRINTS=$(SILENT)$(call info,$(1))
23
24all: $(EXEC)
25
26# pull in dependency info for *existing* .o files
27-include $(DEPS)
28
29$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.c
30 $(SILENT)mkdir -p $(dir $@)
31 $(call PRINTS,CC $(<F))
32 $(SILENT)$(CC) $(CFLAGS) -c -o $@ $<
33 $(SILENT)$(CC) -MM $(CFLAGS) $< -MT $@ > $@.d
34
35$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.S
36 $(call PRINTS,AS $(<F))
37 $(SILENT)mkdir -p $(dir $@)
38 $(SILENT)$(AS) $(ASFLAGS) -c -o $@ $<
39
40$(TMP_LDS): $(LINKER_FILE)
41 $(call PRINTS,PP $(<F))
42 $(SILENT)$(CC) $(CFLAGS) -E -x c - < $< | sed '/#/d' > $@
43
44$(EXEC_ELF): $(OBJ) $(TMP_LDS)
45 $(call PRINTS,LD $(@F))
46 $(SILENT)$(LD) $(LDFLAGS) -o $@ $(OBJ_EXCEPT_CRT0)
47
48clean:
49 $(SILENT)rm -rf $(OBJ) $(DEPS) $(EXEC) $(TMP_LDS) $(TMP_MAP)
diff --git a/utils/hwstub/stmp/logf.c b/utils/hwstub/stub/logf.c
index 3ccc5c5e9f..623ddb1c6c 100644
--- a/utils/hwstub/stmp/logf.c
+++ b/utils/hwstub/stub/logf.c
@@ -22,6 +22,7 @@
22#include "logf.h" 22#include "logf.h"
23#include "format.h" 23#include "format.h"
24#include "string.h" 24#include "string.h"
25#include "memory.h"
25 26
26static unsigned char logfbuffer[MAX_LOGF_SIZE]; 27static unsigned char logfbuffer[MAX_LOGF_SIZE];
27static int logfread = 0; 28static int logfread = 0;
diff --git a/utils/hwstub/stmp/logf.h b/utils/hwstub/stub/logf.h
index 48c8c2c9b9..48c8c2c9b9 100644
--- a/utils/hwstub/stmp/logf.h
+++ b/utils/hwstub/stub/logf.h
diff --git a/utils/hwstub/stmp/memcpy.S b/utils/hwstub/stub/memcpy.S
index 2a55fb5656..2a55fb5656 100644
--- a/utils/hwstub/stmp/memcpy.S
+++ b/utils/hwstub/stub/memcpy.S
diff --git a/utils/hwstub/stmp/memmove.S b/utils/hwstub/stub/memmove.S
index d8cab048be..d8cab048be 100644
--- a/utils/hwstub/stmp/memmove.S
+++ b/utils/hwstub/stub/memmove.S
diff --git a/utils/hwstub/stub/memory.h b/utils/hwstub/stub/memory.h
new file mode 100644
index 0000000000..206ed8604a
--- /dev/null
+++ b/utils/hwstub/stub/memory.h
@@ -0,0 +1,30 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef __HWSTUB_MEMORY__
22#define __HWSTUB_MEMORY__
23
24#include "stddef.h"
25
26void memset(void *dst, int c, size_t n);
27void memcpy(void *dst, const void *src, size_t n);
28void memmove(void *dst, const void *src, size_t n);
29
30#endif /* __HWSTUB_MEMORY__ */ \ No newline at end of file
diff --git a/utils/hwstub/stmp/memset.S b/utils/hwstub/stub/memset.S
index 682da874ce..682da874ce 100644
--- a/utils/hwstub/stmp/memset.S
+++ b/utils/hwstub/stub/memset.S
diff --git a/utils/hwstub/stmp/protocol.h b/utils/hwstub/stub/protocol.h
index 35510fa9b2..35510fa9b2 100644
--- a/utils/hwstub/stmp/protocol.h
+++ b/utils/hwstub/stub/protocol.h
diff --git a/utils/hwstub/stmp/stddef.h b/utils/hwstub/stub/stddef.h
index 9bfd767750..9bfd767750 100644
--- a/utils/hwstub/stmp/stddef.h
+++ b/utils/hwstub/stub/stddef.h
diff --git a/utils/hwstub/stmp/stdint.h b/utils/hwstub/stub/stdint.h
index 4fe3702c86..393ff3fffd 100644
--- a/utils/hwstub/stmp/stdint.h
+++ b/utils/hwstub/stub/stdint.h
@@ -28,6 +28,8 @@ typedef short int16_t;
28typedef unsigned short uint16_t; 28typedef unsigned short uint16_t;
29typedef long int32_t; 29typedef long int32_t;
30typedef unsigned long uint32_t; 30typedef unsigned long uint32_t;
31typedef unsigned long long uint64_t;
32typedef uint32_t intptr_t;
31typedef char bool; 33typedef char bool;
32 34
33#define true 1 35#define true 1
diff --git a/utils/hwstub/stub/stmp/Makefile b/utils/hwstub/stub/stmp/Makefile
new file mode 100644
index 0000000000..14e6d0fbba
--- /dev/null
+++ b/utils/hwstub/stub/stmp/Makefile
@@ -0,0 +1,14 @@
1#
2# common
3#
4CC=arm-elf-eabi-gcc
5LD=arm-elf-eabi-gcc
6AS=arm-elf-eabi-gcc
7OC=arm-elf-eabi-objcopy
8DEFINES=
9INCLUDES=-I$(CURDIR)
10GCCOPTS=-mcpu=arm926ej-s
11BUILD_DIR=$(CURDIR)/build/
12ROOT_DIR=$(CURDIR)/..
13
14include ../hwstub.make \ No newline at end of file
diff --git a/utils/hwstub/stub/stmp/target-config.h b/utils/hwstub/stub/stmp/target-config.h
new file mode 100644
index 0000000000..aba2cf564b
--- /dev/null
+++ b/utils/hwstub/stub/stmp/target-config.h
@@ -0,0 +1,9 @@
1#define CONFIG_STMP
2#define IRAM_ORIG 0
3#define IRAM_SIZE 0x8000
4#define DRAM_ORIG 0x40000000
5#define DRAM_SIZE (MEMORYSIZE * 0x100000)
6#define CPU_ARM
7#define ARM_ARCH 5
8#define USB_BASE 0x80080000
9#define USB_NUM_ENDPOINTS 2 \ No newline at end of file
diff --git a/utils/hwstub/stub/stmp/target.c b/utils/hwstub/stub/stmp/target.c
new file mode 100644
index 0000000000..60411f908e
--- /dev/null
+++ b/utils/hwstub/stub/stmp/target.c
@@ -0,0 +1,205 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "stddef.h"
22#include "target.h"
23#include "system.h"
24#include "logf.h"
25
26#define __REG_SET(reg) (*((volatile uint32_t *)(&reg + 1)))
27#define __REG_CLR(reg) (*((volatile uint32_t *)(&reg + 2)))
28#define __REG_TOG(reg) (*((volatile uint32_t *)(&reg + 3)))
29
30#define __BLOCK_SFTRST (1 << 31)
31#define __BLOCK_CLKGATE (1 << 30)
32
33#define __XTRACT(reg, field) ((reg & reg##__##field##_BM) >> reg##__##field##_BP)
34#define __XTRACT_EX(val, field) (((val) & field##_BM) >> field##_BP)
35#define __FIELD_SET(reg, field, val) reg = (reg & ~reg##__##field##_BM) | (val << reg##__##field##_BP)
36
37/**
38 *
39 * Global
40 *
41 */
42
43enum stmp_family_t
44{
45 UNKNOWN,
46 STMP3600,
47 STMP3700,
48 STMP3770,
49 STMP3780
50};
51
52enum stmp_family_t g_stmp_family = UNKNOWN;
53
54/**
55 *
56 * Clkctrl
57 *
58 */
59
60#define HW_CLKCTRL_BASE 0x80040000
61
62#define HW_CLKCTRL_PLLCTRL0 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x0))
63#define HW_CLKCTRL_PLLCTRL0__BYPASS (1 << 17) /* STMP3600 only */
64#define HW_CLKCTRL_PLLCTRL0__POWER (1 << 16)
65#define HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS (1 << 18)
66
67#define HW_CLKCTRL_PLLCTRL1 (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x10))
68#define HW_CLKCTRL_PLLCTRL1__LOCK (1 << 31)
69
70/* STMP3600 only */
71#define HW_CLKCTRL_CPUCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x20))
72#define HW_CLKCTRL_CPUCLKCTRL__DIV_BP 0
73#define HW_CLKCTRL_CPUCLKCTRL__DIV_BM 0x3ff
74#define HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK (1 << 30)
75
76/* STMP3600 */
77#define HW_CLKCTRL_HBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x30))
78
79/* STMP3600 only */
80#define HW_CLKCTRL_XBUSCLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x40))
81#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BP 0
82#define HW_CLKCTRL_XBUSCLKCTRL__DIV_BM 0x3ff
83
84/* STMP3600 only */
85#define HW_CLKCTRL_UTMICLKCTRL (*(volatile uint32_t *)(HW_CLKCTRL_BASE + 0x70))
86#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE (1 << 30)
87#define HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE (1 << 31)
88
89/**
90 *
91 * Digctl
92 *
93 */
94
95/* Digital control */
96#define HW_DIGCTL_BASE 0x8001C000
97#define HW_DIGCTL_CTRL (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0))
98#define HW_DIGCTL_CTRL__USB_CLKGATE (1 << 2)
99
100#define HW_DIGCTL_MICROSECONDS (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0xC0))
101
102#define HW_DIGCTL_CHIPID (*(volatile uint32_t *)(HW_DIGCTL_BASE + 0x310))
103#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BP 16
104#define HW_DIGCTL_CHIPID__PRODUCT_CODE_BM 0xffff0000
105#define HW_DIGCTL_CHIPID__REVISION_BP 0
106#define HW_DIGCTL_CHIPID__REVISION_BM 0xff
107
108#define HZ 1000000
109
110/**
111 *
112 * USB PHY
113 *
114 */
115/* USB Phy */
116#define HW_USBPHY_BASE 0x8007C000
117#define HW_USBPHY_PWD (*(volatile uint32_t *)(HW_USBPHY_BASE + 0))
118
119#define HW_USBPHY_CTRL (*(volatile uint32_t *)(HW_USBPHY_BASE + 0x30))
120
121void target_init(void)
122{
123 /* detect family */
124 uint16_t product_code = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
125 if(product_code >= 0x3600 && product_code < 0x3700)
126 {
127 logf("identified STMP3600 family\n");
128 g_stmp_family = STMP3600;
129 }
130 else if(product_code == 0x3700)
131 {
132 logf("identified STMP3700 family\n");
133 g_stmp_family = STMP3700;
134 }
135 else if(product_code == 0x37b0)
136 {
137 logf("identified STMP3770 family\n");
138 g_stmp_family = STMP3770;
139 }
140 else if(product_code == 0x3780)
141 {
142 logf("identified STMP3780 family\n");
143 g_stmp_family = STMP3780;
144 }
145 else
146 logf("cannot identify family: 0x%x\n", product_code);
147
148 if(g_stmp_family == STMP3600)
149 {
150 /* CPU clock is always derived from PLL, if we switch to PLL, cpu will
151 * run at 480 MHz unprepared ! That's bad so prepare to run at slow sleed
152 * (1.2MHz) for a safe transition */
153 HW_CLKCTRL_CPUCLKCTRL = HW_CLKCTRL_CPUCLKCTRL__WAIT_PLL_LOCK | 400;
154 /* We need to ensure that XBUS < HBUS but HBUS will be 1.2 MHz after the
155 * switch so lower XBUS too */
156 HW_CLKCTRL_XBUSCLKCTRL = 20;
157 /* Power PLL */
158 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
159 HW_CLKCTRL_PLLCTRL0 = (HW_CLKCTRL_PLLCTRL0 & ~0x3ff) | 480;
160 /* Wait lock */
161 while(!(HW_CLKCTRL_PLLCTRL1 & HW_CLKCTRL_PLLCTRL1__LOCK));
162 /* Switch to PLL source */
163 __REG_CLR(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__BYPASS;
164 /* Get back XBUS = 24 MHz and CPU = HBUS = 64MHz */
165 HW_CLKCTRL_CPUCLKCTRL = 7;
166 HW_CLKCTRL_HBUSCLKCTRL = 7;
167 HW_CLKCTRL_XBUSCLKCTRL = 1;
168 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK120M_GATE;
169 __REG_CLR(HW_CLKCTRL_UTMICLKCTRL) = HW_CLKCTRL_UTMICLKCTRL__UTMI_CLK30M_GATE;
170 }
171 else
172 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__POWER;
173 /* enable USB PHY PLL */
174 __REG_SET(HW_CLKCTRL_PLLCTRL0) = HW_CLKCTRL_PLLCTRL0__EN_USB_CLKS;
175 /* power up USB PHY */
176 __REG_CLR(HW_USBPHY_CTRL) = __BLOCK_CLKGATE | __BLOCK_SFTRST;
177 HW_USBPHY_PWD = 0;
178 /* enable USB controller */
179 __REG_CLR(HW_DIGCTL_CTRL) = HW_DIGCTL_CTRL__USB_CLKGATE;
180}
181
182static struct usb_resp_info_stmp_t g_stmp;
183static struct usb_resp_info_target_t g_target =
184{
185 .id = HWSTUB_TARGET_STMP,
186 .name = "STMP3600 / STMP3700 / STMP3780 (i.MX233)"
187};
188
189int target_get_info(int info, void **buffer)
190{
191 if(info == HWSTUB_INFO_STMP)
192 {
193 g_stmp.chipid = __XTRACT(HW_DIGCTL_CHIPID, PRODUCT_CODE);
194 g_stmp.rev = __XTRACT(HW_DIGCTL_CHIPID, REVISION);
195 g_stmp.is_supported = g_stmp_family != 0;
196 *buffer = &g_stmp;
197 return sizeof(g_stmp);
198 }
199 else
200 return -1;
201}
202
203void target_exit(void)
204{
205}
diff --git a/utils/hwstub/stmp/string.c b/utils/hwstub/stub/string.c
index 1f8c415a99..1f8c415a99 100644
--- a/utils/hwstub/stmp/string.c
+++ b/utils/hwstub/stub/string.c
diff --git a/utils/hwstub/stmp/string.h b/utils/hwstub/stub/string.h
index 184144e525..ae352fe50e 100644
--- a/utils/hwstub/stmp/string.h
+++ b/utils/hwstub/stub/string.h
@@ -23,8 +23,6 @@
23 23
24#include "stddef.h" 24#include "stddef.h"
25 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); 26size_t strlen(const char *s);
29 27
30#endif /* __HWSTUB_STRING__ */ 28#endif /* __HWSTUB_STRING__ */
diff --git a/utils/hwstub/stmp/system.h b/utils/hwstub/stub/system.h
index e5aea12051..e5aea12051 100644
--- a/utils/hwstub/stmp/system.h
+++ b/utils/hwstub/stub/system.h
diff --git a/utils/hwstub/stmp/hwstub.db b/utils/hwstub/stub/target.h
index 1a085da50a..3f1551c72d 100644
--- a/utils/hwstub/stmp/hwstub.db
+++ b/utils/hwstub/stub/target.h
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2012 by Amaury Pouly 10 * Copyright (C) 2013 by Amaury Pouly
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
@@ -18,14 +18,14 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21sources 21#ifndef __TARGET_H__
22{ 22#define __TARGET_H__
23 hwstub = "hwstub.elf";
24}
25 23
26section(0) 24#include "protocol.h"
27{
28 load hwstub;
29 jump hwstub(1);
30}
31 25
26void target_init(void);
27void target_exit(void);
28/* return actual size or -1 if error */
29int target_get_info(int info, void **buffer);
30
31#endif /* __TARGET_H__ */
diff --git a/utils/hwstub/stmp/usb_ch9.h b/utils/hwstub/stub/usb_ch9.h
index 09141b93bd..09141b93bd 100644
--- a/utils/hwstub/stmp/usb_ch9.h
+++ b/utils/hwstub/stub/usb_ch9.h
diff --git a/utils/hwstub/stub/usb_drv.h b/utils/hwstub/stub/usb_drv.h
new file mode 100644
index 0000000000..00f22d8e1a
--- /dev/null
+++ b/utils/hwstub/stub/usb_drv.h
@@ -0,0 +1,47 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Björn Stenberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _USB_DRV_H
22#define _USB_DRV_H
23
24#include "usb_ch9.h"
25
26#define EP_CONTROL 0
27
28#define DIR_OUT 0
29#define DIR_IN 1
30
31#define EP_DIR(ep) (((ep) & USB_ENDPOINT_DIR_MASK) ? DIR_IN : DIR_OUT)
32#define EP_NUM(ep) ((ep) & USB_ENDPOINT_NUMBER_MASK)
33
34void usb_drv_init(void);
35void usb_drv_exit(void);
36void usb_drv_stall(int endpoint, bool stall,bool in);
37int usb_drv_send(int endpoint, void* ptr, int length);
38int usb_drv_send_nonblocking(int endpoint, void* ptr, int length);
39int usb_drv_recv(int endpoint, void* ptr, int length);// blocking !
40int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length);
41int usb_drv_recv_setup(struct usb_ctrlrequest *req);
42void usb_drv_set_address(int address);
43int usb_drv_port_speed(void);
44void usb_drv_configure_endpoint(int ep_num, int type);
45
46#endif /* _USB_DRV_H */
47
diff --git a/utils/hwstub/stub/usb_drv_arc.c b/utils/hwstub/stub/usb_drv_arc.c
new file mode 100644
index 0000000000..32275b6adb
--- /dev/null
+++ b/utils/hwstub/stub/usb_drv_arc.c
@@ -0,0 +1,364 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Driver for ARC USBOTG Device Controller
11 *
12 * Copyright (C) 2007 by Björn Stenberg
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "usb_drv.h"
24#include "config.h"
25#include "memory.h"
26
27#define MAX_PKT_SIZE 1024
28#define MAX_PKT_SIZE_EP0 64
29
30/* USB device mode registers (Little Endian) */
31#define REG_USBCMD (*(volatile unsigned int *)(USB_BASE+0x140))
32#define REG_DEVICEADDR (*(volatile unsigned int *)(USB_BASE+0x154))
33#define REG_ENDPOINTLISTADDR (*(volatile unsigned int *)(USB_BASE+0x158))
34#define REG_PORTSC1 (*(volatile unsigned int *)(USB_BASE+0x184))
35#define REG_USBMODE (*(volatile unsigned int *)(USB_BASE+0x1a8))
36#define REG_ENDPTSETUPSTAT (*(volatile unsigned int *)(USB_BASE+0x1ac))
37#define REG_ENDPTPRIME (*(volatile unsigned int *)(USB_BASE+0x1b0))
38#define REG_ENDPTSTATUS (*(volatile unsigned int *)(USB_BASE+0x1b8))
39#define REG_ENDPTCOMPLETE (*(volatile unsigned int *)(USB_BASE+0x1bc))
40#define REG_ENDPTCTRL0 (*(volatile unsigned int *)(USB_BASE+0x1c0))
41#define REG_ENDPTCTRL1 (*(volatile unsigned int *)(USB_BASE+0x1c4))
42#define REG_ENDPTCTRL2 (*(volatile unsigned int *)(USB_BASE+0x1c8))
43#define REG_ENDPTCTRL(_x_) (*(volatile unsigned int *)(USB_BASE+0x1c0+4*(_x_)))
44
45/* USB CMD Register Bit Masks */
46#define USBCMD_RUN (0x00000001)
47#define USBCMD_CTRL_RESET (0x00000002)
48#define USBCMD_PERIODIC_SCHEDULE_EN (0x00000010)
49#define USBCMD_ASYNC_SCHEDULE_EN (0x00000020)
50#define USBCMD_INT_AA_DOORBELL (0x00000040)
51#define USBCMD_ASP (0x00000300)
52#define USBCMD_ASYNC_SCH_PARK_EN (0x00000800)
53#define USBCMD_SUTW (0x00002000)
54#define USBCMD_ATDTW (0x00004000)
55#define USBCMD_ITC (0x00FF0000)
56
57/* Device Address bit masks */
58#define USBDEVICEADDRESS_MASK (0xFE000000)
59#define USBDEVICEADDRESS_BIT_POS (25)
60
61/* Endpoint Setup Status bit masks */
62#define EPSETUP_STATUS_EP0 (0x00000001)
63
64/* PORTSCX Register Bit Masks */
65#define PORTSCX_CURRENT_CONNECT_STATUS (0x00000001)
66#define PORTSCX_CONNECT_STATUS_CHANGE (0x00000002)
67#define PORTSCX_PORT_ENABLE (0x00000004)
68#define PORTSCX_PORT_EN_DIS_CHANGE (0x00000008)
69#define PORTSCX_OVER_CURRENT_ACT (0x00000010)
70#define PORTSCX_OVER_CURRENT_CHG (0x00000020)
71#define PORTSCX_PORT_FORCE_RESUME (0x00000040)
72#define PORTSCX_PORT_SUSPEND (0x00000080)
73#define PORTSCX_PORT_RESET (0x00000100)
74#define PORTSCX_LINE_STATUS_BITS (0x00000C00)
75#define PORTSCX_PORT_POWER (0x00001000)
76#define PORTSCX_PORT_INDICTOR_CTRL (0x0000C000)
77#define PORTSCX_PORT_TEST_CTRL (0x000F0000)
78#define PORTSCX_WAKE_ON_CONNECT_EN (0x00100000)
79#define PORTSCX_WAKE_ON_CONNECT_DIS (0x00200000)
80#define PORTSCX_WAKE_ON_OVER_CURRENT (0x00400000)
81#define PORTSCX_PHY_LOW_POWER_SPD (0x00800000)
82#define PORTSCX_PORT_FORCE_FULL_SPEED (0x01000000)
83#define PORTSCX_PORT_SPEED_MASK (0x0C000000)
84#define PORTSCX_PORT_WIDTH (0x10000000)
85#define PORTSCX_PHY_TYPE_SEL (0xC0000000)
86
87/* bit 11-10 are line status */
88#define PORTSCX_LINE_STATUS_SE0 (0x00000000)
89#define PORTSCX_LINE_STATUS_JSTATE (0x00000400)
90#define PORTSCX_LINE_STATUS_KSTATE (0x00000800)
91#define PORTSCX_LINE_STATUS_UNDEF (0x00000C00)
92#define PORTSCX_LINE_STATUS_BIT_POS (10)
93
94/* bit 15-14 are port indicator control */
95#define PORTSCX_PIC_OFF (0x00000000)
96#define PORTSCX_PIC_AMBER (0x00004000)
97#define PORTSCX_PIC_GREEN (0x00008000)
98#define PORTSCX_PIC_UNDEF (0x0000C000)
99#define PORTSCX_PIC_BIT_POS (14)
100
101/* bit 19-16 are port test control */
102#define PORTSCX_PTC_DISABLE (0x00000000)
103#define PORTSCX_PTC_JSTATE (0x00010000)
104#define PORTSCX_PTC_KSTATE (0x00020000)
105#define PORTSCX_PTC_SE0NAK (0x00030000)
106#define PORTSCX_PTC_PACKET (0x00040000)
107#define PORTSCX_PTC_FORCE_EN (0x00050000)
108#define PORTSCX_PTC_BIT_POS (16)
109
110/* bit 27-26 are port speed */
111#define PORTSCX_PORT_SPEED_FULL (0x00000000)
112#define PORTSCX_PORT_SPEED_LOW (0x04000000)
113#define PORTSCX_PORT_SPEED_HIGH (0x08000000)
114#define PORTSCX_PORT_SPEED_UNDEF (0x0C000000)
115#define PORTSCX_SPEED_BIT_POS (26)
116
117/* bit 28 is parallel transceiver width for UTMI interface */
118#define PORTSCX_PTW (0x10000000)
119#define PORTSCX_PTW_8BIT (0x00000000)
120#define PORTSCX_PTW_16BIT (0x10000000)
121
122/* bit 31-30 are port transceiver select */
123#define PORTSCX_PTS_UTMI (0x00000000)
124#define PORTSCX_PTS_CLASSIC (0x40000000)
125#define PORTSCX_PTS_ULPI (0x80000000)
126#define PORTSCX_PTS_FSLS (0xC0000000)
127#define PORTSCX_PTS_BIT_POS (30)
128
129/* USB MODE Register Bit Masks */
130#define USBMODE_CTRL_MODE_IDLE (0x00000000)
131#define USBMODE_CTRL_MODE_DEVICE (0x00000002)
132#define USBMODE_CTRL_MODE_HOST (0x00000003)
133#define USBMODE_CTRL_MODE_RSV (0x00000001)
134#define USBMODE_SETUP_LOCK_OFF (0x00000008)
135#define USBMODE_STREAM_DISABLE (0x00000010)
136
137/* ENDPOINTCTRLx Register Bit Masks */
138#define EPCTRL_TX_ENABLE (0x00800000)
139#define EPCTRL_TX_DATA_TOGGLE_RST (0x00400000) /* Not EP0 */
140#define EPCTRL_TX_DATA_TOGGLE_INH (0x00200000) /* Not EP0 */
141#define EPCTRL_TX_TYPE (0x000C0000)
142#define EPCTRL_TX_DATA_SOURCE (0x00020000) /* Not EP0 */
143#define EPCTRL_TX_EP_STALL (0x00010000)
144#define EPCTRL_RX_ENABLE (0x00000080)
145#define EPCTRL_RX_DATA_TOGGLE_RST (0x00000040) /* Not EP0 */
146#define EPCTRL_RX_DATA_TOGGLE_INH (0x00000020) /* Not EP0 */
147#define EPCTRL_RX_TYPE (0x0000000C)
148#define EPCTRL_RX_DATA_SINK (0x00000002) /* Not EP0 */
149#define EPCTRL_RX_EP_STALL (0x00000001)
150
151/* bit 19-18 and 3-2 are endpoint type */
152#define EPCTRL_TX_EP_TYPE_SHIFT (18)
153#define EPCTRL_RX_EP_TYPE_SHIFT (2)
154
155#define QH_MULT_POS (30)
156#define QH_ZLT_SEL (0x20000000)
157#define QH_MAX_PKT_LEN_POS (16)
158#define QH_IOS (0x00008000)
159#define QH_NEXT_TERMINATE (0x00000001)
160#define QH_IOC (0x00008000)
161#define QH_MULTO (0x00000C00)
162#define QH_STATUS_HALT (0x00000040)
163#define QH_STATUS_ACTIVE (0x00000080)
164#define EP_QUEUE_CURRENT_OFFSET_MASK (0x00000FFF)
165#define EP_QUEUE_HEAD_NEXT_POINTER_MASK (0xFFFFFFE0)
166#define EP_QUEUE_FRINDEX_MASK (0x000007FF)
167#define EP_MAX_LENGTH_TRANSFER (0x4000)
168
169#define DTD_NEXT_TERMINATE (0x00000001)
170#define DTD_IOC (0x00008000)
171#define DTD_STATUS_ACTIVE (0x00000080)
172#define DTD_STATUS_HALTED (0x00000040)
173#define DTD_STATUS_DATA_BUFF_ERR (0x00000020)
174#define DTD_STATUS_TRANSACTION_ERR (0x00000008)
175#define DTD_RESERVED_FIELDS (0x80007300)
176#define DTD_ADDR_MASK (0xFFFFFFE0)
177#define DTD_PACKET_SIZE (0x7FFF0000)
178#define DTD_LENGTH_BIT_POS (16)
179#define DTD_ERROR_MASK (DTD_STATUS_HALTED | \
180 DTD_STATUS_DATA_BUFF_ERR | \
181 DTD_STATUS_TRANSACTION_ERR)
182/*-------------------------------------------------------------------------*/
183/* manual: 32.13.2 Endpoint Transfer Descriptor (dTD) */
184struct transfer_descriptor {
185 unsigned int next_td_ptr; /* Next TD pointer(31-5), T(0) set
186 indicate invalid */
187 unsigned int size_ioc_sts; /* Total bytes (30-16), IOC (15),
188 MultO(11-10), STS (7-0) */
189 unsigned int buff_ptr0; /* Buffer pointer Page 0 */
190 unsigned int buff_ptr1; /* Buffer pointer Page 1 */
191 unsigned int buff_ptr2; /* Buffer pointer Page 2 */
192 unsigned int buff_ptr3; /* Buffer pointer Page 3 */
193 unsigned int buff_ptr4; /* Buffer pointer Page 4 */
194 unsigned int reserved;
195} __attribute__ ((packed));
196
197static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2]
198 __attribute__((aligned(32)));
199
200/* manual: 32.13.1 Endpoint Queue Head (dQH) */
201struct queue_head {
202 unsigned int max_pkt_length; /* Mult(31-30) , Zlt(29) , Max Pkt len
203 and IOS(15) */
204 unsigned int curr_dtd_ptr; /* Current dTD Pointer(31-5) */
205 struct transfer_descriptor dtd; /* dTD overlay */
206 unsigned int setup_buffer[2]; /* Setup data 8 bytes */
207 unsigned int reserved; /* for software use, pointer to the first TD */
208 unsigned int status; /* for software use, status of chain in progress */
209 unsigned int length; /* for software use, transfered bytes of chain in progress */
210 unsigned int wait; /* for softwate use, indicates if the transfer is blocking */
211} __attribute__((packed));
212
213static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] __attribute__((aligned(2048)));
214
215static const unsigned int pipe2mask[] = {
216 0x01, 0x010000,
217 0x02, 0x020000,
218 0x04, 0x040000,
219 0x08, 0x080000,
220 0x10, 0x100000,
221};
222
223/* return transfered size if wait=true */
224static int prime_transfer(int ep_num, void *ptr, int len, bool send, bool wait)
225{
226 int pipe = ep_num * 2 + (send ? 1 : 0);
227 unsigned mask = pipe2mask[pipe];
228 struct transfer_descriptor *td = &td_array[pipe];
229 struct queue_head* qh = &qh_array[pipe];
230
231 /* prepare TD */
232 td->next_td_ptr = DTD_NEXT_TERMINATE;
233 td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE;
234 td->buff_ptr0 = (unsigned int)ptr;
235 td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
236 td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
237 td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
238 td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
239 td->reserved = 0;
240 /* prime */
241 qh->dtd.next_td_ptr = (unsigned int)td;
242 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
243 REG_ENDPTPRIME |= mask;
244 /* wait for priming to be taken into account */
245 while(!(REG_ENDPTSTATUS & mask));
246 /* wait for completion */
247 if(wait)
248 {
249 while(!(REG_ENDPTCOMPLETE & mask));
250 REG_ENDPTCOMPLETE = mask;
251 /* memory barrier */
252 asm volatile("":::"memory");
253 /* return transfered size */
254 return len - (td->size_ioc_sts >> DTD_LENGTH_BIT_POS);
255 }
256 else
257 return 0;
258}
259
260void usb_drv_set_address(int address)
261{
262 REG_DEVICEADDR = address << USBDEVICEADDRESS_BIT_POS;
263}
264
265/* endpoints */
266
267int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
268{
269 return prime_transfer(EP_NUM(endpoint), ptr, length, true, false);
270}
271
272int usb_drv_send(int endpoint, void* ptr, int length)
273{
274 return prime_transfer(EP_NUM(endpoint), ptr, length, true, true);
275}
276
277int usb_drv_recv(int endpoint, void* ptr, int length)
278{
279 return prime_transfer(EP_NUM(endpoint), ptr, length, false, true);
280}
281
282int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length)
283{
284 return prime_transfer(EP_NUM(endpoint), ptr, length, false, false);
285}
286
287int usb_drv_port_speed(void)
288{
289 return (REG_PORTSC1 & 0x08000000) ? 1 : 0;
290}
291
292void usb_drv_stall(int endpoint, bool stall, bool in)
293{
294 int ep_num = EP_NUM(endpoint);
295
296 if(in)
297 {
298 if(stall)
299 REG_ENDPTCTRL(ep_num) |= EPCTRL_TX_EP_STALL;
300 else
301 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_TX_EP_STALL;
302 }
303 else
304 {
305 if (stall)
306 REG_ENDPTCTRL(ep_num) |= EPCTRL_RX_EP_STALL;
307 else
308 REG_ENDPTCTRL(ep_num) &= ~EPCTRL_RX_EP_STALL;
309 }
310}
311
312void usb_drv_configure_endpoint(int ep_num, int type)
313{
314 REG_ENDPTCTRL(ep_num) =
315 EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE |
316 EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE |
317 (type << EPCTRL_RX_EP_TYPE_SHIFT) |
318 (type << EPCTRL_TX_EP_TYPE_SHIFT);
319}
320
321void usb_drv_init(void)
322{
323 /* we don't know if USB was connected or not. In USB recovery mode it will
324 * but in other cases it might not be. In doubt, disconnect */
325 REG_USBCMD &= ~USBCMD_RUN;
326 /* reset the controller */
327 REG_USBCMD |= USBCMD_CTRL_RESET;
328 while (REG_USBCMD & USBCMD_CTRL_RESET);
329 /* put it in device mode */
330 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
331 /* reset address */
332 REG_DEVICEADDR = 0;
333 /* prepare qh array */
334 qh_array[0].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
335 qh_array[1].max_pkt_length = 1 << 29 | MAX_PKT_SIZE_EP0 << 16;
336 qh_array[2].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
337 qh_array[3].max_pkt_length = 1 << 29 | MAX_PKT_SIZE << 16;
338 /* setup qh */
339 REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
340 /* clear setup status */
341 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
342 /* run! */
343 REG_USBCMD |= USBCMD_RUN;
344}
345
346void usb_drv_exit(void)
347{
348 REG_USBCMD &= ~USBCMD_RUN;
349 REG_USBCMD |= USBCMD_CTRL_RESET;
350}
351
352int usb_drv_recv_setup(struct usb_ctrlrequest *req)
353{
354 /* wait for setup */
355 while(!(REG_ENDPTSETUPSTAT & EPSETUP_STATUS_EP0))
356 ;
357 /* clear setup status */
358 REG_ENDPTSETUPSTAT = EPSETUP_STATUS_EP0;
359 /* check request */
360 asm volatile("":::"memory");
361 /* copy */
362 memcpy(req, (void *)&qh_array[0].setup_buffer[0], sizeof(struct usb_ctrlrequest));
363 return 0;
364}