4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 #include <linux/delay.h>
23 * packet info function
25 void usbhs_pkt_init(struct usbhs_pkt *pkt)
27 INIT_LIST_HEAD(&pkt->node);
30 void usbhs_pkt_update(struct usbhs_pkt *pkt, void *buf, int len)
38 void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
40 list_del_init(&pkt->node);
41 list_add_tail(&pkt->node, &pipe->list);
46 void usbhs_pkt_pop(struct usbhs_pkt *pkt)
48 list_del_init(&pkt->node);
51 struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe)
53 if (list_empty(&pipe->list))
56 return list_entry(pipe->list.next, struct usbhs_pkt, node);
62 static void usbhsf_send_terminator(struct usbhs_pipe *pipe)
64 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
66 usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
69 static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
74 /* The FIFO port is accessible */
75 if (usbhs_read(priv, CFIFOCTR) & FRDY)
84 static void usbhsf_fifo_clear(struct usbhs_pipe *pipe)
86 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
88 if (!usbhs_pipe_is_dcp(pipe))
89 usbhsf_fifo_barrier(priv);
91 usbhs_write(priv, CFIFOCTR, BCLR);
94 static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
96 return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
99 static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
101 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
102 struct device *dev = usbhs_priv_to_dev(priv);
104 u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
105 u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
107 if (usbhs_pipe_is_dcp(pipe))
108 base |= (1 == write) << 5; /* ISEL */
110 /* "base" will be used below */
111 usbhs_write(priv, CFIFOSEL, base | MBW_32);
113 /* check ISEL and CURPIPE value */
115 if (base == (mask & usbhs_read(priv, CFIFOSEL)))
120 dev_err(dev, "fifo select error\n");
128 int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
130 return usbhsf_fifo_select(pipe, 1);
133 int usbhs_fifo_write(struct usbhs_pkt *pkt)
135 struct usbhs_pipe *pipe = pkt->pipe;
136 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
137 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
138 void __iomem *addr = priv->base + CFIFO;
139 int maxp = usbhs_pipe_get_maxpacket(pipe);
144 ret = usbhs_pipe_is_accessible(pipe);
148 ret = usbhsf_fifo_select(pipe, 1);
152 ret = usbhsf_fifo_barrier(priv);
156 len = min(pkt->length, maxp);
165 !((unsigned long)buf & 0x03)) {
166 iowrite32_rep(addr, buf, len / 4);
168 buf += total_len - len;
171 /* the rest operation */
172 for (i = 0; i < len; i++)
173 iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
175 if (total_len < maxp)
176 usbhsf_send_terminator(pipe);
178 usbhs_pipe_enable(pipe);
182 pkt->actual = total_len;
190 int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
195 * select pipe and enable it to prepare packet receive
197 ret = usbhsf_fifo_select(pipe, 0);
201 usbhs_pipe_enable(pipe);
206 int usbhs_fifo_read(struct usbhs_pkt *pkt)
208 struct usbhs_pipe *pipe = pkt->pipe;
209 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
210 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
211 void __iomem *addr = priv->base + CFIFO;
218 ret = usbhsf_fifo_select(pipe, 0);
222 ret = usbhsf_fifo_barrier(priv);
226 rcv_len = usbhsf_fifo_rcv_len(priv);
229 * Buffer clear if Zero-Length packet
232 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
235 usbhsf_fifo_clear(pipe);
236 goto usbhs_fifo_read_end;
239 len = min(rcv_len, pkt->length);
248 !((unsigned long)buf & 0x03)) {
249 ioread32_rep(addr, buf, len / 4);
251 buf += rcv_len - len;
254 /* the rest operation */
255 for (i = 0; i < len; i++) {
257 data = ioread32(addr);
259 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
265 pkt->actual = total_len;
266 pkt->maxp = usbhs_pipe_get_maxpacket(pipe);