aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorKyungmin Park <kyungmin.park@samsung.com>2007-11-21 18:13:15 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:34:48 -0500
commit527ea73eaea4600120117edd19ac88864a488d57 (patch)
tree4317766b607ea1353e3aaa47c744c61378c92224 /drivers/usb
parent568fdade1415196a4835a9add48586e36a044d82 (diff)
USB: device DMA support on OMAP2
The current omap udc dosen't support the DMA mode and it has some problem at setup time on OMAP2 with previous patch file. I found that the code assumes bulk out required the big data transfer. But MODE SELECT(6) sent the only 24 bytes. it makes a problem. So I implement the small packets handling for it. It is tested with both linux and windows. Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: David Brownell <david-b@pacbell.net> Cc: Tony Lindgren <tony@atomide.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/omap_udc.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index d377154658b5..7d6bef56cb01 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -4,6 +4,8 @@
4 * Copyright (C) 2004 Texas Instruments, Inc. 4 * Copyright (C) 2004 Texas Instruments, Inc.
5 * Copyright (C) 2004-2005 David Brownell 5 * Copyright (C) 2004-2005 David Brownell
6 * 6 *
7 * OMAP2 & DMA support by Kyungmin Park <kyungmin.park@samsung.com>
8 *
7 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 11 * the Free Software Foundation; either version 2 of the License, or
@@ -60,11 +62,6 @@
60/* bulk DMA seems to be behaving for both IN and OUT */ 62/* bulk DMA seems to be behaving for both IN and OUT */
61#define USE_DMA 63#define USE_DMA
62 64
63/* FIXME: OMAP2 currently has some problem in DMA mode */
64#ifdef CONFIG_ARCH_OMAP2
65#undef USE_DMA
66#endif
67
68/* ISO too */ 65/* ISO too */
69#define USE_ISO 66#define USE_ISO
70 67
@@ -73,6 +70,8 @@
73 70
74#define DMA_ADDR_INVALID (~(dma_addr_t)0) 71#define DMA_ADDR_INVALID (~(dma_addr_t)0)
75 72
73#define OMAP2_DMA_CH(ch) (((ch) - 1) << 1)
74#define OMAP24XX_DMA(name, ch) (OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch))
76 75
77/* 76/*
78 * The OMAP UDC needs _very_ early endpoint setup: before enabling the 77 * The OMAP UDC needs _very_ early endpoint setup: before enabling the
@@ -571,20 +570,25 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
571 const int sync_mode = cpu_is_omap15xx() 570 const int sync_mode = cpu_is_omap15xx()
572 ? OMAP_DMA_SYNC_FRAME 571 ? OMAP_DMA_SYNC_FRAME
573 : OMAP_DMA_SYNC_ELEMENT; 572 : OMAP_DMA_SYNC_ELEMENT;
573 int dma_trigger = 0;
574
575 if (cpu_is_omap24xx())
576 dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel);
574 577
575 /* measure length in either bytes or packets */ 578 /* measure length in either bytes or packets */
576 if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC) 579 if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
580 || (cpu_is_omap24xx() && length < ep->maxpacket)
577 || (cpu_is_omap15xx() && length < ep->maxpacket)) { 581 || (cpu_is_omap15xx() && length < ep->maxpacket)) {
578 txdma_ctrl = UDC_TXN_EOT | length; 582 txdma_ctrl = UDC_TXN_EOT | length;
579 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, 583 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
580 length, 1, sync_mode, 0, 0); 584 length, 1, sync_mode, dma_trigger, 0);
581 } else { 585 } else {
582 length = min(length / ep->maxpacket, 586 length = min(length / ep->maxpacket,
583 (unsigned) UDC_TXN_TSC + 1); 587 (unsigned) UDC_TXN_TSC + 1);
584 txdma_ctrl = length; 588 txdma_ctrl = length;
585 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, 589 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
586 ep->ep.maxpacket >> 1, length, sync_mode, 590 ep->ep.maxpacket >> 1, length, sync_mode,
587 0, 0); 591 dma_trigger, 0);
588 length *= ep->maxpacket; 592 length *= ep->maxpacket;
589 } 593 }
590 omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, 594 omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
@@ -622,20 +626,31 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
622 626
623static void next_out_dma(struct omap_ep *ep, struct omap_req *req) 627static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
624{ 628{
625 unsigned packets; 629 unsigned packets = req->req.length - req->req.actual;
630 int dma_trigger = 0;
631
632 if (cpu_is_omap24xx())
633 dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel);
626 634
627 /* NOTE: we filtered out "short reads" before, so we know 635 /* NOTE: we filtered out "short reads" before, so we know
628 * the buffer has only whole numbers of packets. 636 * the buffer has only whole numbers of packets.
637 * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode
629 */ 638 */
630 639 if (cpu_is_omap24xx() && packets < ep->maxpacket) {
631 /* set up this DMA transfer, enable the fifo, start */ 640 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
632 packets = (req->req.length - req->req.actual) / ep->ep.maxpacket; 641 packets, 1, OMAP_DMA_SYNC_ELEMENT,
633 packets = min(packets, (unsigned)UDC_RXN_TC + 1); 642 dma_trigger, 0);
634 req->dma_bytes = packets * ep->ep.maxpacket; 643 req->dma_bytes = packets;
635 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, 644 } else {
636 ep->ep.maxpacket >> 1, packets, 645 /* set up this DMA transfer, enable the fifo, start */
637 OMAP_DMA_SYNC_ELEMENT, 646 packets /= ep->ep.maxpacket;
638 0, 0); 647 packets = min(packets, (unsigned)UDC_RXN_TC + 1);
648 req->dma_bytes = packets * ep->ep.maxpacket;
649 omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
650 ep->ep.maxpacket >> 1, packets,
651 OMAP_DMA_SYNC_ELEMENT,
652 dma_trigger, 0);
653 }
639 omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, 654 omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
640 OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, 655 OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
641 0, 0); 656 0, 0);
@@ -743,6 +758,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
743{ 758{
744 u16 reg; 759 u16 reg;
745 int status, restart, is_in; 760 int status, restart, is_in;
761 int dma_channel;
746 762
747 is_in = ep->bEndpointAddress & USB_DIR_IN; 763 is_in = ep->bEndpointAddress & USB_DIR_IN;
748 if (is_in) 764 if (is_in)
@@ -769,11 +785,15 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
769 ep->dma_channel = channel; 785 ep->dma_channel = channel;
770 786
771 if (is_in) { 787 if (is_in) {
772 status = omap_request_dma(OMAP_DMA_USB_W2FC_TX0 - 1 + channel, 788 if (cpu_is_omap24xx())
789 dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel);
790 else
791 dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
792 status = omap_request_dma(dma_channel,
773 ep->ep.name, dma_error, ep, &ep->lch); 793 ep->ep.name, dma_error, ep, &ep->lch);
774 if (status == 0) { 794 if (status == 0) {
775 UDC_TXDMA_CFG_REG = reg; 795 UDC_TXDMA_CFG_REG = reg;
776 /* EMIFF */ 796 /* EMIFF or SDRC */
777 omap_set_dma_src_burst_mode(ep->lch, 797 omap_set_dma_src_burst_mode(ep->lch,
778 OMAP_DMA_DATA_BURST_4); 798 OMAP_DMA_DATA_BURST_4);
779 omap_set_dma_src_data_pack(ep->lch, 1); 799 omap_set_dma_src_data_pack(ep->lch, 1);
@@ -785,7 +805,12 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
785 0, 0); 805 0, 0);
786 } 806 }
787 } else { 807 } else {
788 status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel, 808 if (cpu_is_omap24xx())
809 dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel);
810 else
811 dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
812
813 status = omap_request_dma(dma_channel,
789 ep->ep.name, dma_error, ep, &ep->lch); 814 ep->ep.name, dma_error, ep, &ep->lch);
790 if (status == 0) { 815 if (status == 0) {
791 UDC_RXDMA_CFG_REG = reg; 816 UDC_RXDMA_CFG_REG = reg;
@@ -795,7 +820,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
795 OMAP_DMA_AMODE_CONSTANT, 820 OMAP_DMA_AMODE_CONSTANT,
796 (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG), 821 (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
797 0, 0); 822 0, 0);
798 /* EMIFF */ 823 /* EMIFF or SDRC */
799 omap_set_dma_dest_burst_mode(ep->lch, 824 omap_set_dma_dest_burst_mode(ep->lch,
800 OMAP_DMA_DATA_BURST_4); 825 OMAP_DMA_DATA_BURST_4);
801 omap_set_dma_dest_data_pack(ep->lch, 1); 826 omap_set_dma_dest_data_pack(ep->lch, 1);
@@ -808,7 +833,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
808 omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ); 833 omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
809 834
810 /* channel type P: hw synch (fifo) */ 835 /* channel type P: hw synch (fifo) */
811 if (!cpu_is_omap15xx()) 836 if (cpu_class_is_omap1() && !cpu_is_omap15xx())
812 OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2; 837 OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
813 } 838 }
814 839
@@ -926,11 +951,13 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
926 951
927 /* this isn't bogus, but OMAP DMA isn't the only hardware to 952 /* this isn't bogus, but OMAP DMA isn't the only hardware to
928 * have a hard time with partial packet reads... reject it. 953 * have a hard time with partial packet reads... reject it.
954 * Except OMAP2 can handle the small packets.
929 */ 955 */
930 if (use_dma 956 if (use_dma
931 && ep->has_dma 957 && ep->has_dma
932 && ep->bEndpointAddress != 0 958 && ep->bEndpointAddress != 0
933 && (ep->bEndpointAddress & USB_DIR_IN) == 0 959 && (ep->bEndpointAddress & USB_DIR_IN) == 0
960 && !cpu_class_is_omap2()
934 && (req->req.length % ep->ep.maxpacket) != 0) { 961 && (req->req.length % ep->ep.maxpacket) != 0) {
935 DBG("%s, no partial packet OUT reads\n", __FUNCTION__); 962 DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
936 return -EMSGSIZE; 963 return -EMSGSIZE;