diff options
author | Ming Lei <tom.leiming@gmail.com> | 2010-09-24 06:44:04 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-10-22 13:21:53 -0400 |
commit | f11d893de444965dfd3e55f726533ae1df5c6471 (patch) | |
tree | eeefd953cfa19481862b9574c20a12f2e076533f /drivers/usb | |
parent | 3ee076dea68e11d4685972df7298b80b8e7673e4 (diff) |
usb: musb: support ISO high bandwidth for gadget mode
This patch has been tested OK on beagle B5 board and
use usbtest #15 and #16 as testcase.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Reviewed-by: Sergei Shtylyov <sshtylyov@mvista.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Anand Gadiyar <gadiyar@ti.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 49 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.h | 2 |
2 files changed, 39 insertions, 12 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ecd5f8cffcbf..f497586e36ec 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -337,13 +337,15 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
337 | csr |= (MUSB_TXCSR_DMAENAB | | 337 | csr |= (MUSB_TXCSR_DMAENAB | |
338 | MUSB_TXCSR_MODE); | 338 | MUSB_TXCSR_MODE); |
339 | /* against programming guide */ | 339 | /* against programming guide */ |
340 | } else | 340 | } else { |
341 | csr |= (MUSB_TXCSR_AUTOSET | 341 | csr |= (MUSB_TXCSR_DMAENAB |
342 | | MUSB_TXCSR_DMAENAB | ||
343 | | MUSB_TXCSR_DMAMODE | 342 | | MUSB_TXCSR_DMAMODE |
344 | | MUSB_TXCSR_MODE); | 343 | | MUSB_TXCSR_MODE); |
345 | 344 | if (!musb_ep->hb_mult) | |
345 | csr |= MUSB_TXCSR_AUTOSET; | ||
346 | } | ||
346 | csr &= ~MUSB_TXCSR_P_UNDERRUN; | 347 | csr &= ~MUSB_TXCSR_P_UNDERRUN; |
348 | |||
347 | musb_writew(epio, MUSB_TXCSR, csr); | 349 | musb_writew(epio, MUSB_TXCSR, csr); |
348 | } | 350 | } |
349 | } | 351 | } |
@@ -643,7 +645,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
643 | */ | 645 | */ |
644 | 646 | ||
645 | csr |= MUSB_RXCSR_DMAENAB; | 647 | csr |= MUSB_RXCSR_DMAENAB; |
646 | csr |= MUSB_RXCSR_AUTOCLEAR; | 648 | if (!musb_ep->hb_mult) |
649 | csr |= MUSB_RXCSR_AUTOCLEAR; | ||
647 | #ifdef USE_MODE1 | 650 | #ifdef USE_MODE1 |
648 | /* csr |= MUSB_RXCSR_DMAMODE; */ | 651 | /* csr |= MUSB_RXCSR_DMAMODE; */ |
649 | 652 | ||
@@ -875,9 +878,25 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
875 | 878 | ||
876 | /* REVISIT this rules out high bandwidth periodic transfers */ | 879 | /* REVISIT this rules out high bandwidth periodic transfers */ |
877 | tmp = le16_to_cpu(desc->wMaxPacketSize); | 880 | tmp = le16_to_cpu(desc->wMaxPacketSize); |
878 | if (tmp & ~0x07ff) | 881 | if (tmp & ~0x07ff) { |
879 | goto fail; | 882 | int ok; |
880 | musb_ep->packet_sz = tmp; | 883 | |
884 | if (usb_endpoint_dir_in(desc)) | ||
885 | ok = musb->hb_iso_tx; | ||
886 | else | ||
887 | ok = musb->hb_iso_rx; | ||
888 | |||
889 | if (!ok) { | ||
890 | DBG(4, "%s: not support ISO high bandwidth\n", __func__); | ||
891 | goto fail; | ||
892 | } | ||
893 | musb_ep->hb_mult = (tmp >> 11) & 3; | ||
894 | } else { | ||
895 | musb_ep->hb_mult = 0; | ||
896 | } | ||
897 | |||
898 | musb_ep->packet_sz = tmp & 0x7ff; | ||
899 | tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1); | ||
881 | 900 | ||
882 | /* enable the interrupts for the endpoint, set the endpoint | 901 | /* enable the interrupts for the endpoint, set the endpoint |
883 | * packet size (or fail), set the mode, clear the fifo | 902 | * packet size (or fail), set the mode, clear the fifo |
@@ -890,8 +909,11 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
890 | musb_ep->is_in = 1; | 909 | musb_ep->is_in = 1; |
891 | if (!musb_ep->is_in) | 910 | if (!musb_ep->is_in) |
892 | goto fail; | 911 | goto fail; |
893 | if (tmp > hw_ep->max_packet_sz_tx) | 912 | |
913 | if (tmp > hw_ep->max_packet_sz_tx) { | ||
914 | DBG(4, "%s: packet size beyond hw fifo size\n", __func__); | ||
894 | goto fail; | 915 | goto fail; |
916 | } | ||
895 | 917 | ||
896 | int_txe |= (1 << epnum); | 918 | int_txe |= (1 << epnum); |
897 | musb_writew(mbase, MUSB_INTRTXE, int_txe); | 919 | musb_writew(mbase, MUSB_INTRTXE, int_txe); |
@@ -906,7 +928,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
906 | if (musb->hwvers < MUSB_HWVERS_2000) | 928 | if (musb->hwvers < MUSB_HWVERS_2000) |
907 | musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); | 929 | musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); |
908 | else | 930 | else |
909 | musb_writew(regs, MUSB_TXMAXP, tmp); | 931 | musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); |
910 | 932 | ||
911 | csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; | 933 | csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; |
912 | if (musb_readw(regs, MUSB_TXCSR) | 934 | if (musb_readw(regs, MUSB_TXCSR) |
@@ -927,8 +949,11 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
927 | musb_ep->is_in = 0; | 949 | musb_ep->is_in = 0; |
928 | if (musb_ep->is_in) | 950 | if (musb_ep->is_in) |
929 | goto fail; | 951 | goto fail; |
930 | if (tmp > hw_ep->max_packet_sz_rx) | 952 | |
953 | if (tmp > hw_ep->max_packet_sz_rx) { | ||
954 | DBG(4, "%s: packet size beyond hw fifo size\n", __func__); | ||
931 | goto fail; | 955 | goto fail; |
956 | } | ||
932 | 957 | ||
933 | int_rxe |= (1 << epnum); | 958 | int_rxe |= (1 << epnum); |
934 | musb_writew(mbase, MUSB_INTRRXE, int_rxe); | 959 | musb_writew(mbase, MUSB_INTRRXE, int_rxe); |
@@ -942,7 +967,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
942 | if (musb->hwvers < MUSB_HWVERS_2000) | 967 | if (musb->hwvers < MUSB_HWVERS_2000) |
943 | musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx); | 968 | musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx); |
944 | else | 969 | else |
945 | musb_writew(regs, MUSB_RXMAXP, tmp); | 970 | musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); |
946 | 971 | ||
947 | /* force shared fifo to OUT-only mode */ | 972 | /* force shared fifo to OUT-only mode */ |
948 | if (hw_ep->is_shared_fifo) { | 973 | if (hw_ep->is_shared_fifo) { |
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 572b1da7f2dc..dec8dc008191 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h | |||
@@ -79,6 +79,8 @@ struct musb_ep { | |||
79 | 79 | ||
80 | /* true if lock must be dropped but req_list may not be advanced */ | 80 | /* true if lock must be dropped but req_list may not be advanced */ |
81 | u8 busy; | 81 | u8 busy; |
82 | |||
83 | u8 hb_mult; | ||
82 | }; | 84 | }; |
83 | 85 | ||
84 | static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) | 86 | static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) |