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)
162 DCTL
|= DCTL_sftdiscon
;
167 bitclr32(&CGU_PERI
, CGU_USB_CLOCK_ENABLE
);
170 static void enable_device_interrupts(void)
172 /* Clear any pending interrupt */
173 GINTSTS
= 0xffffffff;
174 /* Clear any pending otg interrupt */
175 GOTGINT
= 0xffffffff;
176 /* Enable interrupts */
177 GINTMSK
= GINTMSK_usbreset
187 static void flush_tx_fifos(int nums
)
191 GRSTCTL
= (nums
<< GRSTCTL_txfnum_bitp
)
192 | GRSTCTL_txfflsh_flush
;
193 while(GRSTCTL
& GRSTCTL_txfflsh_flush
&& i
< 0x300)
195 if(GRSTCTL
& GRSTCTL_txfflsh_flush
)
196 panicf("usb-drv: hang of flush tx fifos (%x)", nums
);
197 /* wait 3 phy clocks */
201 static void prepare_setup_ep0(void)
203 logf("usb-drv: prepare EP0");
205 DOEPDMA(0) = (unsigned long)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt
);
207 /* Setup EP0 OUT with the following parameters:
209 * setup packet count = 1
210 * transfer size = 8 (setup packet)
212 DOEPTSIZ(0) = (1 << DEPTSIZ0_supcnt_bitp
)
213 | (1 << DEPTSIZ0_pkcnt_bitp
)
216 /* Enable endpoint, clear nak */
217 ep0_state
= EP0_WAIT_SETUP
;
218 DOEPCTL(0) |= DEPCTL_epena
| DEPCTL_cnak
;
221 static void handle_ep0_complete(bool is_ack
)
226 panicf("usb-drv: EP0 completion while waiting for SETUP");
229 /* everything is done, prepare next setup */
232 panicf("usb-drv: EP0 data completion while waiting for ACK");
236 panicf("usb-drv: EP0 ACK while waiting for data completion");
238 /* everything is done, prepare next setup */
241 case EP0_WAIT_DATA_ACK
:
244 ep0_state
= EP0_WAIT_DATA
;
246 ep0_state
= EP0_WAIT_ACK
;
249 panicf("usb-drv: invalid EP0 state");
251 logf("usb-drv: EP0 state updated to %d", ep0_state
);
254 static void handle_ep0_setup(void)
256 if(ep0_state
!= EP0_WAIT_SETUP
)
258 logf("usb-drv: EP0 SETUP while in state %d", ep0_state
);
261 /* determine is there is a data phase */
262 if(ep0_setup_pkt
->wLength
== 0)
263 /* no: wait for ack */
264 ep0_state
= EP0_WAIT_ACK
;
266 /* yes: wait ack and data */
267 ep0_state
= EP0_WAIT_DATA_ACK
;
268 logf("usb-drv: EP0 state updated to %d", ep0_state
);
271 static void reset_endpoints(void)
275 /* disable all endpoints except EP0 */
276 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
278 endpoints
[ep
][DIR_IN
].active
= false;
279 endpoints
[ep
][DIR_IN
].busy
= false;
280 endpoints
[ep
][DIR_IN
].status
= -1;
281 if(endpoints
[ep
][DIR_IN
].wait
)
283 endpoints
[ep
][DIR_IN
].wait
= false;
284 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
286 if(DIEPCTL(ep
) & DEPCTL_epena
)
287 DIEPCTL(ep
) = DEPCTL_snak
;
292 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
294 endpoints
[ep
][DIR_OUT
].active
= false;
295 endpoints
[ep
][DIR_OUT
].busy
= false;
296 endpoints
[ep
][DIR_OUT
].status
= -1;
297 if(endpoints
[ep
][DIR_OUT
].wait
)
299 endpoints
[ep
][DIR_OUT
].wait
= false;
300 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
302 if(DOEPCTL(ep
) & DEPCTL_epena
)
303 DOEPCTL(ep
) = DEPCTL_snak
;
307 /* 64 bytes packet size, active endpoint */
308 DOEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
309 DIEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
310 /* Setup next chain for IN eps */
311 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
313 int next_ep
= in_ep_list
[(i
+ 1) % (NUM_IN_EP
+ 1)];
314 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~bitm(DEPCTL
, nextep
)) | (next_ep
<< DEPCTL_nextep_bitp
);
318 static void cancel_all_transfers(bool cancel_ep0
)
320 logf("usb-drv: cancel all transfers");
321 int flags
= disable_irq_save();
325 FOR_EACH_IN_EP_EX(cancel_ep0
, i
, ep
)
327 endpoints
[ep
][DIR_IN
].status
= -1;
328 endpoints
[ep
][DIR_IN
].busy
= false;
329 if(endpoints
[ep
][DIR_IN
].wait
)
331 endpoints
[ep
][DIR_IN
].wait
= false;
332 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
334 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
336 FOR_EACH_OUT_EP_EX(cancel_ep0
, i
, ep
)
338 endpoints
[ep
][DIR_OUT
].status
= -1;
339 endpoints
[ep
][DIR_OUT
].busy
= false;
340 if(endpoints
[ep
][DIR_OUT
].wait
)
342 endpoints
[ep
][DIR_OUT
].wait
= false;
343 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
345 DOEPCTL(ep
) = (DOEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
351 static void core_dev_init(void)
355 /* Restart the phy clock */
357 /* Set phy speed : high speed */
358 DCFG
= (DCFG
& ~bitm(DCFG
, devspd
)) | DCFG_devspd_hs_phy_hs
;
360 /* Check hardware capabilities */
361 if(extract(GHWCFG2
, arch
) != GHWCFG2_ARCH_INTERNAL_DMA
)
362 panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2
, arch
));
363 if(extract(GHWCFG2
, hs_phy_type
) != GHWCFG2_PHY_TYPE_UTMI
)
364 panicf("usb-drv: wrong HS phy type (%ld)", extract(GHWCFG2
, hs_phy_type
));
365 if(extract(GHWCFG2
, fs_phy_type
) != GHWCFG2_PHY_TYPE_UNSUPPORTED
)
366 panicf("usb-drv: wrong FS phy type (%ld)", extract(GHWCFG2
, fs_phy_type
));
367 if(extract(GHWCFG4
, utmi_phy_data_width
) != 0x2)
368 panicf("usb-drv: wrong utmi data width (%ld)", extract(GHWCFG4
, utmi_phy_data_width
));
369 if(!(GHWCFG4
& GHWCFG4_ded_fifo_en
)) /* it seems to be multiple tx fifo support */
370 panicf("usb-drv: no multiple tx fifo");
372 #ifdef USE_CUSTOM_FIFO_LAYOUT
373 if(!(GHWCFG2
& GHWCFG2_dyn_fifo
))
374 panicf("usb-drv: no dynamic fifo");
375 if(GRXFSIZ
!= DATA_FIFO_DEPTH
)
376 panicf("usb-drv: wrong data fifo size");
377 #endif /* USE_CUSTOM_FIFO_LAYOUT */
379 if(USB_NUM_ENDPOINTS
!= extract(GHWCFG2
, num_ep
))
380 panicf("usb-drv: wrong endpoint number");
382 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
384 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
385 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_IN
)
386 panicf("usb-drv: EP%d is no IN or BIDIR", ep
);
388 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
390 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
391 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_OUT
)
392 panicf("usb-drv: EP%d is no OUT or BIDIR", ep
);
397 GNPTXFSIZ
= MAKE_FIFOSIZE_DATA(512, 512);
399 /* Setup interrupt masks for endpoints */
400 /* Setup interrupt masks */
401 DOEPMSK
= DOEPINT_setup
| DOEPINT_xfercompl
| DOEPINT_ahberr
;
402 DIEPMSK
= DIEPINT_xfercompl
| DIEPINT_timeout
| DIEPINT_ahberr
;
403 DAINTMSK
= 0xffffffff;
409 /* enable USB interrupts */
410 enable_device_interrupts();
413 static void core_init(void)
416 DCTL
|= DCTL_sftdiscon
;
417 /* Select UTMI+ 16 */
418 GUSBCFG
|= GUSBCFG_phy_if
;
419 GUSBCFG
= (GUSBCFG
& ~bitm(GUSBCFG
, toutcal
)) | 7 << GUSBCFG_toutcal_bitp
;
421 /* fixme: the current code is for internal DMA only, the clip+ architecture
422 * define the internal DMA model */
423 /* Set burstlen and enable DMA*/
424 GAHBCFG
= (GAHBCFG_INT_DMA_BURST_INCR
<< GAHBCFG_hburstlen_bitp
)
425 | GAHBCFG_dma_enable
;
426 /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */
427 GUSBCFG
&= ~(GUSBCFG_srpcap
| GUSBCFG_hnpcapp
);
429 /* perform device model specific init */
433 DCTL
&= ~DCTL_sftdiscon
;
436 static void enable_global_interrupts(void)
438 VIC_INT_ENABLE
= INTERRUPT_USB
;
439 GAHBCFG
|= GAHBCFG_glblintrmsk
;
442 static void disable_global_interrupts(void)
444 GAHBCFG
&= ~GAHBCFG_glblintrmsk
;
445 VIC_INT_EN_CLEAR
= INTERRUPT_USB
;
448 void usb_drv_init(void)
451 logf("usb_drv_init");
454 /* Enable PHY and clocks (but leave pullups disabled) */
456 logf("usb-drv: synopsis id: %lx", GSNPSID
);
459 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
460 wakeup_init(&endpoints
[ep
][DIR_IN
].complete
);
461 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
462 wakeup_init(&endpoints
[ep
][DIR_OUT
].complete
);
463 /* Enable global interrupts */
464 enable_global_interrupts();
467 void usb_drv_exit(void)
469 logf("usb_drv_exit");
471 disable_global_interrupts();
472 as3525v2_disconnect();
476 static void handle_ep_in_int(int ep
)
478 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_IN
];
479 unsigned long sts
= DIEPINT(ep
);
480 if(sts
& DIEPINT_ahberr
)
481 panicf("usb-drv: ahb error on EP%d IN", ep
);
482 if(sts
& DIEPINT_xfercompl
)
486 endpoint
->busy
= false;
487 endpoint
->status
= 0;
488 /* works even for EP0 */
489 int size
= (DIEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
490 int transfered
= endpoint
->len
- size
;
491 logf("len=%d reg=%d xfer=%d", endpoint
->len
, size
, transfered
);
492 /* handle EP0 state if necessary,
493 * this is a ack if length is 0 */
495 handle_ep0_complete(endpoint
->len
== 0);
496 endpoint
->len
= size
;
497 usb_core_transfer_complete(ep
, USB_DIR_IN
, 0, transfered
);
500 endpoint
->wait
= false;
501 wakeup_signal(&endpoint
->complete
);
505 if(sts
& DIEPINT_timeout
)
507 panicf("usb-drv: timeout on EP%d IN", ep
);
510 endpoint
->busy
= false;
511 endpoint
->status
= -1;
512 /* for safety, act as if no bytes as been transfered */
514 usb_core_transfer_complete(ep
, USB_DIR_IN
, 1, 0);
517 endpoint
->wait
= false;
518 wakeup_signal(&endpoint
->complete
);
522 /* clear interrupts */
526 static void handle_ep_out_int(int ep
)
528 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_OUT
];
529 unsigned long sts
= DOEPINT(ep
);
530 if(sts
& DOEPINT_ahberr
)
531 panicf("usb-drv: ahb error on EP%d OUT", ep
);
532 if(sts
& DOEPINT_xfercompl
)
534 logf("usb-drv: xfer complete on EP%d OUT", ep
);
537 endpoint
->busy
= false;
538 endpoint
->status
= 0;
539 /* works even for EP0 */
540 int transfered
= endpoint
->len
- (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
541 logf("len=%d reg=%ld xfer=%d", endpoint
->len
,
542 (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
),
544 /* handle EP0 state if necessary,
545 * this is a ack if length is 0 */
547 handle_ep0_complete(endpoint
->len
== 0);
548 usb_core_transfer_complete(ep
, USB_DIR_OUT
, 0, transfered
);
551 endpoint
->wait
= false;
552 wakeup_signal(&endpoint
->complete
);
556 if(sts
& DOEPINT_setup
)
558 logf("usb-drv: setup on EP%d OUT", ep
);
560 panicf("usb-drv: setup not on EP0, this is impossible");
561 if((DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
) != 0)
563 logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
568 /* handle EP0 state */
570 logf(" rt=%x r=%x", ep0_setup_pkt
->bRequestType
, ep0_setup_pkt
->bRequest
);
571 /* handle set address */
572 if(ep0_setup_pkt
->bRequestType
== USB_TYPE_STANDARD
&&
573 ep0_setup_pkt
->bRequest
== USB_REQ_SET_ADDRESS
)
575 /* Set address now */
576 DCFG
= (DCFG
& ~bitm(DCFG
, devadr
)) | (ep0_setup_pkt
->wValue
<< DCFG_devadr_bitp
);
578 usb_core_control_request(ep0_setup_pkt
);
581 /* clear interrupts */
585 static void handle_ep_ints(void)
587 logf("usb-drv: ep int");
588 /* we must read it */
589 unsigned long daint
= DAINT
;
592 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
593 if(daint
& DAINT_IN_EP(ep
))
594 handle_ep_in_int(ep
);
596 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
597 if(daint
& DAINT_OUT_EP(ep
))
598 handle_ep_out_int(ep
);
600 /* write back to clear status */
604 /* interrupt service routine */
607 /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
608 * so AND it with the actual mask */
609 unsigned long sts
= GINTSTS
& GINTMSK
;
611 if(sts
& GINTMSK_usbreset
)
613 logf("usb-drv: bus reset");
615 /* Clear the Remote Wakeup Signalling */
616 DCTL
&= ~DCTL_rmtwkupsig
;
619 flush_tx_fifos(0x10);
621 /* Flush the Learning Queue */
622 GRSTCTL
= GRSTCTL_intknqflsh
;
624 /* Reset Device Address */
625 DCFG
&= ~bitm(DCFG
, devadr
);
630 usb_core_bus_reset();
633 if(sts
& GINTMSK_enumdone
)
635 logf("usb-drv: enum done");
638 if(usb_drv_port_speed())
644 if(sts
& GINTMSK_otgintr
)
646 logf("usb-drv: otg int");
647 GOTGINT
= 0xffffffff;
650 if(sts
& (GINTMSK_outepintr
| GINTMSK_inepintr
))
655 if(sts
& GINTMSK_disconnect
)
657 panicf("usb-drv: disconnect");
658 cancel_all_transfers(true);
665 int usb_drv_port_speed(void)
667 static const uint8_t speed
[4] = {
668 [DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ
] = 1,
669 [DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ
] = 0,
670 [DSTS_ENUMSPD_FS_PHY_48MHZ
] = 0,
671 [DSTS_ENUMSPD_LS_PHY_6MHZ
] = 0,
674 unsigned enumspd
= extract(DSTS
, enumspd
);
676 if(enumspd
== DSTS_ENUMSPD_LS_PHY_6MHZ
)
677 panicf("usb-drv: LS is not supported");
679 return speed
[enumspd
& 3];
682 static unsigned long usb_drv_mps_by_type(int type
)
684 static const uint16_t mps
[4][2] = {
686 [USB_ENDPOINT_XFER_CONTROL
] = { 64, 64 },
687 [USB_ENDPOINT_XFER_ISOC
] = { 1023, 1024 },
688 [USB_ENDPOINT_XFER_BULK
] = { 64, 512 },
689 [USB_ENDPOINT_XFER_INT
] = { 64, 1024 },
691 return mps
[type
& 3][usb_drv_port_speed() & 1];
694 int usb_drv_request_endpoint(int type
, int dir
)
698 logf("usb-drv: request endpoint (type=%d,dir=%s)", type
, dir
== USB_DIR_IN
? "IN" : "OUT");
700 if(dir
== USB_DIR_IN
)
701 FOR_EACH_IN_EP(i
, ep
)
703 if(endpoints
[ep
][DIR_IN
].active
)
705 endpoints
[ep
][DIR_IN
].active
= true;
710 FOR_EACH_OUT_EP(i
, ep
)
712 if(endpoints
[ep
][DIR_OUT
].active
)
714 endpoints
[ep
][DIR_OUT
].active
= true;
721 logf("usb-drv: request failed");
725 unsigned long data
= DEPCTL_setd0pid
| (type
<< DEPCTL_eptype_bitp
)
726 | (usb_drv_mps_by_type(type
) << DEPCTL_mps_bitp
)
727 | DEPCTL_usbactep
| DEPCTL_snak
;
728 unsigned long mask
= ~(bitm(DEPCTL
, eptype
) | bitm(DEPCTL
, mps
));
730 if(dir
== USB_DIR_IN
) DIEPCTL(ep
) = (DIEPCTL(ep
) & mask
) | data
;
731 else DOEPCTL(ep
) = (DOEPCTL(ep
) & mask
) | data
;
736 void usb_drv_release_endpoint(int ep
)
738 logf("usb-drv: release EP%d %s", EP_NUM(ep
), EP_DIR(ep
) == DIR_IN
? "IN" : "OUT");
739 endpoints
[EP_NUM(ep
)][EP_DIR(ep
)].active
= false;
742 void usb_drv_cancel_all_transfers()
744 cancel_all_transfers(false);
747 static int usb_drv_transfer(int ep
, void *ptr
, int len
, bool dir_in
, bool blocking
)
751 logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep
,
752 len
, dir_in
, blocking
);
754 /* disable interrupts to avoid any race */
755 int oldlevel
= disable_irq_save();
757 volatile unsigned long *epctl
= dir_in
? &DIEPCTL(ep
) : &DOEPCTL(ep
);
758 volatile unsigned long *eptsiz
= dir_in
? &DIEPTSIZ(ep
) : &DOEPTSIZ(ep
);
759 volatile unsigned long *epdma
= dir_in
? &DIEPDMA(ep
) : &DOEPDMA(ep
);
760 struct usb_endpoint
*endpoint
= &endpoints
[ep
][dir_in
];
761 #define DEPCTL *epctl
762 #define DEPTSIZ *eptsiz
763 #define DEPDMA *epdma
766 logf("usb-drv: EP%d %s is already busy", ep
, dir_in
? "IN" : "OUT");
768 endpoint
->busy
= true;
770 endpoint
->wait
= blocking
;
771 endpoint
->status
= -1;
773 DEPCTL
&= ~DEPCTL_stall
;
774 DEPCTL
|= DEPCTL_usbactep
;
776 int mps
= usb_drv_mps_by_type(extract(DEPCTL
, eptype
));
777 int nb_packets
= (len
+ mps
- 1) / mps
;
782 DEPTSIZ
= 1 << DEPTSIZ_pkcnt_bitp
;
786 DEPDMA
= (unsigned long)AS3525_PHYSICAL_ADDR(ptr
);
787 DEPTSIZ
= (nb_packets
<< DEPTSIZ_pkcnt_bitp
) | len
;
789 clean_dcache_range(ptr
, len
);
791 dump_dcache_range(ptr
, len
);
794 logf("pkt=%d dma=%lx", nb_packets
, DEPDMA
);
796 DEPCTL
|= DEPCTL_epena
| DEPCTL_cnak
;
798 /* restore interrupts */
799 restore_irq(oldlevel
);
803 wakeup_wait(&endpoint
->complete
, TIMEOUT_BLOCK
);
804 return endpoint
->status
;
814 int usb_drv_recv(int ep
, void *ptr
, int len
)
816 return usb_drv_transfer(ep
, ptr
, len
, false, false);
819 int usb_drv_send(int ep
, void *ptr
, int len
)
821 return usb_drv_transfer(ep
, ptr
, len
, true, true);
824 int usb_drv_send_nonblocking(int ep
, void *ptr
, int len
)
826 return usb_drv_transfer(ep
, ptr
, len
, true, false);
830 void usb_drv_set_test_mode(int mode
)
832 /* there is a perfect matching between usb test mode code
833 * and the register field value */
834 DCTL
= (DCTL
& ~bitm(DCTL
, tstctl
)) | (mode
<< DCTL_tstctl_bitp
);
837 void usb_drv_set_address(int address
)
842 void usb_drv_stall(int ep
, bool stall
, bool in
)
844 logf("usb-drv: %sstall EP%d %s", stall
? "" : "un", ep
, in
? "IN" : "OUT");
847 if(stall
) DIEPCTL(ep
) |= DEPCTL_stall
;
848 else DIEPCTL(ep
) &= ~DEPCTL_stall
;
852 if(stall
) DOEPCTL(ep
) |= DEPCTL_stall
;
853 else DOEPCTL(ep
) &= ~DEPCTL_stall
;
857 bool usb_drv_stalled(int ep
, bool in
)
859 return (in
? DIEPCTL(ep
) : DOEPCTL(ep
)) & DEPCTL_stall
;