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
)
279 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
280 endpoints
[ep
][DIR_IN
].wait
= false;
281 if(DIEPCTL(ep
) & DEPCTL_epena
)
282 DIEPCTL(ep
) = DEPCTL_snak
;
287 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
289 endpoints
[ep
][DIR_OUT
].active
= false;
290 endpoints
[ep
][DIR_OUT
].busy
= false;
291 endpoints
[ep
][DIR_OUT
].status
= -1;
292 if(endpoints
[ep
][DIR_OUT
].wait
)
293 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
294 endpoints
[ep
][DIR_OUT
].wait
= false;
295 if(DOEPCTL(ep
) & DEPCTL_epena
)
296 DOEPCTL(ep
) = DEPCTL_snak
;
300 /* 64 bytes packet size, active endpoint */
301 DOEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
302 DIEPCTL(0) = (DEPCTL_MPS_64
<< DEPCTL_mps_bitp
) | DEPCTL_usbactep
| DEPCTL_snak
;
303 /* Setup next chain for IN eps */
304 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
306 int next_ep
= in_ep_list
[(i
+ 2) % (NUM_IN_EP
+ 1)];
307 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~bitm(DEPCTL
, nextep
)) | (next_ep
<< DEPCTL_nextep_bitp
);
311 static void cancel_all_transfers(bool cancel_ep0
)
313 logf("usb-drv: cancel all transfers");
314 int flags
= disable_irq_save();
318 FOR_EACH_IN_EP_EX(cancel_ep0
, i
, ep
)
320 endpoints
[ep
][DIR_IN
].status
= -1;
321 endpoints
[ep
][DIR_IN
].wait
= false;
322 endpoints
[ep
][DIR_IN
].busy
= false;
323 wakeup_signal(&endpoints
[ep
][DIR_IN
].complete
);
324 DIEPCTL(ep
) = (DIEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
326 FOR_EACH_OUT_EP_EX(cancel_ep0
, i
, ep
)
328 endpoints
[ep
][DIR_OUT
].status
= -1;
329 endpoints
[ep
][DIR_OUT
].wait
= false;
330 endpoints
[ep
][DIR_OUT
].busy
= false;
331 wakeup_signal(&endpoints
[ep
][DIR_OUT
].complete
);
332 DOEPCTL(ep
) = (DOEPCTL(ep
) & ~DEPCTL_usbactep
) | DEPCTL_snak
;
338 static void core_dev_init(void)
342 /* Restart the phy clock */
344 /* Set phy speed : high speed */
345 DCFG
= (DCFG
& ~bitm(DCFG
, devspd
)) | DCFG_devspd_hs_phy_hs
;
347 /* Check hardware capabilities */
348 if(extract(GHWCFG2
, arch
) != GHWCFG2_ARCH_INTERNAL_DMA
)
349 panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2
, arch
));
350 if(extract(GHWCFG2
, hs_phy_type
) != GHWCFG2_PHY_TYPE_UTMI
)
351 panicf("usb-drv: wrong HS phy type (%ld)", extract(GHWCFG2
, hs_phy_type
));
352 if(extract(GHWCFG2
, fs_phy_type
) != GHWCFG2_PHY_TYPE_UNSUPPORTED
)
353 panicf("usb-drv: wrong FS phy type (%ld)", extract(GHWCFG2
, fs_phy_type
));
354 if(extract(GHWCFG4
, utmi_phy_data_width
) != 0x2)
355 panicf("usb-drv: wrong utmi data width (%ld)", extract(GHWCFG4
, utmi_phy_data_width
));
356 if(!(GHWCFG4
& GHWCFG4_ded_fifo_en
)) /* it seems to be multiple tx fifo support */
357 panicf("usb-drv: no multiple tx fifo");
359 #ifdef USE_CUSTOM_FIFO_LAYOUT
360 if(!(GHWCFG2
& GHWCFG2_dyn_fifo
))
361 panicf("usb-drv: no dynamic fifo");
362 if(GRXFSIZ
!= DATA_FIFO_DEPTH
)
363 panicf("usb-drv: wrong data fifo size");
364 #endif /* USE_CUSTOM_FIFO_LAYOUT */
366 if(USB_NUM_ENDPOINTS
!= extract(GHWCFG2
, num_ep
))
367 panicf("usb-drv: wrong endpoint number");
369 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
371 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
372 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_IN
)
373 panicf("usb-drv: EP%d is no IN or BIDIR", ep
);
375 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
377 int type
= (GHWCFG1
>> GHWCFG1_epdir_bitp(ep
)) & GHWCFG1_epdir_bits
;
378 if(type
!= GHWCFG1_EPDIR_BIDIR
&& type
!= GHWCFG1_EPDIR_OUT
)
379 panicf("usb-drv: EP%d is no OUT or BIDIR", ep
);
384 GNPTXFSIZ
= MAKE_FIFOSIZE_DATA(512, 512);
386 /* Setup interrupt masks for endpoints */
387 /* Setup interrupt masks */
388 DOEPMSK
= DOEPINT_setup
| DOEPINT_xfercompl
| DOEPINT_ahberr
;
389 DIEPMSK
= DIEPINT_xfercompl
| DIEPINT_timeout
| DIEPINT_ahberr
;
390 DAINTMSK
= 0xffffffff;
396 /* enable USB interrupts */
397 enable_device_interrupts();
400 static void core_init(void)
403 DCTL
|= DCTL_sftdiscon
;
404 /* Select UTMI+ 16 */
405 GUSBCFG
|= GUSBCFG_phy_if
;
406 GUSBCFG
= (GUSBCFG
& ~bitm(GUSBCFG
, toutcal
)) | 7 << GUSBCFG_toutcal_bitp
;
408 /* fixme: the current code is for internal DMA only, the clip+ architecture
409 * define the internal DMA model */
410 /* Set burstlen and enable DMA*/
411 GAHBCFG
= (GAHBCFG_INT_DMA_BURST_INCR
<< GAHBCFG_hburstlen_bitp
)
412 | GAHBCFG_dma_enable
;
413 /* Disable HNP and SRP, not sure it's useful because we already forced dev mode */
414 GUSBCFG
&= ~(GUSBCFG_srpcap
| GUSBCFG_hnpcapp
);
416 /* perform device model specific init */
420 DCTL
&= ~DCTL_sftdiscon
;
423 static void enable_global_interrupts(void)
425 VIC_INT_ENABLE
= INTERRUPT_USB
;
426 GAHBCFG
|= GAHBCFG_glblintrmsk
;
429 static void disable_global_interrupts(void)
431 GAHBCFG
&= ~GAHBCFG_glblintrmsk
;
432 VIC_INT_EN_CLEAR
= INTERRUPT_USB
;
435 void usb_drv_init(void)
438 logf("usb_drv_init");
441 /* Enable PHY and clocks (but leave pullups disabled) */
443 logf("usb-drv: synopsis id: %lx", GSNPSID
);
446 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
447 wakeup_init(&endpoints
[ep
][DIR_IN
].complete
);
448 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
449 wakeup_init(&endpoints
[ep
][DIR_OUT
].complete
);
450 /* Enable global interrupts */
451 enable_global_interrupts();
454 void usb_drv_exit(void)
456 logf("usb_drv_exit");
458 disable_global_interrupts();
459 as3525v2_disconnect();
463 static void handle_ep_in_int(int ep
)
465 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_IN
];
466 unsigned long sts
= DIEPINT(ep
);
467 if(sts
& DIEPINT_ahberr
)
468 panicf("usb-drv: ahb error on EP%d IN", ep
);
469 if(sts
& DIEPINT_xfercompl
)
473 endpoint
->busy
= false;
474 endpoint
->status
= 0;
475 /* works even for EP0 */
476 int size
= (DIEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
477 int transfered
= endpoint
->len
- size
;
478 logf("len=%d reg=%ld xfer=%d", endpoint
->len
, size
, transfered
);
479 /* handle EP0 state if necessary,
480 * this is a ack if length is 0 */
482 handle_ep0_complete(endpoint
->len
== 0);
483 endpoint
->len
= size
;
484 usb_core_transfer_complete(ep
, USB_DIR_IN
, 0, transfered
);
485 wakeup_signal(&endpoint
->complete
);
488 if(sts
& DIEPINT_timeout
)
490 panicf("usb-drv: timeout on EP%d IN", ep
);
493 endpoint
->busy
= false;
494 endpoint
->status
= -1;
495 /* for safety, act as if no bytes as been transfered */
497 usb_core_transfer_complete(ep
, USB_DIR_IN
, 1, 0);
498 wakeup_signal(&endpoint
->complete
);
501 /* clear interrupts */
505 static void handle_ep_out_int(int ep
)
507 struct usb_endpoint
*endpoint
= &endpoints
[ep
][DIR_OUT
];
508 unsigned long sts
= DOEPINT(ep
);
509 if(sts
& DOEPINT_ahberr
)
510 panicf("usb-drv: ahb error on EP%d OUT", ep
);
511 if(sts
& DOEPINT_xfercompl
)
513 logf("usb-drv: xfer complete on EP%d OUT", ep
);
516 endpoint
->busy
= false;
517 endpoint
->status
= 0;
518 /* works even for EP0 */
519 int transfered
= endpoint
->len
- (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
520 logf("len=%d reg=%ld xfer=%d", endpoint
->len
,
521 (DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
),
523 /* handle EP0 state if necessary,
524 * this is a ack if length is 0 */
526 handle_ep0_complete(endpoint
->len
== 0);
527 usb_core_transfer_complete(ep
, USB_DIR_OUT
, 0, transfered
);
528 wakeup_signal(&endpoint
->complete
);
531 if(sts
& DOEPINT_setup
)
533 logf("usb-drv: setup on EP%d OUT", ep
);
535 panicf("usb-drv: setup not on EP0, this is impossible");
536 if((DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
) != 0)
538 logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep
) & DEPTSIZ_xfersize_bits
);
543 /* handle EP0 state */
545 logf(" rt=%x r=%x", ep0_setup_pkt
->bRequestType
, ep0_setup_pkt
->bRequest
);
546 /* handle set address */
547 if(ep0_setup_pkt
->bRequestType
== USB_TYPE_STANDARD
&&
548 ep0_setup_pkt
->bRequest
== USB_REQ_SET_ADDRESS
)
550 /* Set address now */
551 DCFG
= (DCFG
& ~bitm(DCFG
, devadr
)) | (ep0_setup_pkt
->wValue
<< DCFG_devadr_bitp
);
553 usb_core_control_request(ep0_setup_pkt
);
556 /* clear interrupts */
560 static void handle_ep_ints(void)
562 logf("usb-drv: ep int");
563 /* we must read it */
564 unsigned long daint
= DAINT
;
567 FOR_EACH_IN_EP_AND_EP0(i
, ep
)
568 if(daint
& DAINT_IN_EP(ep
))
569 handle_ep_in_int(ep
);
571 FOR_EACH_OUT_EP_AND_EP0(i
, ep
)
572 if(daint
& DAINT_OUT_EP(ep
))
573 handle_ep_out_int(ep
);
575 /* write back to clear status */
579 /* interrupt service routine */
582 /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
583 * so AND it with the actual mask */
584 unsigned long sts
= GINTSTS
& GINTMSK
;
586 if(sts
& GINTMSK_usbreset
)
588 logf("usb-drv: bus reset");
590 /* Clear the Remote Wakeup Signalling */
591 DCTL
&= ~DCTL_rmtwkupsig
;
594 flush_tx_fifos(0x10);
596 /* Flush the Learning Queue */
597 GRSTCTL
= GRSTCTL_intknqflsh
;
599 /* Reset Device Address */
600 DCFG
&= ~bitm(DCFG
, devadr
);
605 usb_core_bus_reset();
608 if(sts
& GINTMSK_enumdone
)
610 logf("usb-drv: enum done");
613 if(usb_drv_port_speed())
619 if(sts
& GINTMSK_otgintr
)
621 logf("usb-drv: otg int");
622 GOTGINT
= 0xffffffff;
625 if(sts
& (GINTMSK_outepintr
| GINTMSK_inepintr
))
630 if(sts
& GINTMSK_disconnect
)
632 panicf("usb-drv: disconnect");
633 cancel_all_transfers(true);
640 int usb_drv_port_speed(void)
642 static const uint8_t speed
[4] = {
643 [DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ
] = 1,
644 [DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ
] = 0,
645 [DSTS_ENUMSPD_FS_PHY_48MHZ
] = 0,
646 [DSTS_ENUMSPD_LS_PHY_6MHZ
] = 0,
649 unsigned enumspd
= extract(DSTS
, enumspd
);
651 if(enumspd
== DSTS_ENUMSPD_LS_PHY_6MHZ
)
652 panicf("usb-drv: LS is not supported");
654 return speed
[enumspd
& 3];
657 static unsigned long usb_drv_mps_by_type(int type
)
659 static const uint16_t mps
[4][2] = {
661 [USB_ENDPOINT_XFER_CONTROL
] = { 64, 64 },
662 [USB_ENDPOINT_XFER_ISOC
] = { 1023, 1024 },
663 [USB_ENDPOINT_XFER_BULK
] = { 64, 512 },
664 [USB_ENDPOINT_XFER_INT
] = { 64, 1024 },
666 return mps
[type
& 3][usb_drv_port_speed() & 1];
669 int usb_drv_request_endpoint(int type
, int dir
)
673 logf("usb-drv: request endpoint (type=%d,dir=%s)", type
, dir
== USB_DIR_IN
? "IN" : "OUT");
675 if(dir
== USB_DIR_IN
)
676 FOR_EACH_IN_EP(i
, ep
)
678 if(endpoints
[ep
][DIR_IN
].active
)
680 endpoints
[ep
][DIR_IN
].active
= true;
685 FOR_EACH_OUT_EP(i
, ep
)
687 if(endpoints
[ep
][DIR_OUT
].active
)
689 endpoints
[ep
][DIR_OUT
].active
= true;
696 logf("usb-drv: request failed");
700 unsigned long data
= DEPCTL_setd0pid
| (type
<< DEPCTL_eptype_bitp
)
701 | (usb_drv_mps_by_type(type
) << DEPCTL_mps_bitp
)
702 | DEPCTL_usbactep
| DEPCTL_snak
;
703 unsigned long mask
= ~(bitm(DEPCTL
, eptype
) | bitm(DEPCTL
, mps
));
705 if(dir
== USB_DIR_IN
) DIEPCTL(ep
) = (DIEPCTL(ep
) & mask
) | data
;
706 else DOEPCTL(ep
) = (DOEPCTL(ep
) & mask
) | data
;
711 void usb_drv_release_endpoint(int ep
)
713 logf("usb-drv: release EP%d %s", EP_NUM(ep
), EP_DIR(ep
) == DIR_IN
? "IN" : "OUT");
714 endpoints
[EP_NUM(ep
)][EP_DIR(ep
)].active
= false;
717 void usb_drv_cancel_all_transfers()
719 cancel_all_transfers(false);
722 static int usb_drv_transfer(int ep
, void *ptr
, int len
, bool dir_in
, bool blocking
)
726 logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep
,
727 len
, dir_in
, blocking
);
729 volatile unsigned long *epctl
= dir_in
? &DIEPCTL(ep
) : &DOEPCTL(ep
);
730 volatile unsigned long *eptsiz
= dir_in
? &DIEPTSIZ(ep
) : &DOEPTSIZ(ep
);
731 volatile unsigned long *epdma
= dir_in
? &DIEPDMA(ep
) : &DOEPDMA(ep
);
732 struct usb_endpoint
*endpoint
= &endpoints
[ep
][dir_in
];
733 #define DEPCTL *epctl
734 #define DEPTSIZ *eptsiz
735 #define DEPDMA *epdma
738 logf("usb-drv: EP%d %s is already busy", ep
, dir_in
? "IN" : "OUT");
740 endpoint
->busy
= true;
742 endpoint
->wait
= blocking
;
743 endpoint
->status
= -1;
745 DEPCTL
&= ~DEPCTL_stall
;
746 DEPCTL
|= DEPCTL_usbactep
;
748 int mps
= usb_drv_mps_by_type(extract(DEPCTL
, eptype
));
749 int nb_packets
= (len
+ mps
- 1) / mps
;
754 DEPTSIZ
= 1 << DEPTSIZ_pkcnt_bitp
;
758 DEPDMA
= (unsigned long)AS3525_PHYSICAL_ADDR(ptr
);
759 DEPTSIZ
= (nb_packets
<< DEPTSIZ_pkcnt_bitp
) | len
;
761 clean_dcache_range(ptr
, len
);
763 dump_dcache_range(ptr
, len
);
766 logf("pkt=%d dma=%lx", nb_packets
, DEPDMA
);
768 DEPCTL
|= DEPCTL_epena
| DEPCTL_cnak
;
772 wakeup_wait(&endpoint
->complete
, TIMEOUT_BLOCK
);
773 return endpoint
->status
;
783 int usb_drv_recv(int ep
, void *ptr
, int len
)
785 return usb_drv_transfer(ep
, ptr
, len
, false, false);
788 int usb_drv_send(int ep
, void *ptr
, int len
)
790 return usb_drv_transfer(ep
, ptr
, len
, true, true);
793 int usb_drv_send_nonblocking(int ep
, void *ptr
, int len
)
795 return usb_drv_transfer(ep
, ptr
, len
, true, false);
799 void usb_drv_set_test_mode(int mode
)
801 /* there is a perfect matching between usb test mode code
802 * and the register field value */
803 DCTL
= (DCTL
& ~bitm(DCTL
, tstctl
)) | (mode
<< DCTL_tstctl_bitp
);
806 void usb_drv_set_address(int address
)
811 void usb_drv_stall(int ep
, bool stall
, bool in
)
813 logf("usb-drv: %sstall EP%d %s", stall
? "" : "un", ep
, in
? "IN" : "OUT");
816 if(stall
) DIEPCTL(ep
) |= DEPCTL_stall
;
817 else DIEPCTL(ep
) &= ~DEPCTL_stall
;
821 if(stall
) DOEPCTL(ep
) |= DEPCTL_stall
;
822 else DOEPCTL(ep
) &= ~DEPCTL_stall
;
826 bool usb_drv_stalled(int ep
, bool in
)
828 return (in
? DIEPCTL(ep
) : DOEPCTL(ep
)) & DEPCTL_stall
;