diff options
Diffstat (limited to 'drivers/usb/gadget/udc')
-rw-r--r-- | drivers/usb/gadget/udc/aspeed-vhub/core.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/aspeed-vhub/epn.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/dummy_hcd.c | 25 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/fotg210-udc.c | 28 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/net2272.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/pch_udc.c | 241 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/r8a66597-udc.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/s3c2410_udc.c | 24 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/snps_udc_plat.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/tegra-xudc.c | 2 |
10 files changed, 175 insertions, 159 deletions
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c index be7bb64e3594..d11d3d14313f 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/core.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c @@ -36,6 +36,7 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, int status) { bool internal = req->internal; + struct ast_vhub *vhub = ep->vhub; EPVDBG(ep, "completing request @%p, status %d\n", req, status); @@ -46,7 +47,7 @@ void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, if (req->req.dma) { if (!WARN_ON(!ep->dev)) - usb_gadget_unmap_request(&ep->dev->gadget, + usb_gadget_unmap_request_by_dev(&vhub->pdev->dev, &req->req, ep->epn.is_in); req->req.dma = 0; } diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 02d8bfae58fb..cb164c615e6f 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -376,7 +376,7 @@ static int ast_vhub_epn_queue(struct usb_ep* u_ep, struct usb_request *u_req, if (ep->epn.desc_mode || ((((unsigned long)u_req->buf & 7) == 0) && (ep->epn.is_in || !(u_req->length & (u_ep->maxpacket - 1))))) { - rc = usb_gadget_map_request(&ep->dev->gadget, u_req, + rc = usb_gadget_map_request_by_dev(&vhub->pdev->dev, u_req, ep->epn.is_in); if (rc) { dev_warn(&vhub->pdev->dev, diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 57067763b100..7db773c87379 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -903,6 +903,21 @@ static int dummy_pullup(struct usb_gadget *_gadget, int value) spin_lock_irqsave(&dum->lock, flags); dum->pullup = (value != 0); set_link_state(dum_hcd); + if (value == 0) { + /* + * Emulate synchronize_irq(): wait for callbacks to finish. + * This seems to be the best place to emulate the call to + * synchronize_irq() that's in usb_gadget_remove_driver(). + * Doing it in dummy_udc_stop() would be too late since it + * is called after the unbind callback and unbind shouldn't + * be invoked until all the other callbacks are finished. + */ + while (dum->callback_usage > 0) { + spin_unlock_irqrestore(&dum->lock, flags); + usleep_range(1000, 2000); + spin_lock_irqsave(&dum->lock, flags); + } + } spin_unlock_irqrestore(&dum->lock, flags); usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd)); @@ -1004,14 +1019,6 @@ static int dummy_udc_stop(struct usb_gadget *g) spin_lock_irq(&dum->lock); dum->ints_enabled = 0; stop_activity(dum); - - /* emulate synchronize_irq(): wait for callbacks to finish */ - while (dum->callback_usage > 0) { - spin_unlock_irq(&dum->lock); - usleep_range(1000, 2000); - spin_lock_irq(&dum->lock); - } - dum->driver = NULL; spin_unlock_irq(&dum->lock); @@ -1866,7 +1873,7 @@ restart: /* handle control requests */ if (ep == &dum->ep[0] && ep->setup_stage) { struct usb_ctrlrequest setup; - int value = 1; + int value; setup = *(struct usb_ctrlrequest *) urb->setup_packet; /* paranoia, in case of stale queued data */ diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index d6ca50f01985..fdca28e72a3b 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -338,15 +338,16 @@ static void fotg210_start_dma(struct fotg210_ep *ep, } else { buffer = req->req.buf + req->req.actual; length = ioread32(ep->fotg210->reg + - FOTG210_FIBCR(ep->epnum - 1)); - length &= FIBCR_BCFX; + FOTG210_FIBCR(ep->epnum - 1)) & FIBCR_BCFX; + if (length > req->req.length - req->req.actual) + length = req->req.length - req->req.actual; } } else { buffer = req->req.buf + req->req.actual; if (req->req.length - req->req.actual > ep->ep.maxpacket) length = ep->ep.maxpacket; else - length = req->req.length; + length = req->req.length - req->req.actual; } d = dma_map_single(dev, buffer, length, @@ -379,8 +380,7 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep, } if (ep->dir_in) { /* if IN */ fotg210_start_dma(ep, req); - if ((req->req.length == req->req.actual) || - (req->req.actual < ep->ep.maxpacket)) + if (req->req.length == req->req.actual) fotg210_done(ep, req, 0); } else { /* OUT */ u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0); @@ -820,7 +820,7 @@ static void fotg210_ep0in(struct fotg210_udc *fotg210) if (req->req.length) fotg210_start_dma(ep, req); - if ((req->req.length - req->req.actual) < ep->ep.maxpacket) + if (req->req.actual == req->req.length) fotg210_done(ep, req, 0); } else { fotg210_set_cxdone(fotg210); @@ -849,12 +849,16 @@ static void fotg210_out_fifo_handler(struct fotg210_ep *ep) { struct fotg210_request *req = list_entry(ep->queue.next, struct fotg210_request, queue); + int disgr1 = ioread32(ep->fotg210->reg + FOTG210_DISGR1); fotg210_start_dma(ep, req); - /* finish out transfer */ + /* Complete the request when it's full or a short packet arrived. + * Like other drivers, short_not_ok isn't handled. + */ + if (req->req.length == req->req.actual || - req->req.actual < ep->ep.maxpacket) + (disgr1 & DISGR1_SPK_INT(ep->epnum - 1))) fotg210_done(ep, req, 0); } @@ -877,6 +881,8 @@ static irqreturn_t fotg210_irq(int irq, void *_fotg210) int_grp2 &= ~int_msk2; if (int_grp2 & DISGR2_USBRST_INT) { + usb_gadget_udc_reset(&fotg210->gadget, + fotg210->driver); value = ioread32(reg); value &= ~DISGR2_USBRST_INT; iowrite32(value, reg); @@ -1027,6 +1033,12 @@ static void fotg210_init(struct fotg210_udc *fotg210) value &= ~DMCR_GLINT_EN; iowrite32(value, fotg210->reg + FOTG210_DMCR); + /* enable only grp2 irqs we handle */ + iowrite32(~(DISGR2_DMA_ERROR | DISGR2_RX0BYTE_INT | DISGR2_TX0BYTE_INT + | DISGR2_ISO_SEQ_ABORT_INT | DISGR2_ISO_SEQ_ERR_INT + | DISGR2_RESM_INT | DISGR2_SUSP_INT | DISGR2_USBRST_INT), + fotg210->reg + FOTG210_DMISGR2); + /* disable all fifo interrupt */ iowrite32(~(u32)0, fotg210->reg + FOTG210_DMISGR1); diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 23a735641c3d..89f479b78d80 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -539,7 +539,6 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req) int count; int tmp; int cleanup = 0; - int status = -1; dev_vdbg(ep->dev->dev, "read_fifo %s actual %d len %d\n", ep->ep.name, req->req.actual, req->req.length); @@ -591,6 +590,8 @@ net2272_read_fifo(struct net2272_ep *ep, struct net2272_request *req) } if (!list_empty(&ep->queue)) { + int status; + req = list_entry(ep->queue.next, struct net2272_request, queue); status = net2272_kick_dma(ep, req); diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index a3c1fc924268..9bb7a9d7a2fb 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -8,11 +8,12 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> #include <linux/list.h> #include <linux/interrupt.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> -#include <linux/gpio/consumer.h> #include <linux/irq.h> #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ @@ -331,6 +332,7 @@ struct pch_vbus_gpio_data { * @dma_addr: DMA pool for received * @setup_data: Received setup data * @base_addr: for mapped device memory + * @bar: PCI BAR used for mapped device memory * @cfg_data: current cfg, intf, and alt in use * @vbus_gpio: GPIO informaton for detecting VBUS */ @@ -353,6 +355,7 @@ struct pch_udc_dev { dma_addr_t dma_addr; struct usb_ctrlrequest setup_data; void __iomem *base_addr; + unsigned short bar; struct pch_udc_cfg_data cfg_data; struct pch_vbus_gpio_data vbus_gpio; }; @@ -381,11 +384,8 @@ MODULE_PARM_DESC(speed_fs, "true for Full speed operation"); * @td_data_last: last dma desc. of chain * @queue: associated queue * @dma_going: DMA in progress for request - * @dma_mapped: DMA memory mapped for request * @dma_done: DMA completed for request * @chain_len: chain length - * @buf: Buffer memory for align adjustment - * @dma: DMA memory for align adjustment */ struct pch_udc_request { struct usb_request req; @@ -394,11 +394,8 @@ struct pch_udc_request { struct pch_udc_data_dma_desc *td_data_last; struct list_head queue; unsigned dma_going:1, - dma_mapped:1, dma_done:1; unsigned chain_len; - void *buf; - dma_addr_t dma; }; static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg) @@ -563,12 +560,13 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev) pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES); } +static void pch_udc_init(struct pch_udc_dev *dev); + /** * pch_udc_reconnect() - This API initializes usb device controller, * and clear the disconnect status. * @dev: Reference to pch_udc_regs structure */ -static void pch_udc_init(struct pch_udc_dev *dev); static void pch_udc_reconnect(struct pch_udc_dev *dev) { pch_udc_init(dev); @@ -596,18 +594,22 @@ static void pch_udc_reconnect(struct pch_udc_dev *dev) static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, int is_active) { + unsigned long iflags; + + spin_lock_irqsave(&dev->lock, iflags); if (is_active) { pch_udc_reconnect(dev); dev->vbus_session = 1; } else { if (dev->driver && dev->driver->disconnect) { - spin_lock(&dev->lock); + spin_unlock_irqrestore(&dev->lock, iflags); dev->driver->disconnect(&dev->gadget); - spin_unlock(&dev->lock); + spin_lock_irqsave(&dev->lock, iflags); } pch_udc_set_disconnect(dev); dev->vbus_session = 0; } + spin_unlock_irqrestore(&dev->lock, iflags); } /** @@ -1166,20 +1168,25 @@ static int pch_udc_pcd_selfpowered(struct usb_gadget *gadget, int value) static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) { struct pch_udc_dev *dev; + unsigned long iflags; if (!gadget) return -EINVAL; + dev = container_of(gadget, struct pch_udc_dev, gadget); + + spin_lock_irqsave(&dev->lock, iflags); if (is_on) { pch_udc_reconnect(dev); } else { if (dev->driver && dev->driver->disconnect) { - spin_lock(&dev->lock); + spin_unlock_irqrestore(&dev->lock, iflags); dev->driver->disconnect(&dev->gadget); - spin_unlock(&dev->lock); + spin_lock_irqsave(&dev->lock, iflags); } pch_udc_set_disconnect(dev); } + spin_unlock_irqrestore(&dev->lock, iflags); return 0; } @@ -1360,6 +1367,7 @@ static irqreturn_t pch_vbus_gpio_irq(int irq, void *data) */ static int pch_vbus_gpio_init(struct pch_udc_dev *dev) { + struct device *d = &dev->pdev->dev; int err; int irq_num = 0; struct gpio_desc *gpiod; @@ -1368,7 +1376,7 @@ static int pch_vbus_gpio_init(struct pch_udc_dev *dev) dev->vbus_gpio.intr = 0; /* Retrieve the GPIO line from the USB gadget device */ - gpiod = devm_gpiod_get(dev->gadget.dev.parent, NULL, GPIOD_IN); + gpiod = devm_gpiod_get_optional(d, NULL, GPIOD_IN); if (IS_ERR(gpiod)) return PTR_ERR(gpiod); gpiod_set_consumer_name(gpiod, "pch_vbus"); @@ -1428,33 +1436,7 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, status = req->req.status; dev = ep->dev; - if (req->dma_mapped) { - if (req->dma == DMA_ADDR_INVALID) { - if (ep->in) - dma_unmap_single(&dev->pdev->dev, req->req.dma, - req->req.length, - DMA_TO_DEVICE); - else - dma_unmap_single(&dev->pdev->dev, req->req.dma, - req->req.length, - DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - } else { - if (ep->in) - dma_unmap_single(&dev->pdev->dev, req->dma, - req->req.length, - DMA_TO_DEVICE); - else { - dma_unmap_single(&dev->pdev->dev, req->dma, - req->req.length, - DMA_FROM_DEVICE); - memcpy(req->req.buf, req->buf, req->req.length); - } - kfree(req->buf); - req->dma = DMA_ADDR_INVALID; - } - req->dma_mapped = 0; - } + usb_gadget_unmap_request(&dev->gadget, &req->req, ep->in); ep->halted = 1; spin_unlock(&dev->lock); if (!ep->in) @@ -1532,12 +1514,9 @@ static int pch_udc_create_dma_chain(struct pch_udc_ep *ep, if (req->chain_len > 1) pch_udc_free_dma_chain(ep->dev, req); - if (req->dma == DMA_ADDR_INVALID) - td->dataptr = req->req.dma; - else - td->dataptr = req->dma; - + td->dataptr = req->req.dma; td->status = PCH_UDC_BS_HST_BSY; + for (; ; bytes -= buf_len, ++len) { td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes); if (bytes <= buf_len) @@ -1743,7 +1722,6 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, if (!req) return NULL; req->req.dma = DMA_ADDR_INVALID; - req->dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); if (!ep->dev->dma_addr) return &req->req; @@ -1756,7 +1734,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 = cpu_to_le32(DMA_ADDR_INVALID); + dma_desc->dataptr = lower_32_bits(DMA_ADDR_INVALID); req->td_data = dma_desc; req->td_data_last = dma_desc; req->chain_len = 1; @@ -1826,39 +1804,9 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, return -ESHUTDOWN; spin_lock_irqsave(&dev->lock, iflags); /* map the buffer for dma */ - if (usbreq->length && - ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) { - if (!((unsigned long)(usbreq->buf) & 0x03)) { - if (ep->in) - usbreq->dma = dma_map_single(&dev->pdev->dev, - usbreq->buf, - usbreq->length, - DMA_TO_DEVICE); - else - usbreq->dma = dma_map_single(&dev->pdev->dev, - usbreq->buf, - usbreq->length, - DMA_FROM_DEVICE); - } else { - req->buf = kzalloc(usbreq->length, GFP_ATOMIC); - if (!req->buf) { - retval = -ENOMEM; - goto probe_end; - } - if (ep->in) { - memcpy(req->buf, usbreq->buf, usbreq->length); - req->dma = dma_map_single(&dev->pdev->dev, - req->buf, - usbreq->length, - DMA_TO_DEVICE); - } else - req->dma = dma_map_single(&dev->pdev->dev, - req->buf, - usbreq->length, - DMA_FROM_DEVICE); - } - req->dma_mapped = 1; - } + retval = usb_gadget_map_request(&dev->gadget, usbreq, ep->in); + if (retval) + goto probe_end; if (usbreq->length > 0) { retval = prepare_dma(ep, req, GFP_ATOMIC); if (retval) @@ -2298,6 +2246,21 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) pch_udc_set_dma(dev, DMA_DIR_RX); } +static int pch_udc_gadget_setup(struct pch_udc_dev *dev) + __must_hold(&dev->lock) +{ + int rc; + + /* In some cases we can get an interrupt before driver gets setup */ + if (!dev->driver) + return -ESHUTDOWN; + + spin_unlock(&dev->lock); + rc = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_lock(&dev->lock); + return rc; +} + /** * pch_udc_svc_control_in() - Handle Control IN endpoint interrupts * @dev: Reference to the device structure @@ -2369,15 +2332,12 @@ 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_lock(&dev->lock); /* If Mass storage Reset */ if ((dev->setup_data.bRequestType == 0x21) && (dev->setup_data.bRequest == 0xFF)) dev->prot_stall = 0; /* call gadget with setup data received */ - setup_supported = dev->driver->setup(&dev->gadget, - &dev->setup_data); - spin_unlock(&dev->lock); + setup_supported = pch_udc_gadget_setup(dev); if (dev->setup_data.bRequestType & USB_DIR_IN) { ep->td_data->status = (ep->td_data->status & @@ -2625,9 +2585,7 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) dev->ep[i].halted = 0; } dev->stall = 0; - spin_unlock(&dev->lock); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /** @@ -2662,9 +2620,7 @@ 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); - dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + pch_udc_gadget_setup(dev); } /** @@ -2870,14 +2826,20 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) * @dev: Reference to the driver structure * * Return codes: - * 0: Success + * 0: Success + * -ERRNO: All kind of errors when retrieving VBUS GPIO */ static int pch_udc_pcd_init(struct pch_udc_dev *dev) { + int ret; + pch_udc_init(dev); pch_udc_pcd_reinit(dev); - pch_vbus_gpio_init(dev); - return 0; + + ret = pch_vbus_gpio_init(dev); + if (ret) + pch_udc_exit(dev); + return ret; } /** @@ -2938,7 +2900,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) dev->dma_addr = dma_map_single(&dev->pdev->dev, ep0out_buf, UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); - return 0; + return dma_mapping_error(&dev->pdev->dev, dev->dma_addr); } static int pch_udc_start(struct usb_gadget *g, @@ -2976,6 +2938,38 @@ static int pch_udc_stop(struct usb_gadget *g) return 0; } +static void pch_vbus_gpio_remove_table(void *table) +{ + gpiod_remove_lookup_table(table); +} + +static int pch_vbus_gpio_add_table(struct device *d, void *table) +{ + gpiod_add_lookup_table(table); + return devm_add_action_or_reset(d, pch_vbus_gpio_remove_table, table); +} + +static struct gpiod_lookup_table pch_udc_minnow_vbus_gpio_table = { + .dev_id = "0000:02:02.4", + .table = { + GPIO_LOOKUP("sch_gpio.33158", 12, NULL, GPIO_ACTIVE_HIGH), + {} + }, +}; + +static int pch_udc_minnow_platform_init(struct device *d) +{ + return pch_vbus_gpio_add_table(d, &pch_udc_minnow_vbus_gpio_table); +} + +static int pch_udc_quark_platform_init(struct device *d) +{ + struct pch_udc_dev *dev = dev_get_drvdata(d); + + dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000; + return 0; +} + static void pch_udc_shutdown(struct pci_dev *pdev) { struct pch_udc_dev *dev = pci_get_drvdata(pdev); @@ -3024,8 +3018,7 @@ static void pch_udc_remove(struct pci_dev *pdev) pch_udc_exit(dev); } -#ifdef CONFIG_PM_SLEEP -static int pch_udc_suspend(struct device *d) +static int __maybe_unused pch_udc_suspend(struct device *d) { struct pch_udc_dev *dev = dev_get_drvdata(d); @@ -3035,21 +3028,18 @@ static int pch_udc_suspend(struct device *d) return 0; } -static int pch_udc_resume(struct device *d) +static int __maybe_unused pch_udc_resume(struct device *d) { return 0; } static SIMPLE_DEV_PM_OPS(pch_udc_pm, pch_udc_suspend, pch_udc_resume); -#define PCH_UDC_PM_OPS (&pch_udc_pm) -#else -#define PCH_UDC_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ -static int pch_udc_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +typedef int (*platform_init_fn)(struct device *); + +static int pch_udc_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int bar; + platform_init_fn platform_init = (platform_init_fn)id->driver_data; int retval; struct pch_udc_dev *dev; @@ -3063,31 +3053,28 @@ static int pch_udc_probe(struct pci_dev *pdev, if (retval) return retval; + dev->bar = PCH_UDC_PCI_BAR; + dev->pdev = pdev; pci_set_drvdata(pdev, dev); - /* Determine BAR based on PCI ID */ - if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC) - bar = PCH_UDC_PCI_BAR_QUARK_X1000; - else - bar = PCH_UDC_PCI_BAR; + /* Platform specific hook */ + if (platform_init) { + retval = platform_init(&pdev->dev); + if (retval) + return retval; + } /* PCI resource allocation */ - retval = pcim_iomap_regions(pdev, 1 << bar, pci_name(pdev)); + retval = pcim_iomap_regions(pdev, BIT(dev->bar), pci_name(pdev)); if (retval) return retval; - dev->base_addr = pcim_iomap_table(pdev)[bar]; - - /* - * FIXME: add a GPIO descriptor table to pdev.dev using - * gpiod_add_descriptor_table() from <linux/gpio/machine.h> based on - * the PCI subsystem ID. The system-dependent GPIO is necessary for - * VBUS operation. - */ + dev->base_addr = pcim_iomap_table(pdev)[dev->bar]; /* initialize the hardware */ - if (pch_udc_pcd_init(dev)) - return -ENODEV; + retval = pch_udc_pcd_init(dev); + if (retval) + return retval; pci_enable_msi(pdev); @@ -3104,7 +3091,6 @@ static int pch_udc_probe(struct pci_dev *pdev, /* device struct setup */ spin_lock_init(&dev->lock); - dev->pdev = pdev; dev->gadget.ops = &pch_udc_ops; retval = init_dma_pools(dev); @@ -3128,10 +3114,17 @@ finished: static const struct pci_device_id pch_udc_pcidev_id[] = { { - PCI_DEVICE(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), + .class = PCI_CLASS_SERIAL_USB_DEVICE, + .class_mask = 0xffffffff, + .driver_data = (kernel_ulong_t)&pch_udc_quark_platform_init, + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC, + PCI_VENDOR_ID_CIRCUITCO, PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD), .class = PCI_CLASS_SERIAL_USB_DEVICE, .class_mask = 0xffffffff, + .driver_data = (kernel_ulong_t)&pch_udc_minnow_platform_init, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), @@ -3160,7 +3153,7 @@ static struct pci_driver pch_udc_driver = { .remove = pch_udc_remove, .shutdown = pch_udc_shutdown, .driver = { - .pm = PCH_UDC_PM_OPS, + .pm = &pch_udc_pm, }, }; diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 896c1a016d55..65cae4883454 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1849,6 +1849,8 @@ static int r8a66597_probe(struct platform_device *pdev) return PTR_ERR(reg); ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!ires) + return -EINVAL; irq = ires->start; irq_trigger = ires->flags & IRQF_TRIGGER_MASK; diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 1d3ebb07ccd4..b154b62abefa 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -54,8 +54,6 @@ static struct clk *udc_clock; static struct clk *usb_bus_clock; static void __iomem *base_addr; static int irq_usbd; -static u64 rsrc_start; -static u64 rsrc_len; static struct dentry *s3c2410_udc_debugfs_root; static inline u32 udc_read(u32 reg) @@ -1752,7 +1750,8 @@ static int s3c2410_udc_probe(struct platform_device *pdev) udc_clock = clk_get(NULL, "usb-device"); if (IS_ERR(udc_clock)) { dev_err(dev, "failed to get udc clock source\n"); - return PTR_ERR(udc_clock); + retval = PTR_ERR(udc_clock); + goto err_usb_bus_clk; } clk_prepare_enable(udc_clock); @@ -1775,7 +1774,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base_addr)) { retval = PTR_ERR(base_addr); - goto err_mem; + goto err_udc_clk; } the_controller = udc; @@ -1793,7 +1792,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (retval != 0) { dev_err(dev, "cannot get irq %i, err %d\n", irq_usbd, retval); retval = -EBUSY; - goto err_map; + goto err_udc_clk; } dev_dbg(dev, "got irq %i\n", irq_usbd); @@ -1864,10 +1863,14 @@ err_gpio_claim: gpio_free(udc_info->vbus_pin); err_int: free_irq(irq_usbd, udc); -err_map: - iounmap(base_addr); -err_mem: - release_mem_region(rsrc_start, rsrc_len); +err_udc_clk: + clk_disable_unprepare(udc_clock); + clk_put(udc_clock); + udc_clock = NULL; +err_usb_bus_clk: + clk_disable_unprepare(usb_bus_clock); + clk_put(usb_bus_clock); + usb_bus_clock = NULL; return retval; } @@ -1899,9 +1902,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev) free_irq(irq_usbd, udc); - iounmap(base_addr); - release_mem_region(rsrc_start, rsrc_len); - if (!IS_ERR(udc_clock) && udc_clock != NULL) { clk_disable_unprepare(udc_clock); clk_put(udc_clock); diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c index 32f1d3e90c26..99805d60a7ab 100644 --- a/drivers/usb/gadget/udc/snps_udc_plat.c +++ b/drivers/usb/gadget/udc/snps_udc_plat.c @@ -114,8 +114,8 @@ static int udc_plat_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); udc->virt_addr = devm_ioremap_resource(dev, res); - if (IS_ERR(udc->regs)) - return PTR_ERR(udc->regs); + if (IS_ERR(udc->virt_addr)) + return PTR_ERR(udc->virt_addr); /* udc csr registers base */ udc->csr = udc->virt_addr + UDC_CSR_ADDR; diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 580bef8eb4cb..2319c9737c2b 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -3883,7 +3883,7 @@ static int tegra_xudc_remove(struct platform_device *pdev) pm_runtime_get_sync(xudc->dev); - cancel_delayed_work(&xudc->plc_reset_work); + cancel_delayed_work_sync(&xudc->plc_reset_work); cancel_work_sync(&xudc->usb_role_sw_work); usb_del_gadget_udc(&xudc->gadget); |