Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3af90a5 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Greg Kroah-Hartman
Browse files

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: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 97664a20
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -194,6 +194,11 @@ struct usbhs_priv {
	 * pipe control
	 */
	struct usbhs_pipe_info pipe_info;

	/*
	 * fifo control
	 */
	struct usbhs_fifo_info fifo_info;
};

/*
+52 −23
Original line number Diff line number Diff line
@@ -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)
{
}
+12 −0
Original line number Diff line number Diff line
@@ -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);