static int msm72k_set_halt(struct usb_ep *_ep, int value) { struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; unsigned int in = ept->flags & EPT_FLAG_IN; unsigned int n; unsigned long flags; spin_lock_irqsave(&ui->lock, flags); n = readl(USB_ENDPTCTRL(ept->num)); if (in) { if (value) n |= CTRL_TXS; else { n &= ~CTRL_TXS; n |= CTRL_TXR; } } else { if (value) n |= CTRL_RXS; else { n &= ~CTRL_RXS; n |= CTRL_RXR; } } writel(n, USB_ENDPTCTRL(ept->num)); spin_unlock_irqrestore(&ui->lock, flags); return 0; }
static void mxc_ep0_stall(void) { u32 temp; temp = readl(USB_ENDPTCTRL(0)); temp |= EPCTRL_TX_EP_STALL | EPCTRL_RX_EP_STALL; writel(temp, USB_ENDPTCTRL(0)); }
static void usb_ept_enable(struct msm_endpoint *ept, int yes, unsigned char ep_type) { struct usb_info *ui = ept->ui; int in = ept->flags & EPT_FLAG_IN; unsigned n; n = readl(USB_ENDPTCTRL(ept->num)); if (in) { if (yes) { n = (n & (~CTRL_TXT_MASK)) | (ep_type << CTRL_TXT_EP_TYPE_SHIFT); n |= CTRL_TXE | CTRL_TXR; } else n &= (~CTRL_TXE); } else { if (yes) { n = (n & (~CTRL_RXT_MASK)) | (ep_type << CTRL_RXT_EP_TYPE_SHIFT); n |= CTRL_RXE | CTRL_RXR; } else n &= ~(CTRL_RXE); } writel(n, USB_ENDPTCTRL(ept->num)); dev_dbg(&ui->pdev->dev, "ept %d %s %s\n", ept->num, in ? "in" : "out", yes ? "enabled" : "disabled"); }
static void mxc_ep_destroy(u8 ep_num, u8 dir) { u32 epctrl = 0; epctrl = readl(USB_ENDPTCTRL(ep_num)); if (dir) epctrl &= ~EPCTRL_TX_ENABLE; else epctrl &= ~EPCTRL_RX_ENABLE; writel(epctrl, USB_ENDPTCTRL(ep_num)); }
static void mxc_ep_setup(u8 ep_num, u8 dir, u8 ep_type) { u32 epctrl = 0; epctrl = readl(USB_ENDPTCTRL(ep_num)); if (dir) { if (ep_num) epctrl |= EPCTRL_TX_DATA_TOGGLE_RST; epctrl |= EPCTRL_TX_ENABLE; epctrl |= ((u32)(ep_type) << EPCTRL_TX_EP_TYPE_SHIFT); } else { if (ep_num) epctrl |= EPCTRL_RX_DATA_TOGGLE_RST; epctrl |= EPCTRL_RX_ENABLE; epctrl |= ((u32)(ep_type) << EPCTRL_RX_EP_TYPE_SHIFT); } writel(epctrl, USB_ENDPTCTRL(ep_num)); }
static int usb_ep_get_stall(struct msm_endpoint *ept) { unsigned int n; struct usb_info *ui = ept->ui; n = readl(USB_ENDPTCTRL(ept->num)); if (ept->flags & EPT_FLAG_IN) return (CTRL_TXS & n) ? 1 : 0; else return (CTRL_RXS & n) ? 1 : 0; }
static void endpoint_enable(struct udc_endpoint *ept, unsigned yes) { unsigned n = readl(USB_ENDPTCTRL(ept->num)); if (yes) { if (ept->in) { n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); } else { n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); } if (ept->num != 0) { /* XXX should be more dynamic... */ if (usb_highspeed) { ept->head->config = CONFIG_MAX_PKT(512) | CONFIG_ZLT; } else { ept->head->config = CONFIG_MAX_PKT(64) | CONFIG_ZLT; } } } writel(n, USB_ENDPTCTRL(ept->num)); }
static irqreturn_t usb_interrupt(int irq, void *data) { struct usb_info *ui = data; unsigned n; n = readl(USB_USBSTS); writel(n, USB_USBSTS); /* somehow we got an IRQ while in the reset sequence: ignore it */ if (ui->running == 0) return IRQ_HANDLED; if (n & STS_PCI) { switch (readl(USB_PORTSC) & PORTSC_PSPD_MASK) { case PORTSC_PSPD_FS: INFO("msm72k_udc: portchange USB_SPEED_FULL\n"); ui->gadget.speed = USB_SPEED_FULL; break; case PORTSC_PSPD_LS: INFO("msm72k_udc: portchange USB_SPEED_LOW\n"); ui->gadget.speed = USB_SPEED_LOW; break; case PORTSC_PSPD_HS: INFO("msm72k_udc: portchange USB_SPEED_HIGH\n"); ui->gadget.speed = USB_SPEED_HIGH; break; } } if (n & STS_URI) { INFO("msm72k_udc: reset\n"); writel(readl(USB_ENDPTSETUPSTAT), USB_ENDPTSETUPSTAT); writel(readl(USB_ENDPTCOMPLETE), USB_ENDPTCOMPLETE); writel(0xffffffff, USB_ENDPTFLUSH); writel(0, USB_ENDPTCTRL(1)); if (ui->online != 0) { /* marking us offline will cause ept queue attempts ** to fail */ ui->online = 0; flush_all_endpoints(ui); /* XXX: we can't seem to detect going offline, * XXX: so deconfigure on reset for the time being */ if (ui->driver) { printk(KERN_INFO "usb: notify offline\n"); ui->driver->disconnect(&ui->gadget); } } } if (n & STS_SLI) INFO("msm72k_udc: suspend\n"); if (n & STS_UI) { n = readl(USB_ENDPTSETUPSTAT); if (n & EPT_RX(0)) handle_setup(ui); n = readl(USB_ENDPTCOMPLETE); writel(n, USB_ENDPTCOMPLETE); while (n) { unsigned bit = __ffs(n); handle_endpoint(ui, bit); n = n & (~(1 << bit)); } } return IRQ_HANDLED; }
static void ep0_setup_stall(struct usb_info *ui) { writel((1<<16) | (1<<0), USB_ENDPTCTRL(0)); }
static void usb_ept_enable(struct msm_endpoint *ept, int yes, unsigned char ep_type) { struct usb_info *ui = ept->ui; int in = ept->flags & EPT_FLAG_IN; unsigned n; n = readl(USB_ENDPTCTRL(ept->num)); if (in) { n = (n & (~CTRL_TXT_MASK)); if (yes) { n |= CTRL_TXE | CTRL_TXR; } else { n &= (~CTRL_TXE); } if (yes) { switch (ep_type) { case USB_ENDPOINT_XFER_BULK: n |= CTRL_TXT_BULK; break; case USB_ENDPOINT_XFER_INT: n |= CTRL_TXT_INT; break; case USB_ENDPOINT_XFER_ISOC: n |= CTRL_TXT_ISOCH; break; default: pr_err("%s: unsupported ep_type %d for %s\n", __func__, ep_type, ept->ep.name); break; } } } else { n = (n & (~CTRL_RXT_MASK)); if (yes) { n |= CTRL_RXE | CTRL_RXR; } else { n &= ~(CTRL_RXE); } if (yes) { switch (ep_type) { case USB_ENDPOINT_XFER_BULK: n |= CTRL_RXT_BULK; break; case USB_ENDPOINT_XFER_INT: n |= CTRL_RXT_INT; break; case USB_ENDPOINT_XFER_ISOC: n |= CTRL_RXT_ISOCH; break; default: pr_err("%s: unsupported ep_type %d for %s\n", __func__, ep_type, ept->ep.name); break; } } } writel(n, USB_ENDPTCTRL(ept->num)); #if 0 INFO("ept %d %s %s\n", ept->num, in ? "in" : "out", yes ? "enabled" : "disabled"); #endif }