usb: gadget: renesas_usbhs: move usbhs_usbreq_get/set_val() to common.c
[deliverable/linux.git] / drivers / usb / renesas_usbhs / pipe.c
CommitLineData
f1407d5c
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>
f1407d5c
KM
18#include <linux/slab.h>
19#include "./common.h"
20#include "./pipe.h"
21
22/*
23 * macros
24 */
f1407d5c
KM
25#define usbhsp_addr_offset(p) ((usbhs_pipe_number(p) - 1) * 2)
26
f1407d5c
KM
27#define usbhsp_flags_set(p, f) ((p)->flags |= USBHS_PIPE_FLAGS_##f)
28#define usbhsp_flags_clr(p, f) ((p)->flags &= ~USBHS_PIPE_FLAGS_##f)
29#define usbhsp_flags_has(p, f) ((p)->flags & USBHS_PIPE_FLAGS_##f)
30#define usbhsp_flags_init(p) do {(p)->flags = 0; } while (0)
31
f1407d5c
KM
32/*
33 * for debug
34 */
35static char *usbhsp_pipe_name[] = {
36 [USB_ENDPOINT_XFER_CONTROL] = "DCP",
37 [USB_ENDPOINT_XFER_BULK] = "BULK",
38 [USB_ENDPOINT_XFER_INT] = "INT",
39 [USB_ENDPOINT_XFER_ISOC] = "ISO",
40};
41
f1407d5c
KM
42/*
43 * DCPCTR/PIPEnCTR functions
44 */
45static void usbhsp_pipectrl_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
46{
e8d548d5 47 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c
KM
48 int offset = usbhsp_addr_offset(pipe);
49
e8d548d5 50 if (usbhs_pipe_is_dcp(pipe))
f1407d5c
KM
51 usbhs_bset(priv, DCPCTR, mask, val);
52 else
53 usbhs_bset(priv, PIPEnCTR + offset, mask, val);
54}
55
56static u16 usbhsp_pipectrl_get(struct usbhs_pipe *pipe)
57{
e8d548d5 58 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c
KM
59 int offset = usbhsp_addr_offset(pipe);
60
e8d548d5 61 if (usbhs_pipe_is_dcp(pipe))
f1407d5c
KM
62 return usbhs_read(priv, DCPCTR);
63 else
64 return usbhs_read(priv, PIPEnCTR + offset);
65}
66
67/*
68 * DCP/PIPE functions
69 */
70static void __usbhsp_pipe_xxx_set(struct usbhs_pipe *pipe,
71 u16 dcp_reg, u16 pipe_reg,
72 u16 mask, u16 val)
73{
e8d548d5 74 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c 75
e8d548d5 76 if (usbhs_pipe_is_dcp(pipe))
f1407d5c
KM
77 usbhs_bset(priv, dcp_reg, mask, val);
78 else
79 usbhs_bset(priv, pipe_reg, mask, val);
80}
81
f1407d5c
KM
82/*
83 * DCPCFG/PIPECFG functions
84 */
85static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
86{
87 __usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val);
88}
89
90/*
91 * PIPEBUF
92 */
93static void usbhsp_pipe_buf_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
94{
e8d548d5 95 if (usbhs_pipe_is_dcp(pipe))
f1407d5c
KM
96 return;
97
98 __usbhsp_pipe_xxx_set(pipe, 0, PIPEBUF, mask, val);
99}
100
101/*
102 * DCPMAXP/PIPEMAXP
103 */
104static void usbhsp_pipe_maxp_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
105{
106 __usbhsp_pipe_xxx_set(pipe, DCPMAXP, PIPEMAXP, mask, val);
107}
108
f1407d5c
KM
109/*
110 * pipe control functions
111 */
112static void usbhsp_pipe_select(struct usbhs_pipe *pipe)
113{
e8d548d5 114 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c
KM
115
116 /*
117 * On pipe, this is necessary before
118 * accesses to below registers.
119 *
120 * PIPESEL : usbhsp_pipe_select
121 * PIPECFG : usbhsp_pipe_cfg_xxx
122 * PIPEBUF : usbhsp_pipe_buf_xxx
123 * PIPEMAXP : usbhsp_pipe_maxp_xxx
124 * PIPEPERI
125 */
126
127 /*
128 * if pipe is dcp, no pipe is selected.
129 * it is no problem, because dcp have its register
130 */
131 usbhs_write(priv, PIPESEL, 0xF & usbhs_pipe_number(pipe));
132}
133
134static int usbhsp_pipe_barrier(struct usbhs_pipe *pipe)
135{
e8d548d5 136 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
f1407d5c
KM
137 int timeout = 1024;
138 u16 val;
139
140 /*
141 * make sure....
142 *
143 * Modify these bits when CSSTS = 0, PID = NAK, and no pipe number is
144 * specified by the CURPIPE bits.
145 * When changing the setting of this bit after changing
146 * the PID bits for the selected pipe from BUF to NAK,
147 * check that CSSTS = 0 and PBUSY = 0.
148 */
149
150 /*
151 * CURPIPE bit = 0
152 *
153 * see also
154 * "Operation"
155 * - "Pipe Control"
156 * - "Pipe Control Registers Switching Procedure"
157 */
158 usbhs_write(priv, CFIFOSEL, 0);
e8d548d5 159 usbhs_pipe_disable(pipe);
f1407d5c
KM
160
161 do {
162 val = usbhsp_pipectrl_get(pipe);
163 val &= CSSTS | PID_MASK;
164 if (!val)
165 return 0;
166
167 udelay(10);
168
169 } while (timeout--);
170
f1407d5c
KM
171 return -EBUSY;
172}
173
e8d548d5 174int usbhs_pipe_is_accessible(struct usbhs_pipe *pipe)
f1407d5c
KM
175{
176 u16 val;
177
178 val = usbhsp_pipectrl_get(pipe);
179 if (val & BSTS)
180 return 0;
181
182 return -EBUSY;
183}
184
185/*
186 * PID ctrl
187 */
188static void __usbhsp_pid_try_nak_if_stall(struct usbhs_pipe *pipe)
189{
190 u16 pid = usbhsp_pipectrl_get(pipe);
191
192 pid &= PID_MASK;
193
194 /*
195 * see
196 * "Pipe n Control Register" - "PID"
197 */
198 switch (pid) {
199 case PID_STALL11:
200 usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10);
201 /* fall-through */
202 case PID_STALL10:
203 usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK);
204 }
205}
206
e8d548d5 207void usbhs_pipe_disable(struct usbhs_pipe *pipe)
f1407d5c 208{
c786e09c
KM
209 int timeout = 1024;
210 u16 val;
211
f1407d5c
KM
212 /* see "Pipe n Control Register" - "PID" */
213 __usbhsp_pid_try_nak_if_stall(pipe);
214
215 usbhsp_pipectrl_set(pipe, PID_MASK, PID_NAK);
c786e09c
KM
216
217 do {
218 val = usbhsp_pipectrl_get(pipe);
219 val &= PBUSY;
220 if (!val)
221 break;
222
223 udelay(10);
224 } while (timeout--);
f1407d5c
KM
225}
226
e8d548d5 227void usbhs_pipe_enable(struct usbhs_pipe *pipe)
f1407d5c
KM
228{
229 /* see "Pipe n Control Register" - "PID" */
230 __usbhsp_pid_try_nak_if_stall(pipe);
231
232 usbhsp_pipectrl_set(pipe, PID_MASK, PID_BUF);
233}
234
e8d548d5 235void usbhs_pipe_stall(struct usbhs_pipe *pipe)
f1407d5c
KM
236{
237 u16 pid = usbhsp_pipectrl_get(pipe);
238
239 pid &= PID_MASK;
240
241 /*
242 * see
243 * "Pipe n Control Register" - "PID"
244 */
245 switch (pid) {
246 case PID_NAK:
247 usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL10);
248 break;
249 case PID_BUF:
250 usbhsp_pipectrl_set(pipe, PID_MASK, PID_STALL11);
251 break;
252 }
253}
254
f1407d5c
KM
255/*
256 * pipe setup
257 */
258static int usbhsp_possible_double_buffer(struct usbhs_pipe *pipe)
259{
260 /*
261 * only ISO / BULK pipe can use double buffer
262 */
356db7ed
KM
263 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) ||
264 usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC))
f1407d5c
KM
265 return 1;
266
267 return 0;
268}
269
270static u16 usbhsp_setup_pipecfg(struct usbhs_pipe *pipe,
f5aa889f
KM
271 int is_host,
272 int dir_in)
f1407d5c
KM
273{
274 u16 type = 0;
275 u16 bfre = 0;
276 u16 dblb = 0;
277 u16 cntmd = 0;
278 u16 dir = 0;
279 u16 epnum = 0;
280 u16 shtnak = 0;
281 u16 type_array[] = {
282 [USB_ENDPOINT_XFER_BULK] = TYPE_BULK,
283 [USB_ENDPOINT_XFER_INT] = TYPE_INT,
284 [USB_ENDPOINT_XFER_ISOC] = TYPE_ISO,
285 };
286 int is_double = usbhsp_possible_double_buffer(pipe);
287
e8d548d5 288 if (usbhs_pipe_is_dcp(pipe))
f1407d5c
KM
289 return -EINVAL;
290
291 /*
292 * PIPECFG
293 *
294 * see
295 * - "Register Descriptions" - "PIPECFG" register
296 * - "Features" - "Pipe configuration"
297 * - "Operation" - "Pipe Control"
298 */
299
300 /* TYPE */
356db7ed 301 type = type_array[usbhs_pipe_type(pipe)];
f1407d5c
KM
302
303 /* BFRE */
356db7ed
KM
304 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
305 usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c
KM
306 bfre = 0; /* FIXME */
307
308 /* DBLB */
356db7ed
KM
309 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_ISOC) ||
310 usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c
KM
311 dblb = (is_double) ? DBLB : 0;
312
313 /* CNTMD */
356db7ed 314 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
f1407d5c
KM
315 cntmd = 0; /* FIXME */
316
317 /* DIR */
f5aa889f 318 if (dir_in)
ad6f2a8b 319 usbhsp_flags_set(pipe, IS_DIR_HOST);
f1407d5c 320
f5aa889f
KM
321 if ((is_host && !dir_in) ||
322 (!is_host && dir_in))
f1407d5c
KM
323 dir |= DIR_OUT;
324
ad6f2a8b
KM
325 if (!dir)
326 usbhsp_flags_set(pipe, IS_DIR_IN);
327
f1407d5c 328 /* SHTNAK */
356db7ed 329 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK) &&
f1407d5c
KM
330 !dir)
331 shtnak = SHTNAK;
332
333 /* EPNUM */
f5aa889f 334 epnum = 0; /* see usbhs_pipe_config_update() */
f1407d5c
KM
335
336 return type |
337 bfre |
338 dblb |
339 cntmd |
340 dir |
341 shtnak |
342 epnum;
343}
344
f5aa889f 345static u16 usbhsp_setup_pipebuff(struct usbhs_pipe *pipe)
f1407d5c 346{
e8d548d5
KM
347 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
348 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c
KM
349 struct device *dev = usbhs_priv_to_dev(priv);
350 int pipe_num = usbhs_pipe_number(pipe);
351 int is_double = usbhsp_possible_double_buffer(pipe);
352 u16 buff_size;
353 u16 bufnmb;
354 u16 bufnmb_cnt;
355
356 /*
357 * PIPEBUF
358 *
359 * see
360 * - "Register Descriptions" - "PIPEBUF" register
361 * - "Features" - "Pipe configuration"
362 * - "Operation" - "FIFO Buffer Memory"
363 * - "Operation" - "Pipe Control"
364 *
365 * ex) if pipe6 - pipe9 are USB_ENDPOINT_XFER_INT (SH7724)
366 *
367 * BUFNMB: PIPE
368 * 0: pipe0 (DCP 256byte)
369 * 1: -
370 * 2: -
371 * 3: -
372 * 4: pipe6 (INT 64byte)
373 * 5: pipe7 (INT 64byte)
374 * 6: pipe8 (INT 64byte)
375 * 7: pipe9 (INT 64byte)
376 * 8 - xx: free (for BULK, ISOC)
377 */
378
379 /*
380 * FIXME
381 *
382 * it doesn't have good buffer allocator
383 *
384 * DCP : 256 byte
385 * BULK: 512 byte
386 * INT : 64 byte
387 * ISOC: 512 byte
388 */
356db7ed 389 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_CONTROL))
f1407d5c 390 buff_size = 256;
356db7ed 391 else if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
f1407d5c
KM
392 buff_size = 64;
393 else
394 buff_size = 512;
395
396 /* change buff_size to register value */
397 bufnmb_cnt = (buff_size / 64) - 1;
398
399 /* BUFNMB has been reserved for INT pipe
400 * see above */
356db7ed 401 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT)) {
f1407d5c
KM
402 bufnmb = pipe_num - 2;
403 } else {
404 bufnmb = info->bufnmb_last;
405 info->bufnmb_last += bufnmb_cnt + 1;
406
407 /*
408 * double buffer
409 */
410 if (is_double)
411 info->bufnmb_last += bufnmb_cnt + 1;
412 }
413
414 dev_dbg(dev, "pipe : %d : buff_size 0x%x: bufnmb 0x%x\n",
415 pipe_num, buff_size, bufnmb);
416
417 return (0x1f & bufnmb_cnt) << 10 |
418 (0xff & bufnmb) << 0;
419}
420
f5aa889f
KM
421void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 epnum, u16 maxp)
422{
423 usbhsp_pipe_barrier(pipe);
424
7fd097e7
KM
425 pipe->maxp = maxp;
426
f5aa889f
KM
427 usbhsp_pipe_select(pipe);
428 usbhsp_pipe_maxp_set(pipe, 0xFFFF, maxp);
429
430 if (!usbhs_pipe_is_dcp(pipe))
431 usbhsp_pipe_cfg_set(pipe, 0x000F, epnum);
432}
433
f1407d5c
KM
434/*
435 * pipe control
436 */
437int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe)
438{
7fd097e7
KM
439 /*
440 * see
441 * usbhs_pipe_config_update()
442 * usbhs_dcp_malloc()
443 */
444 return pipe->maxp;
f1407d5c
KM
445}
446
447int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe)
448{
449 return usbhsp_flags_has(pipe, IS_DIR_IN);
450}
451
ad6f2a8b
KM
452int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
453{
454 return usbhsp_flags_has(pipe, IS_DIR_HOST);
455}
456
f1407d5c
KM
457void usbhs_pipe_clear_sequence(struct usbhs_pipe *pipe)
458{
459 usbhsp_pipectrl_set(pipe, SQCLR, SQCLR);
460}
461
08e6c611
KM
462void usbhs_pipe_clear(struct usbhs_pipe *pipe)
463{
464 usbhsp_pipectrl_set(pipe, ACLRM, ACLRM);
465 usbhsp_pipectrl_set(pipe, ACLRM, 0);
466}
467
f1407d5c
KM
468static struct usbhs_pipe *usbhsp_get_pipe(struct usbhs_priv *priv, u32 type)
469{
470 struct usbhs_pipe *pos, *pipe;
471 int i;
472
473 /*
474 * find target pipe
475 */
476 pipe = NULL;
477 usbhs_for_each_pipe_with_dcp(pos, priv, i) {
356db7ed 478 if (!usbhs_pipe_type_is(pos, type))
f1407d5c
KM
479 continue;
480 if (usbhsp_flags_has(pos, IS_USED))
481 continue;
482
483 pipe = pos;
484 break;
485 }
486
487 if (!pipe)
488 return NULL;
489
490 /*
491 * initialize pipe flags
492 */
493 usbhsp_flags_init(pipe);
494 usbhsp_flags_set(pipe, IS_USED);
495
496 return pipe;
497}
498
4bd04811 499void usbhs_pipe_init(struct usbhs_priv *priv,
e73a9891
KM
500 void (*done)(struct usbhs_pkt *pkt),
501 int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map))
f1407d5c 502{
e8d548d5 503 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
dad67397 504 struct device *dev = usbhs_priv_to_dev(priv);
f1407d5c
KM
505 struct usbhs_pipe *pipe;
506 int i;
507
dad67397
KM
508 if (!done) {
509 dev_err(dev, "no done function\n");
510 return;
511 }
512
f1407d5c
KM
513 /*
514 * FIXME
515 *
516 * driver needs good allocator.
517 *
518 * find first free buffer area (BULK, ISOC)
519 * (DCP, INT area is fixed)
520 *
521 * buffer number 0 - 3 have been reserved for DCP
522 * see
523 * usbhsp_to_bufnmb
524 */
525 info->bufnmb_last = 4;
526 usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
356db7ed 527 if (usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_INT))
f1407d5c
KM
528 info->bufnmb_last++;
529
530 usbhsp_flags_init(pipe);
d77e3f4e 531 pipe->fifo = NULL;
f1407d5c 532 pipe->mod_private = NULL;
6acb95d4 533 INIT_LIST_HEAD(&pipe->list);
45e13e6e 534
e8d548d5 535 /* pipe force init */
08e6c611 536 usbhs_pipe_clear(pipe);
f1407d5c 537 }
4bd04811 538
dad67397 539 info->done = done;
e73a9891 540 info->dma_map_ctrl = dma_map_ctrl;
f1407d5c
KM
541}
542
543struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
f5aa889f
KM
544 int endpoint_type,
545 int dir_in)
f1407d5c
KM
546{
547 struct device *dev = usbhs_priv_to_dev(priv);
548 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
549 struct usbhs_pipe *pipe;
550 int is_host = usbhs_mod_is_host(priv, mod);
551 int ret;
f5aa889f 552 u16 pipecfg, pipebuf;
f1407d5c 553
f5aa889f 554 pipe = usbhsp_get_pipe(priv, endpoint_type);
f429ea3f
KM
555 if (!pipe) {
556 dev_err(dev, "can't get pipe (%s)\n",
f5aa889f 557 usbhsp_pipe_name[endpoint_type]);
f1407d5c 558 return NULL;
f429ea3f 559 }
f1407d5c 560
6acb95d4
KM
561 INIT_LIST_HEAD(&pipe->list);
562
e8d548d5 563 usbhs_pipe_disable(pipe);
f1407d5c
KM
564
565 /* make sure pipe is not busy */
566 ret = usbhsp_pipe_barrier(pipe);
567 if (ret < 0) {
568 dev_err(dev, "pipe setup failed %d\n", usbhs_pipe_number(pipe));
569 return NULL;
570 }
571
f5aa889f
KM
572 pipecfg = usbhsp_setup_pipecfg(pipe, is_host, dir_in);
573 pipebuf = usbhsp_setup_pipebuff(pipe);
f1407d5c 574
f1407d5c
KM
575 usbhsp_pipe_select(pipe);
576 usbhsp_pipe_cfg_set(pipe, 0xFFFF, pipecfg);
577 usbhsp_pipe_buf_set(pipe, 0xFFFF, pipebuf);
f1407d5c
KM
578
579 usbhs_pipe_clear_sequence(pipe);
580
581 dev_dbg(dev, "enable pipe %d : %s (%s)\n",
582 usbhs_pipe_number(pipe),
f5aa889f 583 usbhsp_pipe_name[endpoint_type],
f1407d5c
KM
584 usbhs_pipe_is_dir_in(pipe) ? "in" : "out");
585
f5aa889f
KM
586 /*
587 * epnum / maxp are still not set to this pipe.
588 * call usbhs_pipe_config_update() after this function !!
589 */
590
f1407d5c
KM
591 return pipe;
592}
593
d77e3f4e
KM
594void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo)
595{
596 if (pipe->fifo)
597 pipe->fifo->pipe = NULL;
598
599 pipe->fifo = fifo;
600
601 if (fifo)
602 fifo->pipe = pipe;
603}
604
605
f1407d5c
KM
606/*
607 * dcp control
608 */
609struct usbhs_pipe *usbhs_dcp_malloc(struct usbhs_priv *priv)
610{
611 struct usbhs_pipe *pipe;
612
613 pipe = usbhsp_get_pipe(priv, USB_ENDPOINT_XFER_CONTROL);
614 if (!pipe)
615 return NULL;
616
f5aa889f
KM
617 INIT_LIST_HEAD(&pipe->list);
618
f1407d5c 619 /*
f5aa889f 620 * call usbhs_pipe_config_update() after this function !!
f1407d5c
KM
621 */
622
f1407d5c
KM
623 return pipe;
624}
625
626void usbhs_dcp_control_transfer_done(struct usbhs_pipe *pipe)
627{
e8d548d5 628 WARN_ON(!usbhs_pipe_is_dcp(pipe));
f1407d5c 629
e8d548d5 630 usbhs_pipe_enable(pipe);
f1407d5c
KM
631 usbhsp_pipectrl_set(pipe, CCPL, CCPL);
632}
633
f1407d5c
KM
634/*
635 * pipe module function
636 */
637int usbhs_pipe_probe(struct usbhs_priv *priv)
638{
e8d548d5 639 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c
KM
640 struct usbhs_pipe *pipe;
641 struct device *dev = usbhs_priv_to_dev(priv);
642 u32 *pipe_type = usbhs_get_dparam(priv, pipe_type);
643 int pipe_size = usbhs_get_dparam(priv, pipe_size);
644 int i;
645
646 /* This driver expects 1st pipe is DCP */
647 if (pipe_type[0] != USB_ENDPOINT_XFER_CONTROL) {
648 dev_err(dev, "1st PIPE is not DCP\n");
649 return -EINVAL;
650 }
651
652 info->pipe = kzalloc(sizeof(struct usbhs_pipe) * pipe_size, GFP_KERNEL);
653 if (!info->pipe) {
654 dev_err(dev, "Could not allocate pipe\n");
655 return -ENOMEM;
656 }
657
658 info->size = pipe_size;
659
660 /*
661 * init pipe
662 */
663 usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
664 pipe->priv = priv;
356db7ed
KM
665
666 usbhs_pipe_type(pipe) =
667 pipe_type[i] & USB_ENDPOINT_XFERTYPE_MASK;
f1407d5c
KM
668
669 dev_dbg(dev, "pipe %x\t: %s\n",
670 i, usbhsp_pipe_name[pipe_type[i]]);
671 }
672
673 return 0;
674}
675
676void usbhs_pipe_remove(struct usbhs_priv *priv)
677{
e8d548d5 678 struct usbhs_pipe_info *info = usbhs_priv_to_pipeinfo(priv);
f1407d5c
KM
679
680 kfree(info->pipe);
681}
This page took 0.095139 seconds and 5 git commands to generate.