summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/usb/gadget/udc
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/usb/gadget/udc
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/usb/gadget/udc')
-rw-r--r--kernel/drivers/usb/gadget/udc/Kconfig2
-rw-r--r--kernel/drivers/usb/gadget/udc/amd5536udc.c724
-rw-r--r--kernel/drivers/usb/gadget/udc/amd5536udc.h5
-rw-r--r--kernel/drivers/usb/gadget/udc/at91_udc.c39
-rw-r--r--kernel/drivers/usb/gadget/udc/at91_udc.h8
-rw-r--r--kernel/drivers/usb/gadget/udc/atmel_usba_udc.c55
-rw-r--r--kernel/drivers/usb/gadget/udc/atmel_usba_udc.h2
-rw-r--r--kernel/drivers/usb/gadget/udc/bcm63xx_udc.c29
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc.h2
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc_core.c3
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/dummy_hcd.c147
-rw-r--r--kernel/drivers/usb/gadget/udc/fotg210-udc.c32
-rw-r--r--kernel/drivers/usb/gadget/udc/fsl_qe_udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/fsl_udc_core.c13
-rw-r--r--kernel/drivers/usb/gadget/udc/fusb300_udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/gadget_chips.h55
-rw-r--r--kernel/drivers/usb/gadget/udc/goku_udc.c38
-rw-r--r--kernel/drivers/usb/gadget/udc/gr_udc.c14
-rw-r--r--kernel/drivers/usb/gadget/udc/lpc32xx_udc.c32
-rw-r--r--kernel/drivers/usb/gadget/udc/m66592-udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/mv_u3d_core.c12
-rw-r--r--kernel/drivers/usb/gadget/udc/mv_udc_core.c12
-rw-r--r--kernel/drivers/usb/gadget/udc/net2272.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/net2280.c237
-rw-r--r--kernel/drivers/usb/gadget/udc/omap_udc.c22
-rw-r--r--kernel/drivers/usb/gadget/udc/pch_udc.c46
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa25x_udc.c30
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa27x_udc.c6
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa27x_udc.h40
-rw-r--r--kernel/drivers/usb/gadget/udc/r8a66597-udc.c10
-rw-r--r--kernel/drivers/usb/gadget/udc/s3c-hsudc.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/s3c2410_udc.c38
-rw-r--r--kernel/drivers/usb/gadget/udc/udc-core.c104
-rw-r--r--kernel/drivers/usb/gadget/udc/udc-xilinx.c9
35 files changed, 1259 insertions, 585 deletions
diff --git a/kernel/drivers/usb/gadget/udc/Kconfig b/kernel/drivers/usb/gadget/udc/Kconfig
index 9a3a6b003..cdbff54e0 100644
--- a/kernel/drivers/usb/gadget/udc/Kconfig
+++ b/kernel/drivers/usb/gadget/udc/Kconfig
@@ -55,7 +55,7 @@ config USB_LPC32XX
config USB_ATMEL_USBA
tristate "Atmel USBA"
- depends on AVR32 || ARCH_AT91
+ depends on ((AVR32 && !OF) || ARCH_AT91)
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
diff --git a/kernel/drivers/usb/gadget/udc/amd5536udc.c b/kernel/drivers/usb/gadget/udc/amd5536udc.c
index de7e5e2cc..cd8764150 100644
--- a/kernel/drivers/usb/gadget/udc/amd5536udc.c
+++ b/kernel/drivers/usb/gadget/udc/amd5536udc.c
@@ -65,18 +65,10 @@
static void udc_tasklet_disconnect(unsigned long);
static void empty_req_queue(struct udc_ep *);
-static int udc_probe(struct udc *dev);
-static void udc_basic_init(struct udc *dev);
static void udc_setup_endpoints(struct udc *dev);
static void udc_soft_reset(struct udc *dev);
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
-static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
/* description */
static const char mod_desc[] = UDC_MOD_DESCRIPTION;
@@ -138,15 +130,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
/* endpoint names used for print */
static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
- ep0_string,
- "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
- "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
- "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
- "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
- "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
- "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
- "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(ep0_string,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep1in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep0out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
/* DMA usage flag */
@@ -548,6 +607,30 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
return &req->req;
}
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+ int ret_val = 0;
+ struct udc_data_dma *td;
+ struct udc_data_dma *td_last = NULL;
+ unsigned int i;
+
+ DBG(dev, "free chain req = %p\n", req);
+
+ /* do not free first desc., will be done by free for request */
+ td_last = req->td_data;
+ td = phys_to_virt(td_last->next);
+
+ for (i = 1; i < req->chain_len; i++) {
+ pci_pool_free(dev->data_requests, td,
+ (dma_addr_t)td_last->next);
+ td_last = td;
+ td = phys_to_virt(td_last->next);
+ }
+
+ return ret_val;
+}
+
/* Frees request packet, called by gadget driver */
static void
udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -722,6 +805,123 @@ udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
return finished;
}
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+ struct udc_ep *ep,
+ struct udc_request *req,
+ unsigned long buf_len, gfp_t gfp_flags
+)
+{
+ unsigned long bytes = req->req.length;
+ unsigned int i;
+ dma_addr_t dma_addr;
+ struct udc_data_dma *td = NULL;
+ struct udc_data_dma *last = NULL;
+ unsigned long txbytes;
+ unsigned create_new_chain = 0;
+ unsigned len;
+
+ VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+ bytes, buf_len);
+ dma_addr = DMA_DONT_USE;
+
+ /* unset L bit in first desc for OUT */
+ if (!ep->in)
+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+
+ /* alloc only new desc's if not already available */
+ len = req->req.length / ep->ep.maxpacket;
+ if (req->req.length % ep->ep.maxpacket)
+ len++;
+
+ if (len > req->chain_len) {
+ /* shorter chain already allocated before */
+ if (req->chain_len > 1)
+ udc_free_dma_chain(ep->dev, req);
+ req->chain_len = len;
+ create_new_chain = 1;
+ }
+
+ td = req->td_data;
+ /* gen. required number of descriptors and buffers */
+ for (i = buf_len; i < bytes; i += buf_len) {
+ /* create or determine next desc. */
+ if (create_new_chain) {
+ td = pci_pool_alloc(ep->dev->data_requests,
+ gfp_flags, &dma_addr);
+ if (!td)
+ return -ENOMEM;
+
+ td->status = 0;
+ } else if (i == buf_len) {
+ /* first td */
+ td = (struct udc_data_dma *)phys_to_virt(
+ req->td_data->next);
+ td->status = 0;
+ } else {
+ td = (struct udc_data_dma *)phys_to_virt(last->next);
+ td->status = 0;
+ }
+
+ if (td)
+ td->bufptr = req->req.dma + i; /* assign buffer */
+ else
+ break;
+
+ /* short packet ? */
+ if ((bytes - i) >= buf_len) {
+ txbytes = buf_len;
+ } else {
+ /* short packet */
+ txbytes = bytes - i;
+ }
+
+ /* link td and assign tx bytes */
+ if (i == buf_len) {
+ if (create_new_chain)
+ req->td_data->next = dma_addr;
+ /*
+ * else
+ * req->td_data->next = virt_to_phys(td);
+ */
+ /* write tx bytes */
+ if (ep->in) {
+ /* first desc */
+ req->td_data->status =
+ AMD_ADDBITS(req->td_data->status,
+ ep->ep.maxpacket,
+ UDC_DMA_IN_STS_TXBYTES);
+ /* second desc */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ } else {
+ if (create_new_chain)
+ last->next = dma_addr;
+ /*
+ * else
+ * last->next = virt_to_phys(td);
+ */
+ if (ep->in) {
+ /* write tx bytes */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ }
+ last = td;
+ }
+ /* set last bit */
+ if (td) {
+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+ /* last desc. points to itself */
+ req->td_data_last = td;
+ }
+
+ return 0;
+}
+
/* create/re-init a DMA descriptor or a DMA descriptor chain */
static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
{
@@ -846,32 +1046,6 @@ __acquires(ep->dev->lock)
ep->halted = halted;
}
-/* frees pci pool descriptors of a DMA chain */
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
-{
-
- int ret_val = 0;
- struct udc_data_dma *td;
- struct udc_data_dma *td_last = NULL;
- unsigned int i;
-
- DBG(dev, "free chain req = %p\n", req);
-
- /* do not free first desc., will be done by free for request */
- td_last = req->td_data;
- td = phys_to_virt(td_last->next);
-
- for (i = 1; i < req->chain_len; i++) {
-
- pci_pool_free(dev->data_requests, td,
- (dma_addr_t) td_last->next);
- td_last = td;
- td = phys_to_virt(td_last->next);
- }
-
- return ret_val;
-}
-
/* Iterates to the end of a DMA chain and returns last descriptor */
static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
{
@@ -908,125 +1082,6 @@ static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
}
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
- struct udc_ep *ep,
- struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags
-)
-{
- unsigned long bytes = req->req.length;
- unsigned int i;
- dma_addr_t dma_addr;
- struct udc_data_dma *td = NULL;
- struct udc_data_dma *last = NULL;
- unsigned long txbytes;
- unsigned create_new_chain = 0;
- unsigned len;
-
- VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
- bytes, buf_len);
- dma_addr = DMA_DONT_USE;
-
- /* unset L bit in first desc for OUT */
- if (!ep->in)
- req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-
- /* alloc only new desc's if not already available */
- len = req->req.length / ep->ep.maxpacket;
- if (req->req.length % ep->ep.maxpacket)
- len++;
-
- if (len > req->chain_len) {
- /* shorter chain already allocated before */
- if (req->chain_len > 1)
- udc_free_dma_chain(ep->dev, req);
- req->chain_len = len;
- create_new_chain = 1;
- }
-
- td = req->td_data;
- /* gen. required number of descriptors and buffers */
- for (i = buf_len; i < bytes; i += buf_len) {
- /* create or determine next desc. */
- if (create_new_chain) {
-
- td = pci_pool_alloc(ep->dev->data_requests,
- gfp_flags, &dma_addr);
- if (!td)
- return -ENOMEM;
-
- td->status = 0;
- } else if (i == buf_len) {
- /* first td */
- td = (struct udc_data_dma *) phys_to_virt(
- req->td_data->next);
- td->status = 0;
- } else {
- td = (struct udc_data_dma *) phys_to_virt(last->next);
- td->status = 0;
- }
-
-
- if (td)
- td->bufptr = req->req.dma + i; /* assign buffer */
- else
- break;
-
- /* short packet ? */
- if ((bytes - i) >= buf_len) {
- txbytes = buf_len;
- } else {
- /* short packet */
- txbytes = bytes - i;
- }
-
- /* link td and assign tx bytes */
- if (i == buf_len) {
- if (create_new_chain)
- req->td_data->next = dma_addr;
- /*
- else
- req->td_data->next = virt_to_phys(td);
- */
- /* write tx bytes */
- if (ep->in) {
- /* first desc */
- req->td_data->status =
- AMD_ADDBITS(req->td_data->status,
- ep->ep.maxpacket,
- UDC_DMA_IN_STS_TXBYTES);
- /* second desc */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- } else {
- if (create_new_chain)
- last->next = dma_addr;
- /*
- else
- last->next = virt_to_phys(td);
- */
- if (ep->in) {
- /* write tx bytes */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- }
- last = td;
- }
- /* set last bit */
- if (td) {
- td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
- /* last desc. points to itself */
- req->td_data_last = td;
- }
-
- return 0;
-}
-
/* Enabling RX DMA */
static void udc_set_rde(struct udc *dev)
{
@@ -1386,6 +1441,26 @@ static int udc_get_frame(struct usb_gadget *gadget)
return -EOPNOTSUPP;
}
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ DBG(dev, "UDC initiates remote wakeup\n");
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ tmp = readl(&dev->regs->ctl);
+ tmp |= AMD_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+ tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return 0;
+}
+
/* Remote wakeup gadget interface */
static int udc_wakeup(struct usb_gadget *gadget)
{
@@ -1431,33 +1506,6 @@ static void make_ep_lists(struct udc *dev)
dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
}
-/* init registers at driver load time */
-static int startup_registers(struct udc *dev)
-{
- u32 tmp;
-
- /* init controller by soft reset */
- udc_soft_reset(dev);
-
- /* mask not needed interrupts */
- udc_mask_unused_interrupts(dev);
-
- /* put into initial config */
- udc_basic_init(dev);
- /* link up all endpoints */
- udc_setup_endpoints(dev);
-
- /* program speed */
- tmp = readl(&dev->regs->cfg);
- if (use_fullspeed)
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
- else
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
- writel(tmp, &dev->regs->cfg);
-
- return 0;
-}
-
/* Inits UDC context */
static void udc_basic_init(struct udc *dev)
{
@@ -1496,6 +1544,33 @@ static void udc_basic_init(struct udc *dev)
dev->data_ep_queued = 0;
}
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+ u32 tmp;
+
+ /* init controller by soft reset */
+ udc_soft_reset(dev);
+
+ /* mask not needed interrupts */
+ udc_mask_unused_interrupts(dev);
+
+ /* put into initial config */
+ udc_basic_init(dev);
+ /* link up all endpoints */
+ udc_setup_endpoints(dev);
+
+ /* program speed */
+ tmp = readl(&dev->regs->cfg);
+ if (use_fullspeed)
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+ else
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+ writel(tmp, &dev->regs->cfg);
+
+ return 0;
+}
+
/* Sets initial endpoint parameters */
static void udc_setup_endpoints(struct udc *dev)
{
@@ -1517,7 +1592,8 @@ static void udc_setup_endpoints(struct udc *dev)
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
ep = &dev->ep[tmp];
ep->dev = dev;
- ep->ep.name = ep_string[tmp];
+ ep->ep.name = ep_info[tmp].name;
+ ep->ep.caps = ep_info[tmp].caps;
ep->num = tmp;
/* txfifo size is calculated at enable time */
ep->txfifo = dev->txfifo;
@@ -2109,7 +2185,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
}
/* DMA */
- } else if (!ep->cancel_transfer && req != NULL) {
+ } else if (!ep->cancel_transfer && req) {
ret_val = IRQ_HANDLED;
/* check for DMA done */
@@ -3039,6 +3115,17 @@ static void udc_remove(struct udc *dev)
udc = NULL;
}
+/* free all the dma pools */
+static void free_dma_pools(struct udc *dev)
+{
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td,
+ dev->ep[UDC_EP0OUT_IX].td_phys);
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+ dma_pool_destroy(dev->stp_requests);
+ dma_pool_destroy(dev->data_requests);
+}
+
/* Reset all pci context */
static void udc_pci_remove(struct pci_dev *pdev)
{
@@ -3048,35 +3135,19 @@ static void udc_pci_remove(struct pci_dev *pdev)
usb_del_gadget_udc(&udc->gadget);
/* gadget driver must not be registered */
- BUG_ON(dev->driver != NULL);
+ if (WARN_ON(dev->driver))
+ return;
/* dma pool cleanup */
- if (dev->data_requests)
- pci_pool_destroy(dev->data_requests);
-
- if (dev->stp_requests) {
- /* cleanup DMA desc's for ep0in */
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td_stp,
- dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td,
- dev->ep[UDC_EP0OUT_IX].td_phys);
-
- pci_pool_destroy(dev->stp_requests);
- }
+ free_dma_pools(dev);
/* reset controller */
writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
- if (dev->irq_registered)
- free_irq(pdev->irq, dev);
- if (dev->regs)
- iounmap(dev->regs);
- if (dev->mem_region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (dev->active)
- pci_disable_device(pdev);
+ free_irq(pdev->irq, dev);
+ iounmap(dev->virt_addr);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
udc_remove(dev);
}
@@ -3101,8 +3172,7 @@ static int init_dma_pools(struct udc *dev)
sizeof(struct udc_data_dma), 0, 0);
if (!dev->data_requests) {
DBG(dev, "can't get request data pool\n");
- retval = -ENOMEM;
- goto finished;
+ return -ENOMEM;
}
/* EP0 in dma regs = dev control regs */
@@ -3114,27 +3184,101 @@ static int init_dma_pools(struct udc *dev)
if (!dev->stp_requests) {
DBG(dev, "can't get stp request pool\n");
retval = -ENOMEM;
- goto finished;
+ goto err_create_dma_pool;
}
/* setup */
td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- if (td_stp == NULL) {
+ if (!td_stp) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_dma;
}
dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
/* data: 0 packets !? */
td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_phys);
- if (td_data == NULL) {
+ if (!td_data) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_phys;
}
dev->ep[UDC_EP0OUT_IX].td = td_data;
return 0;
+err_alloc_phys:
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+err_alloc_dma:
+ dma_pool_destroy(dev->stp_requests);
+ dev->stp_requests = NULL;
+err_create_dma_pool:
+ dma_pool_destroy(dev->data_requests);
+ dev->data_requests = NULL;
+ return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+ char tmp[128];
+ u32 reg;
+ int retval;
+
+ /* mark timer as not initialized */
+ udc_timer.data = 0;
+ udc_pollstall_timer.data = 0;
+
+ /* device struct setup */
+ dev->gadget.ops = &udc_ops;
+
+ dev_set_name(&dev->gadget.dev, "gadget");
+ dev->gadget.name = name;
+ dev->gadget.max_speed = USB_SPEED_HIGH;
+
+ /* init registers, interrupts, ... */
+ startup_registers(dev);
+
+ dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+ snprintf(tmp, sizeof(tmp), "%d", dev->irq);
+ dev_info(&dev->pdev->dev,
+ "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+ tmp, dev->phys_addr, dev->chiprev,
+ (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+ if (dev->chiprev == UDC_HSA0_REV) {
+ dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+ retval = -ENODEV;
+ goto finished;
+ }
+ dev_info(&dev->pdev->dev,
+ "driver version: %s(for Geode5536 B1)\n", tmp);
+ udc = dev;
+
+ retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ gadget_release);
+ if (retval)
+ goto finished;
+
+ /* timer init */
+ init_timer(&udc_timer);
+ udc_timer.function = udc_timer_function;
+ udc_timer.data = 1;
+ /* timer pollstall init */
+ init_timer(&udc_pollstall_timer);
+ udc_pollstall_timer.function = udc_pollstall_timer_function;
+ udc_pollstall_timer.data = 1;
+
+ /* set SD */
+ reg = readl(&dev->regs->ctl);
+ reg |= AMD_BIT(UDC_DEVCTL_SD);
+ writel(reg, &dev->regs->ctl);
+
+ /* print dev register info */
+ print_regs(dev);
+
+ return 0;
+
finished:
return retval;
}
@@ -3158,19 +3302,14 @@ static int udc_pci_probe(
/* init */
dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
- if (!dev) {
- retval = -ENOMEM;
- goto finished;
- }
+ if (!dev)
+ return -ENOMEM;
/* pci setup */
if (pci_enable_device(pdev) < 0) {
- kfree(dev);
- dev = NULL;
retval = -ENODEV;
- goto finished;
+ goto err_pcidev;
}
- dev->active = 1;
/* PCI resource allocation */
resource = pci_resource_start(pdev, 0);
@@ -3178,28 +3317,21 @@ static int udc_pci_probe(
if (!request_mem_region(resource, len, name)) {
dev_dbg(&pdev->dev, "pci device used already\n");
- kfree(dev);
- dev = NULL;
retval = -EBUSY;
- goto finished;
+ goto err_memreg;
}
- dev->mem_region = 1;
dev->virt_addr = ioremap_nocache(resource, len);
- if (dev->virt_addr == NULL) {
+ if (!dev->virt_addr) {
dev_dbg(&pdev->dev, "start address cannot be mapped\n");
- kfree(dev);
- dev = NULL;
retval = -EFAULT;
- goto finished;
+ goto err_ioremap;
}
if (!pdev->irq) {
dev_err(&pdev->dev, "irq not set\n");
- kfree(dev);
- dev = NULL;
retval = -ENODEV;
- goto finished;
+ goto err_irq;
}
spin_lock_init(&dev->lock);
@@ -3215,12 +3347,9 @@ static int udc_pci_probe(
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
- kfree(dev);
- dev = NULL;
retval = -EBUSY;
- goto finished;
+ goto err_irq;
}
- dev->irq_registered = 1;
pci_set_drvdata(pdev, dev);
@@ -3234,7 +3363,7 @@ static int udc_pci_probe(
if (use_dma) {
retval = init_dma_pools(dev);
if (retval != 0)
- goto finished;
+ goto err_dma;
}
dev->phys_addr = resource;
@@ -3242,101 +3371,28 @@ static int udc_pci_probe(
dev->pdev = pdev;
/* general probing */
- if (udc_probe(dev) == 0)
- return 0;
-
-finished:
- if (dev)
- udc_pci_remove(pdev);
- return retval;
-}
-
-/* general probe */
-static int udc_probe(struct udc *dev)
-{
- char tmp[128];
- u32 reg;
- int retval;
-
- /* mark timer as not initialized */
- udc_timer.data = 0;
- udc_pollstall_timer.data = 0;
-
- /* device struct setup */
- dev->gadget.ops = &udc_ops;
-
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.name = name;
- dev->gadget.max_speed = USB_SPEED_HIGH;
-
- /* init registers, interrupts, ... */
- startup_registers(dev);
-
- dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
- snprintf(tmp, sizeof tmp, "%d", dev->irq);
- dev_info(&dev->pdev->dev,
- "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
- tmp, dev->phys_addr, dev->chiprev,
- (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
- strcpy(tmp, UDC_DRIVER_VERSION_STRING);
- if (dev->chiprev == UDC_HSA0_REV) {
- dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+ if (udc_probe(dev)) {
retval = -ENODEV;
- goto finished;
+ goto err_probe;
}
- dev_info(&dev->pdev->dev,
- "driver version: %s(for Geode5536 B1)\n", tmp);
- udc = dev;
-
- retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
- gadget_release);
- if (retval)
- goto finished;
-
- /* timer init */
- init_timer(&udc_timer);
- udc_timer.function = udc_timer_function;
- udc_timer.data = 1;
- /* timer pollstall init */
- init_timer(&udc_pollstall_timer);
- udc_pollstall_timer.function = udc_pollstall_timer_function;
- udc_pollstall_timer.data = 1;
-
- /* set SD */
- reg = readl(&dev->regs->ctl);
- reg |= AMD_BIT(UDC_DEVCTL_SD);
- writel(reg, &dev->regs->ctl);
-
- /* print dev register info */
- print_regs(dev);
-
return 0;
-finished:
+err_probe:
+ if (use_dma)
+ free_dma_pools(dev);
+err_dma:
+ free_irq(pdev->irq, dev);
+err_irq:
+ iounmap(dev->virt_addr);
+err_ioremap:
+ release_mem_region(resource, len);
+err_memreg:
+ pci_disable_device(pdev);
+err_pcidev:
+ kfree(dev);
return retval;
}
-/* Initiates a remote wakeup */
-static int udc_remote_wakeup(struct udc *dev)
-{
- unsigned long flags;
- u32 tmp;
-
- DBG(dev, "UDC initiates remote wakeup\n");
-
- spin_lock_irqsave(&dev->lock, flags);
-
- tmp = readl(&dev->regs->ctl);
- tmp |= AMD_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
- tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
-
- spin_unlock_irqrestore(&dev->lock, flags);
- return 0;
-}
-
/* PCI device parameters */
static const struct pci_device_id pci_id[] = {
{
diff --git a/kernel/drivers/usb/gadget/udc/amd5536udc.h b/kernel/drivers/usb/gadget/udc/amd5536udc.h
index 6744d3b83..4638d707f 100644
--- a/kernel/drivers/usb/gadget/udc/amd5536udc.h
+++ b/kernel/drivers/usb/gadget/udc/amd5536udc.h
@@ -526,14 +526,11 @@ struct udc {
struct udc_ep ep[UDC_EP_NUM];
struct usb_gadget_driver *driver;
/* operational flags */
- unsigned active : 1,
- stall_ep0in : 1,
+ unsigned stall_ep0in : 1,
waiting_zlp_ack_ep0in : 1,
set_cfg_not_acked : 1,
- irq_registered : 1,
data_ep_enabled : 1,
data_ep_queued : 1,
- mem_region : 1,
sys_suspended : 1,
connected;
diff --git a/kernel/drivers/usb/gadget/udc/at91_udc.c b/kernel/drivers/usb/gadget/udc/at91_udc.c
index fc4226462..d0d18947f 100644
--- a/kernel/drivers/usb/gadget/udc/at91_udc.c
+++ b/kernel/drivers/usb/gadget/udc/at91_udc.c
@@ -59,15 +59,34 @@
#define DRIVER_VERSION "3 May 2006"
static const char driver_name [] = "at91_udc";
-static const char * const ep_names[] = {
- "ep0",
- "ep1",
- "ep2",
- "ep3-int",
- "ep4",
- "ep5",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO("ep0",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep2",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep3-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep4",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep5",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+
+#undef EP_INFO
};
-#define ep0name ep_names[0]
+
+#define ep0name ep_info[0].name
#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
@@ -825,6 +844,7 @@ static void udc_reinit(struct at91_udc *udc)
INIT_LIST_HEAD(&udc->gadget.ep_list);
INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+ udc->gadget.quirk_stall_not_supp = 1;
for (i = 0; i < NUM_ENDPOINTS; i++) {
struct at91_ep *ep = &udc->ep[i];
@@ -1830,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev)
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
- ep->ep.name = ep_names[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &at91_ep_ops;
ep->udc = udc;
ep->int_mask = BIT(i);
diff --git a/kernel/drivers/usb/gadget/udc/at91_udc.h b/kernel/drivers/usb/gadget/udc/at91_udc.h
index 2679c8b21..0a433e6b3 100644
--- a/kernel/drivers/usb/gadget/udc/at91_udc.h
+++ b/kernel/drivers/usb/gadget/udc/at91_udc.h
@@ -112,6 +112,14 @@ struct at91_udc_caps {
void (*pullup)(struct at91_udc *udc, int is_on);
};
+struct at91_udc_data {
+ int vbus_pin; /* high == host powering us */
+ u8 vbus_active_low; /* vbus polarity */
+ u8 vbus_polled; /* Use polling, not interrupt */
+ int pullup_pin; /* active == D+ pulled up */
+ u8 pullup_active_low; /* true == pullup_pin is active low */
+};
+
/*
* driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state
diff --git a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
index 351d48550..f9bba26e3 100644
--- a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -17,12 +17,13 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/list.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h>
-#include <linux/platform_data/atmel.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -704,8 +705,8 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
unsigned long flags;
int ret;
- DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n",
- ep->ep.name, req->req.length, req->req.dma,
+ DBG(DBG_DMA, "%s: req l/%u d/%pad %c%c%c\n",
+ ep->ep.name, req->req.length, &req->req.dma,
req->req.zero ? 'Z' : 'z',
req->req.short_not_ok ? 'S' : 's',
req->req.no_interrupt ? 'I' : 'i');
@@ -1634,7 +1635,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
spin_lock(&udc->lock);
int_enb = usba_int_enb_get(udc);
- status = usba_readl(udc, INT_STA) & int_enb;
+ status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
DBG(DBG_INT, "irq, status=%#08x\n", status);
if (status & USBA_DET_SUSPEND) {
@@ -1889,20 +1890,15 @@ static int atmel_usba_stop(struct usb_gadget *gadget)
#ifdef CONFIG_OF
static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on)
{
- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
- if (is_on)
- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
- else
- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN,
+ is_on ? AT91_PMC_BIASEN : 0);
}
static void at91sam9g45_pulse_bias(struct usba_udc *udc)
{
- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, 0);
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN,
+ AT91_PMC_BIASEN);
}
static const struct usba_udc_errata at91sam9rl_errata = {
@@ -1939,6 +1935,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
return ERR_PTR(-EINVAL);
udc->errata = match->data;
+ udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc");
+ if (udc->errata && IS_ERR(udc->pmc))
+ return ERR_CAST(udc->pmc);
udc->num_ep = 0;
@@ -1989,6 +1988,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
ret = of_property_read_string(pp, "name", &name);
+ if (ret) {
+ dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
+ goto err;
+ }
ep->ep.name = name;
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
@@ -1999,6 +2002,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
+ if (ep->index == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = ep->can_isoc;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
@@ -2063,6 +2077,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
ep->can_dma = pdata->ep[i].can_dma;
ep->can_isoc = pdata->ep[i].can_isoc;
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = ep->can_isoc;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
@@ -2203,7 +2228,7 @@ static int usba_udc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int usba_udc_suspend(struct device *dev)
{
struct usba_udc *udc = dev_get_drvdata(dev);
diff --git a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
index ea448a344..3e1c9d589 100644
--- a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -354,6 +354,8 @@ struct usba_udc {
struct dentry *debugfs_root;
struct dentry *debugfs_regs;
#endif
+
+ struct regmap *pmc;
};
static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
diff --git a/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c b/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
index 9db968ba3..8cbb00325 100644
--- a/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -44,9 +44,29 @@
#define DRV_MODULE_NAME "bcm63xx_udc"
static const char bcm63xx_ep0name[] = "ep0";
-static const char *const bcm63xx_ep_name[] = {
- bcm63xx_ep0name,
- "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} bcm63xx_ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(bcm63xx_ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
static bool use_fullspeed;
@@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
for (i = 0; i < BCM63XX_NUM_EP; i++) {
struct bcm63xx_ep *bep = &udc->bep[i];
- bep->ep.name = bcm63xx_ep_name[i];
+ bep->ep.name = bcm63xx_ep_info[i].name;
+ bep->ep.caps = bcm63xx_ep_info[i].caps;
bep->ep_num = i;
bep->ep.ops = &bcm63xx_udc_ep_ops;
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc.h b/kernel/drivers/usb/gadget/udc/bdc/bdc.h
index dc18a20bf..916d47135 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc.h
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc.h
@@ -290,7 +290,7 @@ struct bdc_sr {
__le32 offset[4];
};
-/* bd_table: contigous bd's in a table */
+/* bd_table: contiguous bd's in a table */
struct bd_table {
struct bdc_bd *start_bd;
/* dma address of start bd of table*/
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c b/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
index 5c8f4effb..ccb9c213c 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -324,8 +324,7 @@ static void bdc_mem_free(struct bdc *bdc)
bdc->scratchpad.buff, bdc->scratchpad.sp_dma);
/* Destroy the dma pools */
- if (bdc->bd_table_pool)
- dma_pool_destroy(bdc->bd_table_pool);
+ dma_pool_destroy(bdc->bd_table_pool);
/* Free the bdc_ep array */
kfree(bdc->bdc_ep_array);
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c b/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
index b04980cf6..d6199507f 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
@@ -159,8 +159,10 @@ static int ep_bd_list_alloc(struct bdc_ep *ep)
bd_table->start_bd = dma_pool_alloc(bdc->bd_table_pool,
GFP_ATOMIC,
&dma);
- if (!bd_table->start_bd)
+ if (!bd_table->start_bd) {
+ kfree(bd_table);
goto fail;
+ }
bd_table->dma = dma;
@@ -779,7 +781,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req)
/* The current hw dequeue pointer */
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0));
deq_ptr_64 = tmp_32;
- tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1));
+ tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0));
deq_ptr_64 |= ((u64)tmp_32 << 32);
/* we have the dma addr of next bd that will be fetched by hardware */
@@ -1952,12 +1954,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
ep->bdc = bdc;
ep->dir = dir;
+ if (dir)
+ ep->usb_ep.caps.dir_in = true;
+ else
+ ep->usb_ep.caps.dir_out = true;
+
/* ep->ep_num is the index inside bdc_ep */
if (epnum == 1) {
ep->ep_num = 1;
bdc->bdc_ep_array[ep->ep_num] = ep;
snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1);
usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE);
+ ep->usb_ep.caps.type_control = true;
ep->comp_desc = NULL;
bdc->gadget.ep0 = &ep->usb_ep;
} else {
@@ -1971,6 +1979,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
dir & 1 ? "in" : "out");
usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024);
+ ep->usb_ep.caps.type_iso = true;
+ ep->usb_ep.caps.type_bulk = true;
+ ep->usb_ep.caps.type_int = true;
ep->usb_ep.max_streams = 0;
list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list);
}
diff --git a/kernel/drivers/usb/gadget/udc/dummy_hcd.c b/kernel/drivers/usb/gadget/udc/dummy_hcd.c
index 181112c88..dde44450d 100644
--- a/kernel/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/kernel/drivers/usb/gadget/udc/dummy_hcd.c
@@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name, /* everyone has ep0 */
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+ /* everyone has ep0 */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
/* act like a pxa250: fifteen fixed function endpoints */
- "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
- "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
- "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
- "ep15in-int",
-
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
/* or like sa1100: two fixed function endpoints */
- "ep1out-bulk", "ep2in-bulk",
-
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
/* and now some generic EPs so we have enough in multi config */
- "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
- "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
-#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
+
+#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)
/*-------------------------------------------------------------------------*/
@@ -769,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
/* there are both host and device side versions of this call ... */
static int dummy_g_get_frame(struct usb_gadget *_gadget)
{
- struct timeval tv;
+ struct timespec64 ts64;
- do_gettimeofday(&tv);
- return tv.tv_usec / 1000;
+ ktime_get_ts64(&ts64);
+ return ts64.tv_nsec / NSEC_PER_MSEC;
}
static int dummy_wakeup(struct usb_gadget *_gadget)
@@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
struct dummy_ep *ep = &dum->ep[i];
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
- ep->ep.name = ep_name[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &dummy_ep_ops;
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->wedged = ep->already_seen =
@@ -1283,6 +1348,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
{
struct dummy *dum = dum_hcd->dum;
struct dummy_request *req;
+ int sent = 0;
top:
/* if there's no request queued, the device is NAKing; return */
@@ -1320,12 +1386,15 @@ top:
if (len == 0)
break;
- /* use an extra pass for the final short packet */
- if (len > ep->ep.maxpacket) {
- rescan = 1;
- len -= (len % ep->ep.maxpacket);
+ /* send multiple of maxpacket first, then remainder */
+ if (len >= ep->ep.maxpacket) {
+ is_short = 0;
+ if (len % ep->ep.maxpacket)
+ rescan = 1;
+ len -= len % ep->ep.maxpacket;
+ } else {
+ is_short = 1;
}
- is_short = (len % ep->ep.maxpacket) != 0;
len = dummy_perform_transfer(urb, req, len);
@@ -1334,6 +1403,7 @@ top:
req->req.status = len;
} else {
limit -= len;
+ sent += len;
urb->actual_length += len;
req->req.actual += len;
}
@@ -1356,7 +1426,7 @@ top:
*status = -EOVERFLOW;
else
*status = 0;
- } else if (!to_host) {
+ } else {
*status = 0;
if (host_len > dev_len)
req->req.status = -EOVERFLOW;
@@ -1364,15 +1434,24 @@ top:
req->req.status = 0;
}
- /* many requests terminate without a short packet */
+ /*
+ * many requests terminate without a short packet.
+ * send a zlp if demanded by flags.
+ */
} else {
- if (req->req.length == req->req.actual
- && !req->req.zero)
- req->req.status = 0;
- if (urb->transfer_buffer_length == urb->actual_length
- && !(urb->transfer_flags
- & URB_ZERO_PACKET))
- *status = 0;
+ if (req->req.length == req->req.actual) {
+ if (req->req.zero && to_host)
+ rescan = 1;
+ else
+ req->req.status = 0;
+ }
+ if (urb->transfer_buffer_length == urb->actual_length) {
+ if (urb->transfer_flags & URB_ZERO_PACKET &&
+ !to_host)
+ rescan = 1;
+ else
+ *status = 0;
+ }
}
/* device side completion --> continuable */
@@ -1395,7 +1474,7 @@ top:
if (rescan)
goto top;
}
- return limit;
+ return sent;
}
static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
@@ -1684,7 +1763,7 @@ static void dummy_timer(unsigned long _dum_hcd)
}
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
dum->ep[i].already_seen = 0;
}
@@ -1825,7 +1904,7 @@ restart:
default:
treat_control_like_bulk:
ep->last_io = jiffies;
- total = transfer(dum_hcd, urb, ep, limit, &status);
+ total -= transfer(dum_hcd, urb, ep, limit, &status);
break;
}
diff --git a/kernel/drivers/usb/gadget/udc/fotg210-udc.c b/kernel/drivers/usb/gadget/udc/fotg210-udc.c
index e547ea7f5..6ba122cc7 100644
--- a/kernel/drivers/usb/gadget/udc/fotg210-udc.c
+++ b/kernel/drivers/usb/gadget/udc/fotg210-udc.c
@@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep,
return;
}
if (ep->dir_in) { /* if IN */
- if (req->req.length) {
- fotg210_start_dma(ep, req);
- } else {
- pr_err("%s : req->req.length = 0x%x\n",
- __func__, req->req.length);
- }
+ fotg210_start_dma(ep, req);
if ((req->req.length == req->req.actual) ||
(req->req.actual < ep->ep.maxpacket))
fotg210_done(ep, req, 0);
} else { /* OUT */
- if (!req->req.length) {
- fotg210_done(ep, req, 0);
- } else {
- u32 value = ioread32(ep->fotg210->reg +
- FOTG210_DMISGR0);
+ u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0);
- value &= ~DMISGR0_MCX_OUT_INT;
- iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
- }
+ value &= ~DMISGR0_MCX_OUT_INT;
+ iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
}
}
@@ -1153,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev)
ep->ep.name = fotg210_ep_name[i];
ep->ep.ops = &fotg210_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
@@ -1171,7 +1172,7 @@ static int fotg210_udc_probe(struct platform_device *pdev)
udc_name, fotg210);
if (ret < 0) {
pr_err("request_irq error (%d)\n", ret);
- goto err_irq;
+ goto err_req;
}
ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
@@ -1183,7 +1184,6 @@ static int fotg210_udc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
-err_irq:
free_irq(ires->start, fotg210);
err_req:
diff --git a/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c b/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
index e0822f1b6..5fb6f8b4f 100644
--- a/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
strcpy(ep->name, ep_name[pipe_num]);
ep->ep.name = ep_name[pipe_num];
+ if (pipe_num == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
diff --git a/kernel/drivers/usb/gadget/udc/fsl_udc_core.c b/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
index c60022b46..aab5221d6 100644
--- a/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
ep->ep.ops = &fsl_ep_ops;
ep->stopped = 0;
+ if (index == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ if (index & 1)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
/* for ep0: maxP defined in desc
* for other eps, maxP is set by epautoconfig() called by gadget layer
*/
diff --git a/kernel/drivers/usb/gadget/udc/fusb300_udc.c b/kernel/drivers/usb/gadget/udc/fusb300_udc.c
index 3970f453d..948845c90 100644
--- a/kernel/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/kernel/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev)
ep->ep.name = fusb300_ep_name[i];
ep->ep.ops = &fusb300_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
fusb300->ep[0]->epnum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/gadget_chips.h b/kernel/drivers/usb/gadget/udc/gadget_chips.h
deleted file mode 100644
index bcd04bc66..000000000
--- a/kernel/drivers/usb/gadget/udc/gadget_chips.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * USB device controllers have lots of quirks. Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE: some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-#include <linux/usb/gadget.h>
-
-/*
- * NOTICE: the entries below are alphabetical and should be kept
- * that way.
- *
- * Always be sure to add new entries to the correct position or
- * accept the bashing later.
- *
- * If you have forgotten the alphabetical order let VIM/EMACS
- * do that for you.
- */
-#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
-#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
-#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
-#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
-#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
-#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
- /* PXA 21x/25x/26x has no altsettings at all */
- if (gadget_is_pxa(gadget))
- return false;
-
- /* PXA 27x and 3xx have *broken* altsetting support */
- if (gadget_is_pxa27x(gadget))
- return false;
-
- /* Everything else is *presumably* fine ... */
- return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
diff --git a/kernel/drivers/usb/gadget/udc/goku_udc.c b/kernel/drivers/usb/gadget/udc/goku_udc.c
index 9e8d842e8..1fdfec14a 100644
--- a/kernel/drivers/usb/gadget/udc/goku_udc.c
+++ b/kernel/drivers/usb/gadget/udc/goku_udc.c
@@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget)
return -EOPNOTSUPP;
}
+static struct usb_ep *goku_match_ep(struct usb_gadget *g,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ struct goku_udc *dev = to_goku_udc(g);
+ struct usb_ep *ep;
+
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_INT:
+ /* single buffering is enough */
+ ep = &dev->ep[3].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (usb_endpoint_dir_in(desc)) {
+ /* DMA may be available */
+ ep = &dev->ep[2].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ }
+ break;
+ default:
+ /* nothing */ ;
+ }
+
+ return NULL;
+}
+
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int goku_udc_stop(struct usb_gadget *g);
@@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
.udc_start = goku_udc_start,
.udc_stop = goku_udc_stop,
+ .match_ep = goku_match_ep,
// no remote wakeup
// not selfpowered
};
@@ -1257,6 +1287,14 @@ static void udc_reinit (struct goku_udc *dev)
INIT_LIST_HEAD (&ep->queue);
ep_reset(NULL, ep);
+
+ if (i == 0)
+ ep->ep.caps.type_control = true;
+ else
+ ep->ep.caps.type_bulk = true;
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
dev->ep[0].reg_mode = NULL;
diff --git a/kernel/drivers/usb/gadget/udc/gr_udc.c b/kernel/drivers/usb/gadget/udc/gr_udc.c
index c8868870e..b9429bc42 100644
--- a/kernel/drivers/usb/gadget/udc/gr_udc.c
+++ b/kernel/drivers/usb/gadget/udc/gr_udc.c
@@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+
+ ep->ep.caps.type_control = true;
} else {
usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
}
list_add_tail(&ep->ep_list, &dev->ep_list);
+ if (is_in)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
&ep->tailbuf_paddr, GFP_ATOMIC);
if (!ep->tailbuf)
@@ -2106,8 +2117,7 @@ static int gr_remove(struct platform_device *pdev)
return -EBUSY;
gr_dfs_delete(dev);
- if (dev->desc_pool)
- dma_pool_destroy(dev->desc_pool);
+ dma_pool_destroy(dev->desc_pool);
platform_set_drvdata(pdev, NULL);
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
diff --git a/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c b/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
index 3b6a78528..00b5006ba 100644
--- a/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep0",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 0,
@@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep1-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 2,
@@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep2-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 4,
@@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep3-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 6,
@@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep4-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 8,
@@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep5-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 10,
@@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep6-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 12,
@@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep7-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 14,
@@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep8-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 16,
@@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep9-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 18,
@@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep10-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 20,
@@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep11-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 22,
@@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep12-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 24,
@@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep13-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 26,
@@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep14-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 28,
@@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep15-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 30,
diff --git a/kernel/drivers/usb/gadget/udc/m66592-udc.c b/kernel/drivers/usb/gadget/udc/m66592-udc.c
index 9704053df..b1cfa96cc 100644
--- a/kernel/drivers/usb/gadget/udc/m66592-udc.c
+++ b/kernel/drivers/usb/gadget/udc/m66592-udc.c
@@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev)
ep->ep.name = m66592_ep_name[i];
ep->ep.ops = &m66592_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
m66592->ep[0].pipenum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/mv_u3d_core.c b/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
index ea35a248c..dafe74eb9 100644
--- a/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
ep->ep.ops = &mv_u3d_ep_ops;
ep->wedge = 0;
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_u3d_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
if (i & 1) {
snprintf(name, sizeof(name), "ep%din", i >> 1);
ep->direction = MV_U3D_EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i >> 1);
ep->direction = MV_U3D_EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->u3d = u3d;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_u3d_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;
@@ -1758,8 +1767,7 @@ static int mv_u3d_remove(struct platform_device *dev)
usb_del_gadget_udc(&u3d->gadget);
/* free memory allocated in probe */
- if (u3d->trb_pool)
- dma_pool_destroy(u3d->trb_pool);
+ dma_pool_destroy(u3d->trb_pool);
if (u3d->ep_context)
dma_free_coherent(&dev->dev, u3d->ep_context_size,
diff --git a/kernel/drivers/usb/gadget/udc/mv_udc_core.c b/kernel/drivers/usb/gadget/udc/mv_udc_core.c
index 5da37c957..81b6229c7 100644
--- a/kernel/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/kernel/drivers/usb/gadget/udc/mv_udc_core.c
@@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc)
ep->wedge = 0;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc)
if (i % 2) {
snprintf(name, sizeof(name), "ep%din", i / 2);
ep->direction = EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i / 2);
ep->direction = EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->udc = udc;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_ep_ops;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
@@ -2091,8 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
}
/* free memory allocated in probe */
- if (udc->dtd_pool)
- dma_pool_destroy(udc->dtd_pool);
+ dma_pool_destroy(udc->dtd_pool);
if (udc->ep_dqh)
dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
diff --git a/kernel/drivers/usb/gadget/udc/net2272.c b/kernel/drivers/usb/gadget/udc/net2272.c
index 195baf3e1..18f5ebd44 100644
--- a/kernel/drivers/usb/gadget/udc/net2272.c
+++ b/kernel/drivers/usb/gadget/udc/net2272.c
@@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev)
else
ep->fifo_size = 64;
net2272_ep_reset(ep);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
@@ -1826,9 +1837,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
if (!e || u.r.wLength > 2)
goto do_stall;
if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
- status = __constant_cpu_to_le16(1);
+ status = cpu_to_le16(1);
else
- status = __constant_cpu_to_le16(0);
+ status = cpu_to_le16(0);
/* don't bother with a request object! */
net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
diff --git a/kernel/drivers/usb/gadget/udc/net2280.c b/kernel/drivers/usb/gadget/udc/net2280.c
index 9871b9019..6706aef90 100644
--- a/kernel/drivers/usb/gadget/udc/net2280.c
+++ b/kernel/drivers/usb/gadget/udc/net2280.c
@@ -74,19 +74,58 @@ static const char driver_desc[] = DRIVER_DESC;
static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name,
- "ep-a", "ep-b", "ep-c", "ep-d",
- "ep-e", "ep-f", "ep-g", "ep-h",
-};
-/* Endpoint names for usb3380 advance mode */
-static const char *const ep_name_adv[] = {
- ep0name,
- "ep1in", "ep2out", "ep3in", "ep4out",
- "ep1out", "ep2in", "ep3out", "ep4in",
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info_dft[] = { /* Default endpoint configuration */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-a",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-b",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-c",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-d",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-e",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-f",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-g",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-h",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
};
+#undef EP_INFO
+
/* mode 0 == ep-{a,b,c,d} 1K fifo each
* mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
* mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
@@ -123,6 +162,11 @@ static char *type_string(u8 bmAttributes)
#define valid_bit cpu_to_le32(BIT(VALID_BIT))
#define dma_done_ie cpu_to_le32(BIT(DMA_DONE_INTERRUPT_ENABLE))
+static void ep_clear_seqnum(struct net2280_ep *ep);
+static void stop_activity(struct net2280 *dev,
+ struct usb_gadget_driver *driver);
+static void ep0_start(struct net2280 *dev);
+
/*-------------------------------------------------------------------------*/
static inline void enable_pciirqenb(struct net2280_ep *ep)
{
@@ -142,7 +186,9 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
{
struct net2280 *dev;
struct net2280_ep *ep;
- u32 max, tmp;
+ u32 max;
+ u32 tmp = 0;
+ u32 type;
unsigned long flags;
static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
int ret = 0;
@@ -198,15 +244,29 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* set type, direction, address; reset fifo counters */
writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
- tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
- if (tmp == USB_ENDPOINT_XFER_INT) {
+
+ if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
+ tmp = readl(&ep->cfg->ep_cfg);
+ /* If USB ep number doesn't match hardware ep number */
+ if ((tmp & 0xf) != usb_endpoint_num(desc)) {
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ goto print_err;
+ }
+ if (ep->is_in)
+ tmp &= ~USB3380_EP_CFG_MASK_IN;
+ else
+ tmp &= ~USB3380_EP_CFG_MASK_OUT;
+ }
+ type = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+ if (type == USB_ENDPOINT_XFER_INT) {
/* erratum 0105 workaround prevents hs NYET */
if (dev->chiprev == 0100 &&
dev->gadget.speed == USB_SPEED_HIGH &&
!(desc->bEndpointAddress & USB_DIR_IN))
writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
&ep->regs->ep_rsp);
- } else if (tmp == USB_ENDPOINT_XFER_BULK) {
+ } else if (type == USB_ENDPOINT_XFER_BULK) {
/* catch some particularly blatant driver bugs */
if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
(dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
@@ -216,10 +276,10 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto print_err;
}
}
- ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+ ep->is_iso = (type == USB_ENDPOINT_XFER_ISOC);
/* Enable this endpoint */
if (dev->quirks & PLX_LEGACY) {
- tmp <<= ENDPOINT_TYPE;
+ tmp |= type << ENDPOINT_TYPE;
tmp |= desc->bEndpointAddress;
/* default full fifo lines */
tmp |= (4 << ENDPOINT_BYTE_COUNT);
@@ -228,17 +288,17 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
} else {
/* In Legacy mode, only OUT endpoints are used */
if (dev->enhanced_mode && ep->is_in) {
- tmp <<= IN_ENDPOINT_TYPE;
+ tmp |= type << IN_ENDPOINT_TYPE;
tmp |= BIT(IN_ENDPOINT_ENABLE);
- /* Not applicable to Legacy */
- tmp |= BIT(ENDPOINT_DIRECTION);
} else {
- tmp <<= OUT_ENDPOINT_TYPE;
+ tmp |= type << OUT_ENDPOINT_TYPE;
tmp |= BIT(OUT_ENDPOINT_ENABLE);
tmp |= (ep->is_in << ENDPOINT_DIRECTION);
}
- tmp |= usb_endpoint_num(desc);
+ tmp |= (4 << ENDPOINT_BYTE_COUNT);
+ if (!dev->enhanced_mode)
+ tmp |= usb_endpoint_num(desc);
tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
}
@@ -256,6 +316,8 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
}
+ if (dev->quirks & PLX_SUPERSPEED)
+ ep_clear_seqnum(ep);
writel(tmp, &ep->cfg->ep_cfg);
/* enable irqs */
@@ -441,6 +503,13 @@ static void ep_reset_338x(struct net2280_regs __iomem *regs,
BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
BIT(DATA_IN_TOKEN_INTERRUPT), &ep->regs->ep_stat);
+
+ tmp = readl(&ep->cfg->ep_cfg);
+ if (ep->is_in)
+ tmp &= ~USB3380_EP_CFG_MASK_IN;
+ else
+ tmp &= ~USB3380_EP_CFG_MASK_OUT;
+ writel(tmp, &ep->cfg->ep_cfg);
}
static void nuke(struct net2280_ep *);
@@ -1468,16 +1537,46 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
spin_lock_irqsave(&dev->lock, flags);
tmp = readl(&dev->usb->usbctl);
dev->softconnect = (is_on != 0);
- if (is_on)
- tmp |= BIT(USB_DETECT_ENABLE);
- else
- tmp &= ~BIT(USB_DETECT_ENABLE);
- writel(tmp, &dev->usb->usbctl);
+ if (is_on) {
+ ep0_start(dev);
+ writel(tmp | BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+ } else {
+ writel(tmp & ~BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+ stop_activity(dev, dev->driver);
+ }
+
spin_unlock_irqrestore(&dev->lock, flags);
return 0;
}
+static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ char name[8];
+ struct usb_ep *ep;
+
+ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) {
+ /* ep-e, ep-f are PIO with only 64 byte fifos */
+ ep = gadget_find_ep_by_name(_gadget, "ep-e");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ ep = gadget_find_ep_by_name(_gadget, "ep-f");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ }
+
+ /* USB3380: use same address for usb and hardware endpoints */
+ snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
+ usb_endpoint_dir_in(desc) ? "in" : "out");
+ ep = gadget_find_ep_by_name(_gadget, name);
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+
+ return NULL;
+}
+
static int net2280_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
static int net2280_stop(struct usb_gadget *_gadget);
@@ -1489,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = {
.pullup = net2280_pullup,
.udc_start = net2280_start,
.udc_stop = net2280_stop,
+ .match_ep = net2280_match_ep,
};
/*-------------------------------------------------------------------------*/
@@ -1813,7 +1913,7 @@ static void defect7374_disable_data_eps(struct net2280 *dev)
for (i = 1; i < 5; i++) {
ep = &dev->ep[i];
- writel(0, &ep->cfg->ep_cfg);
+ writel(i, &ep->cfg->ep_cfg);
}
/* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
@@ -1860,8 +1960,8 @@ static void defect7374_enable_data_eps_zero(struct net2280 *dev)
tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) |
(2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) |
((dev->enhanced_mode) ?
- BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) |
- BIT(IN_ENDPOINT_ENABLE));
+ BIT(OUT_ENDPOINT_ENABLE) | BIT(IN_ENDPOINT_ENABLE) :
+ BIT(ENDPOINT_ENABLE)));
for (i = 1; i < 5; i++)
writel(tmp, &dev->ep[i].cfg->ep_cfg);
@@ -1975,9 +2075,15 @@ static void usb_reset_338x(struct net2280 *dev)
/* clear old dma and irq state */
for (tmp = 0; tmp < 4; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp + 1];
+ struct net2280_dma_regs __iomem *dma;
- if (ep->dma)
+ if (ep->dma) {
abort_dma(ep);
+ } else {
+ dma = &dev->dma[tmp];
+ writel(BIT(DMA_ABORT), &dma->dmastat);
+ writel(0, &dma->dmactl);
+ }
}
writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1);
@@ -2016,7 +2122,8 @@ static void usb_reinit_228x(struct net2280 *dev)
for (tmp = 0; tmp < 7; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp];
- ep->ep.name = ep_name[tmp];
+ ep->ep.name = ep_info_dft[tmp].name;
+ ep->ep.caps = ep_info_dft[tmp].caps;
ep->dev = dev;
ep->num = tmp;
@@ -2056,7 +2163,10 @@ static void usb_reinit_338x(struct net2280 *dev)
for (i = 0; i < dev->n_ep; i++) {
struct net2280_ep *ep = &dev->ep[i];
- ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
+ ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name :
+ ep_info_dft[i].name;
+ ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps :
+ ep_info_dft[i].caps;
ep->dev = dev;
ep->num = i;
@@ -2065,6 +2175,12 @@ static void usb_reinit_338x(struct net2280 *dev)
if (dev->enhanced_mode) {
ep->cfg = &dev->epregs[ne[i]];
+ /*
+ * Set USB endpoint number, hardware allows same number
+ * in both directions.
+ */
+ if (i > 0 && i < 5)
+ writel(ne[i], &ep->cfg->ep_cfg);
ep->regs = (struct net2280_ep_regs __iomem *)
(((void __iomem *)&dev->epregs[ne[i]]) +
ep_reg_addr[i]);
@@ -2874,6 +2990,26 @@ next_endpoints3:
return;
}
+static void usb338x_handle_ep_intr(struct net2280 *dev, u32 stat0)
+{
+ u32 index;
+ u32 bit;
+
+ for (index = 0; index < ARRAY_SIZE(ep_bit); index++) {
+ bit = BIT(ep_bit[index]);
+
+ if (!stat0)
+ break;
+
+ if (!(stat0 & bit))
+ continue;
+
+ stat0 &= ~bit;
+
+ handle_ep_small(&dev->ep[index]);
+ }
+}
+
static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
{
struct net2280_ep *ep;
@@ -3098,20 +3234,31 @@ do_stall:
#undef w_length
next_endpoints:
- /* endpoint data irq ? */
- scratch = stat & 0x7f;
- stat &= ~0x7f;
- for (num = 0; scratch; num++) {
- u32 t;
-
- /* do this endpoint's FIFO and queue need tending? */
- t = BIT(num);
- if ((scratch & t) == 0)
- continue;
- scratch ^= t;
+ if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
+ u32 mask = (BIT(ENDPOINT_0_INTERRUPT) |
+ USB3380_IRQSTAT0_EP_INTR_MASK_IN |
+ USB3380_IRQSTAT0_EP_INTR_MASK_OUT);
+
+ if (stat & mask) {
+ usb338x_handle_ep_intr(dev, stat & mask);
+ stat &= ~mask;
+ }
+ } else {
+ /* endpoint data irq ? */
+ scratch = stat & 0x7f;
+ stat &= ~0x7f;
+ for (num = 0; scratch; num++) {
+ u32 t;
+
+ /* do this endpoint's FIFO and queue need tending? */
+ t = BIT(num);
+ if ((scratch & t) == 0)
+ continue;
+ scratch ^= t;
- ep = &dev->ep[num];
- handle_ep_small(ep);
+ ep = &dev->ep[num];
+ handle_ep_small(ep);
+ }
}
if (stat)
diff --git a/kernel/drivers/usb/gadget/udc/omap_udc.c b/kernel/drivers/usb/gadget/udc/omap_udc.c
index e2fcdb8e5..9b7d39484 100644
--- a/kernel/drivers/usb/gadget/udc/omap_udc.c
+++ b/kernel/drivers/usb/gadget/udc/omap_udc.c
@@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->double_buf = dbuf;
ep->udc = udc;
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ ep->ep.caps.type_iso = true;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ ep->ep.caps.type_bulk = true;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ ep->ep.caps.type_int = true;
+ break;
+ };
+
+ if (addr & USB_DIR_IN)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
ep->maxpacket = maxp;
diff --git a/kernel/drivers/usb/gadget/udc/pch_udc.c b/kernel/drivers/usb/gadget/udc/pch_udc.c
index 613547f07..7a04157ff 100644
--- a/kernel/drivers/usb/gadget/udc/pch_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pch_udc.c
@@ -330,7 +330,7 @@ struct pch_vbus_gpio_data {
* @prot_stall: protcol stall requested
* @irq_registered: irq registered with system
* @mem_region: device memory mapped
- * @registered: driver regsitered with system
+ * @registered: driver registered with system
* @suspended: driver in suspended state
* @connected: gadget driver associated
* @vbus_session: required vbus_session state
@@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
dev->vbus_session = 1;
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
dev->vbus_session = 0;
@@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
pch_udc_reconnect(dev);
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
}
@@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
req->dma_mapped = 0;
}
ep->halted = 1;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
if (!ep->in)
pch_udc_ep_clear_rrdy(ep);
usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
ep->halted = halted;
}
@@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
}
/* prevent from using desc. - set HOST BUSY */
dma_desc->status |= PCH_UDC_BS_HST_BSY;
- dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+ dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID);
req->td_data = dma_desc;
req->td_data_last = dma_desc;
req->chain_len = 1;
@@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
else /* OUT */
dev->gadget.ep0 = &ep->ep;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
/* If Mass storage Reset */
if ((dev->setup_data.bRequestType == 0x21) &&
(dev->setup_data.bRequest == 0xFF))
@@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
/* call gadget with setup data received */
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
if (dev->setup_data.bRequestType & USB_DIR_IN) {
ep->td_data->status = (ep->td_data->status &
@@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
empty_req_queue(ep);
}
if (dev->driver) {
- spin_unlock(&dev->lock);
- usb_gadget_udc_reset(&dev->gadget, dev->driver);
spin_lock(&dev->lock);
+ usb_gadget_udc_reset(&dev->gadget, dev->driver);
+ spin_unlock(&dev->lock);
}
}
@@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
dev->ep[i].halted = 0;
}
dev->stall = 0;
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
dev->stall = 0;
/* call gadget zero with setup data received */
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
ep->in = ~i & 1;
ep->ep.name = ep_string[i];
ep->ep.ops = &pch_udc_ep_ops;
- if (ep->in)
+ if (ep->in) {
ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
- else
+ ep->ep.caps.dir_in = true;
+ } else {
ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
UDC_EP_REG_SHIFT;
+ ep->ep.caps.dir_out = true;
+ }
+ if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
/* need to set ep->ep.maxpacket and set Default Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
diff --git a/kernel/drivers/usb/gadget/udc/pxa25x_udc.c b/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
index f6cbe667c..b82cb1485 100644
--- a/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
INIT_LIST_HEAD (&dev->gadget.ep_list);
INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
dev->ep0state = EP0_IDLE;
+ dev->gadget.quirk_altset_not_supp = 1;
/* basic endpoint records init */
for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1821,6 +1822,8 @@ static struct pxa25x_udc memory = {
.name = ep0name,
.ops = &pxa25x_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.reg_udccs = &UDCCS0,
@@ -1833,6 +1836,8 @@ static struct pxa25x_udc memory = {
.name = "ep1in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1846,6 +1851,8 @@ static struct pxa25x_udc memory = {
.name = "ep2out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1861,6 +1868,8 @@ static struct pxa25x_udc memory = {
.name = "ep3in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1874,6 +1883,8 @@ static struct pxa25x_udc memory = {
.name = "ep4out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1888,6 +1899,7 @@ static struct pxa25x_udc memory = {
.name = "ep5in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1903,6 +1915,8 @@ static struct pxa25x_udc memory = {
.name = "ep6in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1916,6 +1930,8 @@ static struct pxa25x_udc memory = {
.name = "ep7out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1930,6 +1946,8 @@ static struct pxa25x_udc memory = {
.name = "ep8in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1943,6 +1961,8 @@ static struct pxa25x_udc memory = {
.name = "ep9out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1957,6 +1977,7 @@ static struct pxa25x_udc memory = {
.name = "ep10in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1972,6 +1993,8 @@ static struct pxa25x_udc memory = {
.name = "ep11in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1985,6 +2008,8 @@ static struct pxa25x_udc memory = {
.name = "ep12out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1999,6 +2024,8 @@ static struct pxa25x_udc memory = {
.name = "ep13in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2012,6 +2039,8 @@ static struct pxa25x_udc memory = {
.name = "ep14out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2026,6 +2055,7 @@ static struct pxa25x_udc memory = {
.name = "ep15in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
diff --git a/kernel/drivers/usb/gadget/udc/pxa27x_udc.c b/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
index b51226aba..001a3b74a 100644
--- a/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev)
INIT_LIST_HEAD(&dev->gadget.ep_list);
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+ dev->gadget.quirk_altset_not_supp = 1;
ep0_idle(dev);
/* PXA endpoints init */
@@ -2422,7 +2423,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
}
udc->udc_command = mach->udc_command;
} else {
- udc->gpiod = devm_gpiod_get(&pdev->dev, NULL);
+ udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2535,6 +2536,9 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
udc->pullup_resume = udc->pullup_on;
dplus_pullup(udc, 0);
+ if (udc->driver)
+ udc->driver->disconnect(&udc->gadget);
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/udc/pxa27x_udc.h b/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
index 11e142327..cea2cb79b 100644
--- a/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
+++ b/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
@@ -234,25 +234,35 @@
/*
* Endpoint definition helpers
*/
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \
+ .caps = USB_EP_CAPS(ctype, cdir), }, \
.desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
- .bmAttributes = type, \
+ .bmAttributes = USB_ENDPOINT_XFER_ ## type, \
.wMaxPacketSize = maxpkt, }, \
.dev = &memory \
}
-#define USB_EP_BULK(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
-#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
+#define USB_EP_BULK(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_BULK, cdir)
+#define USB_EP_ISO(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_ISO, cdir)
+#define USB_EP_INT(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_INT, cdir)
+#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)
#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
{ \
diff --git a/kernel/drivers/usb/gadget/udc/r8a66597-udc.c b/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
index 0293f7169..baa0609a4 100644
--- a/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev)
ep->ep.name = r8a66597_ep_name[i];
ep->ep.ops = &r8a66597_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
r8a66597->ep[0].pipenum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/s3c-hsudc.c b/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
index 85a712a03..e9def42ce 100644
--- a/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
+++ b/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
@@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->stopped = 0;
hsep->wedge = 0;
+ if (epnum == 0) {
+ hsep->ep.caps.type_control = true;
+ hsep->ep.caps.dir_in = true;
+ hsep->ep.caps.dir_out = true;
+ } else {
+ hsep->ep.caps.type_iso = true;
+ hsep->ep.caps.type_bulk = true;
+ hsep->ep.caps.type_int = true;
+ }
+
+ if (epnum & 1)
+ hsep->ep.caps.dir_in = true;
+ else
+ hsep->ep.caps.dir_out = true;
+
set_index(hsudc, epnum);
writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
}
diff --git a/kernel/drivers/usb/gadget/udc/s3c2410_udc.c b/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
index 99fd9a566..eb3571ee5 100644
--- a/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -92,40 +92,38 @@ static struct s3c2410_udc_mach_info *udc_info;
static uint32_t s3c2410_ticks = 0;
-static int dprintk(int level, const char *fmt, ...)
+__printf(2, 3)
+static void dprintk(int level, const char *fmt, ...)
{
- static char printk_buf[1024];
static long prevticks;
static int invocation;
+ struct va_format vaf;
va_list args;
- int len;
if (level > USB_S3C2410_DEBUG_LEVEL)
- return 0;
+ return;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
if (s3c2410_ticks != prevticks) {
prevticks = s3c2410_ticks;
invocation = 0;
}
- len = scnprintf(printk_buf,
- sizeof(printk_buf), "%1lu.%02d USB: ",
- prevticks, invocation++);
+ pr_debug("%1lu.%02d USB: %pV", prevticks, invocation++, &vaf);
- va_start(args, fmt);
- len = vscnprintf(printk_buf+len,
- sizeof(printk_buf)-len, fmt, args);
va_end(args);
-
- pr_debug("%s", printk_buf);
- return len;
}
#else
-static int dprintk(int level, const char *fmt, ...)
+__printf(2, 3)
+static void dprintk(int level, const char *fmt, ...)
{
- return 0;
}
#endif
+
static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
{
u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg;
@@ -1693,6 +1691,8 @@ static struct s3c2410_udc memory = {
.name = ep0name,
.ops = &s3c2410_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
},
@@ -1704,6 +1704,8 @@ static struct s3c2410_udc memory = {
.name = "ep1-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1716,6 +1718,8 @@ static struct s3c2410_udc memory = {
.name = "ep2-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1728,6 +1732,8 @@ static struct s3c2410_udc memory = {
.name = "ep3-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1740,6 +1746,8 @@ static struct s3c2410_udc memory = {
.name = "ep4-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
diff --git a/kernel/drivers/usb/gadget/udc/udc-core.c b/kernel/drivers/usb/gadget/udc/udc-core.c
index 7d69931cf..f660afba7 100644
--- a/kernel/drivers/usb/gadget/udc/udc-core.c
+++ b/kernel/drivers/usb/gadget/udc/udc-core.c
@@ -60,13 +60,15 @@ static DEFINE_MUTEX(udc_lock);
int usb_gadget_map_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in)
{
+ struct device *dev = gadget->dev.parent;
+
if (req->length == 0)
return 0;
if (req->num_sgs) {
int mapped;
- mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+ mapped = dma_map_sg(dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
dev_err(&gadget->dev, "failed to map SGs\n");
@@ -75,11 +77,11 @@ int usb_gadget_map_request(struct usb_gadget *gadget,
req->num_mapped_sgs = mapped;
} else {
- req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+ req->dma = dma_map_single(dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (dma_mapping_error(&gadget->dev, req->dma)) {
- dev_err(&gadget->dev, "failed to map buffer\n");
+ if (dma_mapping_error(dev, req->dma)) {
+ dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
}
@@ -95,12 +97,12 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
return;
if (req->num_mapped_sgs) {
- dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+ dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
} else {
- dma_unmap_single(&gadget->dev, req->dma, req->length,
+ dma_unmap_single(gadget->dev.parent, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
}
}
@@ -129,6 +131,96 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
/* ------------------------------------------------------------------------- */
+/**
+ * gadget_find_ep_by_name - returns ep whose name is the same as sting passed
+ * in second parameter or NULL if searched endpoint not found
+ * @g: controller to check for quirk
+ * @name: name of searched endpoint
+ */
+struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
+{
+ struct usb_ep *ep;
+
+ gadget_for_each_ep(ep, g) {
+ if (!strcmp(ep->name, name))
+ return ep;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
+
+/* ------------------------------------------------------------------------- */
+
+int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+ struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ u8 type;
+ u16 max;
+ int num_req_streams = 0;
+
+ /* endpoint already claimed? */
+ if (ep->claimed)
+ return 0;
+
+ type = usb_endpoint_type(desc);
+ max = 0x7ff & usb_endpoint_maxp(desc);
+
+ if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
+ return 0;
+ if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
+ return 0;
+
+ if (max > ep->maxpacket_limit)
+ return 0;
+
+ /* "high bandwidth" works only at high speed */
+ if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
+ return 0;
+
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* only support ep0 for portable CONTROL traffic */
+ return 0;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (!ep->caps.type_iso)
+ return 0;
+ /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 1023)
+ return 0;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (!ep->caps.type_bulk)
+ return 0;
+ if (ep_comp && gadget_is_superspeed(gadget)) {
+ /* Get the number of required streams from the
+ * EP companion descriptor and see if the EP
+ * matches it
+ */
+ num_req_streams = ep_comp->bmAttributes & 0x1f;
+ if (num_req_streams > ep->max_streams)
+ return 0;
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ /* Bulk endpoints handle interrupt transfers,
+ * except the toggle-quirky iso-synch kind
+ */
+ if (!ep->caps.type_int && !ep->caps.type_bulk)
+ return 0;
+ /* INT: limit 64 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 64)
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+
+/* ------------------------------------------------------------------------- */
+
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);
diff --git a/kernel/drivers/usb/gadget/udc/udc-xilinx.c b/kernel/drivers/usb/gadget/udc/udc-xilinx.c
index 1f2427447..1cbb0ac6b 100644
--- a/kernel/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/kernel/drivers/usb/gadget/udc/udc-xilinx.c
@@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc)
snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number);
ep->ep_usb.name = ep->name;
ep->ep_usb.ops = &xusb_ep_ops;
+
+ ep->ep_usb.caps.type_iso = true;
+ ep->ep_usb.caps.type_bulk = true;
+ ep->ep_usb.caps.type_int = true;
} else {
ep->ep_usb.name = ep0name;
usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET);
ep->ep_usb.ops = &xusb_ep0_ops;
+
+ ep->ep_usb.caps.type_control = true;
}
+ ep->ep_usb.caps.dir_in = true;
+ ep->ep_usb.caps.dir_out = true;
+
ep->udc = udc;
ep->epnumber = ep_number;
ep->desc = NULL;