1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright © 2010 Amaury Pouly
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #include "clock-target.h"
36 #include "usb-drv-as3525v2.h"
39 static const uint8_t in_ep_list
[NUM_IN_EP
+ 1] = {0, IN_EP_LIST
};
40 static const uint8_t out_ep_list
[NUM_OUT_EP
+ 1] = {0, OUT_EP_LIST
};
42 /* iterate through each in/out ep except EP0
43 * 'i' is the counter, 'ep' is the actual value */
44 #define FOR_EACH_EP(list, start, i, ep) \
45 for(ep = list[i = start]; \
46 i < (sizeof(list)/sizeof(*list)); \
49 #define FOR_EACH_IN_EP_EX(include_ep0, i, ep) \
50 FOR_EACH_EP(in_ep_list, (include_ep0) ? 0 : 1, i, ep)
52 #define FOR_EACH_OUT_EP_EX(include_ep0, i, ep) \
53 FOR_EACH_EP(out_ep_list, (include_ep0) ? 0 : 1, i, ep)
55 #define FOR_EACH_IN_EP(i, ep) FOR_EACH_IN_EP_EX (false, i, ep)
56 #define FOR_EACH_IN_EP_AND_EP0(i, ep) FOR_EACH_IN_EP_EX (true, i, ep)
57 #define FOR_EACH_OUT_EP(i, ep) FOR_EACH_OUT_EP_EX(false, i, ep)
58 #define FOR_EACH_OUT_EP_AND_EP0(i, ep) FOR_EACH_OUT_EP_EX(true, i, ep)
60 /* store per endpoint, per direction, information */
63 unsigned int len
; /* length of the data buffer */
64 struct wakeup complete
; /* wait object */
65 int8_t status
; /* completion status (0 for success) */
66 bool active
; /* true is endpoint has been requested (true for EP0) */
67 bool wait
; /* true if usb thread is blocked on completion */
68 bool busy
; /* true is a transfer is pending */
71 /* state of EP0 (to correctly schedule setup packet enqueing) */
74 /* Setup packet is enqueud, waiting for actual data */
76 /* Waiting for ack (either IN or OUT) */
78 /* Ack complete, waiting for data (either IN or OUT)
79 * This state is necessary because if both ack and data complete in the
80 * same interrupt, we might process data completion before ack completion
81 * so we need this bizarre state */
83 /* Setup packet complete, waiting for ack and data */
84 EP0_WAIT_DATA_ACK
= 3,
87 /* endpoints[ep_num][DIR_IN/DIR_OUT] */
88 static struct usb_endpoint endpoints
[USB_NUM_ENDPOINTS
][2];
89 /* setup packet for EP0 */
90 static struct usb_ctrlrequest _ep0_setup_pkt
__attribute__((aligned(32)));
91 static struct usb_ctrlrequest
*ep0_setup_pkt
= AS3525_UNCACHED_ADDR(&_ep0_setup_pkt
);
94 static enum ep0state ep0_state
;
98 logf("usb-drv: attach");
102 static inline void usb_delay(void)
112 static void as3525v2_connect(void)
114 logf("usb-drv: init as3525v2");
115 /* 1) enable usb core clock */
116 bitset32(&CGU_PERI
, CGU_USB_CLOCK_ENABLE
);
118 /* 2) enable usb phy clock */
119 CCU_USB
= (CCU_USB
& ~(3<<24)) | (1 << 24); /* ?? */
121 CGU_USB
= 1<<5 /* enable */
123 | 0; /* source = ? (24MHz crystal?) */
125 /* 3) clear "stop pclk" */
128 /* 4) clear "power clamp" */
131 /* 5) clear "reset power down module" */
134 /* 6) set "power on program done" */
135 DCTL
|= DCTL_pwronprgdone
;
137 /* 7) core soft reset */
138 GRSTCTL
|= GRSTCTL_csftrst
;
140 /* 8) hclk soft reset */
141 GRSTCTL
|= GRSTCTL_hsftrst
;
143 /* 9) flush and reset everything */
146 /* 10) force device mode*/
147 GUSBCFG
&= ~GUSBCFG_force_host_mode
;
148 GUSBCFG
|= GUSBCFG_force_device_mode
;
150 /* 11) Do something that is probably CCU related but undocumented*/
152 CCU_USB
&= ~0x300000;
154 /* 12) reset usb core parameters (dev addr, speed, ...) */
159 static void as3525v2_disconnect(void)
164 bitclr32(&CGU_PERI
, CGU_USB_CLOCK_ENABLE
);
167 static void enable_device_interrupts(void)
169 /* Clear any pending interrupt */
170 GINTSTS
= 0xffffffff;
171 /* Clear any pending otg interrupt */
172 GOTGINT
= 0xffffffff;
173 /* Enable interrupts */
174 GINTMSK
= GINTMSK_usbreset
184 static void flush_tx_fifos(int nums
)
188 GRSTCTL
= (nums
<< GRSTCTL_txfnum_bitp
)
189 | GRSTCTL_txfflsh_flush
;
190 while(GRSTCTL
& GRSTCTL_txfflsh_flush
&& i
< 0x300)
192 if(GRSTCTL
& GRSTCTL_txfflsh_flush
)
193 panicf("usb-drv: hang of flush tx fifos (%x)", nums
);
194 /* wait 3 phy clocks */
198 static void prepare_setup_ep0(void)
200 logf("usb-drv: prepare EP0");
202 DOEPDMA(0) = (unsigned long)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt
);
204 /* Setup EP0 OUT with the following parameters:
206 * setup packet count = 1
207 * transfer size = 8 (setup packet)
209 DOEPTSIZ(0) = (1 << DEPTSIZ0_supcnt_bitp
)
210 | (1 << DEPTSIZ0_pkcnt_bitp
)
213 /* Enable endpoint, clear nak */
214 ep0_state
= EP0_WAIT_SETUP
;
215 DOEPCTL(0) |= DEPCTL_epena
| DEPCTL_cnak
;
218 static void handle_ep0_complete(bool is_ack
)
223 panicf("usb-drv: EP0 completion while waiting for SETUP");
226 /* everything is done, prepare next setup */
229 panicf("usb-drv: EP0 data completion while waiting for ACK");
233 panicf("usb-drv: EP0 ACK while waiting for data completion");
235 /* everything is done, prepare next setup */
238 case EP0_WAIT_DATA_ACK
:
241 ep0_state
= EP0_WAIT_DATA
;
243 ep0_state
= EP0_WAIT_ACK
;
246 panicf("usb-drv: invalid EP0 state");
248 logf("usb-drv: EP0 state updated to %d", ep0_state
);
251 static void handle_ep0_setup(void)
253 if(ep0_state
!= EP0_WAIT_SETUP
)
255 logf("usb-drv: EP0 SETUP while in state %d", ep0_state
);
258 /* determine is there is a data phase */
259 if(ep0_setup_pkt
->wLength
== 0)
260 /* no: wait for ack */
261 ep0_state
= EP0_WAIT_ACK
;
263 /* yes: wait ack and data */
264 ep0_state
= EP0_WAIT_DATA_ACK
;
265 logf("usb-drv: EP0 state updated to %d", ep0_state
);
268 static void reset_endpoints(void)
272 /* disable all endpoints except EP0 */
273 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
275 endpoints
[ep
][DIR_IN
].active
= false;
276 endpoints
[ep
][DIR_IN
].busy
= false;
277 endpoints
[ep
][DIR_IN
].status
= -1;
278 if(endpoints
[ep
][DIR_IN
].wait
)
280 endpoints
[ep
][DIR_IN
].wait
= false;
281 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
283 if(DIEPCTL(ep
) & DEPCTL_epena
)
284 DIEPCTL(ep
) = DEPCTL_snak
;
289 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
291 endpoints
[ep
][DIR_OUT
].active
= false;
292 endpoints
[ep
][DIR_OUT
].busy
= false;
293 endpoints
[ep
][DIR_OUT
].status
= -1;
294 if(endpoints
[ep
][DIR_OUT
].wait
)
296 endpoints
[ep
][DIR_OUT
].wait
= false;
297 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
299 if(DOEPCTL(ep
) & DEPCTL_epena
)
300 DOEPCTL(ep
) = DEPCTL_snak
;
304 /* 64 bytes packet size, active endpoint */
305 DOEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
306 DIEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
307 /* Setup next chain for IN eps */
308 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
310 int next_ep
= in_ep_list
[(i
+ 1) % (NUM_IN_EP
+ 1)];
311 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~bitm(DEPCTL
, nextep
)) | (next_ep
<< DEPCTL_nextep_bitp
);
315 static void cancel_all_transfers(bool cancel_ep0
)
317 logf("usb-drv: cancel all transfers");
318 int flags
= disable_irq_save();
322 FOR_EACH_IN_EP_EX(cancel_ep0
, i
, ep
)
324 endpoints
[ep
][DIR_IN
].status
= -1;
325 endpoints
[ep
][DIR_IN
].busy
= false;
326 if(endpoints
[ep
][DIR_IN
].wait
)
328 endpoints
[ep
][DIR_IN
].wait
= false;
329 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
331 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
333 FOR_EACH_OUT_EP_EX(cancel_ep0
, i
, ep
)
335 endpoints
[ep
][DIR_OUT
].status
= -1;
336 endpoints
[ep
][DIR_OUT
].busy
= false;
337 if(endpoints
[ep
][DIR_OUT
].wait
)
339 endpoints
[ep
][DIR_OUT
].wait
= false;
340 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
342 DOEPCTL(ep
) = (DOEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
348 static void core_dev_init(void)
352 /* Restart the phy clock */
354 /* Set phy speed : high speed */
355 DCFG
= (DCFG
& ~bitm(DCFG
, devspd
)) | DCFG_devspd_hs_phy_hs
;
357 /* Check hardware capabilities */
358 if(extract(GHWCFG2
, arch
) != GHWCFG2_ARCH_INTERNAL_DMA
)
359 panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2
, arch
));
360 if(extract(GHWCFG2
, hs_phy_type
) != GHWCFG2_PHY_TYPE_UTMI
)
361 panicf("usb-drv: wrong HS phy type (%ld)", extract(GHWCFG2
, hs_phy_type
));
362 if(extract(GHWCFG2
, fs_phy_type
) != GHWCFG2_PHY_TYPE_UNSUPPORTED
)
363 panicf("usb-drv: wrong FS phy type (%ld)", extract(GHWCFG2
, fs_phy_type
));
364 if(extract(GHWCFG4
, utmi_phy_data_width
) != 0x2)
365 panicf("usb-drv: wrong utmi data width (%ld)", extract(GHWCFG4
, utmi_phy_data_width
));
366 if(!(GHWCFG4
& GHWCFG4_ded_fifo_en
)) /* it seems to be multiple tx fifo support */
367 panicf("usb-drv: no multiple tx fifo");
369 #ifdef USE_CUSTOM_FIFO_LAYOUT
370 if(!(GHWCFG2
& GHWCFG2_dyn_fifo
))
371 panicf("usb-drv: no dynamic fifo");
372 if(GRXFSIZ
!= DATA_FIFO_DEPTH
)
373 panicf("usb-drv: wrong data fifo size");
374 #endif /* USE_CUSTOM_FIFO_LAYOUT */
376 if(USB_NUM_ENDPOINTS
!= extract(GHWCFG2
, num_ep
))
377 panicf("usb-drv: wrong endpoint number");
379 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
381 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
382 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_IN
)
383 panicf("usb-drv: EP%d is no IN or BIDIR", ep
);
385 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
387 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
388 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_OUT
)
389 panicf("usb-drv: EP%d is no OUT or BIDIR", ep
);
394 GNPTXFSIZ
= MAKE_FIFOSIZE_DATA(512, 512);
396 /* Setup interrupt masks for endpoints */
397 /* Setup interrupt masks */
398 DOEPMSK
= DOEPINT_setup
| DOEPINT_xfercompl
| DOEPINT_ahberr
;
399 DIEPMSK
= DIEPINT_xfercompl
| DIEPINT_timeout
| DIEPINT_ahberr
;
400 DAINTMSK
= 0xffffffff;
406 /* enable USB interrupts */
407 enable_device_interrupts();
410 static void core_init(void)
413 DCTL
|= DCTL_sftdiscon
;
414 /* Select UTMI+ 16 */
415 GUSBCFG
|= GUSBCFG_phy_if
;
416 GUSBCFG
= (GUSBCFG
& ~bitm(GUSBCFG
, toutcal
)) | 7 << GUSBCFG_toutcal_bitp
;
418 /* fixme: the current code is for internal DMA only, the clip+ architecture
419 * define the internal DMA model */
420 /* Set burstlen and enable DMA*/
421 GAHBCFG
= (GAHBCFG_INT_DMA_BURST_INCR
<< GAHBCFG_hburstlen_bitp
)
422 | GAHBCFG_dma_enable
;
423 /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */
424 GUSBCFG
&= ~(GUSBCFG_srpcap
| GUSBCFG_hnpcapp
);
426 /* perform device model specific init */
430 DCTL
&= ~DCTL_sftdiscon
;
433 static void enable_global_interrupts(void)
435 VIC_INT_ENABLE
= INTERRUPT_USB
;
436 GAHBCFG
|= GAHBCFG_glblintrmsk
;
439 static void disable_global_interrupts(void)
441 GAHBCFG
&= ~GAHBCFG_glblintrmsk
;
442 VIC_INT_EN_CLEAR
= INTERRUPT_USB
;
445 void usb_drv_init(void)
448 logf("usb_drv_init");
451 /* Enable PHY and clocks (but leave pullups disabled) */
453 logf("usb-drv: synopsis id: %lx", GSNPSID
);
456 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
457 wakeup_init(&endpoints
[ep
][DIR_IN
].complete
);
458 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
459 wakeup_init(&endpoints
[ep
][DIR_OUT
].complete
);
460 /* Enable global interrupts */
461 enable_global_interrupts();
464 void usb_drv_exit(void)
466 logf("usb_drv_exit");
468 disable_global_interrupts();
469 as3525v2_disconnect();
473 static void handle_ep_in_int(int ep
)
475 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_IN
];
476 unsigned long sts
= DIEPINT(ep
);
477 if(sts
& DIEPINT_ahberr
)
478 panicf("usb-drv: ahb error on EP%d IN", ep
);
479 if(sts
& DIEPINT_xfercompl
)
483 endpoint
->busy
= false;
484 endpoint
->status
= 0;
485 /* works even for EP0 */
486 int size
= (DIEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
487 int transfered
= endpoint
->len
- size
;
488 logf("len=%d reg=%ld xfer=%d", endpoint
->len
, size
, transfered
);
489 /* handle EP0 state if necessary,
490 * this is a ack if length is 0 */
492 handle_ep0_complete(endpoint
->len
== 0);
493 endpoint
->len
= size
;
494 usb_core_transfer_complete(ep
, USB_DIR_IN
, 0, transfered
);
497 endpoint
->wait
= false;
498 wakeup_signal(&endpoint
->complete
);
502 if(sts
& DIEPINT_timeout
)
504 panicf("usb-drv: timeout on EP%d IN", ep
);
507 endpoint
->busy
= false;
508 endpoint
->status
= -1;
509 /* for safety, act as if no bytes as been transfered */
511 usb_core_transfer_complete(ep
, USB_DIR_IN
, 1, 0);
514 endpoint
->wait
= false;
515 wakeup_signal(&endpoint
->complete
);
519 /* clear interrupts */
523 static void handle_ep_out_int(int ep
)
525 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_OUT
];
526 unsigned long sts
= DOEPINT(ep
);
527 if(sts
& DOEPINT_ahberr
)
528 panicf("usb-drv: ahb error on EP%d OUT", ep
);
529 if(sts
& DOEPINT_xfercompl
)
531 logf("usb-drv: xfer complete on EP%d OUT", ep
);
534 endpoint
->busy
= false;
535 endpoint
->status
= 0;
536 /* works even for EP0 */
537 int transfered
= endpoint
->len
- (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
538 logf("len=%d reg=%ld xfer=%d", endpoint
->len
,
539 (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
),
541 /* handle EP0 state if necessary,
542 * this is a ack if length is 0 */
544 handle_ep0_complete(endpoint
->len
== 0);
545 usb_core_transfer_complete(ep
, USB_DIR_OUT
, 0, transfered
);
548 endpoint
->wait
= false;
549 wakeup_signal(&endpoint
->complete
);
553 if(sts
& DOEPINT_setup
)
555 logf("usb-drv: setup on EP%d OUT", ep
);
557 panicf("usb-drv: setup not on EP0, this is impossible");
558 if((DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
) != 0)
560 logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
565 /* handle EP0 state */
567 logf(" rt=%x r=%x", ep0_setup_pkt
->bRequestType
, ep0_setup_pkt
->bRequest
);
568 /* handle set address */
569 if(ep0_setup_pkt
->bRequestType
== USB_TYPE_STANDARD
&&
570 ep0_setup_pkt
->bRequest
== USB_REQ_SET_ADDRESS
)
572 /* Set address now */
573 DCFG
= (DCFG
& ~bitm(DCFG
, devadr
)) | (ep0_setup_pkt
->wValue
<< DCFG_devadr_bitp
);
575 usb_core_control_request(ep0_setup_pkt
);
578 /* clear interrupts */
582 static void handle_ep_ints(void)
584 logf("usb-drv: ep int");
585 /* we must read it */
586 unsigned long daint
= DAINT
;
589 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
590 if(daint
& DAINT_IN_EP(ep
))
591 handle_ep_in_int(ep
);
593 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
594 if(daint
& DAINT_OUT_EP(ep
))
595 handle_ep_out_int(ep
);
597 /* write back to clear status */
601 /* interrupt service routine */
604 /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
605 * so AND it with the actual mask */
606 unsigned long sts
= GINTSTS
& GINTMSK
;
608 if(sts
& GINTMSK_usbreset
)
610 logf("usb-drv: bus reset");
612 /* Clear the Remote Wakeup Signalling */
613 DCTL
&= ~DCTL_rmtwkupsig
;
616 flush_tx_fifos(0x10);
618 /* Flush the Learning Queue */
619 GRSTCTL
= GRSTCTL_intknqflsh
;
621 /* Reset Device Address */
622 DCFG
&= ~bitm(DCFG
, devadr
);
627 usb_core_bus_reset();
630 if(sts
& GINTMSK_enumdone
)
632 logf("usb-drv: enum done");
635 if(usb_drv_port_speed())
641 if(sts
& GINTMSK_otgintr
)
643 logf("usb-drv: otg int");
644 GOTGINT
= 0xffffffff;
647 if(sts
& (GINTMSK_outepintr
| GINTMSK_inepintr
))
652 if(sts
& GINTMSK_disconnect
)
654 panicf("usb-drv: disconnect");
655 cancel_all_transfers(true);
662 int usb_drv_port_speed(void)
664 static const uint8_t speed
[4] = {
665 [DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ
] = 1,
666 [DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ
] = 0,
667 [DSTS_ENUMSPD_FS_PHY_48MHZ
] = 0,
668 [DSTS_ENUMSPD_LS_PHY_6MHZ
] = 0,
671 unsigned enumspd
= extract(DSTS
, enumspd
);
673 if(enumspd
== DSTS_ENUMSPD_LS_PHY_6MHZ
)
674 panicf("usb-drv: LS is not supported");
676 return speed
[enumspd
& 3];
679 static unsigned long usb_drv_mps_by_type(int type
)
681 static const uint16_t mps
[4][2] = {
683 [USB_ENDPOINT_XFER_CONTROL
] = { 64, 64 },
684 [USB_ENDPOINT_XFER_ISOC
] = { 1023, 1024 },
685 [USB_ENDPOINT_XFER_BULK
] = { 64, 512 },
686 [USB_ENDPOINT_XFER_INT
] = { 64, 1024 },
688 return mps
[type
& 3][usb_drv_port_speed() & 1];
691 int usb_drv_request_endpoint(int type
, int dir
)
695 logf("usb-drv: request endpoint (type=%d,dir=%s)", type
, dir
== USB_DIR_IN
? "IN" : "OUT");
697 if(dir
== USB_DIR_IN
)
698 FOR_EACH_IN_EP(i
, ep
)
700 if(endpoints
[ep
][DIR_IN
].active
)
702 endpoints
[ep
][DIR_IN
].active
= true;
707 FOR_EACH_OUT_EP(i
, ep
)
709 if(endpoints
[ep
][DIR_OUT
].active
)
711 endpoints
[ep
][DIR_OUT
].active
= true;
718 logf("usb-drv: request failed");
722 unsigned long data
= DEPCTL_setd0pid
| (type
<< DEPCTL_eptype_bitp
)
723 | (usb_drv_mps_by_type(type
) << DEPCTL_mps_bitp
)
724 | DEPCTL_usbactep
| DEPCTL_snak
;
725 unsigned long mask
= ~(bitm(DEPCTL
, eptype
) | bitm(DEPCTL
, mps
));
727 if(dir
== USB_DIR_IN
) DIEPCTL(ep
) = (DIEPCTL(ep
) & mask
) | data
;
728 else DOEPCTL(ep
) = (DOEPCTL(ep
) & mask
) | data
;
733 void usb_drv_release_endpoint(int ep
)
735 logf("usb-drv: release EP%d %s", EP_NUM(ep
), EP_DIR(ep
) == DIR_IN
? "IN" : "OUT");
736 endpoints
[EP_NUM(ep
)][EP_DIR(ep
)].active
= false;
739 void usb_drv_cancel_all_transfers()
741 cancel_all_transfers(false);
744 static int usb_drv_transfer(int ep
, void *ptr
, int len
, bool dir_in
, bool blocking
)
748 logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep
,
749 len
, dir_in
, blocking
);
751 /* mask the usb interrupt to avoid any race */
752 VIC_INT_EN_CLEAR
= INTERRUPT_USB
;
754 volatile unsigned long *epctl
= dir_in
? &DIEPCTL(ep
) : &DOEPCTL(ep
);
755 volatile unsigned long *eptsiz
= dir_in
? &DIEPTSIZ(ep
) : &DOEPTSIZ(ep
);
756 volatile unsigned long *epdma
= dir_in
? &DIEPDMA(ep
) : &DOEPDMA(ep
);
757 struct usb_endpoint
*endpoint
= &endpoints
[ep
][dir_in
];
758 #define DEPCTL *epctl
759 #define DEPTSIZ *eptsiz
760 #define DEPDMA *epdma
763 logf("usb-drv: EP%d %s is already busy", ep
, dir_in
? "IN" : "OUT");
765 endpoint
->busy
= true;
767 endpoint
->wait
= blocking
;
768 endpoint
->status
= -1;
770 DEPCTL
&= ~DEPCTL_stall
;
771 DEPCTL
|= DEPCTL_usbactep
;
773 int mps
= usb_drv_mps_by_type(extract(DEPCTL
, eptype
));
774 int nb_packets
= (len
+ mps
- 1) / mps
;
779 DEPTSIZ
= 1 << DEPTSIZ_pkcnt_bitp
;
783 DEPDMA
= (unsigned long)AS3525_PHYSICAL_ADDR(ptr
);
784 DEPTSIZ
= (nb_packets
<< DEPTSIZ_pkcnt_bitp
) | len
;
786 clean_dcache_range(ptr
, len
);
788 dump_dcache_range(ptr
, len
);
791 logf("pkt=%d dma=%lx", nb_packets
, DEPDMA
);
793 DEPCTL
|= DEPCTL_epena
| DEPCTL_cnak
;
795 /* unmask the usb interrupt */
796 VIC_INT_ENABLE
= INTERRUPT_USB
;
800 wakeup_wait(&endpoint
->complete
, TIMEOUT_BLOCK
);
801 return endpoint
->status
;
811 int usb_drv_recv(int ep
, void *ptr
, int len
)
813 return usb_drv_transfer(ep
, ptr
, len
, false, false);
816 int usb_drv_send(int ep
, void *ptr
, int len
)
818 return usb_drv_transfer(ep
, ptr
, len
, true, true);
821 int usb_drv_send_nonblocking(int ep
, void *ptr
, int len
)
823 return usb_drv_transfer(ep
, ptr
, len
, true, false);
827 void usb_drv_set_test_mode(int mode
)
829 /* there is a perfect matching between usb test mode code
830 * and the register field value */
831 DCTL
= (DCTL
& ~bitm(DCTL
, tstctl
)) | (mode
<< DCTL_tstctl_bitp
);
834 void usb_drv_set_address(int address
)
839 void usb_drv_stall(int ep
, bool stall
, bool in
)
841 logf("usb-drv: %sstall EP%d %s", stall
? "" : "un", ep
, in
? "IN" : "OUT");
844 if(stall
) DIEPCTL(ep
) |= DEPCTL_stall
;
845 else DIEPCTL(ep
) &= ~DEPCTL_stall
;
849 if(stall
) DOEPCTL(ep
) |= DEPCTL_stall
;
850 else DOEPCTL(ep
) &= ~DEPCTL_stall
;
854 bool usb_drv_stalled(int ep
, bool in
)
856 return (in
? DIEPCTL(ep
) : DOEPCTL(ep
)) & DEPCTL_stall
;