summaryrefslogtreecommitdiff
path: root/drivers/usb/renesas_usbhs
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-06-06 14:18:44 +0900
committerGreg Kroah-Hartman <gregkh@suse.de>2011-06-07 09:10:09 -0700
commitd3af90a5e4e8fb7a93d408799682e566c9270808 (patch)
tree9eb60a7464d0f1eb380d65ff89239b0a5a044f77 /drivers/usb/renesas_usbhs
parent97664a207bc2601a03a300f00e6922038cd5b99c (diff)
usb: renesas_usbhs: add usbhsf_fifo
renesas_usbhs has CFIFO/D0FIFO/D1FIFO. But current renesas_usbhs is using CFIFO (for PIO) only for now. The fifo selection method is needed for DMAEngine support. This is a preparation for DMAEngine support 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')
-rw-r--r--drivers/usb/renesas_usbhs/common.c9
-rw-r--r--drivers/usb/renesas_usbhs/common.h5
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c75
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h12
4 files changed, 77 insertions, 24 deletions
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index f3664d6af661..e510b29216b3 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -323,10 +323,14 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
if (ret < 0)
goto probe_end_iounmap;
- ret = usbhs_mod_probe(priv);
+ ret = usbhs_fifo_probe(priv);
if (ret < 0)
goto probe_end_pipe_exit;
+ ret = usbhs_mod_probe(priv);
+ if (ret < 0)
+ goto probe_end_fifo_exit;
+
/* dev_set_drvdata should be called after usbhs_mod_init */
dev_set_drvdata(&pdev->dev, priv);
@@ -374,6 +378,8 @@ probe_end_call_remove:
usbhs_platform_call(priv, hardware_exit, pdev);
probe_end_mod_exit:
usbhs_mod_remove(priv);
+probe_end_fifo_exit:
+ usbhs_fifo_remove(priv);
probe_end_pipe_exit:
usbhs_pipe_remove(priv);
probe_end_iounmap:
@@ -404,6 +410,7 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
usbhs_platform_call(priv, hardware_exit, pdev);
usbhs_mod_remove(priv);
+ usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv);
iounmap(priv->base);
kfree(priv);
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index 7bf675c23a5e..06d7239a044d 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -194,6 +194,11 @@ struct usbhs_priv {
* pipe control
*/
struct usbhs_pipe_info pipe_info;
+
+ /*
+ * fifo control
+ */
+ struct usbhs_fifo_info fifo_info;
};
/*
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 3cda71e5a35a..53e2b35dd325 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -19,6 +19,8 @@
#include "./common.h"
#include "./pipe.h"
+#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
+
/*
* packet info function
*/
@@ -194,20 +196,22 @@ static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
/*
* FIFO ctrl
*/
-static void usbhsf_send_terminator(struct usbhs_pipe *pipe)
+static void usbhsf_send_terminator(struct usbhs_pipe *pipe,
+ struct usbhs_fifo *fifo)
{
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
- usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
+ usbhs_bset(priv, fifo->ctr, BVAL, BVAL);
}
-static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
+static int usbhsf_fifo_barrier(struct usbhs_priv *priv,
+ struct usbhs_fifo *fifo)
{
int timeout = 1024;
do {
/* The FIFO port is accessible */
- if (usbhs_read(priv, CFIFOCTR) & FRDY)
+ if (usbhs_read(priv, fifo->ctr) & FRDY)
return 0;
udelay(10);
@@ -216,22 +220,26 @@ static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
return -EBUSY;
}
-static void usbhsf_fifo_clear(struct usbhs_pipe *pipe)
+static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
+ struct usbhs_fifo *fifo)
{
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
if (!usbhs_pipe_is_dcp(pipe))
- usbhsf_fifo_barrier(priv);
+ usbhsf_fifo_barrier(priv, fifo);
- usbhs_write(priv, CFIFOCTR, BCLR);
+ usbhs_write(priv, fifo->ctr, BCLR);
}
-static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
+static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
+ struct usbhs_fifo *fifo)
{
- return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
+ return usbhs_read(priv, fifo->ctr) & DTLN_MASK;
}
-static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
+static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
+ struct usbhs_fifo *fifo,
+ int write)
{
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv);
@@ -243,11 +251,11 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
base |= (1 == write) << 5; /* ISEL */
/* "base" will be used below */
- usbhs_write(priv, CFIFOSEL, base | MBW_32);
+ usbhs_write(priv, fifo->sel, base | MBW_32);
/* check ISEL and CURPIPE value */
while (timeout--) {
- if (base == (mask & usbhs_read(priv, CFIFOSEL)))
+ if (base == (mask & usbhs_read(priv, fifo->sel)))
return 0;
udelay(10);
}
@@ -265,14 +273,15 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv);
- void __iomem *addr = priv->base + CFIFO;
+ struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+ void __iomem *addr = priv->base + fifo->port;
u8 *buf;
int maxp = usbhs_pipe_get_maxpacket(pipe);
int total_len;
int i, ret, len;
int is_short;
- ret = usbhsf_fifo_select(pipe, 1);
+ ret = usbhsf_fifo_select(pipe, fifo, 1);
if (ret < 0)
goto usbhs_fifo_write_busy;
@@ -280,7 +289,7 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
if (ret < 0)
goto usbhs_fifo_write_busy;
- ret = usbhsf_fifo_barrier(priv);
+ ret = usbhsf_fifo_barrier(priv, fifo);
if (ret < 0)
goto usbhs_fifo_write_busy;
@@ -321,7 +330,7 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
* pipe/irq handling
*/
if (is_short)
- usbhsf_send_terminator(pipe);
+ usbhsf_send_terminator(pipe, fifo);
usbhsf_tx_irq_ctrl(pipe, !*is_done);
usbhs_pipe_enable(pipe);
@@ -358,19 +367,21 @@ struct usbhs_pkt_handle usbhs_fifo_push_handler = {
static int usbhsf_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); /* CFIFO */
int ret;
/*
* select pipe and enable it to prepare packet receive
*/
- ret = usbhsf_fifo_select(pipe, 0);
+ ret = usbhsf_fifo_select(pipe, fifo, 0);
if (ret < 0)
return ret;
usbhs_pipe_enable(pipe);
usbhsf_rx_irq_ctrl(pipe, 1);
- return ret;
+ return 0;
}
static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
@@ -378,7 +389,8 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv);
- void __iomem *addr = priv->base + CFIFO;
+ struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */
+ void __iomem *addr = priv->base + fifo->port;
u8 *buf;
u32 data = 0;
int maxp = usbhs_pipe_get_maxpacket(pipe);
@@ -386,15 +398,15 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
int i, ret;
int total_len = 0;
- ret = usbhsf_fifo_select(pipe, 0);
+ ret = usbhsf_fifo_select(pipe, fifo, 0);
if (ret < 0)
return ret;
- ret = usbhsf_fifo_barrier(priv);
+ ret = usbhsf_fifo_barrier(priv, fifo);
if (ret < 0)
return ret;
- rcv_len = usbhsf_fifo_rcv_len(priv);
+ rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
buf = pkt->buf + pkt->actual;
len = pkt->length - pkt->actual;
@@ -408,7 +420,7 @@ static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done)
* "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
*/
if (0 == rcv_len) {
- usbhsf_fifo_clear(pipe);
+ usbhsf_fifo_clear(pipe, fifo);
goto usbhs_fifo_read_end;
}
@@ -555,3 +567,20 @@ void usbhs_fifo_quit(struct usbhs_priv *priv)
mod->irq_bempsts = 0;
mod->irq_brdysts = 0;
}
+
+int usbhs_fifo_probe(struct usbhs_priv *priv)
+{
+ struct usbhs_fifo *fifo;
+
+ /* CFIFO */
+ fifo = usbhsf_get_cfifo(priv);
+ fifo->port = CFIFO;
+ fifo->sel = CFIFOSEL;
+ fifo->ctr = CFIFOCTR;
+
+ return 0;
+}
+
+void usbhs_fifo_remove(struct usbhs_priv *priv)
+{
+}
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index fcb1ecef57da..04d000ae7bdc 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -19,6 +19,16 @@
#include "pipe.h"
+struct usbhs_fifo {
+ u32 port; /* xFIFO */
+ u32 sel; /* xFIFOSEL */
+ u32 ctr; /* xFIFOCTR */
+};
+
+struct usbhs_fifo_info {
+ struct usbhs_fifo cfifo;
+};
+
struct usbhs_pkt_handle;
struct usbhs_pkt {
struct list_head node;
@@ -38,6 +48,8 @@ struct usbhs_pkt_handle {
/*
* fifo
*/
+int usbhs_fifo_probe(struct usbhs_priv *priv);
+void usbhs_fifo_remove(struct usbhs_priv *priv);
void usbhs_fifo_init(struct usbhs_priv *priv);
void usbhs_fifo_quit(struct usbhs_priv *priv);