From 51b8a0218b885b5e527da776e20022273a838893 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 21:58:45 -0700 Subject: usb: gadget: renesas_usbhs: move USBHSF_PKT_xxx to pipe.c There is no longer necessity that USBHSF_PKT_xxx are in fifo.h. it are used in only fifo.c now. This patch move it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index a34430f55fb7..7eacacda8589 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -118,7 +118,13 @@ struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) return pkt; } -int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) +enum { + USBHSF_PKT_PREPARE, + USBHSF_PKT_TRY_RUN, + USBHSF_PKT_DMA_DONE, +}; + +static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); @@ -168,6 +174,11 @@ __usbhs_pkt_handler_end: return ret; } +void usbhs_pkt_start(struct usbhs_pipe *pipe) +{ + usbhsf_pkt_handler(pipe, USBHSF_PKT_PREPARE); +} + /* * irq enable/disable function */ @@ -884,7 +895,7 @@ static int usbhsf_irq_empty(struct usbhs_priv *priv, if (!(irq_state->bempsts & (1 << i))) continue; - ret = usbhs_pkt_run(pipe); + ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); if (ret < 0) dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); } @@ -914,7 +925,7 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv, if (!(irq_state->brdysts & (1 << i))) continue; - ret = usbhs_pkt_run(pipe); + ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_TRY_RUN); if (ret < 0) dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); } @@ -929,7 +940,7 @@ static void usbhsf_dma_complete(void *arg) struct device *dev = usbhs_priv_to_dev(priv); int ret; - ret = usbhs_pkt_dmadone(pipe); + ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE); if (ret < 0) dev_err(dev, "dma_complete run_error %d : %d\n", usbhs_pipe_number(pipe), ret); -- cgit v1.2.3 From 0c6ef985ced753b60ecdc091fa49c3f5fa4a4f79 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:00:59 -0700 Subject: usb: gadget: renesas_usbhs: struct usbhs_pipe hold handler packet handler had moved to struct usbhs_pipe from struct usbhsg_uep. it is preparation of mod_host support Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 12 ++++++++---- drivers/usb/renesas_usbhs/fifo.h | 1 - drivers/usb/renesas_usbhs/mod_gadget.c | 14 ++++++-------- drivers/usb/renesas_usbhs/pipe.h | 2 ++ 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 7eacacda8589..328238c373f6 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -54,7 +54,6 @@ static struct usbhs_pkt_handle usbhsf_null_handler = { }; void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, - struct usbhs_pkt_handle *handler, void *buf, int len, int zero) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); @@ -64,17 +63,22 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, /******************** spin lock ********************/ usbhs_lock(priv, flags); - if (!handler) { + if (!pipe->handler) { dev_err(dev, "no handler function\n"); - handler = &usbhsf_null_handler; + pipe->handler = &usbhsf_null_handler; } list_del_init(&pkt->node); list_add_tail(&pkt->node, &pipe->list); + /* + * each pkt must hold own handler. + * because handler might be changed by its situation. + * dma handler -> pio handler. + */ pkt->pipe = pipe; pkt->buf = buf; - pkt->handler = handler; + pkt->handler = pipe->handler; pkt->length = len; pkt->zero = zero; pkt->actual = 0; diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index 7a78440e7647..60aa20fd303e 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -86,7 +86,6 @@ extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, - struct usbhs_pkt_handle *handler, void *buf, int len, int zero); struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); void usbhs_pkt_start(struct usbhs_pipe *pipe); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 5a697b76ff12..babd90c979c1 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -39,7 +39,6 @@ struct usbhsg_uep { char ep_name[EP_NAME_SIZE]; struct usbhsg_gpriv *gpriv; - struct usbhs_pkt_handle *handler; }; struct usbhsg_gpriv { @@ -139,8 +138,7 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, req->actual = 0; req->status = -EINPROGRESS; - usbhs_pkt_push(pipe, pkt, uep->handler, - req->buf, req->length, req->zero); + usbhs_pkt_push(pipe, pkt, req->buf, req->length, req->zero); dev_dbg(dev, "pipe %d : queue push (%d)\n", usbhs_pipe_number(pipe), @@ -389,13 +387,13 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, switch (stage) { case READ_DATA_STAGE: - dcp->handler = &usbhs_fifo_pio_push_handler; + pipe->handler = &usbhs_fifo_pio_push_handler; break; case WRITE_DATA_STAGE: - dcp->handler = &usbhs_fifo_pio_pop_handler; + pipe->handler = &usbhs_fifo_pio_pop_handler; break; case NODATA_STATUS_STAGE: - dcp->handler = &usbhs_ctrl_stage_end_handler; + pipe->handler = &usbhs_ctrl_stage_end_handler; break; default: return ret; @@ -501,9 +499,9 @@ static int usbhsg_ep_enable(struct usb_ep *ep, * It will use pio handler if impossible. */ if (usb_endpoint_dir_in(desc)) - uep->handler = &usbhs_fifo_dma_push_handler; + pipe->handler = &usbhs_fifo_dma_push_handler; else - uep->handler = &usbhs_fifo_dma_pop_handler; + pipe->handler = &usbhs_fifo_dma_pop_handler; ret = 0; } diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 1baa1998c9a5..6760dff0b037 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -37,6 +37,8 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1) #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) + struct usbhs_pkt_handle *handler; + void *mod_private; }; -- cgit v1.2.3 From 923520715b5a698271f8763e97eee65e21d5561e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:02:57 -0700 Subject: usb: gadget: renesas_usbhs: add usbhs_dcp_dir_for_host() renesas_usbhs device needs special bit settings if it was mod_host and dcp pipe. This patch support it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 6 +++++- drivers/usb/renesas_usbhs/pipe.c | 6 ++++++ drivers/usb/renesas_usbhs/pipe.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 328238c373f6..b9ab8aefcae0 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -291,9 +291,13 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, usbhsf_fifo_is_busy(fifo)) return -EBUSY; - if (usbhs_pipe_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) { base |= (1 == write) << 5; /* ISEL */ + if (usbhs_mod_is_host(priv)) + usbhs_dcp_dir_for_host(pipe, write); + } + /* "base" will be used below */ usbhs_write(priv, fifo->sel, base | MBW_32); diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index ff97a8e4fcda..5238287dc2cb 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -630,6 +630,12 @@ void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) usbhsp_pipectrl_set(pipe, CCPL, CCPL); } +void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out) +{ + usbhsp_pipe_cfg_set(pipe, DIR_OUT, + dir_out ? DIR_OUT : 0); +} + /* * pipe module function */ diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 8120fad73b2d..6073a5c77740 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -106,5 +106,6 @@ void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 epnum, u16 maxp); */ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv); void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe); +void usbhs_dcp_dir_for_host(struct usbhs_pipe *pipe, int dir_out); #endif /* RENESAS_USB_PIPE_H */ -- cgit v1.2.3 From 2cc971978c0cabcd7760f4431270088cda72d8df Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:03:39 -0700 Subject: usb: gadget: renesas_usbhs: add struct usbhs_priv to packet done function There was no method to get struct usbhs_priv when packet transfer done function was called. This patch allow that callback function receive it. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 2 +- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- drivers/usb/renesas_usbhs/pipe.c | 3 ++- drivers/usb/renesas_usbhs/pipe.h | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index b9ab8aefcae0..9bf3a437ea0b 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -171,7 +171,7 @@ __usbhs_pkt_handler_end: /******************** spin unlock ******************/ if (is_done) { - info->done(pkt); + info->done(priv, pkt); usbhs_pkt_start(pipe); } diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index ae7d816c23d9..dd4ca37fbab3 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -159,7 +159,7 @@ static void usbhsg_queue_pop(struct usbhsg_uep *uep, ureq->req.complete(&uep->ep, &ureq->req); } -static void usbhsg_queue_done(struct usbhs_pkt *pkt) +static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) { struct usbhs_pipe *pipe = pkt->pipe; struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 5238287dc2cb..08d11b0cab43 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -497,7 +497,8 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) } void usbhs_pipe_init(struct usbhs_priv *priv, - void (*done)(struct usbhs_pkt *pkt), + void (*done)(struct usbhs_priv *priv, + struct usbhs_pkt *pkt), int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)) { struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 6073a5c77740..05b706a09e56 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -47,7 +47,7 @@ struct usbhs_pipe_info { int size; /* array size of "pipe" */ int bufnmb_last; /* FIXME : driver needs good allocator */ - void (*done)(struct usbhs_pkt *pkt); + void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); }; @@ -80,7 +80,8 @@ void usbhs_pipe_remove(struct usbhs_priv *priv); int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); void usbhs_pipe_init(struct usbhs_priv *priv, - void (*done)(struct usbhs_pkt *pkt), + void (*done)(struct usbhs_priv *priv, + struct usbhs_pkt *pkt), int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); -- cgit v1.2.3 From b331872b85c2ab388129af3343474e02e89498af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:04:41 -0700 Subject: usb: gadget: renesas_usbhs: move done callback to struct usbhs_pkt transfer done function was registered in struct struct usbhs_pipe_info. It was good for mod_gadget, but not good for mod_host. This function move it to struct usbhs_pkt. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 11 ++++++++-- drivers/usb/renesas_usbhs/fifo.h | 4 ++++ drivers/usb/renesas_usbhs/mod_gadget.c | 38 +++++++++++++++++----------------- drivers/usb/renesas_usbhs/pipe.c | 9 -------- drivers/usb/renesas_usbhs/pipe.h | 3 --- 5 files changed, 32 insertions(+), 33 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 9bf3a437ea0b..8b40726ba966 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -54,6 +54,8 @@ static struct usbhs_pkt_handle usbhsf_null_handler = { }; void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, + void (*done)(struct usbhs_priv *priv, + struct usbhs_pkt *pkt), void *buf, int len, int zero) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); @@ -63,6 +65,11 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, /******************** spin lock ********************/ usbhs_lock(priv, flags); + if (!done) { + dev_err(dev, "no done function\n"); + return; + } + if (!pipe->handler) { dev_err(dev, "no handler function\n"); pipe->handler = &usbhsf_null_handler; @@ -82,6 +89,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, pkt->length = len; pkt->zero = zero; pkt->actual = 0; + pkt->done = done; usbhs_unlock(priv, flags); /******************** spin unlock ******************/ @@ -131,7 +139,6 @@ enum { static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); - struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); struct usbhs_pkt *pkt; struct device *dev = usbhs_priv_to_dev(priv); int (*func)(struct usbhs_pkt *pkt, int *is_done); @@ -171,7 +178,7 @@ __usbhs_pkt_handler_end: /******************** spin unlock ******************/ if (is_done) { - info->done(priv, pkt); + pkt->done(priv, pkt); usbhs_pkt_start(pipe); } diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index 60aa20fd303e..0e82d67a0257 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -51,6 +51,8 @@ struct usbhs_pkt { struct list_head node; struct usbhs_pipe *pipe; struct usbhs_pkt_handle *handler; + void (*done)(struct usbhs_priv *priv, + struct usbhs_pkt *pkt); dma_addr_t dma; void *buf; int length; @@ -86,6 +88,8 @@ extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, + void (*done)(struct usbhs_priv *priv, + struct usbhs_pkt *pkt), void *buf, int len, int zero); struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt); void usbhs_pkt_start(struct usbhs_pipe *pipe); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index d5f80c4457e5..563128531e65 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -127,24 +127,6 @@ LIST_HEAD(the_controller_link); /* * queue push/pop */ -static void usbhsg_queue_push(struct usbhsg_uep *uep, - struct usbhsg_request *ureq) -{ - struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); - struct device *dev = usbhsg_gpriv_to_dev(gpriv); - struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); - struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); - struct usb_request *req = &ureq->req; - - req->actual = 0; - req->status = -EINPROGRESS; - usbhs_pkt_push(pipe, pkt, req->buf, req->length, req->zero); - - dev_dbg(dev, "pipe %d : queue push (%d)\n", - usbhs_pipe_number(pipe), - req->length); -} - static void usbhsg_queue_pop(struct usbhsg_uep *uep, struct usbhsg_request *ureq, int status) @@ -170,6 +152,25 @@ static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) usbhsg_queue_pop(uep, ureq, 0); } +static void usbhsg_queue_push(struct usbhsg_uep *uep, + struct usbhsg_request *ureq) +{ + struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); + struct device *dev = usbhsg_gpriv_to_dev(gpriv); + struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); + struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq); + struct usb_request *req = &ureq->req; + + req->actual = 0; + req->status = -EINPROGRESS; + usbhs_pkt_push(pipe, pkt, usbhsg_queue_done, + req->buf, req->length, req->zero); + + dev_dbg(dev, "pipe %d : queue push (%d)\n", + usbhs_pipe_number(pipe), + req->length); +} + /* * dma map/unmap */ @@ -664,7 +665,6 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) * pipe initialize and enable DCP */ usbhs_pipe_init(priv, - usbhsg_queue_done, usbhsg_dma_map_ctrl); usbhs_fifo_init(priv); usbhsg_uep_init(gpriv); diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 7636f2353b9d..6bc9e3327064 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -514,20 +514,12 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) } void usbhs_pipe_init(struct usbhs_priv *priv, - void (*done)(struct usbhs_priv *priv, - struct usbhs_pkt *pkt), int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)) { struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); - struct device *dev = usbhs_priv_to_dev(priv); struct usbhs_pipe *pipe; int i; - if (!done) { - dev_err(dev, "no done function\n"); - return; - } - /* * FIXME * @@ -554,7 +546,6 @@ void usbhs_pipe_init(struct usbhs_priv *priv, usbhs_pipe_clear(pipe); } - info->done = done; info->dma_map_ctrl = dma_map_ctrl; } diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 37018351f47c..ddbd3193c1fb 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -47,7 +47,6 @@ struct usbhs_pipe_info { int size; /* array size of "pipe" */ int bufnmb_last; /* FIXME : driver needs good allocator */ - void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map); }; @@ -81,8 +80,6 @@ void usbhs_pipe_remove(struct usbhs_priv *priv); int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe); int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe); void usbhs_pipe_init(struct usbhs_priv *priv, - void (*done)(struct usbhs_priv *priv, - struct usbhs_pkt *pkt), int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map)); int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe); void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe); -- cgit v1.2.3 From 654c35ab5e643aa7ff34fbc11315f4a6e3a3e1f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:04:53 -0700 Subject: usb: gadget: renesas_usbhs: disable auto paket start on usbhs_pkt_push() Automatically packet start by usbhs_pkt_push() was useful. But the pushed packet will be called twice if new packet was pushed on usbhs_pkt :: done callback. (1st is called by usbhs_pkt_push(), 2nd is called by usbhsf_pkt_handler()) This patch disables automatic packet start, and clarified packet start timing. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 2 -- drivers/usb/renesas_usbhs/mod_gadget.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 8b40726ba966..87f56b604809 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -93,8 +93,6 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, usbhs_unlock(priv, flags); /******************** spin unlock ******************/ - - usbhs_pkt_start(pipe); } static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 563128531e65..d3d833bce5f4 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -165,6 +165,7 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, req->status = -EINPROGRESS; usbhs_pkt_push(pipe, pkt, usbhsg_queue_done, req->buf, req->length, req->zero); + usbhs_pkt_start(pipe); dev_dbg(dev, "pipe %d : queue push (%d)\n", usbhs_pipe_number(pipe), -- cgit v1.2.3 From 6ff5d09bd2fd5943f5b16cb1e3453446a1f575e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:05:51 -0700 Subject: usb: gadget: renesas_usbhs: disable pipe on top of interrupt When data read interrupt happened, the pipe is BUF which means "enable". then, next un-necessary interrupt/token might be issued again when all data were popped from fifo. It will cause un-understandable bug. This patch decides pipe disable on top of read interrupt. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 87f56b604809..1a345c20105f 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -475,6 +475,20 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) len = min(len, rcv_len); total_len = len; + /* + * update actual length first here to decide disable pipe. + * if this pipe keeps BUF status and all data were popped, + * then, next interrupt/token will be issued again + */ + pkt->actual += total_len; + + if ((pkt->actual == pkt->length) || /* receive all data */ + (total_len < maxp)) { /* short packet */ + *is_done = 1; + usbhsf_rx_irq_ctrl(pipe, 0); + usbhs_pipe_disable(pipe); /* disable pipe first */ + } + /* * Buffer clear if Zero-Length packet * @@ -505,16 +519,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done) buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; } - pkt->actual += total_len; - usbhs_fifo_read_end: - if ((pkt->actual == pkt->length) || /* receive all data */ - (total_len < maxp)) { /* short packet */ - *is_done = 1; - usbhsf_rx_irq_ctrl(pipe, 0); - usbhs_pipe_disable(pipe); - } - dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", usbhs_pipe_number(pipe), pkt->length, pkt->actual, *is_done, pkt->zero); -- cgit v1.2.3 From 9e74d601de8adb0fe96e100e459ac52f2ddd47f3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:07:08 -0700 Subject: usb: gadget: renesas_usbhs: add data/status stage handler mod_host needs data/status stage handler Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 145 +++++++++++++++++++++++++++++++++++++++ drivers/usb/renesas_usbhs/fifo.h | 5 ++ 2 files changed, 150 insertions(+) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 1a345c20105f..16b12b09110a 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -320,6 +320,151 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, return -EIO; } +/* + * DCP status stage + */ +static int usbhs_dcp_dir_switch_to_write(struct usbhs_pkt *pkt, int *is_done) +{ + struct usbhs_pipe *pipe = pkt->pipe; + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ + struct device *dev = usbhs_priv_to_dev(priv); + int ret; + + usbhs_pipe_disable(pipe); + + ret = usbhsf_fifo_select(pipe, fifo, 1); + if (ret < 0) { + dev_err(dev, "%s() faile\n", __func__); + return ret; + } + + usbhs_pipe_sequence_data1(pipe); /* DATA1 */ + + usbhsf_fifo_clear(pipe, fifo); + usbhsf_send_terminator(pipe, fifo); + + usbhsf_fifo_unselect(pipe, fifo); + + usbhsf_tx_irq_ctrl(pipe, 1); + usbhs_pipe_enable(pipe); + + return ret; +} + +static int usbhs_dcp_dir_switch_to_read(struct usbhs_pkt *pkt, int *is_done) +{ + struct usbhs_pipe *pipe = pkt->pipe; + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ + struct device *dev = usbhs_priv_to_dev(priv); + int ret; + + usbhs_pipe_disable(pipe); + + ret = usbhsf_fifo_select(pipe, fifo, 0); + if (ret < 0) { + dev_err(dev, "%s() fail\n", __func__); + return ret; + } + + usbhs_pipe_sequence_data1(pipe); /* DATA1 */ + usbhsf_fifo_clear(pipe, fifo); + + usbhsf_fifo_unselect(pipe, fifo); + + usbhsf_rx_irq_ctrl(pipe, 1); + usbhs_pipe_enable(pipe); + + return ret; + +} + +static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) +{ + struct usbhs_pipe *pipe = pkt->pipe; + + if (pkt->handler == &usbhs_dcp_status_stage_in_handler) + usbhsf_tx_irq_ctrl(pipe, 0); + else + usbhsf_rx_irq_ctrl(pipe, 0); + + pkt->actual = pkt->length; + *is_done = 1; + + return 0; +} + +struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { + .prepare = usbhs_dcp_dir_switch_to_write, + .try_run = usbhs_dcp_dir_switch_done, +}; + +struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { + .prepare = usbhs_dcp_dir_switch_to_read, + .try_run = usbhs_dcp_dir_switch_done, +}; + +/* + * DCP data stage (push) + */ +static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) +{ + struct usbhs_pipe *pipe = pkt->pipe; + + usbhs_pipe_sequence_data1(pipe); /* DATA1 */ + + /* + * change handler to PIO push + */ + pkt->handler = &usbhs_fifo_pio_push_handler; + + return pkt->handler->prepare(pkt, is_done); +} + +struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { + .prepare = usbhsf_dcp_data_stage_try_push, +}; + +/* + * DCP data stage (pop) + */ +static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, + int *is_done) +{ + struct usbhs_pipe *pipe = pkt->pipe; + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); + + if (usbhs_pipe_is_busy(pipe)) + return 0; + + /* + * prepare pop for DCP should + * - change DCP direction, + * - clear fifo + * - DATA1 + */ + usbhs_pipe_disable(pipe); + + usbhs_pipe_sequence_data1(pipe); /* DATA1 */ + + usbhsf_fifo_select(pipe, fifo, 0); + usbhsf_fifo_clear(pipe, fifo); + usbhsf_fifo_unselect(pipe, fifo); + + /* + * change handler to PIO pop + */ + pkt->handler = &usbhs_fifo_pio_pop_handler; + + return pkt->handler->prepare(pkt, is_done); +} + +struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { + .prepare = usbhsf_dcp_data_stage_prepare_pop, +}; + /* * PIO push handler */ diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index 0e82d67a0257..32a7b246b28d 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -85,6 +85,11 @@ extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; +extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; +extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; + +extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; +extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, -- cgit v1.2.3 From 8a9775ab71218690ac34bed9e237e2b968857d3a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 13 Oct 2011 20:00:03 +0300 Subject: usb: gadget: renesas_usbhs: fix compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit | drivers/usb/renesas_usbhs/fifo.c: In function ‘usbhsf_dma_prepare_push’: | drivers/usb/renesas_usbhs/fifo.c:823:7: warning: cast from pointer \ to integer of different size [-Wpointer-to-int-cast] | drivers/usb/renesas_usbhs/fifo.c: In function ‘usbhsf_dma_try_pop’: | drivers/usb/renesas_usbhs/fifo.c:900:7: warning: cast from pointer \ to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 16b12b09110a..762b7429d8bb 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -820,7 +820,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) if (len % 4) /* 32bit alignment */ goto usbhsf_pio_prepare_push; - if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ + if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; /* get enable DMA fifo */ @@ -897,7 +897,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) if (!fifo) goto usbhsf_pio_prepare_pop; - if (((u32)pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ + if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_pop; ret = usbhsf_fifo_select(pipe, fifo, 0); -- cgit v1.2.3 From a2c76b83fdd763c826f38a55127ccf25708099ce Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 18 Oct 2011 20:05:50 -0700 Subject: usb: renesas_usbhs: fixup inconsistent return from usbhs_pkt_push() usbhs_pkt_push() had inconsistent return under spin lock. This patch fix it up. Special thanks to Dan Cc: Dan Carpenter Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/fifo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/renesas_usbhs/fifo.c') diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 762b7429d8bb..8da685e796d1 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -62,14 +62,14 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; - /******************** spin lock ********************/ - usbhs_lock(priv, flags); - if (!done) { dev_err(dev, "no done function\n"); return; } + /******************** spin lock ********************/ + usbhs_lock(priv, flags); + if (!pipe->handler) { dev_err(dev, "no handler function\n"); pipe->handler = &usbhsf_null_handler; -- cgit v1.2.3