X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fusb%2Frenesas_usbhs%2Fpipe.c;h=56137d59e3b261d48490d26c4aa1261bef381924;hp=5897ddad05f23b7ab9748799ab9254530f4563c7;hb=dad67397f2090b29cd1f169e6a4ac6f3532c6858;hpb=8a1629c771b1a60bc6d73394d869fe69b13200dc diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 5897ddad05f2..56137d59e3b2 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -15,7 +15,6 @@ * */ #include -#include #include #include "./common.h" #include "./pipe.h" @@ -23,13 +22,8 @@ /* * macros */ -#define usbhsp_priv_to_pipeinfo(pr) (&(pr)->pipe_info) -#define usbhsp_pipe_to_priv(p) ((p)->priv) - #define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2) -#define usbhsp_is_dcp(p) ((p)->priv->pipe_info.pipe == (p)) - #define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f) #define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f) #define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f) @@ -77,10 +71,10 @@ void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req) */ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int offset = usbhsp_addr_offset(pipe); - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) usbhs_bset(priv, DCPCTR, mask, val); else usbhs_bset(priv, PIPEnCTR + offset, mask, val); @@ -88,10 +82,10 @@ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int offset = usbhsp_addr_offset(pipe); - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) return usbhs_read(priv, DCPCTR); else return usbhs_read(priv, PIPEnCTR + offset); @@ -104,9 +98,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, u16 dcp_reg, u16 pipe_reg, u16 mask, u16 val) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) usbhs_bset(priv, dcp_reg, mask, val); else usbhs_bset(priv, pipe_reg, mask, val); @@ -115,9 +109,9 @@ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, u16 dcp_reg, u16 pipe_reg) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) return usbhs_read(priv, dcp_reg); else return usbhs_read(priv, pipe_reg); @@ -136,7 +130,7 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val) */ static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) { - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) return; __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val); @@ -160,7 +154,7 @@ static u16 usbhsp_pipe_maxp_get(struct usbhs_pipe *pipe) */ static void usbhsp_pipe_select(struct usbhs_pipe *pipe) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); /* * On pipe, this is necessary before @@ -182,8 +176,7 @@ static void usbhsp_pipe_select(struct usbhs_pipe *pipe) static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - struct device *dev = usbhs_priv_to_dev(priv); + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int timeout = 1024; u16 val; @@ -206,6 +199,7 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) * - "Pipe Control Registers Switching Procedure" */ usbhs_write(priv, CFIFOSEL, 0); + usbhs_pipe_disable(pipe); do { val = usbhsp_pipectrl_get(pipe); @@ -217,25 +211,10 @@ static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe) } while (timeout--); - /* - * force NAK - */ - timeout = 1024; - usbhs_fifo_disable(pipe); - do { - val = usbhsp_pipectrl_get(pipe); - val &= PBUSY; - if (!val) - return 0; - - } while (timeout--); - - dev_err(dev, "pipe barrier failed\n"); - return -EBUSY; } -static int usbhsp_pipe_is_accessible(struct usbhs_pipe *pipe) +int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe) { u16 val; @@ -268,15 +247,27 @@ static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe) } } -void usbhs_fifo_disable(struct usbhs_pipe *pipe) +void usbhs_pipe_disable(struct usbhs_pipe *pipe) { + int timeout = 1024; + u16 val; + /* see "Pipe n Control Register" - "PID" */ __usbhsp_pid_try_nak_if_stall(pipe); usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK); + + do { + val = usbhsp_pipectrl_get(pipe); + val &= PBUSY; + if (!val) + break; + + udelay(10); + } while (timeout--); } -void usbhs_fifo_enable(struct usbhs_pipe *pipe) +void usbhs_pipe_enable(struct usbhs_pipe *pipe) { /* see "Pipe n Control Register" - "PID" */ __usbhsp_pid_try_nak_if_stall(pipe); @@ -284,7 +275,7 @@ void usbhs_fifo_enable(struct usbhs_pipe *pipe) usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF); } -void usbhs_fifo_stall(struct usbhs_pipe *pipe) +void usbhs_pipe_stall(struct usbhs_pipe *pipe) { u16 pid = usbhsp_pipectrl_get(pipe); @@ -304,191 +295,6 @@ void usbhs_fifo_stall(struct usbhs_pipe *pipe) } } -/* - * CFIFO ctrl - */ -void usbhs_fifo_send_terminator(struct usbhs_pipe *pipe) -{ - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - - usbhs_bset(priv, CFIFOCTR, BVAL, BVAL); -} - -static void usbhsp_fifo_clear(struct usbhs_pipe *pipe) -{ - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - - usbhs_write(priv, CFIFOCTR, BCLR); -} - -static int usbhsp_fifo_barrier(struct usbhs_priv *priv) -{ - int timeout = 1024; - - do { - /* The FIFO port is accessible */ - if (usbhs_read(priv, CFIFOCTR) & FRDY) - return 0; - - udelay(10); - } while (timeout--); - - return -EBUSY; -} - -static int usbhsp_fifo_rcv_len(struct usbhs_priv *priv) -{ - return usbhs_read(priv, CFIFOCTR) & DTLN_MASK; -} - -static int usbhsp_fifo_select(struct usbhs_pipe *pipe, int write) -{ - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - struct device *dev = usbhs_priv_to_dev(priv); - int timeout = 1024; - u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ - u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ - - if (usbhsp_is_dcp(pipe)) - base |= (1 == write) << 5; /* ISEL */ - - /* "base" will be used below */ - usbhs_write(priv, CFIFOSEL, base | MBW_32); - - /* check ISEL and CURPIPE value */ - while (timeout--) { - if (base == (mask & usbhs_read(priv, CFIFOSEL))) - return 0; - udelay(10); - } - - dev_err(dev, "fifo select error\n"); - - return -EIO; -} - -int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe) -{ - return usbhsp_fifo_select(pipe, 1); -} - -int usbhs_fifo_write(struct usbhs_pipe *pipe, u8 *buf, int len) -{ - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - void __iomem *addr = priv->base + CFIFO; - int maxp = usbhs_pipe_get_maxpacket(pipe); - int total_len; - int i, ret; - - ret = usbhsp_pipe_is_accessible(pipe); - if (ret < 0) - return ret; - - ret = usbhsp_fifo_select(pipe, 1); - if (ret < 0) - return ret; - - ret = usbhsp_fifo_barrier(priv); - if (ret < 0) - return ret; - - len = min(len, maxp); - total_len = len; - - /* - * FIXME - * - * 32-bit access only - */ - if (len >= 4 && - !((unsigned long)buf & 0x03)) { - iowrite32_rep(addr, buf, len / 4); - len %= 4; - buf += total_len - len; - } - - /* the rest operation */ - for (i = 0; i < len; i++) - iowrite8(buf[i], addr + (0x03 - (i & 0x03))); - - if (total_len < maxp) - usbhs_fifo_send_terminator(pipe); - - return total_len; -} - -int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe) -{ - int ret; - - /* - * select pipe and enable it to prepare packet receive - */ - ret = usbhsp_fifo_select(pipe, 0); - if (ret < 0) - return ret; - - usbhs_fifo_enable(pipe); - - return ret; -} - -int usbhs_fifo_read(struct usbhs_pipe *pipe, u8 *buf, int len) -{ - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - void __iomem *addr = priv->base + CFIFO; - int rcv_len; - int i, ret; - int total_len; - u32 data = 0; - - ret = usbhsp_fifo_select(pipe, 0); - if (ret < 0) - return ret; - - ret = usbhsp_fifo_barrier(priv); - if (ret < 0) - return ret; - - rcv_len = usbhsp_fifo_rcv_len(priv); - - /* - * Buffer clear if Zero-Length packet - * - * see - * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" - */ - if (0 == rcv_len) { - usbhsp_fifo_clear(pipe); - return 0; - } - - len = min(rcv_len, len); - total_len = len; - - /* - * FIXME - * - * 32-bit access only - */ - if (len >= 4 && - !((unsigned long)buf & 0x03)) { - ioread32_rep(addr, buf, len / 4); - len %= 4; - buf += rcv_len - len; - } - - /* the rest operation */ - for (i = 0; i < len; i++) { - if (!(i & 0x03)) - data = ioread32(addr); - - buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; - } - - return total_len; -} - /* * pipe setup */ @@ -522,7 +328,7 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, }; int is_double = usbhsp_possible_double_buffer(pipe); - if (usbhsp_is_dcp(pipe)) + if (usbhs_pipe_is_dcp(pipe)) return -EINVAL; /* @@ -553,12 +359,15 @@ static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe, /* DIR */ if (usb_endpoint_dir_in(desc)) - usbhsp_flags_set(pipe, IS_DIR_IN); + usbhsp_flags_set(pipe, IS_DIR_HOST); if ((is_host && usb_endpoint_dir_out(desc)) || (!is_host && usb_endpoint_dir_in(desc))) dir |= DIR_OUT; + if (!dir) + usbhsp_flags_set(pipe, IS_DIR_IN); + /* SHTNAK */ if (usbhsp_type_is(pipe, USB_ENDPOINT_XFER_BULK) && !dir) @@ -590,8 +399,8 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, const struct usb_endpoint_descriptor *desc, int is_host) { - struct usbhs_priv *priv = usbhsp_pipe_to_priv(pipe); - struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); + 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); int pipe_num = usbhs_pipe_number(pipe); int is_double = usbhsp_possible_double_buffer(pipe); @@ -669,7 +478,7 @@ static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe, */ int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe) { - u16 mask = usbhsp_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; + u16 mask = usbhs_pipe_is_dcp(pipe) ? DCP_MAXP_MASK : PIPE_MAXP_MASK; usbhsp_pipe_select(pipe); @@ -681,6 +490,11 @@ int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe) return usbhsp_flags_has(pipe, IS_DIR_IN); } +int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe) +{ + return usbhsp_flags_has(pipe, IS_DIR_HOST); +} + void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe) { usbhsp_pipectrl_set(pipe, SQCLR, SQCLR); @@ -717,12 +531,19 @@ static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type) return pipe; } -void usbhs_pipe_init(struct usbhs_priv *priv) +void usbhs_pipe_init(struct usbhs_priv *priv, + void (*done)(struct usbhs_pkt *pkt)) { - struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); + 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 * @@ -742,9 +563,14 @@ void usbhs_pipe_init(struct usbhs_priv *priv) usbhsp_flags_init(pipe); pipe->mod_private = NULL; + INIT_LIST_HEAD(&pipe->list); - usbhsp_fifo_clear(pipe); + /* pipe force init */ + usbhsp_pipectrl_set(pipe, ACLRM, ACLRM); + usbhsp_pipectrl_set(pipe, ACLRM, 0); } + + info->done = done; } struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, @@ -764,7 +590,9 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, return NULL; } - usbhs_fifo_disable(pipe); + INIT_LIST_HEAD(&pipe->list); + + usbhs_pipe_disable(pipe); /* make sure pipe is not busy */ ret = usbhsp_pipe_barrier(pipe); @@ -777,11 +605,6 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, pipebuf = usbhsp_setup_pipebuff(pipe, desc, is_host); pipemaxp = usbhsp_setup_pipemaxp(pipe, desc, is_host); - /* buffer clear - * see PIPECFG :: BFRE */ - usbhsp_pipectrl_set(pipe, ACLRM, ACLRM); - usbhsp_pipectrl_set(pipe, ACLRM, 0); - usbhsp_pipe_select(pipe); usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg); usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf); @@ -816,25 +639,25 @@ struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv) usbhsp_pipe_select(pipe); usbhs_pipe_clear_sequence(pipe); + INIT_LIST_HEAD(&pipe->list); return pipe; } void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe) { - WARN_ON(!usbhsp_is_dcp(pipe)); + WARN_ON(!usbhs_pipe_is_dcp(pipe)); - usbhs_fifo_enable(pipe); + usbhs_pipe_enable(pipe); usbhsp_pipectrl_set(pipe, CCPL, CCPL); } - /* * pipe module function */ int usbhs_pipe_probe(struct usbhs_priv *priv) { - struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); + struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); struct usbhs_pipe *pipe; struct device *dev = usbhs_priv_to_dev(priv); u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); @@ -871,7 +694,7 @@ int usbhs_pipe_probe(struct usbhs_priv *priv) void usbhs_pipe_remove(struct usbhs_priv *priv) { - struct usbhs_pipe_info *info = usbhsp_priv_to_pipeinfo(priv); + struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); kfree(info->pipe); }