/* * PIPEBUF */ static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val) { if (usbhs_pipe_is_dcp(pipe)) return; __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val); }
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, fifo); usbhs_write(priv, fifo->ctr, BCLR); }
static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int offset = usbhsp_addr_offset(pipe); if (usbhs_pipe_is_dcp(pipe)) return usbhs_read(priv, DCPCTR); else return usbhs_read(priv, PIPEnCTR + offset); }
/* * DCPCTR/PIPEnCTR functions */ static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); int offset = usbhsp_addr_offset(pipe); if (usbhs_pipe_is_dcp(pipe)) usbhs_bset(priv, DCPCTR, mask, val); else usbhs_bset(priv, PIPEnCTR + offset, mask, val); }
static u16 __usbhsp_pipe_xxx_get(struct usbhs_pipe *pipe, u16 dcp_reg, u16 pipe_reg) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); if (usbhs_pipe_is_dcp(pipe)) return usbhs_read(priv, dcp_reg); else return usbhs_read(priv, pipe_reg); }
/* * DCP/PIPE functions */ static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe, u16 dcp_reg, u16 pipe_reg, u16 mask, u16 val) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); if (usbhs_pipe_is_dcp(pipe)) usbhs_bset(priv, dcp_reg, mask, val); else usbhs_bset(priv, pipe_reg, mask, val); }
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 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); int timeout = 1024; u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ if (usbhs_pipe_is_busy(pipe) || usbhsf_fifo_is_busy(fifo)) return -EBUSY; if (usbhs_pipe_is_dcp(pipe)) { base |= (1 == write) << 5; /* ISEL */ if (usbhs_mod_is_host(priv)) usbhs_dcp_dir_for_host(pipe, write); } /* "base" will be used below */ if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo)) usbhs_write(priv, fifo->sel, base); else usbhs_write(priv, fifo->sel, base | MBW_32); /* check ISEL and CURPIPE value */ while (timeout--) { if (base == (mask & usbhs_read(priv, fifo->sel))) { usbhs_pipe_select_fifo(pipe, fifo); return 0; } udelay(10); } dev_err(dev, "fifo select error\n"); return -EIO; }