Commit | Line | Data |
---|---|---|
e8d548d5 KM |
1 | /* |
2 | * Renesas USB driver | |
3 | * | |
4 | * Copyright (C) 2011 Renesas Solutions Corp. | |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
6 | * | |
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. | |
11 | * | |
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 | |
15 | * | |
16 | */ | |
17 | #include <linux/delay.h> | |
18 | #include <linux/io.h> | |
19 | #include "./common.h" | |
20 | #include "./pipe.h" | |
21 | ||
d3af90a5 KM |
22 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) |
23 | ||
d77e3f4e KM |
24 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ |
25 | ||
4bd04811 KM |
26 | /* |
27 | * packet info function | |
28 | */ | |
97664a20 | 29 | static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) |
dad67397 KM |
30 | { |
31 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pkt->pipe); | |
32 | struct device *dev = usbhs_priv_to_dev(priv); | |
33 | ||
34 | dev_err(dev, "null handler\n"); | |
35 | ||
36 | return -EINVAL; | |
37 | } | |
38 | ||
39 | static struct usbhs_pkt_handle usbhsf_null_handler = { | |
40 | .prepare = usbhsf_null_handle, | |
41 | .try_run = usbhsf_null_handle, | |
42 | }; | |
43 | ||
6acb95d4 KM |
44 | void usbhs_pkt_init(struct usbhs_pkt *pkt) |
45 | { | |
46 | INIT_LIST_HEAD(&pkt->node); | |
47 | } | |
48 | ||
659d4954 | 49 | void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, |
dad67397 | 50 | struct usbhs_pkt_handle *handler, |
659d4954 | 51 | void *buf, int len, int zero) |
6acb95d4 | 52 | { |
dad67397 KM |
53 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
54 | struct device *dev = usbhs_priv_to_dev(priv); | |
97664a20 KM |
55 | unsigned long flags; |
56 | ||
57 | /******************** spin lock ********************/ | |
58 | usbhs_lock(priv, flags); | |
dad67397 KM |
59 | |
60 | if (!handler) { | |
61 | dev_err(dev, "no handler function\n"); | |
62 | handler = &usbhsf_null_handler; | |
63 | } | |
64 | ||
6acb95d4 KM |
65 | list_del_init(&pkt->node); |
66 | list_add_tail(&pkt->node, &pipe->list); | |
67 | ||
659d4954 KM |
68 | pkt->pipe = pipe; |
69 | pkt->buf = buf; | |
dad67397 | 70 | pkt->handler = handler; |
659d4954 KM |
71 | pkt->length = len; |
72 | pkt->zero = zero; | |
73 | pkt->actual = 0; | |
97664a20 KM |
74 | |
75 | usbhs_unlock(priv, flags); | |
76 | /******************** spin unlock ******************/ | |
0432eed0 KM |
77 | |
78 | usbhs_pkt_start(pipe); | |
6acb95d4 KM |
79 | } |
80 | ||
97664a20 | 81 | static void __usbhsf_pkt_del(struct usbhs_pkt *pkt) |
6acb95d4 KM |
82 | { |
83 | list_del_init(&pkt->node); | |
84 | } | |
85 | ||
97664a20 | 86 | static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) |
6acb95d4 KM |
87 | { |
88 | if (list_empty(&pipe->list)) | |
89 | return NULL; | |
90 | ||
91 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | |
92 | } | |
93 | ||
97664a20 KM |
94 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
95 | { | |
96 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
97 | unsigned long flags; | |
98 | ||
99 | /******************** spin lock ********************/ | |
100 | usbhs_lock(priv, flags); | |
101 | ||
102 | if (!pkt) | |
103 | pkt = __usbhsf_pkt_get(pipe); | |
104 | ||
105 | if (pkt) | |
106 | __usbhsf_pkt_del(pkt); | |
107 | ||
108 | usbhs_unlock(priv, flags); | |
109 | /******************** spin unlock ******************/ | |
110 | ||
111 | return pkt; | |
112 | } | |
113 | ||
114 | int __usbhs_pkt_handler(struct usbhs_pipe *pipe, int type) | |
115 | { | |
116 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
117 | struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv); | |
118 | struct usbhs_pkt *pkt; | |
119 | struct device *dev = usbhs_priv_to_dev(priv); | |
120 | int (*func)(struct usbhs_pkt *pkt, int *is_done); | |
121 | unsigned long flags; | |
122 | int ret = 0; | |
123 | int is_done = 0; | |
124 | ||
125 | /******************** spin lock ********************/ | |
126 | usbhs_lock(priv, flags); | |
127 | ||
128 | pkt = __usbhsf_pkt_get(pipe); | |
129 | if (!pkt) | |
130 | goto __usbhs_pkt_handler_end; | |
131 | ||
132 | switch (type) { | |
133 | case USBHSF_PKT_PREPARE: | |
134 | func = pkt->handler->prepare; | |
135 | break; | |
136 | case USBHSF_PKT_TRY_RUN: | |
137 | func = pkt->handler->try_run; | |
138 | break; | |
139 | default: | |
140 | dev_err(dev, "unknown pkt hander\n"); | |
141 | goto __usbhs_pkt_handler_end; | |
142 | } | |
143 | ||
144 | ret = func(pkt, &is_done); | |
145 | ||
146 | if (is_done) | |
147 | __usbhsf_pkt_del(pkt); | |
148 | ||
149 | __usbhs_pkt_handler_end: | |
150 | usbhs_unlock(priv, flags); | |
151 | /******************** spin unlock ******************/ | |
152 | ||
0432eed0 | 153 | if (is_done) { |
97664a20 | 154 | info->done(pkt); |
0432eed0 KM |
155 | usbhs_pkt_start(pipe); |
156 | } | |
97664a20 KM |
157 | |
158 | return ret; | |
159 | } | |
160 | ||
659d4954 KM |
161 | /* |
162 | * irq enable/disable function | |
163 | */ | |
164 | #define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e) | |
165 | #define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e) | |
166 | #define usbhsf_irq_callback_ctrl(pipe, status, enable) \ | |
167 | ({ \ | |
168 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \ | |
169 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); \ | |
170 | u16 status = (1 << usbhs_pipe_number(pipe)); \ | |
171 | if (!mod) \ | |
172 | return; \ | |
173 | if (enable) \ | |
174 | mod->irq_##status |= status; \ | |
175 | else \ | |
176 | mod->irq_##status &= ~status; \ | |
177 | usbhs_irq_callback_update(priv, mod); \ | |
178 | }) | |
179 | ||
180 | static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | |
181 | { | |
182 | /* | |
183 | * And DCP pipe can NOT use "ready interrupt" for "send" | |
184 | * it should use "empty" interrupt. | |
185 | * see | |
186 | * "Operation" - "Interrupt Function" - "BRDY Interrupt" | |
187 | * | |
188 | * on the other hand, normal pipe can use "ready interrupt" for "send" | |
189 | * even though it is single/double buffer | |
190 | */ | |
191 | if (usbhs_pipe_is_dcp(pipe)) | |
192 | usbhsf_irq_empty_ctrl(pipe, enable); | |
193 | else | |
194 | usbhsf_irq_ready_ctrl(pipe, enable); | |
195 | } | |
196 | ||
197 | static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable) | |
198 | { | |
199 | usbhsf_irq_ready_ctrl(pipe, enable); | |
200 | } | |
201 | ||
e8d548d5 KM |
202 | /* |
203 | * FIFO ctrl | |
204 | */ | |
d3af90a5 KM |
205 | static void usbhsf_send_terminator(struct usbhs_pipe *pipe, |
206 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
207 | { |
208 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
209 | ||
d3af90a5 | 210 | usbhs_bset(priv, fifo->ctr, BVAL, BVAL); |
e8d548d5 KM |
211 | } |
212 | ||
d3af90a5 KM |
213 | static int usbhsf_fifo_barrier(struct usbhs_priv *priv, |
214 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
215 | { |
216 | int timeout = 1024; | |
217 | ||
218 | do { | |
219 | /* The FIFO port is accessible */ | |
d3af90a5 | 220 | if (usbhs_read(priv, fifo->ctr) & FRDY) |
e8d548d5 KM |
221 | return 0; |
222 | ||
223 | udelay(10); | |
224 | } while (timeout--); | |
225 | ||
226 | return -EBUSY; | |
227 | } | |
228 | ||
d3af90a5 KM |
229 | static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, |
230 | struct usbhs_fifo *fifo) | |
e8d548d5 KM |
231 | { |
232 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
233 | ||
234 | if (!usbhs_pipe_is_dcp(pipe)) | |
d3af90a5 | 235 | usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 236 | |
d3af90a5 | 237 | usbhs_write(priv, fifo->ctr, BCLR); |
e8d548d5 KM |
238 | } |
239 | ||
d3af90a5 KM |
240 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, |
241 | struct usbhs_fifo *fifo) | |
e8d548d5 | 242 | { |
d3af90a5 | 243 | return usbhs_read(priv, fifo->ctr) & DTLN_MASK; |
e8d548d5 KM |
244 | } |
245 | ||
d77e3f4e KM |
246 | static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe, |
247 | struct usbhs_fifo *fifo) | |
248 | { | |
249 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
250 | ||
251 | usbhs_pipe_select_fifo(pipe, NULL); | |
252 | usbhs_write(priv, fifo->sel, 0); | |
253 | } | |
254 | ||
d3af90a5 KM |
255 | static int usbhsf_fifo_select(struct usbhs_pipe *pipe, |
256 | struct usbhs_fifo *fifo, | |
257 | int write) | |
e8d548d5 KM |
258 | { |
259 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | |
260 | struct device *dev = usbhs_priv_to_dev(priv); | |
261 | int timeout = 1024; | |
262 | u16 mask = ((1 << 5) | 0xF); /* mask of ISEL | CURPIPE */ | |
263 | u16 base = usbhs_pipe_number(pipe); /* CURPIPE */ | |
264 | ||
d77e3f4e KM |
265 | if (usbhs_pipe_is_busy(pipe) || |
266 | usbhsf_fifo_is_busy(fifo)) | |
267 | return -EBUSY; | |
268 | ||
e8d548d5 KM |
269 | if (usbhs_pipe_is_dcp(pipe)) |
270 | base |= (1 == write) << 5; /* ISEL */ | |
271 | ||
272 | /* "base" will be used below */ | |
d3af90a5 | 273 | usbhs_write(priv, fifo->sel, base | MBW_32); |
e8d548d5 KM |
274 | |
275 | /* check ISEL and CURPIPE value */ | |
276 | while (timeout--) { | |
d77e3f4e KM |
277 | if (base == (mask & usbhs_read(priv, fifo->sel))) { |
278 | usbhs_pipe_select_fifo(pipe, fifo); | |
e8d548d5 | 279 | return 0; |
d77e3f4e | 280 | } |
e8d548d5 KM |
281 | udelay(10); |
282 | } | |
283 | ||
284 | dev_err(dev, "fifo select error\n"); | |
285 | ||
286 | return -EIO; | |
287 | } | |
288 | ||
289 | /* | |
290 | * PIO fifo functions | |
291 | */ | |
97664a20 | 292 | static int usbhsf_try_push(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 293 | { |
4bd04811 | 294 | struct usbhs_pipe *pipe = pkt->pipe; |
e8d548d5 | 295 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
659d4954 | 296 | struct device *dev = usbhs_priv_to_dev(priv); |
d3af90a5 KM |
297 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
298 | void __iomem *addr = priv->base + fifo->port; | |
659d4954 | 299 | u8 *buf; |
e8d548d5 KM |
300 | int maxp = usbhs_pipe_get_maxpacket(pipe); |
301 | int total_len; | |
4bd04811 | 302 | int i, ret, len; |
97664a20 | 303 | int is_short; |
e8d548d5 | 304 | |
d3af90a5 | 305 | ret = usbhsf_fifo_select(pipe, fifo, 1); |
e8d548d5 | 306 | if (ret < 0) |
d77e3f4e | 307 | return 0; |
e8d548d5 | 308 | |
dad67397 | 309 | ret = usbhs_pipe_is_accessible(pipe); |
e8d548d5 | 310 | if (ret < 0) |
659d4954 | 311 | goto usbhs_fifo_write_busy; |
e8d548d5 | 312 | |
d3af90a5 | 313 | ret = usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 314 | if (ret < 0) |
659d4954 | 315 | goto usbhs_fifo_write_busy; |
e8d548d5 | 316 | |
659d4954 KM |
317 | buf = pkt->buf + pkt->actual; |
318 | len = pkt->length - pkt->actual; | |
319 | len = min(len, maxp); | |
320 | total_len = len; | |
321 | is_short = total_len < maxp; | |
e8d548d5 KM |
322 | |
323 | /* | |
324 | * FIXME | |
325 | * | |
326 | * 32-bit access only | |
327 | */ | |
659d4954 | 328 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
e8d548d5 KM |
329 | iowrite32_rep(addr, buf, len / 4); |
330 | len %= 4; | |
331 | buf += total_len - len; | |
332 | } | |
333 | ||
334 | /* the rest operation */ | |
335 | for (i = 0; i < len; i++) | |
336 | iowrite8(buf[i], addr + (0x03 - (i & 0x03))); | |
337 | ||
659d4954 KM |
338 | /* |
339 | * variable update | |
340 | */ | |
341 | pkt->actual += total_len; | |
342 | ||
343 | if (pkt->actual < pkt->length) | |
97664a20 | 344 | *is_done = 0; /* there are remainder data */ |
659d4954 | 345 | else if (is_short) |
97664a20 | 346 | *is_done = 1; /* short packet */ |
659d4954 | 347 | else |
97664a20 | 348 | *is_done = !pkt->zero; /* send zero packet ? */ |
659d4954 KM |
349 | |
350 | /* | |
351 | * pipe/irq handling | |
352 | */ | |
353 | if (is_short) | |
d3af90a5 | 354 | usbhsf_send_terminator(pipe, fifo); |
e8d548d5 | 355 | |
97664a20 | 356 | usbhsf_tx_irq_ctrl(pipe, !*is_done); |
4bd04811 KM |
357 | usbhs_pipe_enable(pipe); |
358 | ||
659d4954 KM |
359 | dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", |
360 | usbhs_pipe_number(pipe), | |
97664a20 | 361 | pkt->length, pkt->actual, *is_done, pkt->zero); |
659d4954 KM |
362 | |
363 | /* | |
364 | * Transmission end | |
365 | */ | |
97664a20 | 366 | if (*is_done) { |
659d4954 KM |
367 | if (usbhs_pipe_is_dcp(pipe)) |
368 | usbhs_dcp_control_transfer_done(pipe); | |
4bd04811 KM |
369 | } |
370 | ||
d77e3f4e KM |
371 | usbhsf_fifo_unselect(pipe, fifo); |
372 | ||
4bd04811 | 373 | return 0; |
659d4954 KM |
374 | |
375 | usbhs_fifo_write_busy: | |
d77e3f4e KM |
376 | usbhsf_fifo_unselect(pipe, fifo); |
377 | ||
659d4954 KM |
378 | /* |
379 | * pipe is busy. | |
380 | * retry in interrupt | |
381 | */ | |
382 | usbhsf_tx_irq_ctrl(pipe, 1); | |
383 | ||
384 | return ret; | |
e8d548d5 KM |
385 | } |
386 | ||
dad67397 KM |
387 | struct usbhs_pkt_handle usbhs_fifo_push_handler = { |
388 | .prepare = usbhsf_try_push, | |
389 | .try_run = usbhsf_try_push, | |
390 | }; | |
391 | ||
97664a20 | 392 | static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 393 | { |
dad67397 | 394 | struct usbhs_pipe *pipe = pkt->pipe; |
d77e3f4e KM |
395 | |
396 | if (usbhs_pipe_is_busy(pipe)) | |
397 | return 0; | |
e8d548d5 KM |
398 | |
399 | /* | |
d77e3f4e | 400 | * pipe enable to prepare packet receive |
e8d548d5 | 401 | */ |
e8d548d5 KM |
402 | |
403 | usbhs_pipe_enable(pipe); | |
659d4954 | 404 | usbhsf_rx_irq_ctrl(pipe, 1); |
e8d548d5 | 405 | |
d3af90a5 | 406 | return 0; |
e8d548d5 KM |
407 | } |
408 | ||
97664a20 | 409 | static int usbhsf_try_pop(struct usbhs_pkt *pkt, int *is_done) |
e8d548d5 | 410 | { |
4bd04811 | 411 | struct usbhs_pipe *pipe = pkt->pipe; |
e8d548d5 | 412 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
659d4954 | 413 | struct device *dev = usbhs_priv_to_dev(priv); |
d3af90a5 KM |
414 | struct usbhs_fifo *fifo = usbhsf_get_cfifo(priv); /* CFIFO */ |
415 | void __iomem *addr = priv->base + fifo->port; | |
659d4954 KM |
416 | u8 *buf; |
417 | u32 data = 0; | |
418 | int maxp = usbhs_pipe_get_maxpacket(pipe); | |
4bd04811 | 419 | int rcv_len, len; |
e8d548d5 | 420 | int i, ret; |
4bd04811 | 421 | int total_len = 0; |
e8d548d5 | 422 | |
d3af90a5 | 423 | ret = usbhsf_fifo_select(pipe, fifo, 0); |
e8d548d5 | 424 | if (ret < 0) |
d77e3f4e | 425 | return 0; |
e8d548d5 | 426 | |
d3af90a5 | 427 | ret = usbhsf_fifo_barrier(priv, fifo); |
e8d548d5 | 428 | if (ret < 0) |
d77e3f4e | 429 | goto usbhs_fifo_read_busy; |
e8d548d5 | 430 | |
d3af90a5 | 431 | rcv_len = usbhsf_fifo_rcv_len(priv, fifo); |
e8d548d5 | 432 | |
659d4954 KM |
433 | buf = pkt->buf + pkt->actual; |
434 | len = pkt->length - pkt->actual; | |
435 | len = min(len, rcv_len); | |
436 | total_len = len; | |
437 | ||
e8d548d5 KM |
438 | /* |
439 | * Buffer clear if Zero-Length packet | |
440 | * | |
441 | * see | |
442 | * "Operation" - "FIFO Buffer Memory" - "FIFO Port Function" | |
443 | */ | |
444 | if (0 == rcv_len) { | |
d3af90a5 | 445 | usbhsf_fifo_clear(pipe, fifo); |
4bd04811 | 446 | goto usbhs_fifo_read_end; |
e8d548d5 KM |
447 | } |
448 | ||
e8d548d5 KM |
449 | /* |
450 | * FIXME | |
451 | * | |
452 | * 32-bit access only | |
453 | */ | |
659d4954 | 454 | if (len >= 4 && !((unsigned long)buf & 0x03)) { |
e8d548d5 KM |
455 | ioread32_rep(addr, buf, len / 4); |
456 | len %= 4; | |
659d4954 | 457 | buf += total_len - len; |
e8d548d5 KM |
458 | } |
459 | ||
460 | /* the rest operation */ | |
461 | for (i = 0; i < len; i++) { | |
462 | if (!(i & 0x03)) | |
463 | data = ioread32(addr); | |
464 | ||
465 | buf[i] = (data >> ((i & 0x03) * 8)) & 0xff; | |
466 | } | |
467 | ||
659d4954 KM |
468 | pkt->actual += total_len; |
469 | ||
4bd04811 | 470 | usbhs_fifo_read_end: |
659d4954 | 471 | if ((pkt->actual == pkt->length) || /* receive all data */ |
97664a20 KM |
472 | (total_len < maxp)) { /* short packet */ |
473 | *is_done = 1; | |
659d4954 KM |
474 | usbhsf_rx_irq_ctrl(pipe, 0); |
475 | usbhs_pipe_disable(pipe); | |
4bd04811 KM |
476 | } |
477 | ||
97664a20 KM |
478 | dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", |
479 | usbhs_pipe_number(pipe), | |
480 | pkt->length, pkt->actual, *is_done, pkt->zero); | |
481 | ||
d77e3f4e KM |
482 | usbhs_fifo_read_busy: |
483 | usbhsf_fifo_unselect(pipe, fifo); | |
484 | ||
485 | return ret; | |
e8d548d5 | 486 | } |
dad67397 KM |
487 | |
488 | struct usbhs_pkt_handle usbhs_fifo_pop_handler = { | |
489 | .prepare = usbhsf_prepare_pop, | |
490 | .try_run = usbhsf_try_pop, | |
491 | }; | |
492 | ||
493 | /* | |
494 | * handler function | |
495 | */ | |
97664a20 | 496 | static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) |
dad67397 | 497 | { |
97664a20 | 498 | usbhs_dcp_control_transfer_done(pkt->pipe); |
dad67397 | 499 | |
97664a20 | 500 | *is_done = 1; |
dad67397 KM |
501 | |
502 | return 0; | |
503 | } | |
504 | ||
505 | struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { | |
506 | .prepare = usbhsf_ctrl_stage_end, | |
507 | .try_run = usbhsf_ctrl_stage_end, | |
508 | }; | |
509 | ||
510 | /* | |
511 | * irq functions | |
512 | */ | |
513 | static int usbhsf_irq_empty(struct usbhs_priv *priv, | |
514 | struct usbhs_irq_state *irq_state) | |
515 | { | |
516 | struct usbhs_pipe *pipe; | |
dad67397 KM |
517 | struct device *dev = usbhs_priv_to_dev(priv); |
518 | int i, ret; | |
519 | ||
520 | if (!irq_state->bempsts) { | |
521 | dev_err(dev, "debug %s !!\n", __func__); | |
522 | return -EIO; | |
523 | } | |
524 | ||
525 | dev_dbg(dev, "irq empty [0x%04x]\n", irq_state->bempsts); | |
526 | ||
527 | /* | |
528 | * search interrupted "pipe" | |
529 | * not "uep". | |
530 | */ | |
531 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | |
532 | if (!(irq_state->bempsts & (1 << i))) | |
533 | continue; | |
534 | ||
97664a20 | 535 | ret = usbhs_pkt_run(pipe); |
dad67397 KM |
536 | if (ret < 0) |
537 | dev_err(dev, "irq_empty run_error %d : %d\n", i, ret); | |
538 | } | |
539 | ||
540 | return 0; | |
541 | } | |
542 | ||
543 | static int usbhsf_irq_ready(struct usbhs_priv *priv, | |
544 | struct usbhs_irq_state *irq_state) | |
545 | { | |
546 | struct usbhs_pipe *pipe; | |
dad67397 KM |
547 | struct device *dev = usbhs_priv_to_dev(priv); |
548 | int i, ret; | |
549 | ||
550 | if (!irq_state->brdysts) { | |
551 | dev_err(dev, "debug %s !!\n", __func__); | |
552 | return -EIO; | |
553 | } | |
554 | ||
555 | dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); | |
556 | ||
557 | /* | |
558 | * search interrupted "pipe" | |
559 | * not "uep". | |
560 | */ | |
561 | usbhs_for_each_pipe_with_dcp(pipe, priv, i) { | |
562 | if (!(irq_state->brdysts & (1 << i))) | |
563 | continue; | |
564 | ||
97664a20 | 565 | ret = usbhs_pkt_run(pipe); |
dad67397 KM |
566 | if (ret < 0) |
567 | dev_err(dev, "irq_ready run_error %d : %d\n", i, ret); | |
568 | } | |
569 | ||
570 | return 0; | |
571 | } | |
572 | ||
573 | /* | |
574 | * fifo init | |
575 | */ | |
576 | void usbhs_fifo_init(struct usbhs_priv *priv) | |
577 | { | |
578 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | |
d77e3f4e | 579 | struct usbhs_fifo *cfifo = usbhsf_get_cfifo(priv); |
dad67397 KM |
580 | |
581 | mod->irq_empty = usbhsf_irq_empty; | |
582 | mod->irq_ready = usbhsf_irq_ready; | |
583 | mod->irq_bempsts = 0; | |
584 | mod->irq_brdysts = 0; | |
d77e3f4e KM |
585 | |
586 | cfifo->pipe = NULL; | |
dad67397 KM |
587 | } |
588 | ||
589 | void usbhs_fifo_quit(struct usbhs_priv *priv) | |
590 | { | |
591 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | |
592 | ||
593 | mod->irq_empty = NULL; | |
594 | mod->irq_ready = NULL; | |
595 | mod->irq_bempsts = 0; | |
596 | mod->irq_brdysts = 0; | |
597 | } | |
d3af90a5 KM |
598 | |
599 | int usbhs_fifo_probe(struct usbhs_priv *priv) | |
600 | { | |
601 | struct usbhs_fifo *fifo; | |
602 | ||
603 | /* CFIFO */ | |
604 | fifo = usbhsf_get_cfifo(priv); | |
605 | fifo->port = CFIFO; | |
606 | fifo->sel = CFIFOSEL; | |
607 | fifo->ctr = CFIFOCTR; | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | void usbhs_fifo_remove(struct usbhs_priv *priv) | |
613 | { | |
614 | } |