summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/usb/gadget/udc/amd5536udc.c
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/amd5536udc.c
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/amd5536udc.c')
-rw-r--r--kernel/drivers/usb/gadget/udc/amd5536udc.c724
1 files changed, 390 insertions, 334 deletions
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[] = {
{