00001
00044 #include <assert.h>
00045 #include <byteorder.h>
00046 #include <debug.h>
00047 #include <dma.h>
00048 #include <io.h>
00049 #include <softirq.h>
00050 #include <status-codes.h>
00051 #include <string.h>
00052 #include <util.h>
00053 #include <arch/interrupt.h>
00054 #include <chip/memory-map.h>
00055 #include <chip/usbb.h>
00056 #include <usb/request.h>
00057 #include <usb/function.h>
00058 #include <usb/udc.h>
00059
00060 #include <app/config_usb.h>
00061 #include <app/softirq.h>
00062
00063 #include "usbb_internal.h"
00064 #include "usbb_regs.h"
00065
00066
00067 #if defined(CONFIG_UDC_HIGH_SPEED)
00068 # if !defined(CHIP_USBB_UDC_HIGH_SPEED)
00069 # error High-speed configuration not supported on this chip
00070 # endif
00071 # if !defined(CONFIG_UDC_FULL_SPEED)
00072 # error High-speed selected, but not full-speed
00073 # endif
00074 #endif
00075 #if defined(CONFIG_UDC_FULL_SPEED) && !defined(CHIP_USBB_UDC_FULL_SPEED)
00076 # error Full-speed configuration not supported on this chip
00077 #endif
00078 #if defined(CONFIG_UDC_LOW_SPEED)
00079 # if !defined(CHIP_USBB_UDC_LOW_SPEED)
00080 # error Low-speed configuration not supported on this chip
00081 # endif
00082 # if defined(CONFIG_UDC_HIGH_SPEED) || defined(CONFIG_UDC_FULL_SPEED)
00083 # error Low-speed configuration must be selected exclusively
00084 # endif
00085 #endif
00086
00087 static inline struct usbb_udc *usbb_udc_of(struct udc *udc)
00088 {
00089 return container_of(udc, struct usbb_udc, udc);
00090 }
00091
00092 static void usbb_udc_req_done(struct udc *udc, struct usb_request *req,
00093 int status)
00094 {
00095 req->status = status;
00096
00097 if (req->req_done)
00098 req->req_done(udc, req);
00099 }
00100
00101 static void usbb_udc_kill_last_in_bank(usb_ep_id_t ep_id)
00102 {
00103 usbb_udc_write_reg(UECONSET(ep_id), USBB_UECON_KILLBK);
00104 while (usbb_udc_read_reg(UECON(ep_id)) & USBB_UECON_KILLBK)
00105 barrier();
00106 }
00107
00108 static void usbb_udc_kill_first_out_bank(usb_ep_id_t ep_id)
00109 {
00110 usbb_udc_write_reg(UESTACLR(ep_id), USBB_EP_RXOUTI);
00111 usbb_udc_write_reg(UECONCLR(ep_id), USBB_UECON_FIFOCON);
00112 }
00113
00114 static void usbb_udc_kill_all_banks(usb_ep_id_t ep_id)
00115 {
00116 bool is_in = usbb_udc_read_reg(UECFG(ep_id)) & USBB_UECFG_EPDIR_IN;
00117
00118 while (USBB_UESTA_GET_NBUSYBK(usbb_udc_read_reg(UESTA(ep_id)))) {
00119 if (is_in)
00120 usbb_udc_kill_last_in_bank(ep_id);
00121 else
00122 usbb_udc_kill_first_out_bank(ep_id);
00123 }
00124 }
00125
00129 static void usbb_udc_dma_buf_done(struct buffer *buf)
00130 {
00131 struct usbb_sw_dma_desc *dma_desc = buf->dma_desc;
00132
00133 usbb_dma_desc_free(dma_desc);
00134 buf->dma_desc = NULL;
00135 }
00136
00137 static void usbb_udc_dma_req_done(struct udc *udc, struct slist *queue,
00138 struct usb_request *req, int status)
00139 {
00140 slist_give_back_head(&req->buf_list, queue);
00141
00142 usbb_udc_req_done(udc, req, status);
00143 }
00144
00157 void udc_ep0_submit_out_req(struct udc *udc, struct usb_request *req)
00158 {
00159 struct usbb_udc *udcb = usbb_udc_of(udc);
00160 struct usbb_udc_ep *ep = &udcb->ep[0];
00161
00162 assert(!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags));
00163 assert(slist_is_empty(&ep->buf_queue));
00164 assert(slist_is_empty(&ep->req_queue));
00165 assert(ep->buf_offset == 0);
00166
00167 udcb->ctrl_state = EP0_STATE_DATA_OUT;
00168 set_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00169 slist_borrow_to_tail(&ep->buf_queue, &req->buf_list);
00170 slist_insert_tail(&ep->req_queue, &req->node);
00171 barrier();
00172 usbb_udc_write_reg(UECONSET(0), USBB_EP_RXOUTI);
00173 }
00174
00187 void udc_ep0_submit_in_req(struct udc *udc, struct usb_request *req)
00188 {
00189 struct usbb_udc *udcb = usbb_udc_of(udc);
00190 struct usbb_udc_ep *ep = &udcb->ep[0];
00191
00192 assert(!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags));
00193 assert(slist_is_empty(&ep->buf_queue));
00194 assert(slist_is_empty(&ep->req_queue));
00195 assert(ep->buf_offset == 0);
00196
00197 udcb->ctrl_state = EP0_STATE_DATA_IN;
00198 set_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00199 slist_borrow_to_tail(&ep->buf_queue, &req->buf_list);
00200 slist_insert_tail(&ep->req_queue, &req->node);
00201 barrier();
00202 usbb_udc_write_reg(UECONSET(0), USBB_EP_TXINI);
00203 }
00204
00225 int udc_ep0_write_sync(struct udc *udc, const void *data, size_t len)
00226 {
00227 assert(!test_bit(USBB_EP_ACTIVE_XFER, &usbb_udc_of(udc)->ep[0].flags));
00228 assert(usbb_udc_read_reg(UESTA(0)) & USBB_EP_TXINI);
00229
00230 len = min(len, CONFIG_USB_FUNC_MAXPACKETSIZE0);
00231 memcpy(usbb_ep_fifo(0), data, len);
00232 usbb_udc_write_reg(UESTACLR(0), USBB_EP_TXINI);
00233
00234 while (!(usbb_udc_read_reg(UESTA(0)) & USBB_EP_TXINI))
00235 barrier();
00236
00237 return len;
00238 }
00239
00253 void udc_ep0_send_status(struct udc *udc)
00254 {
00255 struct usbb_udc *udcb = usbb_udc_of(udc);
00256
00257 dbg_printf("usbb-udc: send status\n");
00258
00259 assert(!test_bit(USBB_EP_ACTIVE_XFER, &udcb->ep[0].flags));
00260 assert(usbb_udc_read_reg(UESTA(0)) & USBB_EP_TXINI);
00261
00262 usbb_udc_write_reg(UESTACLR(0), USBB_EP_TXINI);
00263 usbb_udc_write_reg(UECONCLR(0), USBB_EP_RXOUTI);
00264 usbb_udc_write_reg(UECONSET(0), USBB_EP_TXINI);
00265
00266 if (!usbb_udc_entering_test_mode(udcb))
00267 udcb->ctrl_state = EP0_STATE_STATUS_IN;
00268 }
00269
00282 void udc_ep0_expect_status(struct udc *udc)
00283 {
00284 struct usbb_udc *udcb = usbb_udc_of(udc);
00285
00286 assert(!test_bit(USBB_EP_ACTIVE_XFER, &udcb->ep[0].flags));
00287 assert(usbb_udc_read_reg(UESTA(0)) & USBB_EP_TXINI);
00288
00289
00290
00291
00292
00293 udcb->ctrl_state = EP0_STATE_STATUS_OUT;
00294 }
00295
00304 void udc_set_address(struct udc *udc, unsigned int addr)
00305 {
00306
00307 }
00308
00319 static void usbb_udc_submit_out_queue(struct usbb_udc *udcb,
00320 usb_ep_id_t ep_id, struct usbb_udc_ep *ep)
00321 {
00322 struct usbb_sw_dma_desc *dma;
00323 struct usbb_sw_dma_desc *dma_next;
00324 struct buffer *buf;
00325 struct buffer *next;
00326 struct usb_request *req;
00327 phys_addr_t phys;
00328 uint32_t ctrl;
00329
00330 dbg_printf("ep%u-out: submit buf_queue %p req_queue %p status=%08x\n",
00331 ep_id, slist_peek_head_node(&ep->buf_queue),
00332 slist_peek_head_node(&ep->req_queue),
00333 usbb_udc_dma_read_reg(ep_id, STATUS));
00334
00335 assert(!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags));
00336
00337 if (slist_is_empty(&ep->buf_queue)) {
00338 assert(slist_is_empty(&ep->req_queue));
00339 goto queue_empty;
00340 }
00341
00342 set_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00343 cpu_irq_enable();
00344
00345 dma = usbb_dma_desc_alloc(&phys);
00346 if (!dma) {
00347 cpu_irq_disable();
00348 goto no_desc;
00349 }
00350
00351 usbb_udc_dma_write_reg(ep_id, NEXTDESC, phys);
00352
00353 cpu_irq_disable();
00354 if (!test_bit(USBB_EP_ENABLED, &ep->flags))
00355 goto disabled;
00356
00357 req = slist_peek_head(&ep->req_queue, struct usb_request, node);
00358 slist_for_each_safe(&ep->buf_queue, buf, next, node) {
00359 if (!dma)
00360 break;
00361
00362 dma->phys = phys;
00363 dma_next = NULL;
00364 if (!slist_node_is_last(&req->buf_list, &buf->node))
00365 dma_next = usbb_dma_desc_alloc(&phys);
00366
00367
00368 ctrl = USBB_DMA_CH_EN | USBB_DMA_BUFF_CLOSE_IN_EN
00369
00370 | USBB_DMA_BYTE_LEN(buf->len);
00371
00372 if (req->buf_list.last == &buf->node) {
00373 if (req->req_done)
00374 ctrl |= USBB_DMA_EOBUFF | USBB_DMA_EOT;
00375 req = slist_peek_next(&req->node,
00376 struct usb_request, node);
00377 }
00378
00379 dma->hw.buf_addr = buf->addr.phys;
00380
00381 cpu_irq_enable();
00382
00383
00384
00385
00386
00387
00388 if (!dma_next) {
00389 ctrl |= USBB_DMA_EOBUFF | USBB_DMA_EOT;
00390 } else {
00391 ctrl |= USBB_DMA_LD_NXT_CH_DESC_EN;
00392 dma->hw.next = phys;
00393 }
00394
00395 dma->hw.control = ctrl;
00396
00397 dbg_printf("OUT %08lx: %08x %08x %08x\n",
00398 dma->phys, dma->hw.next,
00399 dma->hw.buf_addr, dma->hw.control);
00400
00401 cpu_irq_disable();
00402 if (!test_bit(USBB_EP_ENABLED, &ep->flags))
00403 goto disabled_free_next;
00404
00405 buf->dma_desc = dma;
00406 dma = dma_next;
00407 }
00408
00409
00410 barrier();
00411 usbb_udc_dma_write_reg(ep_id, CONTROL, USBB_DMA_LD_NXT_CH_DESC_EN);
00412 usbb_udc_write_reg(UDINTESET, USBB_UDINT_DMA(ep_id));
00413
00414 return;
00415
00416 disabled_free_next:
00417 usbb_dma_desc_free(dma_next);
00418 disabled:
00419 usbb_dma_desc_free(dma);
00420 no_desc:
00421 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00422 queue_empty:
00423 usbb_udc_write_reg(UDINTECLR, USBB_UDINT_DMA(ep_id));
00424 }
00425
00436 static void usbb_udc_submit_in_queue(struct usbb_udc *udcb,
00437 usb_ep_id_t ep_id, struct usbb_udc_ep *ep)
00438 {
00439 struct usbb_sw_dma_desc *dma;
00440 struct usbb_sw_dma_desc *dma_next;
00441 struct buffer *buf;
00442 struct buffer *next;
00443 struct usb_request *req;
00444 phys_addr_t phys;
00445 uint32_t ctrl;
00446
00447 dbg_printf("ep%u-in: submit buf_queue %p req_queue %p status=%08x\n",
00448 ep_id, slist_peek_head_node(&ep->buf_queue),
00449 slist_peek_head_node(&ep->req_queue),
00450 usbb_udc_dma_read_reg(ep_id, STATUS));
00451
00452 assert(!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags));
00453
00454 if (slist_is_empty(&ep->buf_queue)) {
00455 assert(slist_is_empty(&ep->req_queue));
00456 goto queue_empty;
00457 }
00458
00459 set_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00460 cpu_irq_enable();
00461
00462 dma = usbb_dma_desc_alloc(&phys);
00463 if (!dma) {
00464 cpu_irq_disable();
00465 goto no_desc;
00466 }
00467
00468 usbb_udc_dma_write_reg(ep_id, NEXTDESC, phys);
00469
00470 cpu_irq_disable();
00471 if (!test_bit(USBB_EP_ENABLED, &ep->flags))
00472 goto disabled;
00473
00474 req = slist_peek_head(&ep->req_queue, struct usb_request, node);
00475 slist_for_each_safe(&ep->buf_queue, buf, next, node) {
00476 if (!dma)
00477 break;
00478
00479 dma->phys = phys;
00480 dma_next = NULL;
00481 if (!slist_node_is_last(&req->buf_list, &buf->node))
00482 dma_next = usbb_dma_desc_alloc(&phys);
00483
00484 ctrl = USBB_DMA_CH_EN | USBB_DMA_BYTE_LEN(buf->len);
00485
00486
00487
00488
00489
00490
00491 if (req->buf_list.last == &buf->node) {
00492 if (test_bit(USB_REQ_SHORT_PKT, &req->flags)
00493 || (buf->len % ep->maxpacket))
00494 ctrl |= USBB_DMA_DMAEND_EN;
00495 if (req->req_done)
00496 ctrl |= USBB_DMA_EOBUFF;
00497 req = slist_peek_next(&req->node,
00498 struct usb_request, node);
00499 }
00500
00501 dma->hw.buf_addr = buf->addr.phys;
00502
00503 cpu_irq_enable();
00504
00505
00506
00507
00508
00509
00510 if (!dma_next) {
00511 ctrl |= USBB_DMA_EOBUFF;
00512 } else {
00513 ctrl |= USBB_DMA_LD_NXT_CH_DESC_EN;
00514 dma->hw.next = phys;
00515 }
00516
00517 dma->hw.control = ctrl;
00518
00519 dbg_printf("IN %08lx: %08x %08x %08x\n",
00520 dma->phys, dma->hw.next,
00521 dma->hw.buf_addr, dma->hw.control);
00522
00523 cpu_irq_disable();
00524 if (!test_bit(USBB_EP_ENABLED, &ep->flags))
00525 goto disabled_free_next;
00526
00527 buf->dma_desc = dma;
00528 dma = dma_next;
00529 }
00530
00531
00532 barrier();
00533 usbb_udc_dma_write_reg(ep_id, CONTROL, USBB_DMA_LD_NXT_CH_DESC_EN);
00534 usbb_udc_write_reg(UDINTESET, USBB_UDINT_DMA(ep_id));
00535
00536 return;
00537
00538 disabled_free_next:
00539 usbb_dma_desc_free(dma_next);
00540 disabled:
00541 usbb_dma_desc_free(dma);
00542 no_desc:
00543 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00544 queue_empty:
00545 usbb_udc_write_reg(UDINTECLR, USBB_UDINT_DMA(ep_id));
00546 }
00547
00548 static void usbb_udc_verify_req(struct usb_request *req)
00549 {
00550 #ifdef DEBUG
00551 struct buffer *buf;
00552
00553 assert(!slist_is_empty(&req->buf_list));
00554 usb_req_for_each_buffer(req, buf) {
00555 dbg_printf("verifying buf %p: %p %p %08lx %zu\n",
00556 buf, buf->dma_desc, buf->addr.ptr,
00557 buf->addr.phys, buf->len);
00558 assert(!buf->dma_desc);
00559 }
00560 #endif
00561 }
00562
00576 void udc_ep_submit_out_req(struct udc *udc, usb_ep_id_t ep_id,
00577 struct usb_request *req)
00578 {
00579 struct usbb_udc *udcb = usbb_udc_of(udc);
00580 struct usbb_udc_ep *ep = &udcb->ep[ep_id];
00581 bool queued = true;
00582
00583 assert(cpu_irq_is_enabled());
00584 assert(ep_id > 0 && ep_id < CONFIG_USBB_NR_EP);
00585 usbb_udc_verify_req(req);
00586
00587 cpu_irq_disable();
00588 if (test_bit(USBB_EP_ENABLED, &ep->flags)) {
00589 slist_insert_tail(&ep->req_queue, &req->node);
00590 slist_borrow_to_tail(&ep->buf_queue, &req->buf_list);
00591 if (!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags))
00592 usbb_udc_submit_out_queue(udcb, ep_id, ep);
00593 } else {
00594 queued = false;
00595 }
00596 cpu_irq_enable();
00597
00598 if (!queued)
00599 usbb_udc_req_done(udc, req, -STATUS_IO_ERROR);
00600 }
00601
00615 void udc_ep_submit_in_req(struct udc *udc, usb_ep_id_t ep_id,
00616 struct usb_request *req)
00617 {
00618 struct usbb_udc *udcb = usbb_udc_of(udc);
00619 struct usbb_udc_ep *ep = &udcb->ep[ep_id];
00620 bool queued = true;
00621
00622 assert(cpu_irq_is_enabled());
00623 assert(ep_id > 0 && ep_id < CONFIG_USBB_NR_EP);
00624 usbb_udc_verify_req(req);
00625
00626 cpu_irq_disable();
00627 if (test_bit(USBB_EP_ENABLED, &ep->flags)) {
00628 slist_insert_tail(&ep->req_queue, &req->node);
00629 slist_borrow_to_tail(&ep->buf_queue, &req->buf_list);
00630 if (!test_bit(USBB_EP_ACTIVE_XFER, &ep->flags))
00631 usbb_udc_submit_in_queue(udcb, ep_id, ep);
00632 } else {
00633 queued = false;
00634 }
00635 cpu_irq_enable();
00636
00637 if (!queued)
00638 usbb_udc_req_done(udc, req, -STATUS_IO_ERROR);
00639 }
00640
00652 int udc_ep_is_halted(struct udc *udc, usb_ep_id_t ep)
00653 {
00654 if (ep >= CONFIG_USBB_NR_EP)
00655 return -1;
00656
00657 return !!(usbb_udc_read_reg(UECON(ep)) & USBB_UECON_STALLRQ);
00658 }
00659
00673 int udc_ep_set_halt(struct udc *udc, usb_ep_id_t ep)
00674 {
00675 uint32_t uecfg;
00676
00677 dbg_printf("usbb-udc: ep%d: set halt\n", ep);
00678
00679 if (ep >= CONFIG_USBB_NR_EP)
00680 return -1;
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 uecfg = usbb_udc_read_reg(UECFG(ep));
00708 if (uecfg & USBB_UECFG_EPDIR_IN) {
00709 uint32_t uesta;
00710
00711
00712 do {
00713 uesta = usbb_udc_read_reg(UESTA(ep));
00714 } while (USBB_UESTA_GET_NBUSYBK(uesta) != 0);
00715 }
00716
00717 usbb_udc_write_reg(UECONSET(ep), USBB_UECON_STALLRQ);
00718
00719 if (ep != 0 && !(uecfg & USBB_UECFG_EPDIR_IN)) {
00720
00721
00722
00723
00724
00725 usbb_udc_kill_all_banks(ep);
00726 }
00727
00728 return 0;
00729 }
00730
00744 int udc_ep_clear_halt(struct udc *udc, usb_ep_id_t ep)
00745 {
00746 struct usbb_udc *udcb = usbb_udc_of(udc);
00747
00748 dbg_printf("usbb-udc: ep%d: clear halt (%swedged)\n", ep,
00749 test_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags)
00750 ? "" : "not ");
00751
00752 if (ep >= CONFIG_USBB_NR_EP)
00753 return -1;
00754
00755
00756 usbb_udc_write_reg(UECONSET(ep), USBB_UECON_RSTDT);
00757
00758 if (!test_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags)) {
00759
00760 usbb_udc_write_reg(UECONCLR(ep), USBB_UECON_STALLRQ);
00761 }
00762
00763 return 0;
00764 }
00765
00781 bool udc_ep_is_wedged(struct udc *udc, usb_ep_id_t ep)
00782 {
00783 struct usbb_udc *udcb = usbb_udc_of(udc);
00784
00785 assert(ep < CONFIG_USBB_NR_EP);
00786
00787 return test_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags);
00788 }
00802 void udc_ep_set_wedge(struct udc *udc, usb_ep_id_t ep)
00803 {
00804 struct usbb_udc *udcb = usbb_udc_of(udc);
00805 unsigned long iflags;
00806 int ret;
00807
00808 dbg_printf("usbb-udc: ep%d: set wedge\n", ep);
00809
00810 iflags = cpu_irq_save();
00811 set_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags);
00812
00813
00814
00815
00816
00817 ret = udc_ep_set_halt(udc, ep);
00818 assert(!ret);
00819 cpu_irq_restore(iflags);
00820 }
00821
00838 void udc_ep_clear_wedge(struct udc *udc, usb_ep_id_t ep)
00839 {
00840 struct usbb_udc *udcb = usbb_udc_of(udc);
00841 unsigned long iflags;
00842
00843 dbg_printf("usbb-udc: ep%d: clear wedge\n", ep);
00844
00845 assert(ep < CONFIG_USBB_NR_EP);
00846
00847 iflags = cpu_irq_save();
00848
00849 assert(!test_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags)
00850 || udc_ep_is_halted(udc, ep) > 0);
00851
00852 clear_bit(USBB_EP_WEDGE, &udcb->ep[ep].flags);
00853 cpu_irq_restore(iflags);
00854 }
00855
00867 static int usbb_udc_configure_ep(unsigned int id, unsigned int size,
00868 enum usb_ep_xfer_type type, bool is_in, unsigned int nr_banks,
00869 bool autosw)
00870 {
00871 unsigned long iflags;
00872 uint32_t config;
00873 uint32_t uerst;
00874
00875 assert(nr_banks >= 1 && nr_banks <= 3 && size >= 8);
00876
00877 config = (USBB_UECFG_ALLOC
00878 | USBB_UECFG_EPBK(nr_banks - 1)
00879 | USBB_UECFG_EPSIZE(ilog2(size / 8))
00880 | USBB_UECFG_EPTYPE(type));
00881 if (is_in)
00882 config |= USBB_UECFG_EPDIR_IN;
00883
00884 usbb_udc_write_reg(UECFG(id), config);
00885 if (!(usbb_udc_read_reg(UESTA(id)) & USBB_UESTA_CFGOK)) {
00886 dbg_printf("ep%u: Configuration %08x invalid\n", id, config);
00887 return -STATUS_INVALID_PARAM;
00888 }
00889
00890 iflags = cpu_irq_save();
00891 uerst = usbb_udc_read_reg(UERST);
00892 usbb_udc_write_reg(UERST, uerst | USBB_UERST_EPRST(id));
00893 usbb_udc_write_reg(UERST, uerst | USBB_UERST_EPEN(id));
00894 cpu_irq_restore(iflags);
00895
00896 if (autosw)
00897 usbb_udc_write_reg(UECFG(id), config | USBB_UECFG_EPAUTOSW);
00898
00899 return STATUS_OK;
00900 }
00901
00902 static void usbb_udc_ep_flush(struct usbb_udc *udcb, usb_ep_id_t ep_id,
00903 struct usbb_udc_ep *ep)
00904 {
00905 struct udc *udc = &udcb->udc;
00906 struct buffer *buf;
00907 struct buffer *next_buf;
00908 struct usb_request *req;
00909 unsigned long iflags;
00910
00911 assert(ep_id != 0 && ep_id < CONFIG_USBB_NR_EP);
00912 assert(test_bit(USBB_EP_ENABLED, &ep->flags));
00913
00914
00915
00916
00917
00918 iflags = cpu_irq_save();
00919
00920
00921 clear_bit(USBB_EP_ENABLED, &ep->flags);
00922 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
00923
00924
00925 usbb_udc_write_reg(UDINTECLR, USBB_UDINT_EP(ep_id)
00926 | USBB_UDINT_DMA(ep_id));
00927
00928
00929
00930
00931
00932 usbb_udc_dma_write_reg(ep_id, CONTROL, 0);
00933 usbb_udc_dma_read_reg(ep_id, STATUS);
00934
00935
00936 usbb_udc_kill_all_banks(ep_id);
00937 cpu_irq_restore(iflags);
00938
00939
00940 if (!slist_is_empty(&ep->req_queue)) {
00941 req = slist_pop_head(&ep->req_queue, struct usb_request, node);
00942
00943 slist_for_each_safe(&ep->buf_queue, buf, next_buf, node) {
00944 usbb_udc_dma_buf_done(buf);
00945 dbg_printf("buf %p req [%p %p]\n",
00946 &buf->node, req->buf_list.first.next,
00947 req->buf_list.last);
00948 if (req->buf_list.last == &buf->node) {
00949
00950 usbb_udc_dma_req_done(udc, &ep->buf_queue,
00951 req, -STATUS_IO_ERROR);
00952 if (!slist_is_empty(&ep->req_queue))
00953 req = slist_pop_head(&ep->req_queue,
00954 struct usb_request,
00955 node);
00956 else
00957 assert(slist_is_empty(&ep->buf_queue));
00958 }
00959 }
00960
00961 assert(slist_is_empty(&ep->buf_queue));
00962 assert(slist_is_empty(&ep->req_queue));
00963 } else {
00964 assert(slist_is_empty(&ep->buf_queue));
00965 }
00966 }
00967
00978 void udc_ep_flush(struct udc *udc, usb_ep_id_t ep_id)
00979 {
00980 struct usbb_udc *udcb = usbb_udc_of(udc);
00981 struct usbb_udc_ep *ep;
00982 unsigned long iflags;
00983
00984 dbg_printf("usbb-udc: flush ep%u\n", ep_id);
00985
00986 ep = &udcb->ep[ep_id];
00987 usbb_udc_ep_flush(udcb, ep_id, ep);
00988
00989
00990 iflags = cpu_irq_save();
00991 set_bit(USBB_EP_ENABLED, &ep->flags);
00992 cpu_irq_restore(iflags);
00993 }
00994
01009 usb_ep_id_t udc_ep_create(struct udc *udc,
01010 const struct usb_endpoint_descriptor *desc,
01011 unsigned int nr_banks)
01012 {
01013 struct usbb_udc *udcb = usbb_udc_of(udc);
01014 struct usbb_udc_ep *ep;
01015 unsigned int index;
01016 unsigned long iflags;
01017 int ret;
01018
01019 index = usb_ep_index(desc);
01020 assert(index > 0 && index < CONFIG_USBB_NR_EP);
01021
01022 dbg_printf("usbb-udc: create ep%u addr: %02x attr: %02x banks: %u\n",
01023 index, desc->bEndpointAddress, desc->bmAttributes,
01024 nr_banks);
01025
01026 ret = 0;
01027 ep = &udcb->ep[index];
01028
01029 iflags = cpu_irq_save();
01030 if (ep->desc) {
01031
01032 ret = -STATUS_INVALID_PARAM;
01033 } else {
01034 ep->desc = desc;
01035 ep->flags = 0;
01036 }
01037 cpu_irq_restore(iflags);
01038 if (ret < 0) {
01039 dbg_printf("usbb-udc: ep%u is busy\n", index);
01040 return ret;
01041 }
01042
01043 ret = usbb_udc_configure_ep(index, le16_to_cpu(desc->wMaxPacketSize),
01044 usb_ep_xfer(desc), usb_ep_is_in(desc),
01045 nr_banks, true);
01046 if (ret < 0) {
01047 ep->desc = NULL;
01048 return ret;
01049 }
01050
01051 usbb_udc_write_reg(UDINTESET, USBB_UDINT_EP(index));
01052
01053 slist_init(&ep->req_queue);
01054 slist_init(&ep->buf_queue);
01055
01056 ep->maxpacket = le16_to_cpu(desc->wMaxPacketSize);
01057
01058 set_bit(USBB_EP_ENABLED, &ep->flags);
01059
01060 return index;
01061 }
01062
01072 void udc_ep_destroy(struct udc *udc, usb_ep_id_t ep_id)
01073 {
01074 struct usbb_udc *udcb = usbb_udc_of(udc);
01075 struct usbb_udc_ep *ep;
01076 uint32_t uerst;
01077 unsigned long iflags;
01078
01079 dbg_printf("usbb-udc: destroy ep%u\n", ep_id);
01080
01081 assert(ep_id != 0 && ep_id < CONFIG_USBB_NR_EP);
01082
01083 ep = &udcb->ep[ep_id];
01084 usbb_udc_ep_flush(udcb, ep_id, ep);
01085
01086
01087 iflags = cpu_irq_save();
01088 uerst = usbb_udc_read_reg(UERST);
01089 usbb_udc_write_reg(UERST, uerst & ~USBB_UERST_EPEN(ep_id));
01090 usbb_udc_write_reg(UECFG(ep_id), 0);
01091
01092
01093 ep->flags = 0;
01094 ep->desc = NULL;
01095 cpu_irq_restore(iflags);
01096 }
01097
01098 static void usbb_udc_do_test_mode(struct usbb_udc *udcb)
01099 {
01100 static const char test_packet_data[] = {
01101
01102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01103
01104 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
01105
01106 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
01107
01108 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
01109 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
01110
01111 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
01112
01113 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
01114 };
01115 uint32_t udcon;
01116 int ret;
01117
01118
01119 usbb_udc_write_reg(UDINTECLR, ~0UL);
01120 usbb_udc_read_reg(UDINTE);
01121
01122
01123
01124
01125
01126 usbb_udc_write_reg(UERST, USBB_UERST_EPEN(0));
01127 usbb_udc_read_reg(UERST);
01128
01129 udcon = usbb_udc_read_reg(UDCON);
01130
01131 switch (udcb->ctrl_state) {
01132 case EP0_STATE_TEST_J:
01133 udcon |= USBB_UDCON_TSTJ;
01134 usbb_udc_write_reg(UDCON, udcon);
01135 dbg_info("usbb_udc: Entered Test_J mode\n");
01136 break;
01137
01138 case EP0_STATE_TEST_K:
01139 udcon |= USBB_UDCON_TSTK;
01140 usbb_udc_write_reg(UDCON, udcon);
01141 dbg_info("usbb_udc: Entered Test_K mode\n");
01142 break;
01143
01144 case EP0_STATE_TEST_SE0_NAK:
01145
01146
01147
01148 usbb_udc_write_reg(UERST, 0);
01149 usbb_udc_write_reg(UECFG(0), 0);
01150
01151
01152 ret = usbb_udc_configure_ep(0, 64, USB_EP_XFER_BULK,
01153 true, 1, false);
01154 if (!ret)
01155 dbg_info("usbb_udc: Entered Test_SE0_NAK mode\n");
01156 break;
01157
01158 case EP0_STATE_TEST_PACKET:
01159
01160
01161
01162 usbb_udc_write_reg(UERST, 0);
01163 usbb_udc_write_reg(UECFG(0), 0);
01164
01165
01166 ret = usbb_udc_configure_ep(0, 64, USB_EP_XFER_BULK,
01167 true, 1, false);
01168 if (!ret) {
01169 udcon |= USBB_UDCON_TSTPCKT;
01170 usbb_udc_write_reg(UDCON, udcon);
01171 memcpy(usbb_ep_fifo(0), test_packet_data,
01172 sizeof(test_packet_data));
01173 usbb_udc_write_reg(UECONCLR(0), USBB_UECON_FIFOCON);
01174 dbg_info("usbb_udc: Entered Test_Packet mode\n");
01175 }
01176 break;
01177
01178 default:
01179 dbg_error("usbb_udc: Invalid test state %u!\n",
01180 udcb->ctrl_state);
01181 break;
01182 }
01183 }
01184
01185 int udc_enter_test_mode(struct udc *udc, unsigned int mode)
01186 {
01187 struct usbb_udc *udcb = usbb_udc_of(udc);
01188
01189 switch (mode) {
01190 case USB_TEST_J:
01191 udcb->ctrl_state = EP0_STATE_TEST_J;
01192 break;
01193 case USB_TEST_K:
01194 udcb->ctrl_state = EP0_STATE_TEST_K;
01195 break;
01196 case USB_TEST_SE0_NAK:
01197 udcb->ctrl_state = EP0_STATE_TEST_SE0_NAK;
01198 break;
01199 case USB_TEST_PACKET:
01200 udcb->ctrl_state = EP0_STATE_TEST_PACKET;
01201 break;
01202 default:
01203 return -1;
01204 }
01205
01206 return 0;
01207 }
01208
01209 static void usbb_ep0_tx_complete(struct udc *udc, struct usbb_udc_ep *ep)
01210 {
01211 struct usb_request *req;
01212 struct buffer *buf;
01213 unsigned int buf_offset;
01214 unsigned int bytes_written;
01215
01216 if (slist_is_empty(&ep->req_queue)) {
01217 assert(slist_is_empty(&ep->buf_queue));
01218 return;
01219 }
01220
01221 assert(!slist_is_empty(&ep->buf_queue));
01222
01223 req = slist_peek_head(&ep->req_queue, struct usb_request, node);
01224 buf = slist_peek_head(&ep->buf_queue, struct buffer, node);
01225
01226 buf_offset = ep->buf_offset;
01227 bytes_written = ep->bytes_written;
01228
01229 req->bytes_xfered += bytes_written;
01230
01231 while (bytes_written && buf_offset + bytes_written >= buf->len) {
01232 bytes_written -= buf->len - buf_offset;
01233 buf_offset = 0;
01234 slist_pop_head_node(&ep->buf_queue);
01235 if (bytes_written)
01236 assert(!slist_is_empty(&ep->buf_queue));
01237 buf = slist_peek_head(&ep->buf_queue, struct buffer, node);
01238 }
01239
01240 if (slist_is_empty(&ep->buf_queue)) {
01241 slist_init(&ep->req_queue);
01242
01243 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
01244 slist_give_back_head(&req->buf_list, &ep->buf_queue);
01245 usbb_udc_req_done(udc, req, 0);
01246 }
01247
01248 ep->buf_offset = bytes_written;
01249 ep->bytes_written = 0;
01250 }
01251
01252 static void usbb_ep0_tx_flush(struct udc *udc, struct usbb_udc_ep *ep)
01253 {
01254
01255 usbb_ep0_tx_complete(udc, ep);
01256
01257
01258 if (!slist_is_empty(&ep->req_queue)) {
01259 struct usb_request *req;
01260
01261 req = slist_pop_head(&ep->req_queue, struct usb_request, node);
01262 assert(slist_is_empty(&ep->req_queue));
01263 slist_init(&ep->buf_queue);
01264 ep->buf_offset = 0;
01265 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
01266 usbb_udc_req_done(udc, req, -STATUS_PROTO_ERROR);
01267 }
01268 }
01269
01270 static void usbb_ep0_interrupt(struct usbb_udc *udcb)
01271 {
01272 struct usbb_udc_ep *ep;
01273 uint32_t status;
01274 uint32_t control;
01275 uint32_t pending;
01276
01277 status = usbb_udc_read_reg(UESTA(0));
01278 control = usbb_udc_read_reg(UECON(0));
01279 pending = status & control;
01280
01281 ep = &udcb->ep[0];
01282
01283 if (pending & USBB_EP_RXOUTI) {
01284 struct usb_request *req;
01285 struct buffer *buf;
01286 unsigned int buf_offset;
01287 unsigned int fifo_offset = 0;
01288 unsigned int fifo_len;
01289
01290 if (slist_is_empty(&ep->req_queue)) {
01291 assert(slist_is_empty(&ep->buf_queue));
01292
01293
01294 goto stall;
01295 }
01296
01297 req = slist_peek_head(&ep->req_queue, struct usb_request, node);
01298
01299 buf_offset = ep->buf_offset;
01300 fifo_len = USBB_UESTA_GET_BYCT(status);
01301 while (fifo_offset < fifo_len
01302 && !slist_is_empty(&ep->buf_queue)) {
01303 unsigned int nbytes;
01304
01305 buf = slist_peek_head(&ep->buf_queue,
01306 struct buffer, node);
01307
01308 nbytes = min(fifo_len - fifo_offset,
01309 buf->len - buf_offset);
01310 memcpy(buf->addr.ptr + buf_offset,
01311 usbb_ep_fifo(0) + fifo_offset,
01312 nbytes);
01313
01314 buf_offset += nbytes;
01315 fifo_offset += nbytes;
01316
01317 if (buf_offset == buf->len) {
01318 req->bytes_xfered += buf_offset;
01319 slist_pop_head_node(&ep->buf_queue);
01320
01321 buf_offset = 0;
01322 }
01323 }
01324
01325 usbb_udc_write_reg(UESTACLR(0), USBB_EP_RXOUTI);
01326 ep->buf_offset = buf_offset;
01327
01328 if (slist_is_empty(&ep->buf_queue)) {
01329
01330 assert(buf_offset == 0);
01331 slist_init(&ep->req_queue);
01332 usbb_udc_write_reg(UECONCLR(0), USBB_EP_RXOUTI);
01333 udcb->ctrl_state = EP0_STATE_SETUP;
01334 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
01335 usbb_udc_req_done(&udcb->udc, req, 0);
01336 }
01337 }
01338 if (pending & USBB_EP_TXINI) {
01339 struct usb_request *req;
01340 struct buffer *buf;
01341 unsigned int buf_offset;
01342 void *fifo;
01343 void *fifo_end;
01344
01345 if (usbb_udc_entering_test_mode(udcb)) {
01346
01347 usbb_udc_do_test_mode(udcb);
01348
01349 return;
01350 }
01351
01352 if (udcb->ctrl_state == EP0_STATE_STATUS_IN) {
01353 struct usb_setup_req *setup;
01354
01355
01356 setup = &udcb->setup_req;
01357 if (setup->bRequest == USB_REQ_SET_ADDRESS) {
01358 uint32_t udcon;
01359 uint16_t addr = le16_to_cpu(setup->wValue);
01360
01361 udcon = usbb_udc_read_reg(UDCON);
01362 udcon &= ~USBB_UDCON_UADD_MASK;
01363 udcon |= USBB_UDCON_UADD(addr);
01364 udcon |= USBB_UDCON_ADDEN;
01365 usbb_udc_write_reg(UDCON, udcon);
01366 udcb->udc.address = addr;
01367 }
01368 usbb_udc_write_reg(UECONCLR(0), USBB_EP_TXINI);
01369 udcb->ctrl_state = EP0_STATE_SETUP;
01370 goto out;
01371 }
01372
01373
01374 if (udcb->ctrl_state == EP0_STATE_DATA_ZLP) {
01375 udcb->ctrl_state = EP0_STATE_DATA_IN;
01376 usbb_udc_write_reg(UESTACLR(0), USBB_EP_TXINI);
01377 goto out;
01378 }
01379
01380
01381 usbb_ep0_tx_complete(&udcb->udc, ep);
01382
01383
01384 if (slist_is_empty(&ep->buf_queue)) {
01385 usbb_udc_write_reg(UECONCLR(0), USBB_EP_TXINI);
01386 udcb->ctrl_state = EP0_STATE_SETUP;
01387 goto out;
01388 }
01389
01390 buf_offset = ep->buf_offset;
01391 buf = slist_peek_head(&ep->buf_queue, struct buffer, node);
01392
01393 fifo = usbb_ep_fifo(0);
01394 fifo_end = fifo + CONFIG_USB_FUNC_MAXPACKETSIZE0;
01395 while (fifo < fifo_end) {
01396 unsigned int nbytes;
01397 unsigned int buf_len;
01398
01399 buf_len = buf->len;
01400
01401 nbytes = min(fifo_end - fifo, buf_len - buf_offset);
01402 dbg_printf("fifo %p data %p off %u nbytes %u\n",
01403 fifo, buf->addr.ptr,
01404 buf_offset, nbytes);
01405 memcpy(fifo, buf->addr.ptr + buf_offset, nbytes);
01406
01407 buf_offset += nbytes;
01408 fifo += nbytes;
01409
01410 if (buf_offset == buf_len) {
01411 if (slist_node_is_last(&ep->buf_queue,
01412 &buf->node))
01413 break;
01414 buf = slist_peek_next(&buf->node,
01415 struct buffer, node);
01416 buf_offset = 0;
01417 }
01418 }
01419
01420 ep->bytes_written = CONFIG_USB_FUNC_MAXPACKETSIZE0
01421 - ((unsigned long)fifo_end - (unsigned long)fifo);
01422
01423 req = slist_peek_head(&ep->req_queue, struct usb_request, node);
01424 if (&buf->node == req->buf_list.last
01425 && buf_offset == buf->len
01426 && test_bit(USB_REQ_SHORT_PKT, &req->flags)
01427 && fifo == fifo_end)
01428 udcb->ctrl_state = EP0_STATE_DATA_ZLP;
01429
01430 usbb_udc_write_reg(UESTACLR(0), USBB_EP_TXINI);
01431 }
01432 if (pending & USBB_EP_RXSTPI) {
01433 struct usb_setup_req *setup;
01434
01435 setup = &udcb->setup_req;
01436
01437
01438
01439
01440
01441 if (control & USBB_EP_TXINI) {
01442 usbb_udc_write_reg(UECONCLR(0), USBB_EP_TXINI);
01443 usbb_ep0_tx_flush(&udcb->udc, ep);
01444 }
01445
01446 if (USBB_UESTA_GET_BYCT(status) != sizeof(*setup)) {
01447
01448 usbb_udc_write_reg(UESTACLR(0), USBB_EP_RXSTPI);
01449 goto stall;
01450 }
01451
01452 memcpy(setup, usbb_ep_fifo(0), sizeof(*setup));
01453 usbb_udc_write_reg(UESTACLR(0), USBB_EP_RXSTPI);
01454
01455 if (udc_lib_process_setup_request(&udcb->udc, setup) < 0)
01456 goto stall;
01457 }
01458
01459 out:
01460 usbb_udc_write_reg(UDINTESET, USBB_UDINT_EP(0));
01461 return;
01462
01463 stall:
01464 usbb_udc_write_reg(UECONCLR(0), USBB_EP_TXINI | USBB_EP_RXOUTI);
01465 udc_ep_set_halt(&udcb->udc, 0);
01466 goto out;
01467 }
01468
01473 static void usbb_udc_dma_interrupt(struct usbb_udc *udcb, usb_ep_id_t ep_id)
01474 {
01475 struct usbb_udc_ep *ep = &udcb->ep[ep_id];
01476 struct buffer *buf;
01477 struct usb_request *req;
01478 phys_addr_t next;
01479 uint32_t status;
01480 uint32_t ctrl;
01481
01482 next = usbb_udc_dma_read_reg(ep_id, NEXTDESC);
01483 status = usbb_udc_dma_read_reg(ep_id, STATUS);
01484 ctrl = usbb_udc_dma_read_reg(ep_id, CONTROL);
01485
01486 dbg_printf("dma%u n:%08lx s:%08x c:%08x\n", ep_id, next, status, ctrl);
01487
01488 if (status & USBB_DMA_CH_ACTIVE) {
01489 assert(!slist_is_empty(&ep->buf_queue));
01490
01491 req = NULL;
01492 do {
01493 struct usbb_sw_dma_desc *dma_desc;
01494
01495 if (!req) {
01496 assert(!slist_is_empty(&ep->req_queue));
01497 req = slist_pop_head(&ep->req_queue,
01498 struct usb_request, node);
01499 }
01500
01501 buf = slist_pop_head(&ep->buf_queue,
01502 struct buffer, node);
01503 dma_desc = buf->dma_desc;
01504
01505
01506 assert(dma_desc);
01507
01508 if (slist_is_empty(&ep->buf_queue)
01509 || dma_desc->hw.next == next) {
01510 slist_insert_head(&ep->buf_queue, &buf->node);
01511 slist_insert_head(&ep->req_queue, &req->node);
01512 break;
01513 }
01514
01515 req->bytes_xfered += buf->len;
01516 usbb_udc_dma_buf_done(buf);
01517
01518 if (&buf->node == req->buf_list.last) {
01519 usbb_udc_dma_req_done(&udcb->udc,
01520 &ep->buf_queue, req, 0);
01521 req = NULL;
01522 }
01523 } while (!slist_is_empty(&ep->buf_queue));
01524
01525 dbg_verbose("still active\n");
01526 assert(!slist_is_empty(&ep->buf_queue));
01527 usbb_udc_write_reg(UDINTESET, USBB_UDINT_DMA(ep_id));
01528 } else if (!slist_is_empty(&ep->buf_queue)) {
01529 req = NULL;
01530 do {
01531 if (!req) {
01532 assert(!slist_is_empty(&ep->req_queue));
01533 req = slist_pop_head(&ep->req_queue,
01534 struct usb_request, node);
01535 }
01536
01537 buf = slist_pop_head(&ep->buf_queue,
01538 struct buffer, node);
01539 if (unlikely(!buf->dma_desc)) {
01540 slist_insert_head(&ep->buf_queue, &buf->node);
01541 slist_insert_head(&ep->req_queue, &req->node);
01542 break;
01543 }
01544
01545 req->bytes_xfered += buf->len;
01546
01547 usbb_udc_dma_buf_done(buf);
01548
01549 if (&buf->node == req->buf_list.last) {
01550 struct buffer *next_buf;
01551
01552 next_buf = slist_peek_head(&ep->buf_queue,
01553 struct buffer, node);
01554 if ((slist_is_empty(&ep->buf_queue)
01555 || !next_buf->dma_desc)
01556 && (status & USBB_DMA_EOT)) {
01557 size_t len;
01558 len = USBB_DMA_GET_BYTE_LEN(status);
01559 req->bytes_xfered -= len;
01560 }
01561
01562 usbb_udc_dma_req_done(&udcb->udc,
01563 &ep->buf_queue, req, 0);
01564 req = NULL;
01565 }
01566 } while (!slist_is_empty(&ep->buf_queue));
01567
01568 if (slist_is_empty(&ep->req_queue))
01569 assert(slist_is_empty(&ep->buf_queue));
01570 else
01571 assert(!slist_is_empty(&ep->buf_queue));
01572
01573 clear_bit(USBB_EP_ACTIVE_XFER, &ep->flags);
01574
01575 if (usb_ep_is_in(ep->desc))
01576 usbb_udc_submit_in_queue(udcb, ep_id, ep);
01577 else
01578 usbb_udc_submit_out_queue(udcb, ep_id, ep);
01579 }
01580
01581 }
01582
01587 static void usbb_udc_softirq(void *data)
01588 {
01589 struct usbb_udc *udcb = data;
01590 struct udc *udc = &udcb->udc;
01591 uint32_t udint;
01592 unsigned int i;
01593
01594 udint = usbb_udc_read_reg(UDINT);
01595
01596 if (udint & USBB_UDINT_EORST) {
01597 uint32_t usbsta;
01598
01599 usbb_udc_write_reg(UDINTCLR, USBB_UDINT_EORST);
01600
01601
01602 udc->address = 0;
01603 clear_bit(USB_DEV_IS_SUSPENDED, &udc->flags);
01604
01605
01606 usbsta = usbb_read_reg(USBSTA);
01607 switch (usbsta & USBB_USBSTA_SPEED_MASK) {
01608 case USBB_USBSTA_SPEED_LOW:
01609 udc->speed = USB_SPEED_LOW;
01610 break;
01611 case USBB_USBSTA_SPEED_FULL:
01612 udc->speed = USB_SPEED_FULL;
01613 break;
01614 case USBB_USBSTA_SPEED_HIGH:
01615 udc->speed = USB_SPEED_HIGH;
01616 break;
01617 default:
01618 udc->speed = USB_SPEED_UNKNOWN;
01619 goto out;
01620 }
01621
01622 dbg_printf("usbb-udc: reset speed %u usbsta %08x\n",
01623 udc->speed, usbsta);
01624
01625 usbb_ep0_tx_flush(udc, &udcb->ep[0]);
01626 usb_func_reset(udc);
01627
01628
01629 if (usbb_udc_configure_ep(0, CONFIG_USB_FUNC_MAXPACKETSIZE0,
01630 USB_EP_XFER_CONTROL, 0, 1, false)) {
01631 udc->speed = USB_SPEED_UNKNOWN;
01632 goto out;
01633 }
01634
01635 usbb_udc_write_reg(UDINTESET, USBB_UDINT_EP(0));
01636
01637
01638 udcb->ctrl_state = EP0_STATE_SETUP;
01639 usbb_udc_write_reg(UECONSET(0), USBB_EP_RXSTPI);
01640 } else {
01641 if (udint & USBB_UDINT_EP(0))
01642 usbb_ep0_interrupt(udcb);
01643
01644 for (i = 1; i < CONFIG_USBB_NR_EP; i++) {
01645 udint = usbb_udc_read_reg(UDINT);
01646 if (udint & USBB_UDINT_DMA(i))
01647 usbb_udc_dma_interrupt(udcb, i);
01648 }
01649 }
01650
01651 out:
01652 usbb_udc_write_reg(UDINTESET, USBB_UDINT_EORST);
01653 }
01654
01661 void usbb_udc_interrupt(struct usbb_udc *udcb)
01662 {
01663 usbb_udc_write_reg(UDINTECLR, usbb_udc_read_reg(UDINT));
01664 softirq_raise(SOFTIRQ_ID_USBB_UDC);
01665 usbb_udc_read_reg(UDINTE);
01666 }
01667
01668 static void usbb_udc_maybe_attach(struct usbb_udc *udcb)
01669 {
01670 struct udc *udc = &udcb->udc;
01671
01672 dbg_printf("usbb_udc maybe attach: flags=0x%lx\n", udc->flags);
01673 if (usbb_udc_is_enabled(udcb)
01674 && test_bit(USB_DEV_HAS_POWER, &udc->flags)
01675 && test_bit(USB_DEV_AUTOATTACH, &udc->flags)) {
01676 dbg_printf("usbb_udc: attaching...\n");
01677 usbb_udc_write_reg(UDCON,
01678 usbb_udc_read_reg(UDCON) & ~USBB_UDCON_DETACH);
01679 usbb_udc_write_reg(UDINTESET, USBB_UDINT_EORST);
01680 }
01681 }
01682
01683 static void usbb_udc_detach(struct usbb_udc *udcb)
01684 {
01685 struct udc *udc = &udcb->udc;
01686 uint32_t udcon;
01687
01688 dbg_printf("usbb_udc detach: flags=0x%lx\n", udc->flags);
01689
01690 udc->speed = USB_SPEED_UNKNOWN;
01691 udc->address = 0;
01692 udc->flags &= (1 << USB_DEV_IS_ENABLED) | (1 << USB_DEV_HAS_POWER)
01693 | (1 << USB_DEV_AUTOATTACH);
01694
01695 udcon = usbb_udc_read_reg(UDCON);
01696
01697 if (!(udcon & USBB_UDCON_DETACH)) {
01698 usb_func_reset(&udcb->udc);
01699
01700 usbb_udc_write_reg(UDCON, udcon | USBB_UDCON_DETACH);
01701 usbb_udc_write_reg(UDINTECLR, ~0UL);
01702 }
01703 }
01704
01714 void usbb_udc_vbus_on(struct usbb_udc *udcb)
01715 {
01716 struct udc *udc = &udcb->udc;
01717
01718 if (!test_bit(USB_DEV_HAS_POWER, &udc->flags)) {
01719 dbg_printf("usbb_udc: Vbus ON\n");
01720 set_bit(USB_DEV_HAS_POWER, &udc->flags);
01721 usbb_udc_maybe_attach(udcb);
01722 }
01723 }
01724
01734 void usbb_udc_vbus_off(struct usbb_udc *udcb)
01735 {
01736 struct udc *udc = &udcb->udc;
01737
01738 if (test_bit(USB_DEV_HAS_POWER, &udc->flags)) {
01739 dbg_printf("usbb_udc: Vbus OFF\n");
01740
01741 clear_bit(USB_DEV_HAS_POWER, &udc->flags);
01742
01743 usbb_udc_detach(udcb);
01744 }
01745 }
01746
01757 void udc_attach(struct udc *udc)
01758 {
01759 struct usbb_udc *udcb = usbb_udc_of(udc);
01760 unsigned long iflags;
01761
01762 iflags = cpu_irq_save();
01763 if (!test_bit(USB_DEV_AUTOATTACH, &udc->flags)) {
01764 set_bit(USB_DEV_AUTOATTACH, &udc->flags);
01765 usbb_udc_maybe_attach(udcb);
01766 }
01767 cpu_irq_restore(iflags);
01768 }
01769
01777 void udc_detach(struct udc *udc)
01778 {
01779 struct usbb_udc *udcb = usbb_udc_of(udc);
01780 unsigned long iflags;
01781
01782 iflags = cpu_irq_save();
01783 if (test_bit(USB_DEV_AUTOATTACH, &udc->flags)) {
01784 clear_bit(USB_DEV_AUTOATTACH, &udc->flags);
01785 usbb_udc_detach(udcb);
01786 }
01787 cpu_irq_restore(iflags);
01788 }
01789
01790 static struct usbb_udc the_usbb_udc;
01791
01802 struct usbb_udc *usbb_udc_init(void)
01803 {
01804 struct usbb_udc *udcb = &the_usbb_udc;
01805
01806 slist_init(&udcb->ep[0].req_queue);
01807 slist_init(&udcb->ep[0].buf_queue);
01808
01809 udcb->udc.flags = 0;
01810
01811 #if defined(CHIP_USBB_UDC_HIGH_SPEED) && !defined(CONFIG_UDC_HIGH_SPEED)
01812
01813 usbb_udc_write_reg(UDCON, USBB_UDCON_SPDCONF_FULL);
01814 #elif defined(CONFIG_UDC_LOW_SPEED)
01815 usbb_udc_write_reg(UDCON, USBB_UDCON_LS);
01816 #else
01817 usbb_udc_write_reg(UDCON, 0);
01818 #endif
01819
01820 softirq_set_handler(SOFTIRQ_ID_USBB_UDC, usbb_udc_softirq, udcb);
01821
01822 return udcb;
01823 }
01824
01834 void usbb_udc_shutdown(struct usbb_udc *udcb)
01835 {
01836 udcb->udc.flags = 0;
01837 }