diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 72 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod.c | 5 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.c | 13 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.h | 4 |
4 files changed, 88 insertions, 6 deletions
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 4fd36530bfa3..b0c97a3f1bfe 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) | |||
108 | return list_first_entry(&pipe->list, struct usbhs_pkt, node); | 108 | return list_first_entry(&pipe->list, struct usbhs_pkt, node); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, | ||
112 | struct usbhs_fifo *fifo); | ||
113 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, | ||
114 | struct usbhs_fifo *fifo); | ||
115 | static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo, | ||
116 | struct usbhs_pkt *pkt); | ||
117 | #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) | ||
118 | #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) | ||
119 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map); | ||
111 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | 120 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
112 | { | 121 | { |
113 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 122 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
123 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); | ||
114 | unsigned long flags; | 124 | unsigned long flags; |
115 | 125 | ||
116 | /******************** spin lock ********************/ | 126 | /******************** spin lock ********************/ |
117 | usbhs_lock(priv, flags); | 127 | usbhs_lock(priv, flags); |
118 | 128 | ||
129 | usbhs_pipe_disable(pipe); | ||
130 | |||
119 | if (!pkt) | 131 | if (!pkt) |
120 | pkt = __usbhsf_pkt_get(pipe); | 132 | pkt = __usbhsf_pkt_get(pipe); |
121 | 133 | ||
122 | if (pkt) | 134 | if (pkt) { |
135 | struct dma_chan *chan = NULL; | ||
136 | |||
137 | if (fifo) | ||
138 | chan = usbhsf_dma_chan_get(fifo, pkt); | ||
139 | if (chan) { | ||
140 | dmaengine_terminate_all(chan); | ||
141 | usbhsf_fifo_clear(pipe, fifo); | ||
142 | usbhsf_dma_unmap(pkt); | ||
143 | } | ||
144 | |||
123 | __usbhsf_pkt_del(pkt); | 145 | __usbhsf_pkt_del(pkt); |
146 | } | ||
147 | |||
148 | if (fifo) | ||
149 | usbhsf_fifo_unselect(pipe, fifo); | ||
124 | 150 | ||
125 | usbhs_unlock(priv, flags); | 151 | usbhs_unlock(priv, flags); |
126 | /******************** spin unlock ******************/ | 152 | /******************** spin unlock ******************/ |
@@ -544,6 +570,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done) | |||
544 | usbhsf_send_terminator(pipe, fifo); | 570 | usbhsf_send_terminator(pipe, fifo); |
545 | 571 | ||
546 | usbhsf_tx_irq_ctrl(pipe, !*is_done); | 572 | usbhsf_tx_irq_ctrl(pipe, !*is_done); |
573 | usbhs_pipe_running(pipe, !*is_done); | ||
547 | usbhs_pipe_enable(pipe); | 574 | usbhs_pipe_enable(pipe); |
548 | 575 | ||
549 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", | 576 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", |
@@ -570,12 +597,21 @@ usbhs_fifo_write_busy: | |||
570 | * retry in interrupt | 597 | * retry in interrupt |
571 | */ | 598 | */ |
572 | usbhsf_tx_irq_ctrl(pipe, 1); | 599 | usbhsf_tx_irq_ctrl(pipe, 1); |
600 | usbhs_pipe_running(pipe, 1); | ||
573 | 601 | ||
574 | return ret; | 602 | return ret; |
575 | } | 603 | } |
576 | 604 | ||
605 | static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) | ||
606 | { | ||
607 | if (usbhs_pipe_is_running(pkt->pipe)) | ||
608 | return 0; | ||
609 | |||
610 | return usbhsf_pio_try_push(pkt, is_done); | ||
611 | } | ||
612 | |||
577 | struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { | 613 | struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { |
578 | .prepare = usbhsf_pio_try_push, | 614 | .prepare = usbhsf_pio_prepare_push, |
579 | .try_run = usbhsf_pio_try_push, | 615 | .try_run = usbhsf_pio_try_push, |
580 | }; | 616 | }; |
581 | 617 | ||
@@ -589,6 +625,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) | |||
589 | if (usbhs_pipe_is_busy(pipe)) | 625 | if (usbhs_pipe_is_busy(pipe)) |
590 | return 0; | 626 | return 0; |
591 | 627 | ||
628 | if (usbhs_pipe_is_running(pipe)) | ||
629 | return 0; | ||
630 | |||
592 | /* | 631 | /* |
593 | * pipe enable to prepare packet receive | 632 | * pipe enable to prepare packet receive |
594 | */ | 633 | */ |
@@ -597,6 +636,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) | |||
597 | 636 | ||
598 | usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); | 637 | usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length); |
599 | usbhs_pipe_enable(pipe); | 638 | usbhs_pipe_enable(pipe); |
639 | usbhs_pipe_running(pipe, 1); | ||
600 | usbhsf_rx_irq_ctrl(pipe, 1); | 640 | usbhsf_rx_irq_ctrl(pipe, 1); |
601 | 641 | ||
602 | return 0; | 642 | return 0; |
@@ -642,6 +682,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
642 | (total_len < maxp)) { /* short packet */ | 682 | (total_len < maxp)) { /* short packet */ |
643 | *is_done = 1; | 683 | *is_done = 1; |
644 | usbhsf_rx_irq_ctrl(pipe, 0); | 684 | usbhsf_rx_irq_ctrl(pipe, 0); |
685 | usbhs_pipe_running(pipe, 0); | ||
645 | usbhs_pipe_disable(pipe); /* disable pipe first */ | 686 | usbhs_pipe_disable(pipe); /* disable pipe first */ |
646 | } | 687 | } |
647 | 688 | ||
@@ -763,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe, | |||
763 | usbhs_bset(priv, fifo->sel, DREQE, dreqe); | 804 | usbhs_bset(priv, fifo->sel, DREQE, dreqe); |
764 | } | 805 | } |
765 | 806 | ||
766 | #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) | ||
767 | #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) | ||
768 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | 807 | static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) |
769 | { | 808 | { |
770 | struct usbhs_pipe *pipe = pkt->pipe; | 809 | struct usbhs_pipe *pipe = pkt->pipe; |
@@ -805,6 +844,7 @@ static void xfer_work(struct work_struct *work) | |||
805 | dev_dbg(dev, " %s %d (%d/ %d)\n", | 844 | dev_dbg(dev, " %s %d (%d/ %d)\n", |
806 | fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); | 845 | fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); |
807 | 846 | ||
847 | usbhs_pipe_running(pipe, 1); | ||
808 | usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); | 848 | usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); |
809 | usbhs_pipe_enable(pipe); | 849 | usbhs_pipe_enable(pipe); |
810 | usbhsf_dma_start(pipe, fifo); | 850 | usbhsf_dma_start(pipe, fifo); |
@@ -836,6 +876,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | |||
836 | if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ | 876 | if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ |
837 | goto usbhsf_pio_prepare_push; | 877 | goto usbhsf_pio_prepare_push; |
838 | 878 | ||
879 | /* return at this time if the pipe is running */ | ||
880 | if (usbhs_pipe_is_running(pipe)) | ||
881 | return 0; | ||
882 | |||
839 | /* get enable DMA fifo */ | 883 | /* get enable DMA fifo */ |
840 | fifo = usbhsf_get_dma_fifo(priv, pkt); | 884 | fifo = usbhsf_get_dma_fifo(priv, pkt); |
841 | if (!fifo) | 885 | if (!fifo) |
@@ -869,15 +913,29 @@ usbhsf_pio_prepare_push: | |||
869 | static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) | 913 | static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) |
870 | { | 914 | { |
871 | struct usbhs_pipe *pipe = pkt->pipe; | 915 | struct usbhs_pipe *pipe = pkt->pipe; |
916 | int is_short = pkt->trans % usbhs_pipe_get_maxpacket(pipe); | ||
917 | |||
918 | pkt->actual += pkt->trans; | ||
872 | 919 | ||
873 | pkt->actual = pkt->trans; | 920 | if (pkt->actual < pkt->length) |
921 | *is_done = 0; /* there are remainder data */ | ||
922 | else if (is_short) | ||
923 | *is_done = 1; /* short packet */ | ||
924 | else | ||
925 | *is_done = !pkt->zero; /* send zero packet? */ | ||
874 | 926 | ||
875 | *is_done = !pkt->zero; /* send zero packet ? */ | 927 | usbhs_pipe_running(pipe, !*is_done); |
876 | 928 | ||
877 | usbhsf_dma_stop(pipe, pipe->fifo); | 929 | usbhsf_dma_stop(pipe, pipe->fifo); |
878 | usbhsf_dma_unmap(pkt); | 930 | usbhsf_dma_unmap(pkt); |
879 | usbhsf_fifo_unselect(pipe, pipe->fifo); | 931 | usbhsf_fifo_unselect(pipe, pipe->fifo); |
880 | 932 | ||
933 | if (!*is_done) { | ||
934 | /* change handler to PIO */ | ||
935 | pkt->handler = &usbhs_fifo_pio_push_handler; | ||
936 | return pkt->handler->try_run(pkt, is_done); | ||
937 | } | ||
938 | |||
881 | return 0; | 939 | return 0; |
882 | } | 940 | } |
883 | 941 | ||
@@ -972,8 +1030,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) | |||
972 | if ((pkt->actual == pkt->length) || /* receive all data */ | 1030 | if ((pkt->actual == pkt->length) || /* receive all data */ |
973 | (pkt->trans < maxp)) { /* short packet */ | 1031 | (pkt->trans < maxp)) { /* short packet */ |
974 | *is_done = 1; | 1032 | *is_done = 1; |
1033 | usbhs_pipe_running(pipe, 0); | ||
975 | } else { | 1034 | } else { |
976 | /* re-enable */ | 1035 | /* re-enable */ |
1036 | usbhs_pipe_running(pipe, 0); | ||
977 | usbhsf_prepare_pop(pkt, is_done); | 1037 | usbhsf_prepare_pop(pkt, is_done); |
978 | } | 1038 | } |
979 | 1039 | ||
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 6a030b931a3b..9a705b15b3a1 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c | |||
@@ -213,7 +213,10 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, | |||
213 | { | 213 | { |
214 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 214 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
215 | u16 intenb0, intenb1; | 215 | u16 intenb0, intenb1; |
216 | unsigned long flags; | ||
216 | 217 | ||
218 | /******************** spin lock ********************/ | ||
219 | usbhs_lock(priv, flags); | ||
217 | state->intsts0 = usbhs_read(priv, INTSTS0); | 220 | state->intsts0 = usbhs_read(priv, INTSTS0); |
218 | state->intsts1 = usbhs_read(priv, INTSTS1); | 221 | state->intsts1 = usbhs_read(priv, INTSTS1); |
219 | 222 | ||
@@ -229,6 +232,8 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv, | |||
229 | state->bempsts &= mod->irq_bempsts; | 232 | state->bempsts &= mod->irq_bempsts; |
230 | state->brdysts &= mod->irq_brdysts; | 233 | state->brdysts &= mod->irq_brdysts; |
231 | } | 234 | } |
235 | usbhs_unlock(priv, flags); | ||
236 | /******************** spin unlock ******************/ | ||
232 | 237 | ||
233 | /* | 238 | /* |
234 | * Check whether the irq enable registers and the irq status are set | 239 | * Check whether the irq enable registers and the irq status are set |
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 75fbcf6b102e..040bcefcb040 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c | |||
@@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) | |||
578 | return usbhsp_flags_has(pipe, IS_DIR_HOST); | 578 | return usbhsp_flags_has(pipe, IS_DIR_HOST); |
579 | } | 579 | } |
580 | 580 | ||
581 | int usbhs_pipe_is_running(struct usbhs_pipe *pipe) | ||
582 | { | ||
583 | return usbhsp_flags_has(pipe, IS_RUNNING); | ||
584 | } | ||
585 | |||
586 | void usbhs_pipe_running(struct usbhs_pipe *pipe, int running) | ||
587 | { | ||
588 | if (running) | ||
589 | usbhsp_flags_set(pipe, IS_RUNNING); | ||
590 | else | ||
591 | usbhsp_flags_clr(pipe, IS_RUNNING); | ||
592 | } | ||
593 | |||
581 | void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence) | 594 | void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence) |
582 | { | 595 | { |
583 | u16 mask = (SQCLR | SQSET); | 596 | u16 mask = (SQCLR | SQSET); |
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 406f36d050e4..d24a05972370 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h | |||
@@ -36,6 +36,7 @@ struct usbhs_pipe { | |||
36 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) | 36 | #define USBHS_PIPE_FLAGS_IS_USED (1 << 0) |
37 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) | 37 | #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) |
38 | #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) | 38 | #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) |
39 | #define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) | ||
39 | 40 | ||
40 | struct usbhs_pkt_handle *handler; | 41 | struct usbhs_pkt_handle *handler; |
41 | 42 | ||
@@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv); | |||
80 | void usbhs_pipe_remove(struct usbhs_priv *priv); | 81 | void usbhs_pipe_remove(struct usbhs_priv *priv); |
81 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); | 82 | int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); |
82 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); | 83 | int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); |
84 | int usbhs_pipe_is_running(struct usbhs_pipe *pipe); | ||
85 | void usbhs_pipe_running(struct usbhs_pipe *pipe, int running); | ||
86 | |||
83 | void usbhs_pipe_init(struct usbhs_priv *priv, | 87 | void usbhs_pipe_init(struct usbhs_priv *priv, |
84 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); | 88 | int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); |
85 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); | 89 | int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); |