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_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
31 void *buf, int len, int zero)
33 list_del_init(&pkt->node);
34 list_add_tail(&pkt->node, &pipe->list);
43 void usbhs_pkt_pop(struct usbhs_pkt *pkt)
45 list_del_init(&pkt->node);
48 struct usbhs_pkt *usbhs_pkt_get(struct usbhs_pipe *pipe)
50 if (list_empty(&pipe->list))
53 return list_entry(pipe->list.next, struct usbhs_pkt, node);
57 * irq enable/disable function
59 #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
60 #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
61 #define usbhsf_irq_callback_ctrl(pipe, status, enable) \
63 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \
64 struct usbhs_mod *mod = usbhs_mod_get_current(priv); \
65 u16 status = (1 << usbhs_pipe_number(pipe)); \
69 mod->irq_##status |= status; \
71 mod->irq_##status &= ~status; \
72 usbhs_irq_callback_update(priv, mod); \
75 static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
78 * And DCP pipe can NOT use "ready interrupt" for "send"
79 * it should use "empty" interrupt.
81 * "Operation" - "Interrupt Function" - "BRDY Interrupt"
83 * on the other hand, normal pipe can use "ready interrupt" for "send"
84 * even though it is single/double buffer
86 if (usbhs_pipe_is_dcp(pipe))
87 usbhsf_irq_empty_ctrl(pipe, enable);
89 usbhsf_irq_ready_ctrl(pipe, enable);
92 static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable)
94 usbhsf_irq_ready_ctrl(pipe, enable);
100 static void usbhsf_send_terminator(struct usbhs_pipe *pipe)
102 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
104 usbhs_bset(priv, CFIFOCTR, BVAL, BVAL);
107 static int usbhsf_fifo_barrier(struct usbhs_priv *priv)
112 /* The FIFO port is accessible */
113 if (usbhs_read(priv, CFIFOCTR) & FRDY)
122 static void usbhsf_fifo_clear(struct usbhs_pipe *pipe)
124 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
126 if (!usbhs_pipe_is_dcp(pipe))
127 usbhsf_fifo_barrier(priv);
129 usbhs_write(priv, CFIFOCTR, BCLR);
132 static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv)
134 return usbhs_read(priv, CFIFOCTR) & DTLN_MASK;
137 static int usbhsf_fifo_select(struct usbhs_pipe *pipe, int write)
139 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
140 struct device *dev = usbhs_priv_to_dev(priv);
142 u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */
143 u16 base = usbhs_pipe_number(pipe); /* CURPIPE */
145 if (usbhs_pipe_is_dcp(pipe))
146 base |= (1 == write) << 5; /* ISEL */
148 /* "base" will be used below */
149 usbhs_write(priv, CFIFOSEL, base | MBW_32);
151 /* check ISEL and CURPIPE value */
153 if (base == (mask & usbhs_read(priv, CFIFOSEL)))
158 dev_err(dev, "fifo select error\n");
166 int usbhs_fifo_prepare_write(struct usbhs_pipe *pipe)
168 return usbhsf_fifo_select(pipe, 1);
171 int usbhs_fifo_write(struct usbhs_pkt *pkt)
173 struct usbhs_pipe *pipe = pkt->pipe;
174 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
175 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
176 struct device *dev = usbhs_priv_to_dev(priv);
177 void __iomem *addr = priv->base + CFIFO;
179 int maxp = usbhs_pipe_get_maxpacket(pipe);
182 int is_short, is_done;
184 ret = usbhs_pipe_is_accessible(pipe);
186 goto usbhs_fifo_write_busy;
188 ret = usbhsf_fifo_select(pipe, 1);
190 goto usbhs_fifo_write_busy;
192 ret = usbhsf_fifo_barrier(priv);
194 goto usbhs_fifo_write_busy;
196 buf = pkt->buf + pkt->actual;
197 len = pkt->length - pkt->actual;
198 len = min(len, maxp);
200 is_short = total_len < maxp;
207 if (len >= 4 && !((unsigned long)buf & 0x03)) {
208 iowrite32_rep(addr, buf, len / 4);
210 buf += total_len - len;
213 /* the rest operation */
214 for (i = 0; i < len; i++)
215 iowrite8(buf[i], addr + (0x03 - (i & 0x03)));
220 pkt->actual += total_len;
222 if (pkt->actual < pkt->length)
223 is_done = 0; /* there are remainder data */
225 is_done = 1; /* short packet */
227 is_done = !pkt->zero; /* send zero packet ? */
233 usbhsf_send_terminator(pipe);
235 usbhsf_tx_irq_ctrl(pipe, !is_done);
236 usbhs_pipe_enable(pipe);
238 dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
239 usbhs_pipe_number(pipe),
240 pkt->length, pkt->actual, is_done, pkt->zero);
246 if (usbhs_pipe_is_dcp(pipe))
247 usbhs_dcp_control_transfer_done(pipe);
255 usbhs_fifo_write_busy:
260 usbhsf_tx_irq_ctrl(pipe, 1);
265 int usbhs_fifo_prepare_read(struct usbhs_pipe *pipe)
270 * select pipe and enable it to prepare packet receive
272 ret = usbhsf_fifo_select(pipe, 0);
276 usbhs_pipe_enable(pipe);
277 usbhsf_rx_irq_ctrl(pipe, 1);
282 int usbhs_fifo_read(struct usbhs_pkt *pkt)
284 struct usbhs_pipe *pipe = pkt->pipe;
285 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
286 struct device *dev = usbhs_priv_to_dev(priv);
287 void __iomem *addr = priv->base + CFIFO;
290 int maxp = usbhs_pipe_get_maxpacket(pipe);
296 ret = usbhsf_fifo_select(pipe, 0);
300 ret = usbhsf_fifo_barrier(priv);
304 rcv_len = usbhsf_fifo_rcv_len(priv);
306 buf = pkt->buf + pkt->actual;
307 len = pkt->length - pkt->actual;
308 len = min(len, rcv_len);
312 * Buffer clear if Zero-Length packet
315 * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function"
318 usbhsf_fifo_clear(pipe);
319 goto usbhs_fifo_read_end;
327 if (len >= 4 && !((unsigned long)buf & 0x03)) {
328 ioread32_rep(addr, buf, len / 4);
330 buf += total_len - len;
333 /* the rest operation */
334 for (i = 0; i < len; i++) {
336 data = ioread32(addr);
338 buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
341 pkt->actual += total_len;
344 if ((pkt->actual == pkt->length) || /* receive all data */
345 (total_len < maxp)) /* short packet */
348 dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n",
349 usbhs_pipe_number(pipe),
350 pkt->length, pkt->actual, is_done, pkt->zero);
353 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
355 usbhsf_rx_irq_ctrl(pipe, 0);
356 usbhs_pipe_disable(pipe);