diff options
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/at91_udc.c | 236 | ||||
-rw-r--r-- | drivers/usb/gadget/at91_udc.h | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/gmidi.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/goku_udc.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/net2280.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/omap_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/serial.c | 2 |
11 files changed, 180 insertions, 142 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 3e0abbb49fe..812c733ba8c 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -43,14 +43,16 @@ #include <linux/usb_gadget.h> #include <asm/byteorder.h> +#include <asm/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/system.h> #include <asm/mach-types.h> -#include <asm/arch/hardware.h> #include <asm/arch/gpio.h> #include <asm/arch/board.h> +#include <asm/arch/cpu.h> +#include <asm/arch/at91sam9261_matrix.h> #include "at91_udc.h" @@ -78,27 +80,11 @@ static const char driver_name [] = "at91_udc"; static const char ep0name[] = "ep0"; -/*-------------------------------------------------------------------------*/ -/* - * Read from a UDP register. - */ -static inline unsigned long at91_udp_read(unsigned int reg) -{ - void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; - - return __raw_readl(udp_base + reg); -} - -/* - * Write to a UDP register. - */ -static inline void at91_udp_write(unsigned int reg, unsigned long value) -{ - void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; - - __raw_writel(value, udp_base + reg); -} +#define at91_udp_read(dev, reg) \ + __raw_readl((dev)->udp_baseaddr + (reg)) +#define at91_udp_write(dev, reg, val) \ + __raw_writel((val), (dev)->udp_baseaddr + (reg)) /*-------------------------------------------------------------------------*/ @@ -210,13 +196,13 @@ static int proc_udc_show(struct seq_file *s, void *unused) return 0; } - tmp = at91_udp_read(AT91_UDP_FRM_NUM); + tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM); seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp, (tmp & AT91_UDP_FRM_OK) ? " ok" : "", (tmp & AT91_UDP_FRM_ERR) ? " err" : "", (tmp & AT91_UDP_NUM)); - tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp, (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "", (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "", @@ -224,13 +210,13 @@ static int proc_udc_show(struct seq_file *s, void *unused) (tmp & AT91_UDP_CONFG) ? " confg" : "", (tmp & AT91_UDP_FADDEN) ? " fadden" : ""); - tmp = at91_udp_read(AT91_UDP_FADDR); + tmp = at91_udp_read(udc, AT91_UDP_FADDR); seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp, (tmp & AT91_UDP_FEN) ? " fen" : "", (tmp & AT91_UDP_FADD)); - proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR)); - proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR)); + proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR)); + proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR)); if (udc->enabled && udc->vbus) { proc_ep_show(s, &udc->ep[0]); @@ -286,6 +272,7 @@ static inline void remove_debug_file(struct at91_udc *udc) {} static void done(struct at91_ep *ep, struct at91_request *req, int status) { unsigned stopped = ep->stopped; + struct at91_udc *udc = ep->udc; list_del_init(&req->queue); if (req->req.status == -EINPROGRESS) @@ -301,7 +288,7 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status) /* ep0 is always ready; other endpoints need a non-empty queue */ if (list_empty(&ep->queue) && ep->int_mask != (1 << 0)) - at91_udp_write(AT91_UDP_IDR, ep->int_mask); + at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask); } /*-------------------------------------------------------------------------*/ @@ -554,8 +541,8 @@ ok: * reset/init endpoint fifo. NOTE: leaves fifo_bank alone, * since endpoint resets don't reset hw pingpong state. */ - at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); - at91_udp_write(AT91_UDP_RST_EP, 0); + at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(dev, AT91_UDP_RST_EP, 0); local_irq_restore(flags); return 0; @@ -564,6 +551,7 @@ ok: static int at91_ep_disable (struct usb_ep * _ep) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + struct at91_udc *udc = ep->udc; unsigned long flags; if (ep == &ep->udc->ep[0]) @@ -579,8 +567,8 @@ static int at91_ep_disable (struct usb_ep * _ep) /* reset fifos and endpoint */ if (ep->udc->clocked) { - at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); - at91_udp_write(AT91_UDP_RST_EP, 0); + at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(udc, AT91_UDP_RST_EP, 0); __raw_writel(0, ep->creg); } @@ -695,10 +683,10 @@ static int at91_ep_queue(struct usb_ep *_ep, * reconfigures the endpoints. */ if (dev->wait_for_config_ack) { - tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT); tmp ^= AT91_UDP_CONFG; VDBG("toggle config\n"); - at91_udp_write(AT91_UDP_GLB_STAT, tmp); + at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp); } if (req->req.length == 0) { ep0_in_status: @@ -727,7 +715,7 @@ ep0_in_status: if (req && !status) { list_add_tail (&req->queue, &ep->queue); - at91_udp_write(AT91_UDP_IER, ep->int_mask); + at91_udp_write(dev, AT91_UDP_IER, ep->int_mask); } done: local_irq_restore(flags); @@ -758,6 +746,7 @@ static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) static int at91_ep_set_halt(struct usb_ep *_ep, int value) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); + struct at91_udc *udc = ep->udc; u32 __iomem *creg; u32 csr; unsigned long flags; @@ -785,8 +774,8 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value) csr |= AT91_UDP_FORCESTALL; VDBG("halt %s\n", ep->ep.name); } else { - at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); - at91_udp_write(AT91_UDP_RST_EP, 0); + at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(udc, AT91_UDP_RST_EP, 0); csr &= ~AT91_UDP_FORCESTALL; } __raw_writel(csr, creg); @@ -813,9 +802,11 @@ static struct usb_ep_ops at91_ep_ops = { static int at91_get_frame(struct usb_gadget *gadget) { + struct at91_udc *udc = to_udc(gadget); + if (!to_udc(gadget)->clocked) return -EINVAL; - return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM; + return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM; } static int at91_wakeup(struct usb_gadget *gadget) @@ -833,11 +824,11 @@ static int at91_wakeup(struct usb_gadget *gadget) /* NOTE: some "early versions" handle ESR differently ... */ - glbstate = at91_udp_read(AT91_UDP_GLB_STAT); + glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT); if (!(glbstate & AT91_UDP_ESR)) goto done; glbstate |= AT91_UDP_ESR; - at91_udp_write(AT91_UDP_GLB_STAT, glbstate); + at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate); done: local_irq_restore(flags); @@ -861,6 +852,7 @@ static void udc_reinit(struct at91_udc *udc) ep->stopped = 0; ep->fifo_bank = 0; ep->ep.maxpacket = ep->maxpacket; + ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i); // initialiser une queue par endpoint INIT_LIST_HEAD(&ep->queue); } @@ -915,14 +907,41 @@ static void pullup(struct at91_udc *udc, int is_on) if (!udc->enabled || !udc->vbus) is_on = 0; DBG("%sactive\n", is_on ? "" : "in"); + if (is_on) { clk_on(udc); - at91_udp_write(AT91_UDP_TXVC, 0); - at91_set_gpio_value(udc->board.pullup_pin, 1); - } else { + at91_udp_write(udc, AT91_UDP_TXVC, 0); + if (cpu_is_at91rm9200()) + at91_set_gpio_value(udc->board.pullup_pin, 1); + else if (cpu_is_at91sam9260()) { + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); + + txvc |= AT91_UDP_TXVC_PUON; + at91_udp_write(udc, AT91_UDP_TXVC, txvc); + } else if (cpu_is_at91sam9261()) { + u32 usbpucr; + + usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); + usbpucr |= AT91_MATRIX_USBPUCR_PUON; + at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); + } + } else { stop_activity(udc); - at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); - at91_set_gpio_value(udc->board.pullup_pin, 0); + at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + if (cpu_is_at91rm9200()) + at91_set_gpio_value(udc->board.pullup_pin, 0); + else if (cpu_is_at91sam9260()) { + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); + + txvc &= ~AT91_UDP_TXVC_PUON; + at91_udp_write(udc, AT91_UDP_TXVC, txvc); + } else if (cpu_is_at91sam9261()) { + u32 usbpucr; + + usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR); + usbpucr &= ~AT91_MATRIX_USBPUCR_PUON; + at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr); + } clk_off(udc); } } @@ -936,7 +955,10 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active) // VDBG("vbus %s\n", is_active ? "on" : "off"); local_irq_save(flags); udc->vbus = (is_active != 0); - pullup(udc, is_active); + if (udc->driver) + pullup(udc, is_active); + else + pullup(udc, 0); local_irq_restore(flags); return 0; } @@ -1086,7 +1108,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) | USB_REQ_SET_CONFIGURATION: - tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG; + tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG; if (pkt.r.wValue) udc->wait_for_config_ack = (tmp == 0); else @@ -1103,7 +1125,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) | USB_REQ_GET_STATUS: tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED); - if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR) + if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR) tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP); PACKET("get device status\n"); __raw_writeb(tmp, dreg); @@ -1114,17 +1136,17 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) | USB_REQ_SET_FEATURE: if (w_value != USB_DEVICE_REMOTE_WAKEUP) goto stall; - tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); tmp |= AT91_UDP_ESR; - at91_udp_write(AT91_UDP_GLB_STAT, tmp); + at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); goto succeed; case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) | USB_REQ_CLEAR_FEATURE: if (w_value != USB_DEVICE_REMOTE_WAKEUP) goto stall; - tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); tmp &= ~AT91_UDP_ESR; - at91_udp_write(AT91_UDP_GLB_STAT, tmp); + at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); goto succeed; /* @@ -1206,8 +1228,8 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) } else if (ep->is_in) goto stall; - at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); - at91_udp_write(AT91_UDP_RST_EP, 0); + at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask); + at91_udp_write(udc, AT91_UDP_RST_EP, 0); tmp = __raw_readl(ep->creg); tmp |= CLR_FX; tmp &= ~(SET_FX | AT91_UDP_FORCESTALL); @@ -1222,7 +1244,10 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) #undef w_length /* pass request up to the gadget driver */ - status = udc->driver->setup(&udc->gadget, &pkt.r); + if (udc->driver) + status = udc->driver->setup(&udc->gadget, &pkt.r); + else + status = -ENODEV; if (status < 0) { stall: VDBG("req %02x.%02x protocol STALL; stat %d\n", @@ -1300,13 +1325,13 @@ static void handle_ep0(struct at91_udc *udc) if (udc->wait_for_addr_ack) { u32 tmp; - at91_udp_write(AT91_UDP_FADDR, + at91_udp_write(udc, AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); - tmp = at91_udp_read(AT91_UDP_GLB_STAT); + tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT); tmp &= ~AT91_UDP_FADDEN; if (udc->addr) tmp |= AT91_UDP_FADDEN; - at91_udp_write(AT91_UDP_GLB_STAT, tmp); + at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp); udc->wait_for_addr_ack = 0; VDBG("address %d\n", udc->addr); @@ -1374,28 +1399,28 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc) while (rescans--) { u32 status; - status = at91_udp_read(AT91_UDP_ISR) - & at91_udp_read(AT91_UDP_IMR); + status = at91_udp_read(udc, AT91_UDP_ISR) + & at91_udp_read(udc, AT91_UDP_IMR); if (!status) break; /* USB reset irq: not maskable */ if (status & AT91_UDP_ENDBUSRES) { - at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS); - at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS); + at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS); + at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS); /* Atmel code clears this irq twice */ - at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); - at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES); VDBG("end bus reset\n"); udc->addr = 0; stop_activity(udc); /* enable ep0 */ - at91_udp_write(AT91_UDP_CSR(0), + at91_udp_write(udc, AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); udc->gadget.speed = USB_SPEED_FULL; udc->suspended = 0; - at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); + at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0)); /* * NOTE: this driver keeps clocks off unless the @@ -1406,9 +1431,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc) /* host initiated suspend (3+ms bus idle) */ } else if (status & AT91_UDP_RXSUSP) { - at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP); - at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM); - at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP); + at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP); + at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP); // VDBG("bus suspend\n"); if (udc->suspended) continue; @@ -1425,9 +1450,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc) /* host initiated resume */ } else if (status & AT91_UDP_RXRSM) { - at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM); - at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP); - at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM); + at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); + at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); // VDBG("bus resume\n"); if (!udc->suspended) continue; @@ -1485,8 +1510,6 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(0)), .int_mask = 1 << 0, }, .ep[1] = { @@ -1497,8 +1520,6 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(1)), .int_mask = 1 << 1, }, .ep[2] = { @@ -1509,8 +1530,6 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(2)), .int_mask = 1 << 2, }, .ep[3] = { @@ -1521,8 +1540,6 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(3)), .int_mask = 1 << 3, }, .ep[4] = { @@ -1533,8 +1550,6 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(4)), .int_mask = 1 << 4, }, .ep[5] = { @@ -1545,8 +1560,6 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(5)), .int_mask = 1 << 5, }, /* ep6 and ep7 are also reserved (custom silicon might use them) */ @@ -1572,9 +1585,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) int retval; if (!driver - || driver->speed != USB_SPEED_FULL + || driver->speed < USB_SPEED_FULL || !driver->bind - || !driver->unbind || !driver->setup) { DBG("bad parameter.\n"); return -EINVAL; @@ -1595,6 +1607,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (retval) { DBG("driver->bind() returned %d\n", retval); udc->driver = NULL; + udc->gadget.dev.driver = NULL; + udc->gadget.dev.driver_data = NULL; + udc->enabled = 0; + udc->selfpowered = 0; return retval; } @@ -1611,12 +1627,12 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) { struct at91_udc *udc = &controller; - if (!driver || driver != udc->driver) + if (!driver || driver != udc->driver || !driver->unbind) return -EINVAL; local_irq_disable(); udc->enabled = 0; - at91_udp_write(AT91_UDP_IDR, ~0); + at91_udp_write(udc, AT91_UDP_IDR, ~0); pullup(udc, 0); local_irq_enable(); @@ -1641,6 +1657,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct at91_udc *udc; int retval; + struct resource *res; if (!dev->platform_data) { /* small (so we copy it) but critical! */ @@ -1658,7 +1675,13 @@ static int __devinit at91udc_probe(struct platform_device *pdev) return -ENODEV; } - if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + if (!request_mem_region(res->start, + res->end - res->start + 1, + driver_name)) { DBG("someone's using UDC memory\n"); return -EBUSY; } @@ -1668,15 +1691,23 @@ static int __devinit at91udc_probe(struct platform_device *pdev) udc->gadget.dev.parent = dev; udc->board = *(struct at91_udc_data *) dev->platform_data; udc->pdev = pdev; - udc_reinit(udc); udc->enabled = 0; + udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1); + if (!udc->udp_baseaddr) { + release_mem_region(res->start, res->end - res->start + 1); + return -ENOMEM; + } + + udc_reinit(udc); + /* get interface and function clocks */ udc->iclk = clk_get(dev, "udc_clk"); udc->fclk = clk_get(dev, "udpck"); if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { DBG("clocks missing\n"); - return -ENODEV; + retval = -ENODEV; + goto fail0; } retval = device_register(&udc->gadget.dev); @@ -1685,8 +1716,10 @@ static int __devinit at91udc_probe(struct platform_device *pdev) /* don't do anything until we have both gadget driver and VBUS */ clk_enable(udc->iclk); - at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); - at91_udp_write(AT91_UDP_IDR, 0xffffffff); + at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff); + /* Clear all pending interrupts - UDP may be used by bootloader. */ + at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff); clk_disable(udc->iclk); /* request UDC and maybe VBUS irqs */ @@ -1698,6 +1731,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev) goto fail1; } if (udc->board.vbus_pin > 0) { + /* + * Get the initial state of VBUS - we cannot expect + * a pending interrupt. + */ + udc->vbus = at91_get_gpio_value(udc->board.vbus_pin); if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) { DBG("request vbus irq %d failed\n", @@ -1720,7 +1758,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) fail1: device_unregister(&udc->gadget.dev); fail0: - release_mem_region(AT91RM9200_BASE_UDP, SZ_16K); + release_mem_region(res->start, res->end - res->start + 1); DBG("%s probe failed, %d\n", driver_name, retval); return retval; } @@ -1728,13 +1766,14 @@ fail0: static int __devexit at91udc_remove(struct platform_device *pdev) { struct at91_udc *udc = platform_get_drvdata(pdev); + struct resource *res; DBG("remove\n"); - pullup(udc, 0); + if (udc->driver) + return -EBUSY; - if (udc->driver != 0) - usb_gadget_unregister_driver(udc->driver); + pullup(udc, 0); device_init_wakeup(&pdev->dev, 0); remove_debug_file(udc); @@ -1742,7 +1781,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev) free_irq(udc->board.vbus_pin, udc); free_irq(udc->udp_irq, udc); device_unregister(&udc->gadget.dev); - release_mem_region(AT91RM9200_BASE_UDP, SZ_16K); + + iounmap(udc->udp_baseaddr); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); clk_put(udc->iclk); clk_put(udc->fclk); diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index 882af42e86c..677089baa59 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -51,10 +51,10 @@ #define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */ #define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */ #define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */ -#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */ +#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */ #define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */ #define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */ -#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */ +#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */ #define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */ #define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */ @@ -84,7 +84,7 @@ #define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */ #define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */ - +#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */ /*-------------------------------------------------------------------------*/ @@ -141,6 +141,7 @@ struct at91_udc { struct clk *iclk, *fclk; struct platform_device *pdev; struct proc_dir_entry *pde; + void __iomem *udp_baseaddr; int udp_irq; }; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index f1f32d7be5f..3c2bc075ef4 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) return -EINVAL; if (dum->driver) return -EBUSY; - if (!driver->bind || !driver->unbind || !driver->setup + if (!driver->bind || !driver->setup || driver->speed == USB_SPEED_UNKNOWN) return -EINVAL; @@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) err_bind_driver: driver_unregister (&driver->driver); err_register: - driver->unbind (&dum->gadget); + if (driver->unbind) + driver->unbind (&dum->gadget); spin_lock_irq (&dum->lock); dum->pullup = 0; set_link_state (dum); @@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (!dum) return -ENODEV; - if (!driver || driver != dum->driver) + if (!driver || driver != dum->driver || !driver->unbind) return -EINVAL; dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n", diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a265e262a2e..72f2ae96fbf 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = { #endif .function = (char *) longname, .bind = fsg_bind, - .unbind = __exit_p(fsg_unbind), + .unbind = fsg_unbind, .disconnect = fsg_disconnect, .setup = fsg_setup, .suspend = fsg_suspend, diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 31351826f2b..f1a679656c9 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -123,7 +123,7 @@ struct gmidi_device { struct usb_request *req; /* for control responses */ u8 config; struct usb_ep *in_ep, *out_ep; - struct snd_card *card; + struct snd_card *card; struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *in_substream; struct snd_rawmidi_substream *out_substream; @@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) int status = req->status; switch (status) { - case 0: /* normal completion */ + case 0: /* normal completion */ if (ep == dev->out_ep) { /* we received stuff. req is queued again, below */ @@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req) break; /* this endpoint is normally active while we're configured */ - case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, @@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) case USB_SPEED_LOW: speed = "low"; break; case USB_SPEED_FULL: speed = "full"; break; case USB_SPEED_HIGH: speed = "high"; break; - default: speed = "?"; break; + default: speed = "?"; break; } dev->config = number; @@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = { .speed = USB_SPEED_FULL, .function = (char *)longname, .bind = gmidi_bind, - .unbind = __exit_p(gmidi_unbind), + .unbind = gmidi_unbind, .setup = gmidi_setup, .disconnect = gmidi_disconnect, @@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = { .suspend = gmidi_suspend, .resume = gmidi_resume, - .driver = { + .driver = { .name = (char *)shortname, .owner = THIS_MODULE, }, diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 805a9826842..d0ef1d6b3fa 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind - || !driver->unbind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - if (!driver || driver != dev->driver) + if (!driver || driver != dev->driver || !driver->unbind) return -EINVAL; spin_lock_irqsave(&dev->lock, flags); @@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev) struct goku_udc *dev = pci_get_drvdata(pdev); DBG(dev, "%s\n", __FUNCTION__); - /* start with the driver above us */ - if (dev->driver) { - /* should have been done already by driver model core */ - WARN(dev, "pci remove, driver '%s' is still registered\n", - dev->driver->driver.name); - usb_gadget_unregister_driver(dev->driver); - } + + BUG_ON(dev->driver); #ifdef CONFIG_USB_GADGET_DEBUG_FILES remove_proc_entry(proc_node_name, NULL); diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 4a991564a03..a0a73c08a34 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -422,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name); if (!driver - || driver->speed != USB_SPEED_FULL - || !driver->bind - || !driver->unbind || !driver->disconnect || !driver->setup) + || driver->speed != USB_SPEED_FULL + || !driver->bind + || !driver->disconnect + || !driver->setup) return -EINVAL; if (!dev) return -ENODEV; @@ -471,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - if (!driver || driver != dev->driver) + if (!driver || driver != dev->driver || !driver->unbind) return -EINVAL; spin_lock_irqsave(&dev->lock, flags); @@ -2125,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev) DEBUG("%s: %p\n", __FUNCTION__, pdev); + if (dev->driver) + return -EBUSY; + udc_disable(dev); remove_proc_files(); - usb_gadget_unregister_driver(dev->driver); free_irq(IRQ_USBINTR, dev); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3024c679e38..569eb8ccf23 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2020,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) if (!driver || driver->speed != USB_SPEED_HIGH || !driver->bind - || !driver->unbind || !driver->setup) return -EINVAL; if (!dev) @@ -2107,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - if (!driver || driver != dev->driver) + if (!driver || driver != dev->driver || !driver->unbind) return -EINVAL; spin_lock_irqsave (&dev->lock, flags); @@ -2803,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev) { struct net2280 *dev = pci_get_drvdata (pdev); - /* start with the driver above us */ - if (dev->driver) { - /* should have been done already by driver model core */ - WARN (dev, "pci remove, driver '%s' is still registered\n", - dev->driver->driver.name); - usb_gadget_unregister_driver (dev->driver); - } + BUG_ON(dev->driver); /* then clean up the resources we allocated during probe() */ net2280_led_shutdown (dev); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 030d87c28c2..15d77c30793 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2043,7 +2043,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) // FIXME if otg, check: driver->is_otg || driver->speed < USB_SPEED_FULL || !driver->bind - || !driver->unbind || !driver->setup) return -EINVAL; @@ -2087,9 +2086,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) status = otg_set_peripheral(udc->transceiver, &udc->gadget); if (status < 0) { ERR("can't bind to transceiver\n"); - driver->unbind (&udc->gadget); - udc->gadget.dev.driver = NULL; - udc->driver = NULL; + if (driver->unbind) { + driver->unbind (&udc->gadget); + udc->gadget.dev.driver = NULL; + udc->driver = NULL; + } goto done; } } else { @@ -2117,7 +2118,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) if (!udc) return -ENODEV; - if (!driver || driver != udc->driver) + if (!driver || driver != udc->driver || !driver->unbind) return -EINVAL; if (machine_is_omap_innovator() || machine_is_omap_osk()) @@ -2870,6 +2871,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev) if (!udc) return -ENODEV; + if (udc->driver) + return -EBUSY; udc->done = &done; diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1ed506e9598..b78de969466 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind - || !driver->unbind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!dev) return -ENODEV; - if (!driver || driver != dev->driver) + if (!driver || driver != dev->driver || !driver->unbind) return -EINVAL; local_irq_disable(); @@ -2638,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) { struct pxa2xx_udc *dev = platform_get_drvdata(pdev); + if (dev->driver) + return -EBUSY; + udc_disable(dev); remove_proc_files(); - usb_gadget_unregister_driver(dev->driver); if (dev->got_irq) { free_irq(IRQ_USB, dev); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 2d12bf9f19d..f8a3ec64635 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = { #endif /* CONFIG_USB_GADGET_DUALSPEED */ .function = GS_LONG_NAME, .bind = gs_bind, - .unbind = __exit_p(gs_unbind), + .unbind = gs_unbind, .setup = gs_setup, .disconnect = gs_disconnect, .driver = { |