summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2016-02-29 08:26:33 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2016-03-14 12:21:42 +0100
commit0e2b4908d012dbd45a58002774f32b64ea8f83e3 (patch)
treee96bab47a439893fb0edf4afa2239918ae19ed20
parent22927828393b3364bc2fb918e8af7b16f8204497 (diff)
downloadrockbox-0e2b4908d012dbd45a58002774f32b64ea8f83e3.tar.gz
rockbox-0e2b4908d012dbd45a58002774f32b64ea8f83e3.zip
hwstub: rework usb driver for atj213x
Change-Id: I7b175103e567ae4375ff94e74ed1a06215f640c3
-rw-r--r--utils/hwstub/stub/atj213x/usb_drv_atj213x.c246
1 files changed, 142 insertions, 104 deletions
diff --git a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
index ef66766527..0017378473 100644
--- a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
+++ b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c
@@ -31,6 +31,17 @@
31volatile bool setup_data_valid = false; 31volatile bool setup_data_valid = false;
32volatile int udc_speed = USB_FULL_SPEED; 32volatile int udc_speed = USB_FULL_SPEED;
33 33
34struct endpoint_t
35{
36 void *buf;
37 int length;
38 bool zlp;
39 bool finished;
40};
41
42static volatile struct endpoint_t ep0in = {NULL,0,false,false};
43static volatile struct endpoint_t ep0out = {NULL,0,false,false};
44
34static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) 45static void usb_copy_from(void *ptr, volatile void *reg, size_t sz)
35{ 46{
36 uint32_t *p = ptr; 47 uint32_t *p = ptr;
@@ -67,65 +78,6 @@ static void usb_copy_to(volatile void *reg, void *ptr, size_t sz)
67 *rp++ = *p++; 78 *rp++ = *p++;
68} 79}
69 80
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) 81void usb_drv_init(void)
130{ 82{
131 OTG_USBCS |= 0x40; /* soft disconnect */ 83 OTG_USBCS |= 0x40; /* soft disconnect */
@@ -144,9 +96,9 @@ void usb_drv_init(void)
144 OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */ 96 OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */
145 OTG_OTGIEN = 0; 97 OTG_OTGIEN = 0;
146 98
147 /* disable interrupts from ep0 */ 99 /* enable interrupts from ep0 */
148 OTG_IN04IEN = 0; 100 OTG_IN04IEN = 1;
149 OTG_OUT04IEN = 0; 101 OTG_OUT04IEN = 1;
150 102
151 /* unmask UDC interrupt in interrupt controller */ 103 /* unmask UDC interrupt in interrupt controller */
152 INTC_MSK = (1<<4); 104 INTC_MSK = (1<<4);
@@ -183,71 +135,75 @@ void usb_drv_set_address(int address)
183 /* UDC sets this automaticaly */ 135 /* UDC sets this automaticaly */
184} 136}
185 137
138static void ep0_write(void)
139{
140 int xfer_size = MIN(ep0in.length, 64);
141
142 /* copy data to UDC buffer */
143 usb_copy_to(&OTG_EP0INDAT, ep0in.buf, xfer_size);
144 ep0in.buf += xfer_size;
145 ep0in.length -= xfer_size;
146
147 /* this marks data as ready to send */
148 OTG_IN0BC = xfer_size;
149}
150
186/* TODO: Maybe adapt to irq scheme */ 151/* TODO: Maybe adapt to irq scheme */
187int usb_drv_send(int endpoint, void *ptr, int length) 152int usb_drv_send(int endpoint, void *ptr, int length)
188{ 153{
189 (void)endpoint; 154 (void)endpoint;
190 155
191 int xfer_size, cnt = length; 156 if (length)
192
193 while (cnt)
194 { 157 {
195 xfer_size = MIN(cnt, 64); 158 ep0in.length = length;
159 ep0in.buf = ptr;
160 ep0in.zlp = (length % 64 == 0) ? true : false;
161 ep0in.finished = false;
196 162
197 /* copy data to ep0in buffer */ 163 ep0_write();
198 usb_copy_to(&OTG_EP0INDAT, ptr, xfer_size);
199 164
200 /* this marks data as ready to send */ 165 while(!ep0in.finished)
201 OTG_IN0BC = xfer_size;
202
203 /* wait for the transfer end */
204 while(OTG_EP0CS & 0x04)
205 ; 166 ;
206
207 cnt -= xfer_size;
208 ptr += xfer_size;
209 } 167 }
210 168 else
211 /* ZLP stage */ 169 {
212 if((length % 64) == 0)
213 OTG_EP0CS = 2; 170 OTG_EP0CS = 2;
171 }
214 172
215 return 0; 173 return 0;
216} 174}
217 175
176static int ep0_read(void)
177{
178 int xfer_size = OTG_OUT0BC;
179 usb_copy_from(ep0out.buf, &OTG_EP0OUTDAT, xfer_size);
180 ep0out.buf += xfer_size;
181 ep0out.length -= xfer_size;
182
183 return xfer_size;
184}
185
218/* TODO: Maybe adapt to irq scheme */ 186/* TODO: Maybe adapt to irq scheme */
219int usb_drv_recv(int endpoint, void* ptr, int length) 187int usb_drv_recv(int endpoint, void* ptr, int length)
220{ 188{
221 (void)endpoint; 189 (void)endpoint;
222 int xfer_size, cnt = 0;
223 190
224 while (cnt < length) 191 ep0out.length = length;
225 { 192 ep0out.buf = ptr;
226 /* Arm receiving buffer by writing 193 ep0out.zlp = (length == 0) ? true : false;
227 * any value to OUT0BC. This sets 194 ep0out.finished = false;
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 195
236 xfer_size = OTG_OUT0BC; 196 /* Arm receiving buffer by writing
197 * any value to OUT0BC. This sets
198 * OUT_BUSY bit in EP0CS until the data
199 * are correctly received and ACK'd
200 */
201 OTG_OUT0BC = 0;
237 202
238 usb_copy_from(ptr, &OTG_EP0OUTDAT, xfer_size); 203 while (!ep0out.finished)
239 cnt += xfer_size; 204 ;
240 ptr += xfer_size;
241
242 if (xfer_size < 64)
243 break;
244 }
245 205
246 /* ZLP stage */ 206 return (length - ep0out.length);
247 if (length == 0)
248 OTG_EP0CS = 2;
249
250 return cnt;
251} 207}
252 208
253void usb_drv_stall(int endpoint, bool stall, bool in) 209void usb_drv_stall(int endpoint, bool stall, bool in)
@@ -265,3 +221,85 @@ void usb_drv_stall(int endpoint, bool stall, bool in)
265void usb_drv_exit(void) 221void usb_drv_exit(void)
266{ 222{
267} 223}
224
225void INT_UDC(void)
226{
227 /* get possible sources */
228 unsigned int usbirq = OTG_USBIRQ;
229 unsigned int otgirq = OTG_OTGIRQ;
230 unsigned int epinirq = OTG_IN04IRQ;
231 unsigned int epoutirq = OTG_OUT04IRQ;
232
233 /* HS, Reset, Setup */
234 if (usbirq)
235 {
236
237 if (usbirq & (1<<5))
238 {
239 /* HS irq */
240 udc_speed = USB_HIGH_SPEED;
241 }
242 else if (usbirq & (1<<4))
243 {
244 /* Reset */
245 udc_speed = USB_FULL_SPEED;
246
247 /* clear all pending irqs */
248 OTG_OUT04IRQ = 0xff;
249 OTG_IN04IRQ = 0xff;
250 }
251 else if (usbirq & (1<<0))
252 {
253 /* Setup data valid */
254 setup_data_valid = true;
255 }
256
257 /* clear irq flags */
258 OTG_USBIRQ = usbirq;
259 }
260
261 if (epoutirq)
262 {
263 if (ep0_read() == 64)
264 {
265 /* rearm receive buffer */
266 OTG_OUT0BC = 0;
267 }
268 else
269 {
270 if (ep0out.length == 0 && ep0out.zlp)
271 {
272 OTG_EP0CS = 2;
273 }
274 ep0out.finished = true;
275 }
276 OTG_OUT04IRQ = epoutirq;
277 }
278
279 if (epinirq)
280 {
281 if (ep0in.length)
282 {
283 ep0_write();
284 }
285 else
286 {
287 if (ep0in.zlp)
288 {
289 OTG_EP0CS = 2;
290 }
291
292 ep0in.finished = true;
293 }
294
295 /* ack interrupt */
296 OTG_IN04IRQ = epinirq;
297 }
298
299 if (otgirq)
300 {
301 OTG_OTGIRQ = otgirq;
302 }
303
304 OTG_USBEIRQ = 0x50;
305}