-static void defect7374_workaround(struct net2280 *dev, struct usb_ctrlrequest r)
-{
- u32 scratch, fsmvalue;
- u32 ack_wait_timeout, state;
-
- /* Workaround for Defect 7374 (U1/U2 erroneously rejected): */
- scratch = get_idx_reg(dev->regs, SCRATCH);
- fsmvalue = scratch & (0xf << DEFECT7374_FSM_FIELD);
- scratch &= ~(0xf << DEFECT7374_FSM_FIELD);
-
- if (!((fsmvalue == DEFECT7374_FSM_WAITING_FOR_CONTROL_READ) &&
- (r.bRequestType & USB_DIR_IN)))
- return;
-
- /* This is the first Control Read for this connection: */
- if (!(readl(&dev->usb->usbstat) & (1 << SUPER_SPEED_MODE))) {
- /*
- * Connection is NOT SS:
- * - Connection must be FS or HS.
- * - This FSM state should allow workaround software to
- * run after the next USB connection.
- */
- scratch |= DEFECT7374_FSM_NON_SS_CONTROL_READ;
- goto restore_data_eps;
- }
-
- /* Connection is SS: */
- for (ack_wait_timeout = 0;
- ack_wait_timeout < DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS;
- ack_wait_timeout++) {
-
- state = readl(&dev->plregs->pl_ep_status_1)
- & (0xff << STATE);
- if ((state >= (ACK_GOOD_NORMAL << STATE)) &&
- (state <= (ACK_GOOD_MORE_ACKS_TO_COME << STATE))) {
- scratch |= DEFECT7374_FSM_SS_CONTROL_READ;
- break;
- }
-
- /*
- * We have not yet received host's Data Phase ACK
- * - Wait and try again.
- */
- udelay(DEFECT_7374_PROCESSOR_WAIT_TIME);
-
- continue;
- }
-
-
- if (ack_wait_timeout >= DEFECT_7374_NUMBEROF_MAX_WAIT_LOOPS) {
- ERROR(dev, "FAIL: Defect 7374 workaround waited but failed");
- ERROR(dev, "to detect SS host's data phase ACK.");
- ERROR(dev, "PL_EP_STATUS_1(23:16):.Expected from 0x11 to 0x16");
- ERROR(dev, "got 0x%2.2x.\n", state >> STATE);
- } else {
- WARNING(dev, "INFO: Defect 7374 workaround waited about\n");
- WARNING(dev, "%duSec for Control Read Data Phase ACK\n",
- DEFECT_7374_PROCESSOR_WAIT_TIME * ack_wait_timeout);
- }
-
-restore_data_eps:
- /*
- * Restore data EPs to their pre-workaround settings (disabled,
- * initialized, and other details).
- */
- defect7374_disable_data_eps(dev);
-
- set_idx_reg(dev->regs, SCRATCH, scratch);
-
- return;
-}
-
-static void ep_stall(struct net2280_ep *ep, int stall)
-{
- struct net2280 *dev = ep->dev;
- u32 val;
- static const u32 ep_pl[9] = { 0, 3, 4, 7, 8, 2, 5, 6, 9 };
-
- if (stall) {
- writel((1 << SET_ENDPOINT_HALT) |
- /* (1 << SET_NAK_PACKETS) | */
- (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE),
- &ep->regs->ep_rsp);
- ep->is_halt = 1;
- } else {
- if (dev->gadget.speed == USB_SPEED_SUPER) {
- /*
- * Workaround for SS SeqNum not cleared via
- * Endpoint Halt (Clear) bit. select endpoint
- */
- val = readl(&dev->plregs->pl_ep_ctrl);
- val = (val & ~0x1f) | ep_pl[ep->num];
- writel(val, &dev->plregs->pl_ep_ctrl);
-
- val |= (1 << SEQUENCE_NUMBER_RESET);
- writel(val, &dev->plregs->pl_ep_ctrl);
- }
- val = readl(&ep->regs->ep_rsp);
- val |= (1 << CLEAR_ENDPOINT_HALT) |
- (1 << CLEAR_ENDPOINT_TOGGLE);
- writel(val
- /* | (1 << CLEAR_NAK_PACKETS)*/
- , &ep->regs->ep_rsp);
- ep->is_halt = 0;
- val = readl(&ep->regs->ep_rsp);
- }
-}
-
-static void ep_stdrsp(struct net2280_ep *ep, int value, int wedged)
-{
- /* set/clear, then synch memory views with the device */
- if (value) {
- ep->stopped = 1;
- if (ep->num == 0)
- ep->dev->protocol_stall = 1;
- else {
- if (ep->dma)
- ep_stop_dma(ep);
- ep_stall(ep, true);
- }
-
- if (wedged)
- ep->wedged = 1;
- } else {
- ep->stopped = 0;
- ep->wedged = 0;
-
- ep_stall(ep, false);
-
- /* Flush the queue */
- if (!list_empty(&ep->queue)) {
- struct net2280_request *req =
- list_entry(ep->queue.next, struct net2280_request,
- queue);
- if (ep->dma)
- resume_dma(ep);
- else {
- if (ep->is_in)
- write_fifo(ep, &req->req);
- else {
- if (read_fifo(ep, req))
- done(ep, req, 0);
- }
- }
- }
- }
-}
-
-static void handle_stat0_irqs_superspeed(struct net2280 *dev,
- struct net2280_ep *ep, struct usb_ctrlrequest r)
-{
- int tmp = 0;
-
-#define w_value le16_to_cpu(r.wValue)
-#define w_index le16_to_cpu(r.wIndex)
-#define w_length le16_to_cpu(r.wLength)
-
- switch (r.bRequest) {
- struct net2280_ep *e;
- u16 status;
-
- case USB_REQ_SET_CONFIGURATION:
- dev->addressed_state = !w_value;
- goto usb3_delegate;
-
- case USB_REQ_GET_STATUS:
- switch (r.bRequestType) {
- case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
- status = dev->wakeup_enable ? 0x02 : 0x00;
- if (dev->selfpowered)
- status |= 1 << 0;
- status |= (dev->u1_enable << 2 | dev->u2_enable << 3 |
- dev->ltm_enable << 4);
- writel(0, &dev->epregs[0].ep_irqenb);
- set_fifo_bytecount(ep, sizeof(status));
- writel((__force u32) status, &dev->epregs[0].ep_data);
- allow_status_338x(ep);
- break;
-
- case (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
- e = get_ep_by_addr(dev, w_index);
- if (!e)
- goto do_stall3;
- status = readl(&e->regs->ep_rsp) &
- (1 << CLEAR_ENDPOINT_HALT);
- writel(0, &dev->epregs[0].ep_irqenb);
- set_fifo_bytecount(ep, sizeof(status));
- writel((__force u32) status, &dev->epregs[0].ep_data);
- allow_status_338x(ep);
- break;
-
- default:
- goto usb3_delegate;
- }
- break;
-
- case USB_REQ_CLEAR_FEATURE:
- switch (r.bRequestType) {
- case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
- if (!dev->addressed_state) {
- switch (w_value) {
- case USB_DEVICE_U1_ENABLE:
- dev->u1_enable = 0;
- writel(readl(&dev->usb_ext->usbctl2) &
- ~(1 << U1_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
-
- case USB_DEVICE_U2_ENABLE:
- dev->u2_enable = 0;
- writel(readl(&dev->usb_ext->usbctl2) &
- ~(1 << U2_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
-
- case USB_DEVICE_LTM_ENABLE:
- dev->ltm_enable = 0;
- writel(readl(&dev->usb_ext->usbctl2) &
- ~(1 << LTM_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
-
- default:
- break;
- }
- }
- if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->wakeup_enable = 0;
- writel(readl(&dev->usb->usbctl) &
- ~(1 << DEVICE_REMOTE_WAKEUP_ENABLE),
- &dev->usb->usbctl);
- allow_status_338x(ep);
- break;
- }
- goto usb3_delegate;
-
- case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
- e = get_ep_by_addr(dev, w_index);
- if (!e)
- goto do_stall3;
- if (w_value != USB_ENDPOINT_HALT)
- goto do_stall3;
- VDEBUG(dev, "%s clear halt\n", e->ep.name);
- ep_stall(e, false);
- if (!list_empty(&e->queue) && e->td_dma)
- restart_dma(e);
- allow_status(ep);
- ep->stopped = 1;
- break;
-
- default:
- goto usb3_delegate;
- }
- break;
- case USB_REQ_SET_FEATURE:
- switch (r.bRequestType) {
- case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE):
- if (!dev->addressed_state) {
- switch (w_value) {
- case USB_DEVICE_U1_ENABLE:
- dev->u1_enable = 1;
- writel(readl(&dev->usb_ext->usbctl2) |
- (1 << U1_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
-
- case USB_DEVICE_U2_ENABLE:
- dev->u2_enable = 1;
- writel(readl(&dev->usb_ext->usbctl2) |
- (1 << U2_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
-
- case USB_DEVICE_LTM_ENABLE:
- dev->ltm_enable = 1;
- writel(readl(&dev->usb_ext->usbctl2) |
- (1 << LTM_ENABLE),
- &dev->usb_ext->usbctl2);
- allow_status_338x(ep);
- goto next_endpoints3;
- default:
- break;
- }
- }
-
- if (w_value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->wakeup_enable = 1;
- writel(readl(&dev->usb->usbctl) |
- (1 << DEVICE_REMOTE_WAKEUP_ENABLE),
- &dev->usb->usbctl);
- allow_status_338x(ep);
- break;
- }
- goto usb3_delegate;
-
- case (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT):
- e = get_ep_by_addr(dev, w_index);
- if (!e || (w_value != USB_ENDPOINT_HALT))
- goto do_stall3;
- ep_stdrsp(e, true, false);
- allow_status_338x(ep);
- break;
-
- default:
- goto usb3_delegate;
- }
-
- break;
- default:
-
-usb3_delegate:
- VDEBUG(dev, "setup %02x.%02x v%04x i%04x l%04x ep_cfg %08x\n",
- r.bRequestType, r.bRequest,
- w_value, w_index, w_length,
- readl(&ep->cfg->ep_cfg));
-
- ep->responded = 0;
- spin_unlock(&dev->lock);
- tmp = dev->driver->setup(&dev->gadget, &r);
- spin_lock(&dev->lock);
- }
-do_stall3:
- if (tmp < 0) {
- VDEBUG(dev, "req %02x.%02x protocol STALL; stat %d\n",
- r.bRequestType, r.bRequest, tmp);
- dev->protocol_stall = 1;
- /* TD 9.9 Halt Endpoint test. TD 9.22 Set feature test */
- ep_stall(ep, true);
- }
-
-next_endpoints3:
-
-#undef w_value
-#undef w_index
-#undef w_length
-
- return;
-}
-