summaryrefslogtreecommitdiff
path: root/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2014-09-23 13:30:17 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2014-11-05 08:18:59 +0100
commitd11704fed5fd218b2ed26182de877bc6e5b513a4 (patch)
tree0eceaf96f006e9047b698ea99bf452faa79884d3 /utils/hwstub/stub/atj213x/usb_drv_atj213x.c
parent791be56cff14a7a41774ce80ce401384291985d9 (diff)
downloadrockbox-d11704fed5fd218b2ed26182de877bc6e5b513a4.tar.gz
rockbox-d11704fed5fd218b2ed26182de877bc6e5b513a4.zip
hwstub: Add atj213x supportbootloader_zenxfi3_v1
Change-Id: Ic32200f9ab2c6977e503307a9cbe43a1328d0341
Diffstat (limited to 'utils/hwstub/stub/atj213x/usb_drv_atj213x.c')
-rw-r--r--utils/hwstub/stub/atj213x/usb_drv_atj213x.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
new file mode 100644
index 0000000000..ef66766527
--- /dev/null
+++ b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
@@ -0,0 +1,267 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by Marcin Bukat
10 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
22#include "usb_drv.h"
23#include "config.h"
24#include "memory.h"
25#include "target.h"
26#include "atj213x.h"
27
28#define USB_FULL_SPEED 0
29#define USB_HIGH_SPEED 1
30
31volatile bool setup_data_valid = false;
32volatile int udc_speed = USB_FULL_SPEED;
33
34static void usb_copy_from(void *ptr, volatile void *reg, size_t sz)
35{
36 uint32_t *p = ptr;
37 volatile uint32_t *rp = reg;
38 /* do not overflow the destination buffer ! */
39 while(sz >= 4)
40 {
41 *p++ = *rp++;
42 sz -= 4;
43 }
44
45 if(sz == 0)
46 return;
47
48 /* reminder */
49 uint32_t cache = *rp;
50 uint8_t *p8 = (void *)p;
51 while(sz-- > 0)
52 {
53 *p8++ = cache;
54 cache >>= 8;
55 }
56}
57
58static void usb_copy_to(volatile void *reg, void *ptr, size_t sz)
59{
60 uint32_t *p = ptr;
61 volatile uint32_t *rp = reg;
62 sz = (sz + 3) / 4;
63 /* read may overflow the source buffer but
64 * it will not overwrite anything
65 */
66 while(sz-- > 0)
67 *rp++ = *p++;
68}
69
70void INT_UDC(void)
71{
72 /* get possible sources */
73 unsigned int usbirq = OTG_USBIRQ;
74 unsigned int otgirq = OTG_OTGIRQ;
75#if 0
76 unsigned int usbeirq = OTG_USBEIRQ;
77 unsigned int epinirq = OTG_IN04IRQ;
78 unsigned int epoutirq = OTG_OUT04IRQ;
79#endif
80
81 /* HS, Reset, Setup */
82 if (usbirq)
83 {
84
85 if (usbirq & (1<<5))
86 {
87 /* HS irq */
88 udc_speed = USB_HIGH_SPEED;
89 }
90 else if (usbirq & (1<<4))
91 {
92 /* Reset */
93 udc_speed = USB_FULL_SPEED;
94
95 /* clear all pending irqs */
96 OTG_OUT04IRQ = 0xff;
97 OTG_IN04IRQ = 0xff;
98 }
99 else if (usbirq & (1<<0))
100 {
101 /* Setup data valid */
102 setup_data_valid = true;
103 }
104
105 /* clear irq flags */
106 OTG_USBIRQ = usbirq;
107 }
108
109#if 0
110 if (epoutirq)
111 {
112 OTG_OUT04IRQ = epoutirq;
113 }
114
115 if (epinirq)
116 {
117 OTG_IN04IRQ = epinirq;
118 }
119#endif
120
121 if (otgirq)
122 {
123 OTG_OTGIRQ = otgirq;
124 }
125
126 OTG_USBEIRQ = 0x50;
127}
128
129void usb_drv_init(void)
130{
131 OTG_USBCS |= 0x40; /* soft disconnect */
132
133 OTG_ENDPRST = 0x10; /* reset all ep fifos */
134 OTG_ENDPRST = 0x70;
135 OTG_ENDPRST = 0x00;
136 OTG_ENDPRST = 0x60;
137
138 OTG_USBIRQ = 0xff; /* clear all pending interrupts */
139 OTG_OTGIRQ = 0xff;
140 OTG_IN04IRQ = 0xff;
141 OTG_OUT04IRQ = 0xff;
142 OTG_USBEIRQ = 0x50; /* UDC ? with 0x40 there is irq storm */
143
144 OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */
145 OTG_OTGIEN = 0;
146
147 /* disable interrupts from ep0 */
148 OTG_IN04IEN = 0;
149 OTG_OUT04IEN = 0;
150
151 /* unmask UDC interrupt in interrupt controller */
152 INTC_MSK = (1<<4);
153
154 target_mdelay(100);
155
156 OTG_USBCS &= ~0x40; /* soft connect */
157}
158
159int usb_drv_recv_setup(struct usb_ctrlrequest *req)
160{
161 while (!setup_data_valid)
162 ;
163
164 usb_copy_from(req, &OTG_SETUPDAT, sizeof(struct usb_ctrlrequest));
165 setup_data_valid = false;
166 return 0;
167}
168
169int usb_drv_port_speed(void)
170{
171 return (int)udc_speed;
172}
173
174/* Set the address (usually it's in a register).
175 * There is a problem here: some controller want the address to be set between
176 * control out and ack and some want to wait for the end of the transaction.
177 * In the first case, you need to write some code special code when getting
178 * setup packets and ignore this function (have a look at other drives)
179 */
180void usb_drv_set_address(int address)
181{
182 (void)address;
183 /* UDC sets this automaticaly */
184}
185
186/* TODO: Maybe adapt to irq scheme */
187int usb_drv_send(int endpoint, void *ptr, int length)
188{
189 (void)endpoint;
190
191 int xfer_size, cnt = length;
192
193 while (cnt)
194 {
195 xfer_size = MIN(cnt, 64);
196
197 /* copy data to ep0in buffer */
198 usb_copy_to(&OTG_EP0INDAT, ptr, xfer_size);
199
200 /* this marks data as ready to send */
201 OTG_IN0BC = xfer_size;
202
203 /* wait for the transfer end */
204 while(OTG_EP0CS & 0x04)
205 ;
206
207 cnt -= xfer_size;
208 ptr += xfer_size;
209 }
210
211 /* ZLP stage */
212 if((length % 64) == 0)
213 OTG_EP0CS = 2;
214
215 return 0;
216}
217
218/* TODO: Maybe adapt to irq scheme */
219int usb_drv_recv(int endpoint, void* ptr, int length)
220{
221 (void)endpoint;
222 int xfer_size, cnt = 0;
223
224 while (cnt < length)
225 {
226 /* Arm receiving buffer by writing
227 * any value to OUT0BC. This sets
228 * OUT_BUSY bit in EP0CS until the data
229 * are correctly received and ACK'd
230 */
231 OTG_OUT0BC = 0;
232
233 while (OTG_EP0CS & 0x08)
234 ;
235
236 xfer_size = OTG_OUT0BC;
237
238 usb_copy_from(ptr, &OTG_EP0OUTDAT, xfer_size);
239 cnt += xfer_size;
240 ptr += xfer_size;
241
242 if (xfer_size < 64)
243 break;
244 }
245
246 /* ZLP stage */
247 if (length == 0)
248 OTG_EP0CS = 2;
249
250 return cnt;
251}
252
253void usb_drv_stall(int endpoint, bool stall, bool in)
254{
255 (void)endpoint;
256 (void)in;
257
258 /* only EP0 in hwstub */
259 if (stall)
260 OTG_EP0CS |= 1;
261 else
262 OTG_EP0CS &= ~1;
263}
264
265void usb_drv_exit(void)
266{
267}