dect
/
linux-2.6
Archived
13
0
Fork 0

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>
This commit is contained in:
Kuninori Morimoto 2011-06-06 14:18:44 +09:00 committed by Greg Kroah-Hartman
parent 97664a207b
commit d3af90a5e4
4 changed files with 77 additions and 24 deletions

View File

@ -323,10 +323,14 @@ static int __devinit usbhs_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto probe_end_iounmap; goto probe_end_iounmap;
ret = usbhs_mod_probe(priv); ret = usbhs_fifo_probe(priv);
if (ret < 0) if (ret < 0)
goto probe_end_pipe_exit; 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 should be called after usbhs_mod_init */
dev_set_drvdata(&pdev->dev, priv); dev_set_drvdata(&pdev->dev, priv);
@ -374,6 +378,8 @@ probe_end_call_remove:
usbhs_platform_call(priv, hardware_exit, pdev); usbhs_platform_call(priv, hardware_exit, pdev);
probe_end_mod_exit: probe_end_mod_exit:
usbhs_mod_remove(priv); usbhs_mod_remove(priv);
probe_end_fifo_exit:
usbhs_fifo_remove(priv);
probe_end_pipe_exit: probe_end_pipe_exit:
usbhs_pipe_remove(priv); usbhs_pipe_remove(priv);
probe_end_iounmap: probe_end_iounmap:
@ -404,6 +410,7 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
usbhs_platform_call(priv, hardware_exit, pdev); usbhs_platform_call(priv, hardware_exit, pdev);
usbhs_mod_remove(priv); usbhs_mod_remove(priv);
usbhs_fifo_remove(priv);
usbhs_pipe_remove(priv); usbhs_pipe_remove(priv);
iounmap(priv->base); iounmap(priv->base);
kfree(priv); kfree(priv);

View File

@ -194,6 +194,11 @@ struct usbhs_priv {
* pipe control * pipe control
*/ */
struct usbhs_pipe_info pipe_info; struct usbhs_pipe_info pipe_info;
/*
* fifo control
*/
struct usbhs_fifo_info fifo_info;
}; };
/* /*

View File

@ -19,6 +19,8 @@
#include "./common.h" #include "./common.h"
#include "./pipe.h" #include "./pipe.h"
#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
/* /*
* packet info function * packet info function
*/ */
@ -194,20 +196,22 @@ static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
/* /*
* FIFO ctrl * 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); 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; int timeout = 1024;
do { do {
/* The FIFO port is accessible */ /* The FIFO port is accessible */
if (usbhs_read(priv, CFIFOCTR) & FRDY) if (usbhs_read(priv, fifo->ctr) & FRDY)
return 0; return 0;
udelay(10); udelay(10);
@ -216,22 +220,26 @@ static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
return -EBUSY; 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); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
if (!usbhs_pipe_is_dcp(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 usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv); 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 |= (1 == write) << 5; /* ISEL */
/* "base" will be used below */ /* "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 */ /* check ISEL and CURPIPE value */
while (timeout--) { while (timeout--) {
if (base == (mask & usbhs_read(priv, CFIFOSEL))) if (base == (mask & usbhs_read(priv, fifo->sel)))
return 0; return 0;
udelay(10); 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_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv); 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; u8 *buf;
int maxp = usbhs_pipe_get_maxpacket(pipe); int maxp = usbhs_pipe_get_maxpacket(pipe);
int total_len; int total_len;
int i, ret, len; int i, ret, len;
int is_short; int is_short;
ret = usbhsf_fifo_select(pipe, 1); ret = usbhsf_fifo_select(pipe, fifo, 1);
if (ret < 0) if (ret < 0)
goto usbhs_fifo_write_busy; goto usbhs_fifo_write_busy;
@ -280,7 +289,7 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
if (ret < 0) if (ret < 0)
goto usbhs_fifo_write_busy; goto usbhs_fifo_write_busy;
ret = usbhsf_fifo_barrier(priv); ret = usbhsf_fifo_barrier(priv, fifo);
if (ret < 0) if (ret < 0)
goto usbhs_fifo_write_busy; goto usbhs_fifo_write_busy;
@ -321,7 +330,7 @@ static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done)
* pipe/irq handling * pipe/irq handling
*/ */
if (is_short) if (is_short)
usbhsf_send_terminator(pipe); usbhsf_send_terminator(pipe, fifo);
usbhsf_tx_irq_ctrl(pipe, !*is_done); usbhsf_tx_irq_ctrl(pipe, !*is_done);
usbhs_pipe_enable(pipe); 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) static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
{ {
struct usbhs_pipe *pipe = pkt->pipe; 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; int ret;
/* /*
* select pipe and enable it to prepare packet receive * 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) if (ret < 0)
return ret; return ret;
usbhs_pipe_enable(pipe); usbhs_pipe_enable(pipe);
usbhsf_rx_irq_ctrl(pipe, 1); usbhsf_rx_irq_ctrl(pipe, 1);
return ret; return 0;
} }
static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done) 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_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv); 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; u8 *buf;
u32 data = 0; u32 data = 0;
int maxp = usbhs_pipe_get_maxpacket(pipe); 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 i, ret;
int total_len = 0; int total_len = 0;
ret = usbhsf_fifo_select(pipe, 0); ret = usbhsf_fifo_select(pipe, fifo, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = usbhsf_fifo_barrier(priv); ret = usbhsf_fifo_barrier(priv, fifo);
if (ret < 0) if (ret < 0)
return ret; return ret;
rcv_len = usbhsf_fifo_rcv_len(priv); rcv_len = usbhsf_fifo_rcv_len(priv, fifo);
buf = pkt->buf + pkt->actual; buf = pkt->buf + pkt->actual;
len = pkt->length - 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" * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
*/ */
if (0 == rcv_len) { if (0 == rcv_len) {
usbhsf_fifo_clear(pipe); usbhsf_fifo_clear(pipe, fifo);
goto usbhs_fifo_read_end; goto usbhs_fifo_read_end;
} }
@ -555,3 +567,20 @@ void usbhs_fifo_quit(struct usbhs_priv *priv)
mod->irq_bempsts = 0; mod->irq_bempsts = 0;
mod->irq_brdysts = 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)
{
}

View File

@ -19,6 +19,16 @@
#include "pipe.h" #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_handle;
struct usbhs_pkt { struct usbhs_pkt {
struct list_head node; struct list_head node;
@ -38,6 +48,8 @@ struct usbhs_pkt_handle {
/* /*
* fifo * 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_init(struct usbhs_priv *priv);
void usbhs_fifo_quit(struct usbhs_priv *priv); void usbhs_fifo_quit(struct usbhs_priv *priv);