Lines Matching refs:udc
221 struct bcm63xx_udc *udc; member
246 struct bcm63xx_udc *udc; member
363 static inline u32 usbd_readl(struct bcm63xx_udc *udc, u32 off) in usbd_readl() argument
365 return bcm_readl(udc->usbd_regs + off); in usbd_readl()
368 static inline void usbd_writel(struct bcm63xx_udc *udc, u32 val, u32 off) in usbd_writel() argument
370 bcm_writel(val, udc->usbd_regs + off); in usbd_writel()
373 static inline u32 usb_dma_readl(struct bcm63xx_udc *udc, u32 off) in usb_dma_readl() argument
375 return bcm_readl(udc->iudma_regs + off); in usb_dma_readl()
378 static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off) in usb_dma_writel() argument
380 bcm_writel(val, udc->iudma_regs + off); in usb_dma_writel()
383 static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off, int chan) in usb_dmac_readl() argument
385 return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off + in usb_dmac_readl()
389 static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off, in usb_dmac_writel() argument
392 bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off + in usb_dmac_writel()
396 static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off, int chan) in usb_dmas_readl() argument
398 return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off + in usb_dmas_readl()
402 static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off, in usb_dmas_writel() argument
405 bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off + in usb_dmas_writel()
409 static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled) in set_clocks() argument
412 clk_enable(udc->usbh_clk); in set_clocks()
413 clk_enable(udc->usbd_clk); in set_clocks()
416 clk_disable(udc->usbd_clk); in set_clocks()
417 clk_disable(udc->usbh_clk); in set_clocks()
434 static void bcm63xx_ep_dma_select(struct bcm63xx_udc *udc, int idx) in bcm63xx_ep_dma_select() argument
436 u32 val = usbd_readl(udc, USBD_CONTROL_REG); in bcm63xx_ep_dma_select()
440 usbd_writel(udc, val, USBD_CONTROL_REG); in bcm63xx_ep_dma_select()
452 static void bcm63xx_set_stall(struct bcm63xx_udc *udc, struct bcm63xx_ep *bep, in bcm63xx_set_stall() argument
460 usbd_writel(udc, val, USBD_STALL_REG); in bcm63xx_set_stall()
470 static void bcm63xx_fifo_setup(struct bcm63xx_udc *udc) in bcm63xx_fifo_setup() argument
472 int is_hs = udc->gadget.speed == USB_SPEED_HIGH; in bcm63xx_fifo_setup()
481 bcm63xx_ep_dma_select(udc, i >> 1); in bcm63xx_fifo_setup()
487 usbd_writel(udc, val, USBD_RXFIFO_CONFIG_REG); in bcm63xx_fifo_setup()
488 usbd_writel(udc, in bcm63xx_fifo_setup()
496 usbd_writel(udc, val, USBD_TXFIFO_CONFIG_REG); in bcm63xx_fifo_setup()
497 usbd_writel(udc, in bcm63xx_fifo_setup()
501 usbd_readl(udc, USBD_TXFIFO_EPSIZE_REG); in bcm63xx_fifo_setup()
510 static void bcm63xx_fifo_reset_ep(struct bcm63xx_udc *udc, int ep_num) in bcm63xx_fifo_reset_ep() argument
514 bcm63xx_ep_dma_select(udc, ep_num); in bcm63xx_fifo_reset_ep()
516 val = usbd_readl(udc, USBD_CONTROL_REG); in bcm63xx_fifo_reset_ep()
518 usbd_writel(udc, val, USBD_CONTROL_REG); in bcm63xx_fifo_reset_ep()
519 usbd_readl(udc, USBD_CONTROL_REG); in bcm63xx_fifo_reset_ep()
526 static void bcm63xx_fifo_reset(struct bcm63xx_udc *udc) in bcm63xx_fifo_reset() argument
531 bcm63xx_fifo_reset_ep(udc, i); in bcm63xx_fifo_reset()
538 static void bcm63xx_ep_init(struct bcm63xx_udc *udc) in bcm63xx_ep_init() argument
548 bcm63xx_ep_dma_select(udc, cfg->ep_num); in bcm63xx_ep_init()
551 usbd_writel(udc, val, USBD_EPNUM_TYPEMAP_REG); in bcm63xx_ep_init()
561 static void bcm63xx_ep_setup(struct bcm63xx_udc *udc) in bcm63xx_ep_setup() argument
565 usbd_writel(udc, USBD_CSR_SETUPADDR_DEF, USBD_CSR_SETUPADDR_REG); in bcm63xx_ep_setup()
569 int max_pkt = udc->gadget.speed == USB_SPEED_HIGH ? in bcm63xx_ep_setup()
573 udc->iudma[i].max_pkt = max_pkt; in bcm63xx_ep_setup()
577 usb_ep_set_maxpacket_limit(&udc->bep[idx].ep, max_pkt); in bcm63xx_ep_setup()
582 (udc->cfg << USBD_CSR_EP_CFG_SHIFT) | in bcm63xx_ep_setup()
583 (udc->iface << USBD_CSR_EP_IFACE_SHIFT) | in bcm63xx_ep_setup()
584 (udc->alt_iface << USBD_CSR_EP_ALTIFACE_SHIFT) | in bcm63xx_ep_setup()
586 usbd_writel(udc, val, USBD_CSR_EP_REG(idx)); in bcm63xx_ep_setup()
603 static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma, in iudma_write() argument
666 usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK, in iudma_write()
679 static int iudma_read(struct bcm63xx_udc *udc, struct iudma_ch *iudma) in iudma_read() argument
713 static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) in iudma_reset_channel() argument
720 bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num)); in iudma_reset_channel()
723 usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG, ch_idx); in iudma_reset_channel()
725 while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx) & in iudma_reset_channel()
731 bcm63xx_fifo_reset_ep(udc, iudma->ep_num); in iudma_reset_channel()
734 dev_err(udc->dev, "can't reset IUDMA channel %d\n", in iudma_reset_channel()
739 dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n", in iudma_reset_channel()
741 usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK, in iudma_reset_channel()
745 usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG, ch_idx); in iudma_reset_channel()
756 usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, in iudma_reset_channel()
758 usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG, ch_idx); in iudma_reset_channel()
760 usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG, ch_idx); in iudma_reset_channel()
761 usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG, ch_idx); in iudma_reset_channel()
769 static int iudma_init_channel(struct bcm63xx_udc *udc, unsigned int ch_idx) in iudma_init_channel() argument
771 struct iudma_ch *iudma = &udc->iudma[ch_idx]; in iudma_init_channel()
780 bep = &udc->bep[iudma->ep_num]; in iudma_init_channel()
786 iudma->udc = udc; in iudma_init_channel()
793 iudma->bd_ring = dmam_alloc_coherent(udc->dev, in iudma_init_channel()
809 static int iudma_init(struct bcm63xx_udc *udc) in iudma_init() argument
813 usb_dma_writel(udc, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); in iudma_init()
816 rc = iudma_init_channel(udc, i); in iudma_init()
819 iudma_reset_channel(udc, &udc->iudma[i]); in iudma_init()
822 usb_dma_writel(udc, BIT(BCM63XX_NUM_IUDMA)-1, ENETDMA_GLB_IRQMASK_REG); in iudma_init()
832 static void iudma_uninit(struct bcm63xx_udc *udc) in iudma_uninit() argument
836 usb_dma_writel(udc, 0, ENETDMA_GLB_IRQMASK_REG); in iudma_uninit()
839 iudma_reset_channel(udc, &udc->iudma[i]); in iudma_uninit()
841 usb_dma_writel(udc, 0, ENETDMA_CFG_REG); in iudma_uninit()
853 static void bcm63xx_set_ctrl_irqs(struct bcm63xx_udc *udc, bool enable_irqs) in bcm63xx_set_ctrl_irqs() argument
857 usbd_writel(udc, 0, USBD_STATUS_REG); in bcm63xx_set_ctrl_irqs()
864 usbd_writel(udc, enable_irqs ? val : 0, USBD_EVENT_IRQ_MASK_REG); in bcm63xx_set_ctrl_irqs()
865 usbd_writel(udc, val, USBD_EVENT_IRQ_STATUS_REG); in bcm63xx_set_ctrl_irqs()
879 static void bcm63xx_select_phy_mode(struct bcm63xx_udc *udc, bool is_device) in bcm63xx_select_phy_mode() argument
881 u32 val, portmask = BIT(udc->pd->port_no); in bcm63xx_select_phy_mode()
919 static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on) in bcm63xx_select_pullup() argument
921 u32 val, portmask = BIT(udc->pd->port_no); in bcm63xx_select_pullup()
938 static void bcm63xx_uninit_udc_hw(struct bcm63xx_udc *udc) in bcm63xx_uninit_udc_hw() argument
940 set_clocks(udc, true); in bcm63xx_uninit_udc_hw()
941 iudma_uninit(udc); in bcm63xx_uninit_udc_hw()
942 set_clocks(udc, false); in bcm63xx_uninit_udc_hw()
944 clk_put(udc->usbd_clk); in bcm63xx_uninit_udc_hw()
945 clk_put(udc->usbh_clk); in bcm63xx_uninit_udc_hw()
952 static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc) in bcm63xx_init_udc_hw() argument
957 udc->ep0_ctrl_buf = devm_kzalloc(udc->dev, BCM63XX_MAX_CTRL_PKT, in bcm63xx_init_udc_hw()
959 if (!udc->ep0_ctrl_buf) in bcm63xx_init_udc_hw()
962 INIT_LIST_HEAD(&udc->gadget.ep_list); in bcm63xx_init_udc_hw()
964 struct bcm63xx_ep *bep = &udc->bep[i]; in bcm63xx_init_udc_hw()
970 list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list); in bcm63xx_init_udc_hw()
973 bep->udc = udc; in bcm63xx_init_udc_hw()
978 udc->gadget.ep0 = &udc->bep[0].ep; in bcm63xx_init_udc_hw()
979 list_del(&udc->bep[0].ep.ep_list); in bcm63xx_init_udc_hw()
981 udc->gadget.speed = USB_SPEED_UNKNOWN; in bcm63xx_init_udc_hw()
982 udc->ep0state = EP0_SHUTDOWN; in bcm63xx_init_udc_hw()
984 udc->usbh_clk = clk_get(udc->dev, "usbh"); in bcm63xx_init_udc_hw()
985 if (IS_ERR(udc->usbh_clk)) in bcm63xx_init_udc_hw()
988 udc->usbd_clk = clk_get(udc->dev, "usbd"); in bcm63xx_init_udc_hw()
989 if (IS_ERR(udc->usbd_clk)) { in bcm63xx_init_udc_hw()
990 clk_put(udc->usbh_clk); in bcm63xx_init_udc_hw()
994 set_clocks(udc, true); in bcm63xx_init_udc_hw()
999 usbd_writel(udc, val, USBD_CONTROL_REG); in bcm63xx_init_udc_hw()
1007 if (udc->gadget.max_speed == USB_SPEED_HIGH) in bcm63xx_init_udc_hw()
1011 usbd_writel(udc, val, USBD_STRAPS_REG); in bcm63xx_init_udc_hw()
1013 bcm63xx_set_ctrl_irqs(udc, false); in bcm63xx_init_udc_hw()
1015 usbd_writel(udc, 0, USBD_EVENT_IRQ_CFG_LO_REG); in bcm63xx_init_udc_hw()
1019 usbd_writel(udc, val, USBD_EVENT_IRQ_CFG_HI_REG); in bcm63xx_init_udc_hw()
1021 rc = iudma_init(udc); in bcm63xx_init_udc_hw()
1022 set_clocks(udc, false); in bcm63xx_init_udc_hw()
1024 bcm63xx_uninit_udc_hw(udc); in bcm63xx_init_udc_hw()
1045 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_ep_enable() local
1052 if (!udc->driver) in bcm63xx_ep_enable()
1055 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_ep_enable()
1057 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_ep_enable()
1064 iudma_reset_channel(udc, iudma); in bcm63xx_ep_enable()
1067 bcm63xx_set_stall(udc, bep, false); in bcm63xx_ep_enable()
1068 clear_bit(bep->ep_num, &udc->wedgemap); in bcm63xx_ep_enable()
1073 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_ep_enable()
1084 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_ep_disable() local
1092 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_ep_disable()
1094 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_ep_disable()
1099 iudma_reset_channel(udc, iudma); in bcm63xx_ep_disable()
1106 usb_gadget_unmap_request(&udc->gadget, &breq->req, in bcm63xx_ep_disable()
1111 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_ep_disable()
1113 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_ep_disable()
1118 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_ep_disable()
1168 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_udc_queue() local
1180 if (bep == &udc->bep[0]) { in bcm63xx_udc_queue()
1182 if (udc->ep0_reply) in bcm63xx_udc_queue()
1185 udc->ep0_reply = req; in bcm63xx_udc_queue()
1186 schedule_work(&udc->ep0_wq); in bcm63xx_udc_queue()
1190 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_queue()
1196 rc = usb_gadget_map_request(&udc->gadget, req, bep->iudma->is_tx); in bcm63xx_udc_queue()
1200 iudma_write(udc, bep->iudma, breq); in bcm63xx_udc_queue()
1204 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_queue()
1220 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_udc_dequeue() local
1225 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_dequeue()
1232 usb_gadget_unmap_request(&udc->gadget, &breq->req, bep->iudma->is_tx); in bcm63xx_udc_dequeue()
1235 iudma_reset_channel(udc, bep->iudma); in bcm63xx_udc_dequeue()
1243 iudma_write(udc, bep->iudma, next); in bcm63xx_udc_dequeue()
1250 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_dequeue()
1268 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_udc_set_halt() local
1271 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_set_halt()
1272 bcm63xx_set_stall(udc, bep, !!value); in bcm63xx_udc_set_halt()
1274 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_set_halt()
1288 struct bcm63xx_udc *udc = bep->udc; in bcm63xx_udc_set_wedge() local
1291 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_set_wedge()
1292 set_bit(bep->ep_num, &udc->wedgemap); in bcm63xx_udc_set_wedge()
1293 bcm63xx_set_stall(udc, bep, true); in bcm63xx_udc_set_wedge()
1294 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_set_wedge()
1322 static int bcm63xx_ep0_setup_callback(struct bcm63xx_udc *udc, in bcm63xx_ep0_setup_callback() argument
1327 spin_unlock_irq(&udc->lock); in bcm63xx_ep0_setup_callback()
1328 rc = udc->driver->setup(&udc->gadget, ctrl); in bcm63xx_ep0_setup_callback()
1329 spin_lock_irq(&udc->lock); in bcm63xx_ep0_setup_callback()
1345 static int bcm63xx_ep0_spoof_set_cfg(struct bcm63xx_udc *udc) in bcm63xx_ep0_spoof_set_cfg() argument
1352 ctrl.wValue = cpu_to_le16(udc->cfg); in bcm63xx_ep0_spoof_set_cfg()
1356 rc = bcm63xx_ep0_setup_callback(udc, &ctrl); in bcm63xx_ep0_spoof_set_cfg()
1358 dev_warn_ratelimited(udc->dev, in bcm63xx_ep0_spoof_set_cfg()
1360 udc->cfg); in bcm63xx_ep0_spoof_set_cfg()
1369 static int bcm63xx_ep0_spoof_set_iface(struct bcm63xx_udc *udc) in bcm63xx_ep0_spoof_set_iface() argument
1376 ctrl.wValue = cpu_to_le16(udc->alt_iface); in bcm63xx_ep0_spoof_set_iface()
1377 ctrl.wIndex = cpu_to_le16(udc->iface); in bcm63xx_ep0_spoof_set_iface()
1380 rc = bcm63xx_ep0_setup_callback(udc, &ctrl); in bcm63xx_ep0_spoof_set_iface()
1382 dev_warn_ratelimited(udc->dev, in bcm63xx_ep0_spoof_set_iface()
1384 udc->iface, udc->alt_iface); in bcm63xx_ep0_spoof_set_iface()
1395 static void bcm63xx_ep0_map_write(struct bcm63xx_udc *udc, int ch_idx, in bcm63xx_ep0_map_write() argument
1399 struct iudma_ch *iudma = &udc->iudma[ch_idx]; in bcm63xx_ep0_map_write()
1401 BUG_ON(udc->ep0_request); in bcm63xx_ep0_map_write()
1402 udc->ep0_request = req; in bcm63xx_ep0_map_write()
1406 usb_gadget_map_request(&udc->gadget, req, iudma->is_tx); in bcm63xx_ep0_map_write()
1407 iudma_write(udc, iudma, breq); in bcm63xx_ep0_map_write()
1416 static void bcm63xx_ep0_complete(struct bcm63xx_udc *udc, in bcm63xx_ep0_complete() argument
1423 spin_unlock_irq(&udc->lock); in bcm63xx_ep0_complete()
1424 req->complete(&udc->bep[0].ep, req); in bcm63xx_ep0_complete()
1425 spin_lock_irq(&udc->lock); in bcm63xx_ep0_complete()
1435 static void bcm63xx_ep0_nuke_reply(struct bcm63xx_udc *udc, int is_tx) in bcm63xx_ep0_nuke_reply() argument
1437 struct usb_request *req = udc->ep0_reply; in bcm63xx_ep0_nuke_reply()
1439 udc->ep0_reply = NULL; in bcm63xx_ep0_nuke_reply()
1440 usb_gadget_unmap_request(&udc->gadget, req, is_tx); in bcm63xx_ep0_nuke_reply()
1441 if (udc->ep0_request == req) { in bcm63xx_ep0_nuke_reply()
1442 udc->ep0_req_completed = 0; in bcm63xx_ep0_nuke_reply()
1443 udc->ep0_request = NULL; in bcm63xx_ep0_nuke_reply()
1445 bcm63xx_ep0_complete(udc, req, -ESHUTDOWN); in bcm63xx_ep0_nuke_reply()
1453 static int bcm63xx_ep0_read_complete(struct bcm63xx_udc *udc) in bcm63xx_ep0_read_complete() argument
1455 struct usb_request *req = udc->ep0_request; in bcm63xx_ep0_read_complete()
1457 udc->ep0_req_completed = 0; in bcm63xx_ep0_read_complete()
1458 udc->ep0_request = NULL; in bcm63xx_ep0_read_complete()
1472 static void bcm63xx_ep0_internal_request(struct bcm63xx_udc *udc, int ch_idx, in bcm63xx_ep0_internal_request() argument
1475 struct usb_request *req = &udc->ep0_ctrl_req.req; in bcm63xx_ep0_internal_request()
1477 req->buf = udc->ep0_ctrl_buf; in bcm63xx_ep0_internal_request()
1481 bcm63xx_ep0_map_write(udc, ch_idx, req); in bcm63xx_ep0_internal_request()
1492 static enum bcm63xx_ep0_state bcm63xx_ep0_do_setup(struct bcm63xx_udc *udc) in bcm63xx_ep0_do_setup() argument
1495 struct usb_ctrlrequest *ctrl = (void *)udc->ep0_ctrl_buf; in bcm63xx_ep0_do_setup()
1497 rc = bcm63xx_ep0_read_complete(udc); in bcm63xx_ep0_do_setup()
1500 dev_err(udc->dev, "missing SETUP packet\n"); in bcm63xx_ep0_do_setup()
1514 dev_warn_ratelimited(udc->dev, in bcm63xx_ep0_do_setup()
1520 rc = bcm63xx_ep0_setup_callback(udc, ctrl); in bcm63xx_ep0_do_setup()
1522 bcm63xx_set_stall(udc, &udc->bep[0], true); in bcm63xx_ep0_do_setup()
1545 static int bcm63xx_ep0_do_idle(struct bcm63xx_udc *udc) in bcm63xx_ep0_do_idle() argument
1547 if (udc->ep0_req_reset) { in bcm63xx_ep0_do_idle()
1548 udc->ep0_req_reset = 0; in bcm63xx_ep0_do_idle()
1549 } else if (udc->ep0_req_set_cfg) { in bcm63xx_ep0_do_idle()
1550 udc->ep0_req_set_cfg = 0; in bcm63xx_ep0_do_idle()
1551 if (bcm63xx_ep0_spoof_set_cfg(udc) >= 0) in bcm63xx_ep0_do_idle()
1552 udc->ep0state = EP0_IN_FAKE_STATUS_PHASE; in bcm63xx_ep0_do_idle()
1553 } else if (udc->ep0_req_set_iface) { in bcm63xx_ep0_do_idle()
1554 udc->ep0_req_set_iface = 0; in bcm63xx_ep0_do_idle()
1555 if (bcm63xx_ep0_spoof_set_iface(udc) >= 0) in bcm63xx_ep0_do_idle()
1556 udc->ep0state = EP0_IN_FAKE_STATUS_PHASE; in bcm63xx_ep0_do_idle()
1557 } else if (udc->ep0_req_completed) { in bcm63xx_ep0_do_idle()
1558 udc->ep0state = bcm63xx_ep0_do_setup(udc); in bcm63xx_ep0_do_idle()
1559 return udc->ep0state == EP0_IDLE ? -EAGAIN : 0; in bcm63xx_ep0_do_idle()
1560 } else if (udc->ep0_req_shutdown) { in bcm63xx_ep0_do_idle()
1561 udc->ep0_req_shutdown = 0; in bcm63xx_ep0_do_idle()
1562 udc->ep0_req_completed = 0; in bcm63xx_ep0_do_idle()
1563 udc->ep0_request = NULL; in bcm63xx_ep0_do_idle()
1564 iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]); in bcm63xx_ep0_do_idle()
1565 usb_gadget_unmap_request(&udc->gadget, in bcm63xx_ep0_do_idle()
1566 &udc->ep0_ctrl_req.req, 0); in bcm63xx_ep0_do_idle()
1570 udc->ep0state = EP0_SHUTDOWN; in bcm63xx_ep0_do_idle()
1571 } else if (udc->ep0_reply) { in bcm63xx_ep0_do_idle()
1577 dev_warn(udc->dev, "nuking unexpected reply\n"); in bcm63xx_ep0_do_idle()
1578 bcm63xx_ep0_nuke_reply(udc, 0); in bcm63xx_ep0_do_idle()
1592 static int bcm63xx_ep0_one_round(struct bcm63xx_udc *udc) in bcm63xx_ep0_one_round() argument
1594 enum bcm63xx_ep0_state ep0state = udc->ep0state; in bcm63xx_ep0_one_round()
1595 bool shutdown = udc->ep0_req_reset || udc->ep0_req_shutdown; in bcm63xx_ep0_one_round()
1597 switch (udc->ep0state) { in bcm63xx_ep0_one_round()
1600 bcm63xx_ep0_internal_request(udc, IUDMA_EP0_RXCHAN, in bcm63xx_ep0_one_round()
1605 return bcm63xx_ep0_do_idle(udc); in bcm63xx_ep0_one_round()
1616 if (udc->ep0_reply) { in bcm63xx_ep0_one_round()
1617 bcm63xx_ep0_map_write(udc, IUDMA_EP0_TXCHAN, in bcm63xx_ep0_one_round()
1618 udc->ep0_reply); in bcm63xx_ep0_one_round()
1632 if (udc->ep0_req_completed) { in bcm63xx_ep0_one_round()
1633 udc->ep0_reply = NULL; in bcm63xx_ep0_one_round()
1634 bcm63xx_ep0_read_complete(udc); in bcm63xx_ep0_one_round()
1641 iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]); in bcm63xx_ep0_one_round()
1642 bcm63xx_ep0_nuke_reply(udc, 1); in bcm63xx_ep0_one_round()
1649 if (udc->ep0_reply) { in bcm63xx_ep0_one_round()
1650 bcm63xx_ep0_map_write(udc, IUDMA_EP0_RXCHAN, in bcm63xx_ep0_one_round()
1651 udc->ep0_reply); in bcm63xx_ep0_one_round()
1659 if (udc->ep0_req_completed) { in bcm63xx_ep0_one_round()
1660 udc->ep0_reply = NULL; in bcm63xx_ep0_one_round()
1661 bcm63xx_ep0_read_complete(udc); in bcm63xx_ep0_one_round()
1664 bcm63xx_ep0_internal_request(udc, IUDMA_EP0_TXCHAN, 0); in bcm63xx_ep0_one_round()
1667 iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]); in bcm63xx_ep0_one_round()
1668 bcm63xx_ep0_nuke_reply(udc, 0); in bcm63xx_ep0_one_round()
1682 if (udc->ep0_req_completed) { in bcm63xx_ep0_one_round()
1683 bcm63xx_ep0_read_complete(udc); in bcm63xx_ep0_one_round()
1686 iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]); in bcm63xx_ep0_one_round()
1687 udc->ep0_request = NULL; in bcm63xx_ep0_one_round()
1706 struct usb_request *r = udc->ep0_reply; in bcm63xx_ep0_one_round()
1714 bcm63xx_ep0_complete(udc, r, 0); in bcm63xx_ep0_one_round()
1715 udc->ep0_reply = NULL; in bcm63xx_ep0_one_round()
1723 if (udc->ep0state == ep0state) in bcm63xx_ep0_one_round()
1726 udc->ep0state = ep0state; in bcm63xx_ep0_one_round()
1746 struct bcm63xx_udc *udc = container_of(w, struct bcm63xx_udc, ep0_wq); in bcm63xx_ep0_process() local
1747 spin_lock_irq(&udc->lock); in bcm63xx_ep0_process()
1748 while (bcm63xx_ep0_one_round(udc) == 0) in bcm63xx_ep0_process()
1750 spin_unlock_irq(&udc->lock); in bcm63xx_ep0_process()
1763 struct bcm63xx_udc *udc = gadget_to_udc(gadget); in bcm63xx_udc_get_frame() local
1765 return (usbd_readl(udc, USBD_STATUS_REG) & in bcm63xx_udc_get_frame()
1778 struct bcm63xx_udc *udc = gadget_to_udc(gadget); in bcm63xx_udc_pullup() local
1782 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_pullup()
1783 if (is_on && udc->ep0state == EP0_SHUTDOWN) { in bcm63xx_udc_pullup()
1784 udc->gadget.speed = USB_SPEED_UNKNOWN; in bcm63xx_udc_pullup()
1785 udc->ep0state = EP0_REQUEUE; in bcm63xx_udc_pullup()
1786 bcm63xx_fifo_setup(udc); in bcm63xx_udc_pullup()
1787 bcm63xx_fifo_reset(udc); in bcm63xx_udc_pullup()
1788 bcm63xx_ep_setup(udc); in bcm63xx_udc_pullup()
1790 bitmap_zero(&udc->wedgemap, BCM63XX_NUM_EP); in bcm63xx_udc_pullup()
1792 bcm63xx_set_stall(udc, &udc->bep[i], false); in bcm63xx_udc_pullup()
1794 bcm63xx_set_ctrl_irqs(udc, true); in bcm63xx_udc_pullup()
1797 } else if (!is_on && udc->ep0state != EP0_SHUTDOWN) { in bcm63xx_udc_pullup()
1800 udc->ep0_req_shutdown = 1; in bcm63xx_udc_pullup()
1801 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_pullup()
1804 schedule_work(&udc->ep0_wq); in bcm63xx_udc_pullup()
1805 if (udc->ep0state == EP0_SHUTDOWN) in bcm63xx_udc_pullup()
1809 bcm63xx_set_ctrl_irqs(udc, false); in bcm63xx_udc_pullup()
1810 cancel_work_sync(&udc->ep0_wq); in bcm63xx_udc_pullup()
1814 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_pullup()
1826 struct bcm63xx_udc *udc = gadget_to_udc(gadget); in bcm63xx_udc_start() local
1832 if (!udc) in bcm63xx_udc_start()
1834 if (udc->driver) in bcm63xx_udc_start()
1837 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_start()
1839 set_clocks(udc, true); in bcm63xx_udc_start()
1840 bcm63xx_fifo_setup(udc); in bcm63xx_udc_start()
1841 bcm63xx_ep_init(udc); in bcm63xx_udc_start()
1842 bcm63xx_ep_setup(udc); in bcm63xx_udc_start()
1843 bcm63xx_fifo_reset(udc); in bcm63xx_udc_start()
1844 bcm63xx_select_phy_mode(udc, true); in bcm63xx_udc_start()
1846 udc->driver = driver; in bcm63xx_udc_start()
1848 udc->gadget.dev.of_node = udc->dev->of_node; in bcm63xx_udc_start()
1850 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_start()
1862 struct bcm63xx_udc *udc = gadget_to_udc(gadget); in bcm63xx_udc_stop() local
1865 spin_lock_irqsave(&udc->lock, flags); in bcm63xx_udc_stop()
1867 udc->driver = NULL; in bcm63xx_udc_stop()
1877 bcm63xx_select_phy_mode(udc, false); in bcm63xx_udc_stop()
1878 set_clocks(udc, false); in bcm63xx_udc_stop()
1880 spin_unlock_irqrestore(&udc->lock, flags); in bcm63xx_udc_stop()
1905 static void bcm63xx_update_cfg_iface(struct bcm63xx_udc *udc) in bcm63xx_update_cfg_iface() argument
1907 u32 reg = usbd_readl(udc, USBD_STATUS_REG); in bcm63xx_update_cfg_iface()
1909 udc->cfg = (reg & USBD_STATUS_CFG_MASK) >> USBD_STATUS_CFG_SHIFT; in bcm63xx_update_cfg_iface()
1910 udc->iface = (reg & USBD_STATUS_INTF_MASK) >> USBD_STATUS_INTF_SHIFT; in bcm63xx_update_cfg_iface()
1911 udc->alt_iface = (reg & USBD_STATUS_ALTINTF_MASK) >> in bcm63xx_update_cfg_iface()
1913 bcm63xx_ep_setup(udc); in bcm63xx_update_cfg_iface()
1923 static int bcm63xx_update_link_speed(struct bcm63xx_udc *udc) in bcm63xx_update_link_speed() argument
1925 u32 reg = usbd_readl(udc, USBD_STATUS_REG); in bcm63xx_update_link_speed()
1926 enum usb_device_speed oldspeed = udc->gadget.speed; in bcm63xx_update_link_speed()
1930 udc->gadget.speed = USB_SPEED_HIGH; in bcm63xx_update_link_speed()
1933 udc->gadget.speed = USB_SPEED_FULL; in bcm63xx_update_link_speed()
1937 udc->gadget.speed = USB_SPEED_UNKNOWN; in bcm63xx_update_link_speed()
1938 dev_err(udc->dev, in bcm63xx_update_link_speed()
1943 if (udc->gadget.speed != oldspeed) { in bcm63xx_update_link_speed()
1944 dev_info(udc->dev, "link up, %s-speed mode\n", in bcm63xx_update_link_speed()
1945 udc->gadget.speed == USB_SPEED_HIGH ? "high" : "full"); in bcm63xx_update_link_speed()
1963 static void bcm63xx_update_wedge(struct bcm63xx_udc *udc, bool new_status) in bcm63xx_update_wedge() argument
1967 for_each_set_bit(i, &udc->wedgemap, BCM63XX_NUM_EP) { in bcm63xx_update_wedge()
1968 bcm63xx_set_stall(udc, &udc->bep[i], new_status); in bcm63xx_update_wedge()
1970 clear_bit(i, &udc->wedgemap); in bcm63xx_update_wedge()
1984 struct bcm63xx_udc *udc = dev_id; in bcm63xx_udc_ctrl_isr() local
1988 stat = usbd_readl(udc, USBD_EVENT_IRQ_STATUS_REG) & in bcm63xx_udc_ctrl_isr()
1989 usbd_readl(udc, USBD_EVENT_IRQ_MASK_REG); in bcm63xx_udc_ctrl_isr()
1991 usbd_writel(udc, stat, USBD_EVENT_IRQ_STATUS_REG); in bcm63xx_udc_ctrl_isr()
1993 spin_lock(&udc->lock); in bcm63xx_udc_ctrl_isr()
1997 if (!(usbd_readl(udc, USBD_EVENTS_REG) & in bcm63xx_udc_ctrl_isr()
1999 udc->gadget.speed != USB_SPEED_UNKNOWN) in bcm63xx_udc_ctrl_isr()
2000 dev_info(udc->dev, "link down\n"); in bcm63xx_udc_ctrl_isr()
2002 udc->gadget.speed = USB_SPEED_UNKNOWN; in bcm63xx_udc_ctrl_isr()
2006 bcm63xx_fifo_setup(udc); in bcm63xx_udc_ctrl_isr()
2007 bcm63xx_fifo_reset(udc); in bcm63xx_udc_ctrl_isr()
2008 bcm63xx_ep_setup(udc); in bcm63xx_udc_ctrl_isr()
2010 bcm63xx_update_wedge(udc, false); in bcm63xx_udc_ctrl_isr()
2012 udc->ep0_req_reset = 1; in bcm63xx_udc_ctrl_isr()
2013 schedule_work(&udc->ep0_wq); in bcm63xx_udc_ctrl_isr()
2017 if (bcm63xx_update_link_speed(udc)) { in bcm63xx_udc_ctrl_isr()
2018 bcm63xx_fifo_setup(udc); in bcm63xx_udc_ctrl_isr()
2019 bcm63xx_ep_setup(udc); in bcm63xx_udc_ctrl_isr()
2021 bcm63xx_update_wedge(udc, true); in bcm63xx_udc_ctrl_isr()
2024 bcm63xx_update_cfg_iface(udc); in bcm63xx_udc_ctrl_isr()
2025 udc->ep0_req_set_cfg = 1; in bcm63xx_udc_ctrl_isr()
2026 schedule_work(&udc->ep0_wq); in bcm63xx_udc_ctrl_isr()
2029 bcm63xx_update_cfg_iface(udc); in bcm63xx_udc_ctrl_isr()
2030 udc->ep0_req_set_iface = 1; in bcm63xx_udc_ctrl_isr()
2031 schedule_work(&udc->ep0_wq); in bcm63xx_udc_ctrl_isr()
2033 spin_unlock(&udc->lock); in bcm63xx_udc_ctrl_isr()
2035 if (disconnected && udc->driver) in bcm63xx_udc_ctrl_isr()
2036 udc->driver->disconnect(&udc->gadget); in bcm63xx_udc_ctrl_isr()
2037 else if (bus_reset && udc->driver) in bcm63xx_udc_ctrl_isr()
2038 usb_gadget_udc_reset(&udc->gadget, udc->driver); in bcm63xx_udc_ctrl_isr()
2056 struct bcm63xx_udc *udc = iudma->udc; in bcm63xx_udc_data_isr() local
2063 spin_lock(&udc->lock); in bcm63xx_udc_data_isr()
2065 usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, in bcm63xx_udc_data_isr()
2068 rc = iudma_read(udc, iudma); in bcm63xx_udc_data_isr()
2073 req = udc->ep0_request; in bcm63xx_udc_data_isr()
2081 udc->ep0_req_completed = 1; in bcm63xx_udc_data_isr()
2083 schedule_work(&udc->ep0_wq); in bcm63xx_udc_data_isr()
2089 iudma_write(udc, iudma, breq); in bcm63xx_udc_data_isr()
2110 iudma_write(udc, iudma, next); in bcm63xx_udc_data_isr()
2113 iudma_write(udc, iudma, breq); in bcm63xx_udc_data_isr()
2117 spin_unlock(&udc->lock); in bcm63xx_udc_data_isr()
2120 usb_gadget_unmap_request(&udc->gadget, req, iudma->is_tx); in bcm63xx_udc_data_isr()
2141 struct bcm63xx_udc *udc = s->private; in bcm63xx_usbd_dbg_show() local
2143 if (!udc->driver) in bcm63xx_usbd_dbg_show()
2147 bcm63xx_ep0_state_names[udc->ep0state]); in bcm63xx_usbd_dbg_show()
2149 udc->ep0_req_reset ? "reset " : "", in bcm63xx_usbd_dbg_show()
2150 udc->ep0_req_set_cfg ? "set_cfg " : "", in bcm63xx_usbd_dbg_show()
2151 udc->ep0_req_set_iface ? "set_iface " : "", in bcm63xx_usbd_dbg_show()
2152 udc->ep0_req_shutdown ? "shutdown " : "", in bcm63xx_usbd_dbg_show()
2153 udc->ep0_request ? "pending " : "", in bcm63xx_usbd_dbg_show()
2154 udc->ep0_req_completed ? "completed " : "", in bcm63xx_usbd_dbg_show()
2155 udc->ep0_reply ? "reply " : ""); in bcm63xx_usbd_dbg_show()
2157 udc->cfg, udc->iface, udc->alt_iface); in bcm63xx_usbd_dbg_show()
2160 usbd_readl(udc, USBD_CONTROL_REG), in bcm63xx_usbd_dbg_show()
2161 usbd_readl(udc, USBD_STRAPS_REG), in bcm63xx_usbd_dbg_show()
2162 usbd_readl(udc, USBD_STATUS_REG)); in bcm63xx_usbd_dbg_show()
2164 usbd_readl(udc, USBD_EVENTS_REG), in bcm63xx_usbd_dbg_show()
2165 usbd_readl(udc, USBD_STALL_REG)); in bcm63xx_usbd_dbg_show()
2179 struct bcm63xx_udc *udc = s->private; in bcm63xx_iudma_dbg_show() local
2183 if (!udc->driver) in bcm63xx_iudma_dbg_show()
2187 struct iudma_ch *iudma = &udc->iudma[ch_idx]; in bcm63xx_iudma_dbg_show()
2206 usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG, ch_idx), in bcm63xx_iudma_dbg_show()
2207 usb_dmac_readl(udc, ENETDMAC_IR_REG, ch_idx), in bcm63xx_iudma_dbg_show()
2208 usb_dmac_readl(udc, ENETDMAC_IRMASK_REG, ch_idx), in bcm63xx_iudma_dbg_show()
2209 usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG, ch_idx)); in bcm63xx_iudma_dbg_show()
2211 sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG, ch_idx); in bcm63xx_iudma_dbg_show()
2212 sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG, ch_idx); in bcm63xx_iudma_dbg_show()
2214 usb_dmas_readl(udc, ENETDMAS_RSTART_REG, ch_idx), in bcm63xx_iudma_dbg_show()
2217 usb_dmas_readl(udc, ENETDMAS_SRAM4_REG, ch_idx)); in bcm63xx_iudma_dbg_show()
2281 static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) in bcm63xx_udc_init_debugfs() argument
2288 root = debugfs_create_dir(udc->gadget.name, NULL); in bcm63xx_udc_init_debugfs()
2292 usbd = debugfs_create_file("usbd", 0400, root, udc, in bcm63xx_udc_init_debugfs()
2296 iudma = debugfs_create_file("iudma", 0400, root, udc, in bcm63xx_udc_init_debugfs()
2301 udc->debugfs_root = root; in bcm63xx_udc_init_debugfs()
2302 udc->debugfs_usbd = usbd; in bcm63xx_udc_init_debugfs()
2303 udc->debugfs_iudma = iudma; in bcm63xx_udc_init_debugfs()
2310 dev_err(udc->dev, "debugfs is not available\n"); in bcm63xx_udc_init_debugfs()
2319 static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) in bcm63xx_udc_cleanup_debugfs() argument
2321 debugfs_remove(udc->debugfs_iudma); in bcm63xx_udc_cleanup_debugfs()
2322 debugfs_remove(udc->debugfs_usbd); in bcm63xx_udc_cleanup_debugfs()
2323 debugfs_remove(udc->debugfs_root); in bcm63xx_udc_cleanup_debugfs()
2324 udc->debugfs_iudma = NULL; in bcm63xx_udc_cleanup_debugfs()
2325 udc->debugfs_usbd = NULL; in bcm63xx_udc_cleanup_debugfs()
2326 udc->debugfs_root = NULL; in bcm63xx_udc_cleanup_debugfs()
2344 struct bcm63xx_udc *udc; in bcm63xx_udc_probe() local
2348 udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); in bcm63xx_udc_probe()
2349 if (!udc) in bcm63xx_udc_probe()
2352 platform_set_drvdata(pdev, udc); in bcm63xx_udc_probe()
2353 udc->dev = dev; in bcm63xx_udc_probe()
2354 udc->pd = pd; in bcm63xx_udc_probe()
2362 udc->usbd_regs = devm_ioremap_resource(dev, res); in bcm63xx_udc_probe()
2363 if (IS_ERR(udc->usbd_regs)) in bcm63xx_udc_probe()
2364 return PTR_ERR(udc->usbd_regs); in bcm63xx_udc_probe()
2367 udc->iudma_regs = devm_ioremap_resource(dev, res); in bcm63xx_udc_probe()
2368 if (IS_ERR(udc->iudma_regs)) in bcm63xx_udc_probe()
2369 return PTR_ERR(udc->iudma_regs); in bcm63xx_udc_probe()
2371 spin_lock_init(&udc->lock); in bcm63xx_udc_probe()
2372 INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process); in bcm63xx_udc_probe()
2374 udc->gadget.ops = &bcm63xx_udc_ops; in bcm63xx_udc_probe()
2375 udc->gadget.name = dev_name(dev); in bcm63xx_udc_probe()
2378 udc->gadget.max_speed = USB_SPEED_HIGH; in bcm63xx_udc_probe()
2380 udc->gadget.max_speed = USB_SPEED_FULL; in bcm63xx_udc_probe()
2383 rc = bcm63xx_init_udc_hw(udc); in bcm63xx_udc_probe()
2396 dev_name(dev), udc) < 0) { in bcm63xx_udc_probe()
2409 dev_name(dev), &udc->iudma[i]) < 0) { in bcm63xx_udc_probe()
2415 bcm63xx_udc_init_debugfs(udc); in bcm63xx_udc_probe()
2416 rc = usb_add_gadget_udc(dev, &udc->gadget); in bcm63xx_udc_probe()
2420 bcm63xx_udc_cleanup_debugfs(udc); in bcm63xx_udc_probe()
2422 bcm63xx_uninit_udc_hw(udc); in bcm63xx_udc_probe()
2432 struct bcm63xx_udc *udc = platform_get_drvdata(pdev); in bcm63xx_udc_remove() local
2434 bcm63xx_udc_cleanup_debugfs(udc); in bcm63xx_udc_remove()
2435 usb_del_gadget_udc(&udc->gadget); in bcm63xx_udc_remove()
2436 BUG_ON(udc->driver); in bcm63xx_udc_remove()
2438 bcm63xx_uninit_udc_hw(udc); in bcm63xx_udc_remove()