Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 259207
b: refs/heads/master
c: 659d495
h: refs/heads/master
i:
  259205: becf44f
  259203: 1c6ca78
  259199: d8610c7
v: v3
  • Loading branch information
Kuninori Morimoto authored and Greg Kroah-Hartman committed Jun 7, 2011
1 parent 7eeef28 commit 9b5d10e
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 164 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6acb95d4e0709a582023e87f9b3537fb4d837fd0
refs/heads/master: 659d495404d20ff8f96644fca82c772455f1226c
168 changes: 130 additions & 38 deletions trunk/drivers/usb/renesas_usbhs/fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,17 @@ void usbhs_pkt_init(struct usbhs_pkt *pkt)
INIT_LIST_HEAD(&pkt->node);
}

void usbhs_pkt_update(struct usbhs_pkt *pkt, void *buf, int len)
{
pkt->buf = buf;
pkt->length = len;
pkt->actual = 0;
pkt->maxp = 0;
}

void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
void *buf, int len, int zero)
{
list_del_init(&pkt->node);
list_add_tail(&pkt->node, &pipe->list);

pkt->pipe = pipe;
pkt->pipe = pipe;
pkt->buf = buf;
pkt->length = len;
pkt->zero = zero;
pkt->actual = 0;
}

void usbhs_pkt_pop(struct usbhs_pkt *pkt)
Expand All @@ -56,6 +53,47 @@ struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe)
return list_entry(pipe->list.next, struct usbhs_pkt, node);
}

/*
* irq enable/disable function
*/
#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
#define usbhsf_irq_callback_ctrl(pipe, status, enable) \
({ \
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \
struct usbhs_mod *mod = usbhs_mod_get_current(priv); \
u16 status = (1 << usbhs_pipe_number(pipe)); \
if (!mod) \
return; \
if (enable) \
mod->irq_##status |= status; \
else \
mod->irq_##status &= ~status; \
usbhs_irq_callback_update(priv, mod); \
})

static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
{
/*
* And DCP pipe can NOT use "ready interrupt" for "send"
* it should use "empty" interrupt.
* see
* "Operation" - "Interrupt Function" - "BRDY Interrupt"
*
* on the other hand, normal pipe can use "ready interrupt" for "send"
* even though it is single/double buffer
*/
if (usbhs_pipe_is_dcp(pipe))
usbhsf_irq_empty_ctrl(pipe, enable);
else
usbhsf_irq_ready_ctrl(pipe, enable);
}

static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
{
usbhsf_irq_ready_ctrl(pipe, enable);
}

/*
* FIFO ctrl
*/
Expand Down Expand Up @@ -135,34 +173,38 @@ int usbhs_fifo_write(struct usbhs_pkt *pkt)
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct device *dev = usbhs_priv_to_dev(priv);
void __iomem *addr = priv->base + CFIFO;
u8 *buf;
int maxp = usbhs_pipe_get_maxpacket(pipe);
int total_len;
u8 *buf = pkt->buf;
int i, ret, len;
int is_short, is_done;

ret = usbhs_pipe_is_accessible(pipe);
if (ret < 0)
return ret;
goto usbhs_fifo_write_busy;

ret = usbhsf_fifo_select(pipe, 1);
if (ret < 0)
return ret;
goto usbhs_fifo_write_busy;

ret = usbhsf_fifo_barrier(priv);
if (ret < 0)
return ret;
goto usbhs_fifo_write_busy;

len = min(pkt->length, maxp);
total_len = len;
buf = pkt->buf + pkt->actual;
len = pkt->length - pkt->actual;
len = min(len, maxp);
total_len = len;
is_short = total_len < maxp;

