diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2011-12-14 17:12:52 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2011-12-14 17:12:52 +0000 |
commit | d985d659078d8216becb310ad3237f4024d0f473 (patch) | |
tree | 40ac5a518e32a9967299da473d5c0e3cec6b4a28 | |
parent | 3042c441f2c5cdc88825c96f5d0bcda5d332fe9b (diff) | |
download | rockbox-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.c | 106 |
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 | ||
39 | static const uint8_t in_ep_list[] = {0, 3, 5}; | 39 | static const uint8_t in_ep_list[] = {0, 1, 3}; // FIXME : EP5 ? |
40 | static const uint8_t out_ep_list[] = {0, 2, 4}; | 40 | static 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 | ||
106 | static size_t num_eps(bool out) | ||
107 | { | ||
108 | return out ? sizeof(out_ep_list) : sizeof(in_ep_list); | ||
109 | } | ||
110 | |||
106 | static void reset_endpoints(void) | 111 | static 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 | ||
378 | static 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 | |||
390 | int usb_drv_request_endpoint(int type, int dir) | 399 | int 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 | ||
418 | static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in) | 427 | static 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 | ||
453 | int usb_drv_recv(int ep, void *ptr, int len) | 463 | int 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 | ||
470 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) | 480 | int 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 | ||