summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2011-12-14 17:12:52 +0000
committerRafaël Carré <rafael.carre@gmail.com>2011-12-14 17:12:52 +0000
commitd985d659078d8216becb310ad3237f4024d0f473 (patch)
tree40ac5a518e32a9967299da473d5c0e3cec6b4a28
parent3042c441f2c5cdc88825c96f5d0bcda5d332fe9b (diff)
downloadrockbox-d985d659078d8216becb310ad3237f4024d0f473.tar.gz
rockbox-d985d659078d8216becb310ad3237f4024d0f473.zip
usb-drv-as3525v2: make it look more like usb-s3c6400
use 0, 1, 3 as input endpoints instead of 0, 3, 5 (0, 1, 3, 5 doesn't work) use a helper to know the number of endpoints (could be hardcoded since we have 3 input and 3 outputs) previous check was not correct (sizeof(if?a:b)) change endpoint reset/request set packet size at enumdone interrupt we don't have isochronous or interrupt endpoints, remove that table reverse usb_drv_transfer direction argument (in -> out) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31251 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.c106
1 files changed, 58 insertions, 48 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index fdc0b6c19e..7b5ce886c5 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c
@@ -36,7 +36,7 @@
36#include "usb-drv-as3525v2.h" 36#include "usb-drv-as3525v2.h"
37#include "usb_core.h" 37#include "usb_core.h"
38 38
39static const uint8_t in_ep_list[] = {0, 3, 5}; 39static const uint8_t in_ep_list[] = {0, 1, 3}; // FIXME : EP5 ?
40static const uint8_t out_ep_list[] = {0, 2, 4}; 40static const uint8_t out_ep_list[] = {0, 2, 4};
41 41
42/* store per endpoint, per direction, information */ 42/* store per endpoint, per direction, information */
@@ -103,34 +103,39 @@ static void prepare_setup_ep0(void)
103 ep0_state = EP0_WAIT_SETUP; 103 ep0_state = EP0_WAIT_SETUP;
104} 104}
105 105
106static size_t num_eps(bool out)
107{
108 return out ? sizeof(out_ep_list) : sizeof(in_ep_list);
109}
110
106static void reset_endpoints(void) 111static void reset_endpoints(void)
107{ 112{
108 for (int dir = 0; dir < 2; dir++) 113 for (int dir = 0; dir < 2; dir++)
109 for (unsigned i = 0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++) 114 {
115 bool out = dir == DIR_OUT;
116 for (unsigned i = 0; i < num_eps(dir == DIR_OUT); i++)
110 { 117 {
111 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; 118 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
112 endpoints[ep][dir == DIR_OUT] = (struct usb_endpoint) { 119 endpoints[ep][out] = (struct usb_endpoint) {
113 .active = false, 120 .active = false,
114 .busy = false, 121 .busy = false,
115 .status = -1, 122 .status = -1,
116 .done = false, 123 .done = false,
117 }; 124 };
118 semaphore_release(&endpoints[ep][dir == DIR_OUT].complete); 125 semaphore_release(&endpoints[ep][out].complete);
119 126
120 if (i != 0) 127 if (i != 0)
121 DEPCTL(ep, dir == DIR_OUT) = (DEPCTL(ep, dir == DIR_OUT) & DEPCTL_epena) 128 DEPCTL(ep, out) = DEPCTL_setd0pid;
122 ? DEPCTL_snak
123 : 0;
124 else
125 DEPCTL(0, dir == DIR_OUT) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak;
126 } 129 }
130 DEPCTL(0, out) = /*(DEPCTL_MPS_64 << DEPCTL_mps_bitp) | */ DEPCTL_usbactep;
131 }
127 132
128 /* Setup next chain for IN eps */ 133 /* Setup next chain for IN eps */
129 for (unsigned i = 0; i < sizeof(in_ep_list); i++) 134 for (unsigned i = 0; i < num_eps(false); i++)
130 { 135 {
131 int ep = in_ep_list[i]; 136 int ep = in_ep_list[i];
132 int next_ep = in_ep_list[(i + 1) % sizeof(in_ep_list)]; 137 int next_ep = in_ep_list[(i + 1) % num_eps(false)];
133 DEPCTL(ep, false) = (DEPCTL(ep, false) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp); 138 DEPCTL(ep, false) |= next_ep << DEPCTL_nextep_bitp;
134 } 139 }
135 140
136 prepare_setup_ep0(); 141 prepare_setup_ep0();
@@ -141,7 +146,7 @@ static void cancel_all_transfers(bool cancel_ep0)
141 int flags = disable_irq_save(); 146 int flags = disable_irq_save();
142 147
143 for (int dir = 0; dir < 2; dir++) 148 for (int dir = 0; dir < 2; dir++)
144 for (unsigned i = !!cancel_ep0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++) 149 for (unsigned i = !!cancel_ep0; i < num_eps(dir == DIR_OUT); i++)
145 { 150 {
146 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; 151 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
147 endpoints[ep][dir == DIR_OUT] = (struct usb_endpoint) { 152 endpoints[ep][dir == DIR_OUT] = (struct usb_endpoint) {
@@ -150,7 +155,7 @@ static void cancel_all_transfers(bool cancel_ep0)
150 .done = false, 155 .done = false,
151 }; 156 };
152 semaphore_release(&endpoints[ep][dir == DIR_OUT].complete); 157 semaphore_release(&endpoints[ep][dir == DIR_OUT].complete);
153 DEPCTL(ep, dir) = (DEPCTL(ep, dir) & ~DEPCTL_usbactep) | DEPCTL_snak; 158 DEPCTL(ep, dir) = (DEPCTL(ep, dir) & ~DEPCTL_usbactep);
154 } 159 }
155 160
156 restore_irq(flags); 161 restore_irq(flags);
@@ -210,7 +215,7 @@ void usb_drv_init(void)
210 panicf("usb-drv: wrong endpoint number"); 215 panicf("usb-drv: wrong endpoint number");
211 216
212 for (int dir = 0; dir < 2; dir++) 217 for (int dir = 0; dir < 2; dir++)
213 for (unsigned i = 0; i < sizeof((dir == DIR_IN) ? in_ep_list : out_ep_list); i++) 218 for (unsigned i = 0; i < num_eps(dir == DIR_OUT); i++)
214 { 219 {
215 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i]; 220 int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
216 int type = (GHWCFG1 >> GHWCFG1_epdir_bitp(ep)) & GHWCFG1_epdir_bits; 221 int type = (GHWCFG1 >> GHWCFG1_epdir_bitp(ep)) & GHWCFG1_epdir_bits;
@@ -337,6 +342,22 @@ void INT_USB(void)
337 usb_core_bus_reset(); 342 usb_core_bus_reset();
338 } 343 }
339 344
345 if(sts & GINTMSK_enumdone) /* enumeration done, we now know the speed */
346 {
347 /* Set up the maximum packet sizes accordingly */
348 uint32_t maxpacket = (usb_drv_port_speed() ? 512 : 64) << DEPCTL_mps_bitp;
349 for (int dir = 0; dir < 2; dir++)
350 {
351 bool out = dir == DIR_OUT;
352 for (unsigned i = 1; i < num_eps(out); i++)
353 {
354 int ep = (out ? out_ep_list : in_ep_list)[i];
355 DEPCTL(ep, out) &= ~(DEPCTL_mps_bits << DEPCTL_mps_bitp);
356 DEPCTL(ep, out) |= maxpacket;
357 }
358 }
359 }
360
340 if(sts & (GINTMSK_outepintr | GINTMSK_inepintr)) 361 if(sts & (GINTMSK_outepintr | GINTMSK_inepintr))
341 { 362 {
342 unsigned long daint = DAINT; 363 unsigned long daint = DAINT;
@@ -375,30 +396,18 @@ int usb_drv_port_speed(void)
375 return speed[enumspd & 3]; 396 return speed[enumspd & 3];
376} 397}
377 398
378static unsigned long usb_drv_mps_by_type(int type)
379{
380 static const uint16_t mps[4][2] = {
381 /* type fs hs */
382 [USB_ENDPOINT_XFER_CONTROL] = { 64, 64 },
383 [USB_ENDPOINT_XFER_ISOC] = { 1023, 1024 },
384 [USB_ENDPOINT_XFER_BULK] = { 64, 512 },
385 [USB_ENDPOINT_XFER_INT] = { 64, 1024 },
386 };
387 return mps[type & 3][usb_drv_port_speed() & 1];
388}
389
390int usb_drv_request_endpoint(int type, int dir) 399int usb_drv_request_endpoint(int type, int dir)
391{ 400{
392 for (unsigned i = 1; i < sizeof((dir == USB_DIR_IN) ? in_ep_list : out_ep_list); i++) 401 bool out = dir == USB_DIR_OUT;
402 for (unsigned i = 1; i < num_eps(out); i++)
393 { 403 {
394 int ep = ((dir == USB_DIR_IN) ? in_ep_list : out_ep_list)[i]; 404 int ep = (out ? out_ep_list : in_ep_list)[i];
395 bool *active = &endpoints[ep][(dir == USB_DIR_IN) ? DIR_IN : DIR_OUT].active; 405 bool *active = &endpoints[ep][out ? DIR_OUT : DIR_IN].active;
396 if(*active) 406 if(*active)
397 continue; 407 continue;
398 *active = true; 408 *active = true;
399 DEPCTL(ep, dir != USB_DIR_IN) = (DEPCTL(ep, dir != USB_DIR_IN) & ~(bitm(DEPCTL, eptype) | bitm(DEPCTL, mps))) 409 DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp))
400 | DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) 410 | DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) | DEPCTL_usbactep;
401 | (usb_drv_mps_by_type(type) << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak;
402 return ep | dir; 411 return ep | dir;
403 } 412 }
404 413
@@ -415,44 +424,45 @@ void usb_drv_cancel_all_transfers()
415 cancel_all_transfers(false); 424 cancel_all_transfers(false);
416} 425}
417 426
418static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) 427static void usb_drv_transfer(int ep, void *ptr, int len, bool out)
419{ 428{
420 /* disable interrupts to avoid any race */ 429 /* disable interrupts to avoid any race */
421 int oldlevel = disable_irq_save(); 430 int oldlevel = disable_irq_save();
422 431
423 endpoints[ep][dir_in] = (struct usb_endpoint) { 432 endpoints[ep][out ? DIR_OUT : DIR_IN] = (struct usb_endpoint) {
424 .busy = true, 433 .busy = true,
425 .len = len, 434 .len = len,
426 .status = -1, 435 .status = -1,
427 }; 436 };
428 437
429 DEPCTL(ep, !dir_in) = (DEPCTL(ep, !dir_in) & ~DEPCTL_stall) | DEPCTL_usbactep; 438 if (out)
439 DEPCTL(ep, out) &= ~DEPCTL_naksts;
440 DEPCTL(ep, out) |= DEPCTL_usbactep;
430 441
431 int type = (DEPCTL(ep, !dir_in) >> DEPCTL_eptype_bitp) & DEPCTL_eptype_bits; 442 int mps = usb_drv_port_speed() ? 512 : 64;
432 int mps = usb_drv_mps_by_type(type);
433 int nb_packets = (len + mps - 1) / mps; 443 int nb_packets = (len + mps - 1) / mps;
434 if (nb_packets == 0) 444 if (nb_packets == 0)
435 nb_packets = 1; 445 nb_packets = 1;
436 446
437 DEPDMA(ep, !dir_in) = len 447 DEPDMA(ep, out) = len
438 ? (void*)AS3525_PHYSICAL_ADDR(ptr) 448 ? (void*)AS3525_PHYSICAL_ADDR(ptr)
439 : (void*)0x10000000; 449 : (void*)0x10000000;
440 DEPTSIZ(ep, !dir_in) = (nb_packets << DEPTSIZ_pkcnt_bitp) | len; 450 DEPTSIZ(ep, out) = (nb_packets << DEPTSIZ_pkcnt_bitp) | len;
441 if(dir_in) 451 if(out)
442 clean_dcache_range(ptr, len);
443 else
444 dump_dcache_range(ptr, len); 452 dump_dcache_range(ptr, len);
453 else
454 clean_dcache_range(ptr, len);
445 455
446 logf("pkt=%d dma=%lx", nb_packets, DEPDMA(ep, !dir_in)); 456 logf("pkt=%d dma=%lx", nb_packets, DEPDMA(ep, out));
447 457
448 DEPCTL(ep, !dir_in) |= DEPCTL_epena | DEPCTL_cnak; 458 DEPCTL(ep, out) |= DEPCTL_epena | DEPCTL_cnak;
449 459
450 restore_irq(oldlevel); 460 restore_irq(oldlevel);
451} 461}
452 462
453int usb_drv_recv(int ep, void *ptr, int len) 463int usb_drv_recv(int ep, void *ptr, int len)
454{ 464{
455 usb_drv_transfer(EP_NUM(ep), ptr, len, false); 465 usb_drv_transfer(EP_NUM(ep), ptr, len, true);
456 return 0; 466 return 0;
457} 467}
458 468
@@ -461,7 +471,7 @@ int usb_drv_send(int ep, void *ptr, int len)
461 ep = EP_NUM(ep); 471 ep = EP_NUM(ep);
462 struct usb_endpoint *endpoint = &endpoints[ep][1]; 472 struct usb_endpoint *endpoint = &endpoints[ep][1];
463 endpoint->done = false; 473 endpoint->done = false;
464 usb_drv_transfer(ep, ptr, len, true); 474 usb_drv_transfer(ep, ptr, len, false);
465 while (endpoint->busy && !endpoint->done) 475 while (endpoint->busy && !endpoint->done)
466 semaphore_wait(&endpoint->complete, TIMEOUT_BLOCK); 476 semaphore_wait(&endpoint->complete, TIMEOUT_BLOCK);
467 return endpoint->status; 477 return endpoint->status;
@@ -469,7 +479,7 @@ int usb_drv_send(int ep, void *ptr, int len)
469 479
470int usb_drv_send_nonblocking(int ep, void *ptr, int len) 480int usb_drv_send_nonblocking(int ep, void *ptr, int len)
471{ 481{
472 usb_drv_transfer(EP_NUM(ep), ptr, len, true); 482 usb_drv_transfer(EP_NUM(ep), ptr, len, false);
473 return 0; 483 return 0;
474} 484}
475 485