aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs/fifo.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-06-06 01:18:50 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 12:10:09 -0400
commitd77e3f4e1743834c7b4acb54004ffd7f57c82582 (patch)
tree5ef953674c897b32134578654bc679e41039bfa9 /drivers/usb/renesas_usbhs/fifo.c
parentd3af90a5e4e8fb7a93d408799682e566c9270808 (diff)
usb: renesas_usbhs: add pipe/fifo link
renesas_usbhs has CFIFO which is for PIO transfer, and D0FIFO/D1FIFO which are for DMA transfer. The pipe selects one of these fifo when it send/recv data. But fifo must not be selected to different pipe in same time. This patch add pipe/fifo link for each other, and fifo is not selected by another pipe until it is unselected. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/renesas_usbhs/fifo.c')
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 53e2b35dd32..8852423313a 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -21,6 +21,8 @@
21 21
22#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) 22#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
23 23
24#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */
25
24/* 26/*
25 * packet info function 27 * packet info function
26 */ 28 */
@@ -237,6 +239,15 @@ static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
237 return usbhs_read(priv, fifo->ctr) & DTLN_MASK; 239 return usbhs_read(priv, fifo->ctr) & DTLN_MASK;
238} 240}
239 241
242static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
243 struct usbhs_fifo *fifo)
244{
245 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
246
247 usbhs_pipe_select_fifo(pipe, NULL);
248 usbhs_write(priv, fifo->sel, 0);
249}
250
240static int usbhsf_fifo_select(struct usbhs_pipe *pipe, 251static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
241 struct usbhs_fifo *fifo, 252 struct usbhs_fifo *fifo,
242 int write) 253 int write)
@@ -247,6 +258,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
247 u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ 258 u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
248 u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ 259 u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
249 260
261 if (usbhs_pipe_is_busy(pipe) ||
262 usbhsf_fifo_is_busy(fifo))
263 return -EBUSY;
264
250 if (usbhs_pipe_is_dcp(pipe)) 265 if (usbhs_pipe_is_dcp(pipe))
251 base |= (1 == write) << 5; /* ISEL */ 266 base |= (1 == write) << 5; /* ISEL */
252 267
@@ -255,8 +270,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
255 270
256 /* check ISEL and CURPIPE value */ 271 /* check ISEL and CURPIPE value */
257 while (timeout--) { 272 while (timeout--) {
258 if (base == (mask & usbhs_read(priv, fifo->sel))) 273 if (base == (mask & usbhs_read(priv, fifo->sel))) {
274 usbhs_pipe_select_fifo(pipe, fifo);
259 return 0; 275 return 0;
276 }
260 udelay(10); 277 udelay(10);
261 } 278 }
262 279
@@ -283,7 +300,7 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
283 300
284 ret = usbhsf_fifo_select(pipe, fifo, 1); 301 ret = usbhsf_fifo_select(pipe, fifo, 1);
285 if (ret < 0) 302 if (ret < 0)
286 goto usbhs_fifo_write_busy; 303 return 0;
287 304
288 ret = usbhs_pipe_is_accessible(pipe); 305 ret = usbhs_pipe_is_accessible(pipe);
289 if (ret < 0) 306 if (ret < 0)
@@ -347,9 +364,13 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
347 usbhs_dcp_control_transfer_done(pipe); 364 usbhs_dcp_control_transfer_done(pipe);
348 } 365 }
349 366
367 usbhsf_fifo_unselect(pipe, fifo);
368
350 return 0; 369 return 0;
351 370
352usbhs_fifo_write_busy: 371usbhs_fifo_write_busy:
372 usbhsf_fifo_unselect(pipe, fifo);
373
353 /* 374 /*
354 * pipe is busy. 375 * pipe is busy.
355 * retry in interrupt 376 * retry in interrupt
@@ -367,16 +388,13 @@ struct usbhs_pkt_handle usbhs_fifo_push_handler = {
367static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) 388static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
368{ 389{
369 struct usbhs_pipe *pipe = pkt->pipe; 390 struct usbhs_pipe *pipe = pkt->pipe;
370 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); 391
371 struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ 392 if (usbhs_pipe_is_busy(pipe))
372 int ret; 393 return 0;
373 394
374 /* 395 /*
375 * select pipe and enable it to prepare packet receive 396 * pipe enable to prepare packet receive
376 */ 397 */
377 ret = usbhsf_fifo_select(pipe, fifo, 0);
378 if (ret < 0)
379 return ret;
380 398
381 usbhs_pipe_enable(pipe); 399 usbhs_pipe_enable(pipe);
382 usbhsf_rx_irq_ctrl(pipe, 1); 400 usbhsf_rx_irq_ctrl(pipe, 1);
@@ -400,11 +418,11 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
400 418
401 ret = usbhsf_fifo_select(pipe, fifo, 0); 419 ret = usbhsf_fifo_select(pipe, fifo, 0);
402 if (ret < 0) 420 if (ret < 0)
403 return ret; 421 return 0;
404 422
405 ret = usbhsf_fifo_barrier(priv, fifo); 423 ret = usbhsf_fifo_barrier(priv, fifo);
406 if (ret < 0) 424 if (ret < 0)
407 return ret; 425 goto usbhs_fifo_read_busy;
408 426
409 rcv_len = usbhsf_fifo_rcv_len(priv, fifo); 427 rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
410 428
@@ -457,7 +475,10 @@ usbhs_fifo_read_end:
457 usbhs_pipe_number(pipe), 475 usbhs_pipe_number(pipe),
458 pkt->length, pkt->actual, *is_done, pkt->zero); 476 pkt->length, pkt->actual, *is_done, pkt->zero);
459 477
460 return 0; 478usbhs_fifo_read_busy:
479 usbhsf_fifo_unselect(pipe, fifo);
480
481 return ret;
461} 482}
462 483
463struct usbhs_pkt_handle usbhs_fifo_pop_handler = { 484struct usbhs_pkt_handle usbhs_fifo_pop_handler = {
@@ -551,11 +572,14 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv,
551void usbhs_fifo_init(struct usbhs_priv *priv) 572void usbhs_fifo_init(struct usbhs_priv *priv)
552{ 573{
553 struct usbhs_mod *mod = usbhs_mod_get_current(priv); 574 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
575 struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv);
554 576
555 mod->irq_empty = usbhsf_irq_empty; 577 mod->irq_empty = usbhsf_irq_empty;
556 mod->irq_ready = usbhsf_irq_ready; 578 mod->irq_ready = usbhsf_irq_ready;
557 mod->irq_bempsts = 0; 579 mod->irq_bempsts = 0;
558 mod->irq_brdysts = 0; 580 mod->irq_brdysts = 0;
581
582 cfifo->pipe = NULL;
559} 583}
560 584
561void usbhs_fifo_quit(struct usbhs_priv *priv) 585void usbhs_fifo_quit(struct usbhs_priv *priv)