/*
* FIXME
*
* 32-bit access only
*/
if (len >= 4 &&
!((unsigned long)buf & 0x03)) {
if (len >= 4 && !((unsigned long)buf & 0x03)) {
iowrite32_rep(addr, buf, len / 4);
len %= 4;
buf += total_len - len;
Expand All @@ -172,19 +214,52 @@ int usbhs_fifo_write(struct usbhs_pkt *pkt)
for (i = 0; i < len; i++)
iowrite8(buf[i], addr + (0x03 - (i & 0x03)));

if (total_len < maxp)
/*
* variable update
*/
pkt->actual += total_len;

if (pkt->actual < pkt->length)
is_done = 0; /* there are remainder data */
else if (is_short)
is_done = 1; /* short packet */
else
is_done = !pkt->zero; /* send zero packet ? */

/*
* pipe/irq handling
*/
if (is_short)
usbhsf_send_terminator(pipe);

usbhsf_tx_irq_ctrl(pipe, !is_done);
usbhs_pipe_enable(pipe);

/* update pkt */
if (info->tx_done) {
pkt->actual = total_len;
pkt->maxp = maxp;
info->tx_done(pkt);
dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
usbhs_pipe_number(pipe),
pkt->length, pkt->actual, is_done, pkt->zero);

/*
* Transmission end
*/
if (is_done) {
if (usbhs_pipe_is_dcp(pipe))
usbhs_dcp_control_transfer_done(pipe);

if (info->tx_done)
info->tx_done(pkt);
}

return 0;

usbhs_fifo_write_busy:
/*
* pipe is busy.
* retry in interrupt
*/
usbhsf_tx_irq_ctrl(pipe, 1);

return ret;
}

int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
Expand All @@ -199,6 +274,7 @@ int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
return ret;

usbhs_pipe_enable(pipe);
usbhsf_rx_irq_ctrl(pipe, 1);

return ret;
}
Expand All @@ -207,13 +283,15 @@ int usbhs_fifo_read(struct usbhs_pkt *pkt)
{
struct usbhs_pipe *pipe = pkt->pipe;
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
struct device *dev = usbhs_priv_to_dev(priv);
void __iomem *addr = priv->base + CFIFO;
u8 *buf = pkt->buf;
u8 *buf;
u32 data = 0;
int maxp = usbhs_pipe_get_maxpacket(pipe);
int rcv_len, len;
int i, ret;
int total_len = 0;
u32 data = 0;
int is_done = 0;

ret = usbhsf_fifo_select(pipe, 0);
if (ret < 0)
Expand All @@ -225,6 +303,11 @@ int usbhs_fifo_read(struct usbhs_pkt *pkt)

rcv_len = usbhsf_fifo_rcv_len(priv);

buf = pkt->buf + pkt->actual;
len = pkt->length - pkt->actual;
len = min(len, rcv_len);
total_len = len;

/*
* Buffer clear if Zero-Length packet
*
Expand All @@ -236,19 +319,15 @@ int usbhs_fifo_read(struct usbhs_pkt *pkt)
goto usbhs_fifo_read_end;
}

len = min(rcv_len, pkt->length);
total_len = len;

/*
* FIXME
*
* 32-bit access only
*/
if (len >= 4 &&
!((unsigned long)buf & 0x03)) {
if (len >= 4 && !((unsigned long)buf & 0x03)) {
ioread32_rep(addr, buf, len / 4);
len %= 4;
buf += rcv_len - len;
buf += total_len - len;
}

/* the rest operation */
Expand All @@ -259,12 +338,25 @@ int usbhs_fifo_read(struct usbhs_pkt *pkt)
buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
}

pkt->actual += total_len;

usbhs_fifo_read_end:
if (info->rx_done) {
/* update pkt */
pkt->actual = total_len;
pkt->maxp = usbhs_pipe_get_maxpacket(pipe);
info->rx_done(pkt);
if ((pkt->actual == pkt->length) || /* receive all data */
(total_len < maxp)) /* short packet */
is_done = 1;

dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n",
usbhs_pipe_number(pipe),
pkt->length, pkt->actual, is_done, pkt->zero);

if (is_done) {
struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);

usbhsf_rx_irq_ctrl(pipe, 0);
usbhs_pipe_disable(pipe);

if (info->rx_done)
info->rx_done(pkt);
}

return 0;
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/usb/renesas_usbhs/fifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
struct usbhs_pkt {
struct list_head node;
struct usbhs_pipe *pipe;
int maxp;
void *buf;
int length;
int actual;
int zero;
};

/*
Expand All @@ -40,8 +40,8 @@ int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe);
* packet info
*/
void usbhs_pkt_init(struct usbhs_pkt *pkt);
void usbhs_pkt_update(struct usbhs_pkt *pkt, void *buf, int len);
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt);
void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
void *buf, int len, int zero);
void usbhs_pkt_pop(struct usbhs_pkt *pkt);
struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe);

Expand Down
Loading

0 comments on commit 9b5d10e

Please sign in to comment.