aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-06-06 01:19:03 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 12:10:10 -0400
commite73a9891b3a1c9fc0970e0c9dbe2cc47933ad752 (patch)
treea40457485733fc6a08eae7f0d5efcbc98cf93a7d
parent0cb7e61d16ac68a2c5dd73a00e211287848d16e7 (diff)
usb: renesas_usbhs: add DMAEngine support
USB DMA was installed on "normal DMAC" when SH7724 or older SuperH, but the "USB-DMAC" was prepared on recent SuperH. These 2 DMAC have a little bit different behavior. This patch add DMAEngine code for "normal DMAC", but it is still using PIO fifo. The DMA fifo will be formally supported in the future. You can enable DMA fifo by local fixup usbhs_fifo_pio_push_handler -> usbhs_fifo_dma_push_handler usbhs_fifo_pio_pop_handler -> usbhs_fifo_dma_pop_handler on usbhsg_ep_enable. This DMAEngine was tested by g_file_storage on SH7724 Ecovec board Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/renesas_usbhs/common.c2
-rw-r--r--drivers/usb/renesas_usbhs/common.h35
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c380
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h24
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c70
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c4
-rw-r--r--drivers/usb/renesas_usbhs/pipe.h4
-rw-r--r--include/linux/usb/renesas_usbhs.h17
8 files changed, 533 insertions, 3 deletions
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index e510b29216b3..665259aec871 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -304,6 +304,8 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
304 priv->dparam->pipe_type = usbhsc_default_pipe_type; 304 priv->dparam->pipe_type = usbhsc_default_pipe_type;
305 priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type); 305 priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
306 } 306 }
307 if (!priv->dparam->pio_dma_border)
308 priv->dparam->pio_dma_border = 64; /* 64byte */
307 309
308 /* FIXME */ 310 /* FIXME */
309 /* runtime power control ? */ 311 /* runtime power control ? */
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index 06d7239a044d..b410463a1212 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -36,6 +36,12 @@ struct usbhs_priv;
36#define CFIFO 0x0014 36#define CFIFO 0x0014
37#define CFIFOSEL 0x0020 37#define CFIFOSEL 0x0020
38#define CFIFOCTR 0x0022 38#define CFIFOCTR 0x0022
39#define D0FIFO 0x0100
40#define D0FIFOSEL 0x0028
41#define D0FIFOCTR 0x002A
42#define D1FIFO 0x0120
43#define D1FIFOSEL 0x002C
44#define D1FIFOCTR 0x002E
39#define INTENB0 0x0030 45#define INTENB0 0x0030
40#define INTENB1 0x0032 46#define INTENB1 0x0032
41#define BRDYENB 0x0036 47#define BRDYENB 0x0036
@@ -60,6 +66,30 @@ struct usbhs_priv;
60#define PIPEMAXP 0x006C 66#define PIPEMAXP 0x006C
61#define PIPEPERI 0x006E 67#define PIPEPERI 0x006E
62#define PIPEnCTR 0x0070 68#define PIPEnCTR 0x0070
69#define PIPE1TRE 0x0090
70#define PIPE1TRN 0x0092
71#define PIPE2TRE 0x0094
72#define PIPE2TRN 0x0096
73#define PIPE3TRE 0x0098
74#define PIPE3TRN 0x009A
75#define PIPE4TRE 0x009C
76#define PIPE4TRN 0x009E
77#define PIPE5TRE 0x00A0
78#define PIPE5TRN 0x00A2
79#define PIPEBTRE 0x00A4
80#define PIPEBTRN 0x00A6
81#define PIPECTRE 0x00A8
82#define PIPECTRN 0x00AA
83#define PIPEDTRE 0x00AC
84#define PIPEDTRN 0x00AE
85#define PIPEETRE 0x00B0
86#define PIPEETRN 0x00B2
87#define PIPEFTRE 0x00B4
88#define PIPEFTRN 0x00B6
89#define PIPE9TRE 0x00B8
90#define PIPE9TRN 0x00BA
91#define PIPEATRE 0x00BC
92#define PIPEATRN 0x00BE
63 93
64/* SYSCFG */ 94/* SYSCFG */
65#define SCKE (1 << 10) /* USB Module Clock Enable */ 95#define SCKE (1 << 10) /* USB Module Clock Enable */
@@ -78,6 +108,7 @@ struct usbhs_priv;
78#define RHST_HIGH_SPEED 3 /* High-speed connection */ 108#define RHST_HIGH_SPEED 3 /* High-speed connection */
79 109
80/* CFIFOSEL */ 110/* CFIFOSEL */
111#define DREQE (1 << 12) /* DMA Transfer Request Enable */
81#define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */ 112#define MBW_32 (0x2 << 10) /* CFIFO Port Access Bit Width */
82 113
83/* CFIFOCTR */ 114/* CFIFOCTR */
@@ -164,6 +195,10 @@ struct usbhs_priv;
164 195
165#define CCPL (1 << 2) /* Control Transfer End Enable */ 196#define CCPL (1 << 2) /* Control Transfer End Enable */
166 197
198/* PIPEnTRE */
199#define TRENB (1 << 9) /* Transaction Counter Enable */
200#define TRCLR (1 << 8) /* Transaction Counter Clear */
201
167/* FRMNUM */ 202/* FRMNUM */
168#define FRNM_MASK (0x7FF) 203#define FRNM_MASK (0x7FF)
169 204
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 14baaad20b79..2016a2448ccb 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -20,6 +20,8 @@
20#include "./pipe.h" 20#include "./pipe.h"
21 21
22#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) 22#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
23#define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo))
24#define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo))
23 25
24#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ 26#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */
25 27
@@ -43,6 +45,7 @@ static struct usbhs_pkt_handle usbhsf_null_handler = {
43 45
44void usbhs_pkt_init(struct usbhs_pkt *pkt) 46void usbhs_pkt_init(struct usbhs_pkt *pkt)
45{ 47{
48 pkt->dma = DMA_ADDR_INVALID;
46 INIT_LIST_HEAD(&pkt->node); 49 INIT_LIST_HEAD(&pkt->node);
47} 50}
48 51
@@ -136,6 +139,9 @@ int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type)
136 case USBHSF_PKT_TRY_RUN: 139 case USBHSF_PKT_TRY_RUN:
137 func = pkt->handler->try_run; 140 func = pkt->handler->try_run;
138 break; 141 break;
142 case USBHSF_PKT_DMA_DONE:
143 func = pkt->handler->dma_done;
144 break;
139 default: 145 default:
140 dev_err(dev, "unknown pkt hander\n"); 146 dev_err(dev, "unknown pkt hander\n");
141 goto __usbhs_pkt_handler_end; 147 goto __usbhs_pkt_handler_end;
@@ -508,6 +514,330 @@ struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = {
508}; 514};
509 515
510/* 516/*
517 * DMA fifo functions
518 */
519static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
520 struct usbhs_pkt *pkt)
521{
522 if (&usbhs_fifo_dma_push_handler == pkt->handler)
523 return fifo->tx_chan;
524
525 if (&usbhs_fifo_dma_pop_handler == pkt->handler)
526 return fifo->rx_chan;
527
528 return NULL;
529}
530
531static struct usbhs_fifo *usbhsf_get_dma_fifo(struct usbhs_priv *priv,
532 struct usbhs_pkt *pkt)
533{
534 struct usbhs_fifo *fifo;
535
536 /* DMA :: D0FIFO */
537 fifo = usbhsf_get_d0fifo(priv);
538 if (usbhsf_dma_chan_get(fifo, pkt) &&
539 !usbhsf_fifo_is_busy(fifo))
540 return fifo;
541
542 /* DMA :: D1FIFO */
543 fifo = usbhsf_get_d1fifo(priv);
544 if (usbhsf_dma_chan_get(fifo, pkt) &&
545 !usbhsf_fifo_is_busy(fifo))
546 return fifo;
547
548 return NULL;
549}
550
551#define usbhsf_dma_start(p, f) __usbhsf_dma_ctrl(p, f, DREQE)
552#define usbhsf_dma_stop(p, f) __usbhsf_dma_ctrl(p, f, 0)
553static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe,
554 struct usbhs_fifo *fifo,
555 u16 dreqe)
556{
557 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
558
559 usbhs_bset(priv, fifo->sel, DREQE, dreqe);
560}
561
562#define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1)
563#define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0)
564static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
565{
566 struct usbhs_pipe *pipe = pkt->pipe;
567 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
568 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
569
570 return info->dma_map_ctrl(pkt, map);
571}
572
573static void usbhsf_dma_complete(void *arg);
574static void usbhsf_dma_prepare_tasklet(unsigned long data)
575{
576 struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
577 struct usbhs_pipe *pipe = pkt->pipe;
578 struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
579 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
580 struct scatterlist sg;
581 struct dma_async_tx_descriptor *desc;
582 struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
583 struct device *dev = usbhs_priv_to_dev(priv);
584 enum dma_data_direction dir;
585 dma_cookie_t cookie;
586
587 dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
588
589 sg_init_table(&sg, 1);
590 sg_set_page(&sg, virt_to_page(pkt->dma),
591 pkt->length, offset_in_page(pkt->dma));
592 sg_dma_address(&sg) = pkt->dma + pkt->actual;
593 sg_dma_len(&sg) = pkt->trans;
594
595 desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
596 DMA_PREP_INTERRUPT |
597 DMA_CTRL_ACK);
598 if (!desc)
599 return;
600
601 desc->callback = usbhsf_dma_complete;
602 desc->callback_param = pipe;
603
604 cookie = desc->tx_submit(desc);
605 if (cookie < 0) {
606 dev_err(dev, "Failed to submit dma descriptor\n");
607 return;
608 }
609
610 dev_dbg(dev, " %s %d (%d/ %d)\n",
611 fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
612
613 usbhsf_dma_start(pipe, fifo);
614 dma_async_issue_pending(chan);
615}
616
617static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
618{
619 struct usbhs_pipe *pipe = pkt->pipe;
620 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
621 struct usbhs_fifo *fifo;
622 int len = pkt->length - pkt->actual;
623 int ret;
624
625 if (usbhs_pipe_is_busy(pipe))
626 return 0;
627
628 /* use PIO if packet is less than pio_dma_border or pipe is DCP */
629 if ((len < usbhs_get_dparam(priv, pio_dma_border)) ||
630 usbhs_pipe_is_dcp(pipe))
631 goto usbhsf_pio_prepare_push;
632
633 if (len % 4) /* 32bit alignment */
634 goto usbhsf_pio_prepare_push;
635
636 /* get enable DMA fifo */
637 fifo = usbhsf_get_dma_fifo(priv, pkt);
638 if (!fifo)
639 goto usbhsf_pio_prepare_push;
640
641 if (usbhsf_dma_map(pkt) < 0)
642 goto usbhsf_pio_prepare_push;
643
644 ret = usbhsf_fifo_select(pipe, fifo, 0);
645 if (ret < 0)
646 goto usbhsf_pio_prepare_push_unmap;
647
648 pkt->trans = len;
649
650 tasklet_init(&fifo->tasklet,
651 usbhsf_dma_prepare_tasklet,
652 (unsigned long)pkt);
653
654 tasklet_schedule(&fifo->tasklet);
655
656 return 0;
657
658usbhsf_pio_prepare_push_unmap:
659 usbhsf_dma_unmap(pkt);
660usbhsf_pio_prepare_push:
661 /*
662 * change handler to PIO
663 */
664 pkt->handler = &usbhs_fifo_pio_push_handler;
665
666 return pkt->handler->prepare(pkt, is_done);
667}
668
669static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done)
670{
671 struct usbhs_pipe *pipe = pkt->pipe;
672
673 pkt->actual = pkt->trans;
674
675 *is_done = !pkt->zero; /* send zero packet ? */
676
677 usbhsf_dma_stop(pipe, pipe->fifo);
678 usbhsf_dma_unmap(pkt);
679 usbhsf_fifo_unselect(pipe, pipe->fifo);
680
681 return 0;
682}
683
684struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = {
685 .prepare = usbhsf_dma_prepare_push,
686 .dma_done = usbhsf_dma_push_done,
687};
688
689static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
690{
691 struct usbhs_pipe *pipe = pkt->pipe;
692 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
693 struct usbhs_fifo *fifo;
694 int len, ret;
695
696 if (usbhs_pipe_is_busy(pipe))
697 return 0;
698
699 if (usbhs_pipe_is_dcp(pipe))
700 goto usbhsf_pio_prepare_pop;
701
702 /* get enable DMA fifo */
703 fifo = usbhsf_get_dma_fifo(priv, pkt);
704 if (!fifo)
705 goto usbhsf_pio_prepare_pop;
706
707 ret = usbhsf_fifo_select(pipe, fifo, 0);
708 if (ret < 0)
709 goto usbhsf_pio_prepare_pop;
710
711 /* use PIO if packet is less than pio_dma_border */
712 len = usbhsf_fifo_rcv_len(priv, fifo);
713 len = min(pkt->length - pkt->actual, len);
714 if (len % 4) /* 32bit alignment */
715 goto usbhsf_pio_prepare_pop_unselect;
716
717 if (len < usbhs_get_dparam(priv, pio_dma_border))
718 goto usbhsf_pio_prepare_pop_unselect;
719
720 ret = usbhsf_fifo_barrier(priv, fifo);
721 if (ret < 0)
722 goto usbhsf_pio_prepare_pop_unselect;
723
724 if (usbhsf_dma_map(pkt) < 0)
725 goto usbhsf_pio_prepare_pop_unselect;
726
727 /* DMA */
728
729 /*
730 * usbhs_fifo_dma_pop_handler :: prepare
731 * enabled irq to come here.
732 * but it is no longer needed for DMA. disable it.
733 */
734 usbhsf_rx_irq_ctrl(pipe, 0);
735
736 pkt->trans = len;
737
738 tasklet_init(&fifo->tasklet,
739 usbhsf_dma_prepare_tasklet,
740 (unsigned long)pkt);
741
742 tasklet_schedule(&fifo->tasklet);
743
744 return 0;
745
746usbhsf_pio_prepare_pop_unselect:
747 usbhsf_fifo_unselect(pipe, fifo);
748usbhsf_pio_prepare_pop:
749
750 /*
751 * change handler to PIO
752 */
753 pkt->handler = &usbhs_fifo_pio_pop_handler;
754
755 return pkt->handler->try_run(pkt, is_done);
756}
757
758static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
759{
760 struct usbhs_pipe *pipe = pkt->pipe;
761 int maxp = usbhs_pipe_get_maxpacket(pipe);
762
763 usbhsf_dma_stop(pipe, pipe->fifo);
764 usbhsf_dma_unmap(pkt);
765 usbhsf_fifo_unselect(pipe, pipe->fifo);
766
767 pkt->actual += pkt->trans;
768
769 if ((pkt->actual == pkt->length) || /* receive all data */
770 (pkt->trans < maxp)) { /* short packet */
771 *is_done = 1;
772 } else {
773 /* re-enable */
774 usbhsf_prepare_pop(pkt, is_done);
775 }
776
777 return 0;
778}
779
780struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = {
781 .prepare = usbhsf_prepare_pop,
782 .try_run = usbhsf_dma_try_pop,
783 .dma_done = usbhsf_dma_pop_done
784};
785
786/*
787 * DMA setting
788 */
789static bool usbhsf_dma_filter(struct dma_chan *chan, void *param)
790{
791 struct sh_dmae_slave *slave = param;
792
793 /*
794 * FIXME
795 *
796 * usbhs doesn't recognize id = 0 as valid DMA
797 */
798 if (0 == slave->slave_id)
799 return false;
800
801 chan->private = slave;
802
803 return true;
804}
805
806static void usbhsf_dma_quit(struct usbhs_priv *priv, struct usbhs_fifo *fifo)
807{
808 if (fifo->tx_chan)
809 dma_release_channel(fifo->tx_chan);
810 if (fifo->rx_chan)
811 dma_release_channel(fifo->rx_chan);
812
813 fifo->tx_chan = NULL;
814 fifo->rx_chan = NULL;
815}
816
817static void usbhsf_dma_init(struct usbhs_priv *priv,
818 struct usbhs_fifo *fifo)
819{
820 struct device *dev = usbhs_priv_to_dev(priv);
821 dma_cap_mask_t mask;
822
823 dma_cap_zero(mask);
824 dma_cap_set(DMA_SLAVE, mask);
825 fifo->tx_chan = dma_request_channel(mask, usbhsf_dma_filter,
826 &fifo->tx_slave);
827
828 dma_cap_zero(mask);
829 dma_cap_set(DMA_SLAVE, mask);
830 fifo->rx_chan = dma_request_channel(mask, usbhsf_dma_filter,
831 &fifo->rx_slave);
832
833 if (fifo->tx_chan || fifo->rx_chan)
834 dev_info(dev, "enable DMAEngine (%s%s%s)\n",
835 fifo->name,
836 fifo->tx_chan ? "[TX]" : " ",
837 fifo->rx_chan ? "[RX]" : " ");
838}
839
840/*
511 * irq functions 841 * irq functions
512 */ 842 */
513static int usbhsf_irq_empty(struct usbhs_priv *priv, 843static int usbhsf_irq_empty(struct usbhs_priv *priv,
@@ -570,6 +900,19 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv,
570 return 0; 900 return 0;
571} 901}
572 902
903static void usbhsf_dma_complete(void *arg)
904{
905 struct usbhs_pipe *pipe = arg;
906 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
907 struct device *dev = usbhs_priv_to_dev(priv);
908 int ret;
909
910 ret = usbhs_pkt_dmadone(pipe);
911 if (ret < 0)
912 dev_err(dev, "dma_complete run_error %d : %d\n",
913 usbhs_pipe_number(pipe), ret);
914}
915
573/* 916/*
574 * fifo init 917 * fifo init
575 */ 918 */
@@ -577,6 +920,8 @@ void usbhs_fifo_init(struct usbhs_priv *priv)
577{ 920{
578 struct usbhs_mod *mod = usbhs_mod_get_current(priv); 921 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
579 struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); 922 struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv);
923 struct usbhs_fifo *d0fifo = usbhsf_get_d0fifo(priv);
924 struct usbhs_fifo *d1fifo = usbhsf_get_d1fifo(priv);
580 925
581 mod->irq_empty = usbhsf_irq_empty; 926 mod->irq_empty = usbhsf_irq_empty;
582 mod->irq_ready = usbhsf_irq_ready; 927 mod->irq_ready = usbhsf_irq_ready;
@@ -584,6 +929,19 @@ void usbhs_fifo_init(struct usbhs_priv *priv)
584 mod->irq_brdysts = 0; 929 mod->irq_brdysts = 0;
585 930
586 cfifo->pipe = NULL; 931 cfifo->pipe = NULL;
932 cfifo->tx_chan = NULL;
933 cfifo->rx_chan = NULL;
934
935 d0fifo->pipe = NULL;
936 d0fifo->tx_chan = NULL;
937 d0fifo->rx_chan = NULL;
938
939 d1fifo->pipe = NULL;
940 d1fifo->tx_chan = NULL;
941 d1fifo->rx_chan = NULL;
942
943 usbhsf_dma_init(priv, usbhsf_get_d0fifo(priv));
944 usbhsf_dma_init(priv, usbhsf_get_d1fifo(priv));
587} 945}
588 946
589void usbhs_fifo_quit(struct usbhs_priv *priv) 947void usbhs_fifo_quit(struct usbhs_priv *priv)
@@ -594,6 +952,9 @@ void usbhs_fifo_quit(struct usbhs_priv *priv)
594 mod->irq_ready = NULL; 952 mod->irq_ready = NULL;
595 mod->irq_bempsts = 0; 953 mod->irq_bempsts = 0;
596 mod->irq_brdysts = 0; 954 mod->irq_brdysts = 0;
955
956 usbhsf_dma_quit(priv, usbhsf_get_d0fifo(priv));
957 usbhsf_dma_quit(priv, usbhsf_get_d1fifo(priv));
597} 958}
598 959
599int usbhs_fifo_probe(struct usbhs_priv *priv) 960int usbhs_fifo_probe(struct usbhs_priv *priv)
@@ -602,10 +963,29 @@ int usbhs_fifo_probe(struct usbhs_priv *priv)
602 963
603 /* CFIFO */ 964 /* CFIFO */
604 fifo = usbhsf_get_cfifo(priv); 965 fifo = usbhsf_get_cfifo(priv);
966 fifo->name = "CFIFO";
605 fifo->port = CFIFO; 967 fifo->port = CFIFO;
606 fifo->sel = CFIFOSEL; 968 fifo->sel = CFIFOSEL;
607 fifo->ctr = CFIFOCTR; 969 fifo->ctr = CFIFOCTR;
608 970
971 /* D0FIFO */
972 fifo = usbhsf_get_d0fifo(priv);
973 fifo->name = "D0FIFO";
974 fifo->port = D0FIFO;
975 fifo->sel = D0FIFOSEL;
976 fifo->ctr = D0FIFOCTR;
977 fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d0_tx_id);
978 fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d0_rx_id);
979
980 /* D1FIFO */
981 fifo = usbhsf_get_d1fifo(priv);
982 fifo->name = "D1FIFO";
983 fifo->port = D1FIFO;
984 fifo->sel = D1FIFOSEL;
985 fifo->ctr = D1FIFOCTR;
986 fifo->tx_slave.slave_id = usbhs_get_dparam(priv, d1_tx_id);
987 fifo->rx_slave.slave_id = usbhs_get_dparam(priv, d1_rx_id);
988
609 return 0; 989 return 0;
610} 990}
611 991
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index 94db269f84c2..ed6d8e56c13c 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -17,18 +17,33 @@
17#ifndef RENESAS_USB_FIFO_H 17#ifndef RENESAS_USB_FIFO_H
18#define RENESAS_USB_FIFO_H 18#define RENESAS_USB_FIFO_H
19 19
20#include <linux/interrupt.h>
21#include <linux/sh_dma.h>
22#include <asm/dma.h>
20#include "pipe.h" 23#include "pipe.h"
21 24
25#define DMA_ADDR_INVALID (~(dma_addr_t)0)
26
22struct usbhs_fifo { 27struct usbhs_fifo {
28 char *name;
23 u32 port; /* xFIFO */ 29 u32 port; /* xFIFO */
24 u32 sel; /* xFIFOSEL */ 30 u32 sel; /* xFIFOSEL */
25 u32 ctr; /* xFIFOCTR */ 31 u32 ctr; /* xFIFOCTR */
26 32
27 struct usbhs_pipe *pipe; 33 struct usbhs_pipe *pipe;
34 struct tasklet_struct tasklet;
35
36 struct dma_chan *tx_chan;
37 struct dma_chan *rx_chan;
38
39 struct sh_dmae_slave tx_slave;
40 struct sh_dmae_slave rx_slave;
28}; 41};
29 42
30struct usbhs_fifo_info { 43struct usbhs_fifo_info {
31 struct usbhs_fifo cfifo; 44 struct usbhs_fifo cfifo;
45 struct usbhs_fifo d0fifo;
46 struct usbhs_fifo d1fifo;
32}; 47};
33 48
34struct usbhs_pkt_handle; 49struct usbhs_pkt_handle;
@@ -36,8 +51,10 @@ struct usbhs_pkt {
36 struct list_head node; 51 struct list_head node;
37 struct usbhs_pipe *pipe; 52 struct usbhs_pipe *pipe;
38 struct usbhs_pkt_handle *handler; 53 struct usbhs_pkt_handle *handler;
54 dma_addr_t dma;
39 void *buf; 55 void *buf;
40 int length; 56 int length;
57 int trans;
41 int actual; 58 int actual;
42 int zero; 59 int zero;
43}; 60};
@@ -45,6 +62,7 @@ struct usbhs_pkt {
45struct usbhs_pkt_handle { 62struct usbhs_pkt_handle {
46 int (*prepare)(struct usbhs_pkt *pkt, int *is_done); 63 int (*prepare)(struct usbhs_pkt *pkt, int *is_done);
47 int (*try_run)(struct usbhs_pkt *pkt, int *is_done); 64 int (*try_run)(struct usbhs_pkt *pkt, int *is_done);
65 int (*dma_done)(struct usbhs_pkt *pkt, int *is_done);
48}; 66};
49 67
50/* 68/*
@@ -61,12 +79,17 @@ void usbhs_fifo_quit(struct usbhs_priv *priv);
61enum { 79enum {
62 USBHSF_PKT_PREPARE, 80 USBHSF_PKT_PREPARE,
63 USBHSF_PKT_TRY_RUN, 81 USBHSF_PKT_TRY_RUN,
82 USBHSF_PKT_DMA_DONE,
64}; 83};
65 84
66extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; 85extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler;
67extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; 86extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler;
68extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; 87extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler;
69 88
89extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler;
90extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler;
91
92
70void usbhs_pkt_init(struct usbhs_pkt *pkt); 93void usbhs_pkt_init(struct usbhs_pkt *pkt);
71void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, 94void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
72 struct usbhs_pkt_handle *handler, 95 struct usbhs_pkt_handle *handler,
@@ -76,5 +99,6 @@ int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type);
76 99
77#define usbhs_pkt_start(p) __usbhs_pkt_handler(p, USBHSF_PKT_PREPARE) 100#define usbhs_pkt_start(p) __usbhs_pkt_handler(p, USBHSF_PKT_PREPARE)
78#define usbhs_pkt_run(p) __usbhs_pkt_handler(p, USBHSF_PKT_TRY_RUN) 101#define usbhs_pkt_run(p) __usbhs_pkt_handler(p, USBHSF_PKT_TRY_RUN)
102#define usbhs_pkt_dmadone(p) __usbhs_pkt_handler(p, USBHSF_PKT_DMA_DONE)
79 103
80#endif /* RENESAS_USB_FIFO_H */ 104#endif /* RENESAS_USB_FIFO_H */
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 89d2b16fbb10..31d28dc78aa3 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -160,6 +160,71 @@ static void usbhsg_queue_done(struct usbhs_pkt *pkt)
160 usbhsg_queue_pop(uep, ureq, 0); 160 usbhsg_queue_pop(uep, ureq, 0);
161} 161}
162 162
163static int usbhsg_dma_map(struct device *dev,
164 struct usbhs_pkt *pkt,
165 enum dma_data_direction dir)
166{
167 struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
168 struct usb_request *req = &ureq->req;
169
170 if (pkt->dma != DMA_ADDR_INVALID) {
171 dev_err(dev, "dma is already mapped\n");
172 return -EIO;
173 }
174
175 if (req->dma == DMA_ADDR_INVALID) {
176 pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
177 } else {
178 dma_sync_single_for_device(dev, req->dma, req->length, dir);
179 pkt->dma = req->dma;
180 }
181
182 if (dma_mapping_error(dev, pkt->dma)) {
183 dev_err(dev, "dma mapping error %x\n", pkt->dma);
184 return -EIO;
185 }
186
187 return 0;
188}
189
190static int usbhsg_dma_unmap(struct device *dev,
191 struct usbhs_pkt *pkt,
192 enum dma_data_direction dir)
193{
194 struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
195 struct usb_request *req = &ureq->req;
196
197 if (pkt->dma == DMA_ADDR_INVALID) {
198 dev_err(dev, "dma is not mapped\n");
199 return -EIO;
200 }
201
202 if (req->dma == DMA_ADDR_INVALID)
203 dma_unmap_single(dev, pkt->dma, pkt->length, dir);
204 else
205 dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
206
207 pkt->dma = DMA_ADDR_INVALID;
208
209 return 0;
210}
211
212static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
213{
214 struct usbhs_pipe *pipe = pkt->pipe;
215 struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
216 struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
217 struct device *dev = usbhsg_gpriv_to_dev(gpriv);
218 enum dma_data_direction dir;
219
220 dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
221
222 if (map)
223 return usbhsg_dma_map(dev, pkt, dir);
224 else
225 return usbhsg_dma_unmap(dev, pkt, dir);
226}
227
163/* 228/*
164 * USB_TYPE_STANDARD / clear feature functions 229 * USB_TYPE_STANDARD / clear feature functions
165 */ 230 */
@@ -434,6 +499,8 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
434 499
435 usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); 500 usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
436 501
502 ureq->req.dma = DMA_ADDR_INVALID;
503
437 return &ureq->req; 504 return &ureq->req;
438} 505}
439 506
@@ -569,7 +636,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
569 * pipe initialize and enable DCP 636 * pipe initialize and enable DCP
570 */ 637 */
571 usbhs_pipe_init(priv, 638 usbhs_pipe_init(priv,
572 usbhsg_queue_done); 639 usbhsg_queue_done,
640 usbhsg_dma_map_ctrl);
573 usbhs_fifo_init(priv); 641 usbhs_fifo_init(priv);
574 usbhsg_uep_init(gpriv); 642 usbhsg_uep_init(gpriv);
575 643
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index c0505876fd8c..d0ae846632cd 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -532,7 +532,8 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
532} 532}
533 533
534void usbhs_pipe_init(struct usbhs_priv *priv, 534void usbhs_pipe_init(struct usbhs_priv *priv,
535 void (*done)(struct usbhs_pkt *pkt)) 535 void (*done)(struct usbhs_pkt *pkt),
536 int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
536{ 537{
537 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); 538 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
538 struct device *dev = usbhs_priv_to_dev(priv); 539 struct device *dev = usbhs_priv_to_dev(priv);
@@ -572,6 +573,7 @@ void usbhs_pipe_init(struct usbhs_priv *priv,
572 } 573 }
573 574
574 info->done = done; 575 info->done = done;
576 info->dma_map_ctrl = dma_map_ctrl;
575} 577}
576 578
577struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, 579struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h
index 484adbed6dfb..35e100477e55 100644
--- a/drivers/usb/renesas_usbhs/pipe.h
+++ b/drivers/usb/renesas_usbhs/pipe.h
@@ -44,6 +44,7 @@ struct usbhs_pipe_info {
44 int bufnmb_last; /* FIXME : driver needs good allocator */ 44 int bufnmb_last; /* FIXME : driver needs good allocator */
45 45
46 void (*done)(struct usbhs_pkt *pkt); 46 void (*done)(struct usbhs_pkt *pkt);
47 int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map);
47}; 48};
48 49
49/* 50/*
@@ -82,7 +83,8 @@ void usbhs_pipe_remove(struct usbhs_priv *priv);
82int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); 83int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
83int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); 84int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
84void usbhs_pipe_init(struct usbhs_priv *priv, 85void usbhs_pipe_init(struct usbhs_priv *priv,
85 void (*done)(struct usbhs_pkt *pkt)); 86 void (*done)(struct usbhs_pkt *pkt),
87 int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
86int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); 88int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
87void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); 89void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe);
88int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe); 90int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe);
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index 3a7f1d982dd6..8977431259c6 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -110,6 +110,23 @@ struct renesas_usbhs_driver_param {
110 * delay time from notify_hotplug callback 110 * delay time from notify_hotplug callback
111 */ 111 */
112 int detection_delay; 112 int detection_delay;
113
114 /*
115 * option:
116 *
117 * dma id for dmaengine
118 */
119 int d0_tx_id;
120 int d0_rx_id;
121 int d1_tx_id;
122 int d1_rx_id;
123
124 /*
125 * option:
126 *
127 * pio <--> dma border.
128 */
129 int pio_dma_border; /* default is 64byte */
113}; 130};
114 131
115/* 132/*