diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-02-10 01:26:32 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-02-10 01:26:32 -0500 |
commit | b22364c8eec89e6b0c081a237f3b6348df87796f (patch) | |
tree | 233a923281fb640106465d076997ff511efb6edf /drivers/usb/gadget | |
parent | 2c8dc071517ec2843869024dc82be2e246f41064 (diff) | |
parent | 66efc5a7e3061c3597ac43a8bb1026488d57e66b (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/at91_udc.c | 259 | ||||
-rw-r--r-- | drivers/usb/gadget/at91_udc.h | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/config.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/dummy_hcd.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/epautoconf.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/ether.c | 148 | ||||
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 51 | ||||
-rw-r--r-- | drivers/usb/gadget/gadget_chips.h | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/gmidi.c | 14 | ||||
-rw-r--r-- | drivers/usb/gadget/goku_udc.c | 14 | ||||
-rw-r--r-- | drivers/usb/gadget/inode.c | 240 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/lh7a40x_udc.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/net2280.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/omap_udc.c | 260 | ||||
-rw-r--r-- | drivers/usb/gadget/omap_udc.h | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/serial.c | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/usbstring.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/zero.c | 2 |
20 files changed, 648 insertions, 419 deletions
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 72f3db99ff9..f39050145f1 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -39,18 +39,20 @@ #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/clk.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #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); } @@ -598,7 +586,7 @@ at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) { struct at91_request *req; - req = kcalloc(1, sizeof (struct at91_request), gfp_flags); + req = kzalloc(sizeof (struct at91_request), gfp_flags); if (!req) return NULL; @@ -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); @@ -1765,16 +1807,13 @@ static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) || !wake || at91_suspend_entering_slow_clock()) { pullup(udc, 0); - disable_irq_wake(udc->udp_irq); + wake = 0; } else enable_irq_wake(udc->udp_irq); - if (udc->board.vbus_pin > 0) { - if (wake) - enable_irq_wake(udc->board.vbus_pin); - else - disable_irq_wake(udc->board.vbus_pin); - } + udc->active_suspend = wake; + if (udc->board.vbus_pin > 0 && wake) + enable_irq_wake(udc->board.vbus_pin); return 0; } @@ -1782,8 +1821,14 @@ static int at91udc_resume(struct platform_device *pdev) { struct at91_udc *udc = platform_get_drvdata(pdev); + if (udc->board.vbus_pin > 0 && udc->active_suspend) + disable_irq_wake(udc->board.vbus_pin); + /* maybe reconnect to host; if so, clocks on */ - pullup(udc, 1); + if (udc->active_suspend) + disable_irq_wake(udc->udp_irq); + else + pullup(udc, 1); return 0; } #else diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index 882af42e86c..7e34e2f864f 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] */ /*-------------------------------------------------------------------------*/ @@ -136,11 +136,13 @@ struct at91_udc { unsigned wait_for_addr_ack:1; unsigned wait_for_config_ack:1; unsigned selfpowered:1; + unsigned active_suspend:1; u8 addr; struct at91_udc_data board; 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/config.c b/drivers/usb/gadget/config.c index 83b4866df9a..d18901b92cd 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -24,7 +24,7 @@ #include <linux/string.h> #include <linux/device.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> 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/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 53d584589c2..f28af06905a 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -27,7 +27,7 @@ #include <linux/ctype.h> #include <linux/string.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include "gadget_chips.h" diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index d15bf22b9a0..22e3c944364 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -47,7 +47,7 @@ #include <asm/uaccess.h> #include <asm/unaligned.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb/cdc.h> #include <linux/usb_gadget.h> @@ -72,9 +72,18 @@ * * There's some hardware that can't talk CDC. We make that hardware * implement a "minimalist" vendor-agnostic CDC core: same framing, but - * link-level setup only requires activating the configuration. - * Linux supports it, but other host operating systems may not. - * (This is a subset of CDC Ethernet.) + * link-level setup only requires activating the configuration. Only the + * endpoint descriptors, and product/vendor IDs, are relevant; no control + * operations are available. Linux supports it, but other host operating + * systems may not. (This is a subset of CDC Ethernet.) + * + * It turns out that if you add a few descriptors to that "CDC Subset", + * (Windows) host side drivers from MCCI can treat it as one submode of + * a proprietary scheme called "SAFE" ... without needing to know about + * specific product/vendor IDs. So we do that, making it easier to use + * those MS-Windows drivers. Those added descriptors make it resemble a + * CDC MDLM device, but they don't change device behavior at all. (See + * MCCI Engineering report 950198 "SAFE Networking Functions".) * * A third option is also in use. Rather than CDC Ethernet, or something * simpler, Microsoft pushes their own approach: RNDIS. The published @@ -254,6 +263,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_S3C2410 +#define DEV_CONFIG_CDC +#endif + #ifdef CONFIG_USB_GADGET_AT91 #define DEV_CONFIG_CDC #endif @@ -266,6 +279,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_HUSB2DEV +#define DEV_CONFIG_CDC +#endif + /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. @@ -283,9 +300,6 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_SUBSET #endif -#ifdef CONFIG_USB_GADGET_S3C2410 -#define DEV_CONFIG_CDC -#endif /*-------------------------------------------------------------------------*/ @@ -487,8 +501,17 @@ rndis_config = { * endpoint. Both have a "data" interface and two bulk endpoints. * There are also differences in how control requests are handled. * - * RNDIS shares a lot with CDC-Ethernet, since it's a variant of - * the CDC-ACM (modem) spec. + * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the + * CDC-ACM (modem) spec. Unfortunately MSFT's RNDIS driver is buggy; it + * may hang or oops. Since bugfixes (or accurate specs, letting Linux + * work around those bugs) are unlikely to ever come from MSFT, you may + * wish to avoid using RNDIS. + * + * MCCI offers an alternative to RNDIS if you need to connect to Windows + * but have hardware that can't support CDC Ethernet. We add descriptors + * to present the CDC Subset as a (nonconformant) CDC MDLM variant called + * "SAFE". That borrows from both CDC Ethernet and CDC MDLM. You can + * get those drivers from MCCI, or bundled with various products. */ #ifdef DEV_CONFIG_CDC @@ -522,8 +545,6 @@ rndis_control_intf = { }; #endif -#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - static const struct usb_cdc_header_desc header_desc = { .bLength = sizeof header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, @@ -532,6 +553,8 @@ static const struct usb_cdc_header_desc header_desc = { .bcdCDC = __constant_cpu_to_le16 (0x0110), }; +#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) + static const struct usb_cdc_union_desc union_desc = { .bLength = sizeof union_desc, .bDescriptorType = USB_DT_CS_INTERFACE, @@ -564,7 +587,40 @@ static const struct usb_cdc_acm_descriptor acm_descriptor = { #endif -#ifdef DEV_CONFIG_CDC +#ifndef DEV_CONFIG_CDC + +/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various + * ways: data endpoints live in the control interface, there's no data + * interface, and it's not used to talk to a cell phone radio. + */ + +static const struct usb_cdc_mdlm_desc mdlm_desc = { + .bLength = sizeof mdlm_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_MDLM_TYPE, + + .bcdVersion = __constant_cpu_to_le16(0x0100), + .bGUID = { + 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, + 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, + }, +}; + +/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we + * can't really use its struct. All we do here is say that we're using + * the submode of "SAFE" which directly matches the CDC Subset. + */ +static const u8 mdlm_detail_desc[] = { + 6, + USB_DT_CS_INTERFACE, + USB_CDC_MDLM_DETAIL_TYPE, + + 0, /* "SAFE" */ + 0, /* network control capabilities (none) */ + 0, /* network data capabilities ("raw" encapsulation) */ +}; + +#endif static const struct usb_cdc_ether_desc ether_desc = { .bLength = sizeof ether_desc, @@ -579,7 +635,6 @@ static const struct usb_cdc_ether_desc ether_desc = { .bNumberPowerFilters = 0, }; -#endif #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) @@ -672,6 +727,9 @@ rndis_data_intf = { /* * "Simple" CDC-subset option is a simple vendor-neutral model that most * full speed controllers can handle: one interface, two bulk endpoints. + * + * To assist host side drivers, we fancy it up a bit, and add descriptors + * so some host side drivers will understand it as a "SAFE" variant. */ static const struct usb_interface_descriptor @@ -682,8 +740,8 @@ subset_data_intf = { .bInterfaceNumber = 0, .bAlternateSetting = 0, .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 0, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, .bInterfaceProtocol = 0, .iInterface = STRING_DATA, }; @@ -731,10 +789,15 @@ static const struct usb_descriptor_header *fs_eth_function [11] = { static inline void __init fs_subset_descriptors(void) { #ifdef DEV_CONFIG_SUBSET + /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - fs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; - fs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; - fs_eth_function[4] = NULL; + fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; + fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; + fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; + fs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; + fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc; + fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc; + fs_eth_function[8] = NULL; #else fs_eth_function[1] = NULL; #endif @@ -828,10 +891,15 @@ static const struct usb_descriptor_header *hs_eth_function [11] = { static inline void __init hs_subset_descriptors(void) { #ifdef DEV_CONFIG_SUBSET + /* behavior is "CDC Subset"; extra descriptors say "SAFE" */ hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf; - hs_eth_function[2] = (struct usb_descriptor_header *) &fs_source_desc; - hs_eth_function[3] = (struct usb_descriptor_header *) &fs_sink_desc; - hs_eth_function[4] = NULL; + hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc; + hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc; + hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc; + hs_eth_function[5] = (struct usb_descriptor_header *) ðer_desc; + hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc; + hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc; + hs_eth_function[8] = NULL; #else hs_eth_function[1] = NULL; #endif @@ -878,10 +946,8 @@ static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; static char serial_number [20]; -#ifdef DEV_CONFIG_CDC /* address that the host will use ... usually assigned at random */ static char ethaddr [2 * ETH_ALEN + 1]; -#endif /* static strings, in UTF-8 */ static struct usb_string strings [] = { @@ -889,9 +955,9 @@ static struct usb_string strings [] = { { STRING_PRODUCT, product_desc, }, { STRING_SERIALNUMBER, serial_number, }, { STRING_DATA, "Ethernet Data", }, + { STRING_ETHADDR, ethaddr, }, #ifdef DEV_CONFIG_CDC { STRING_CDC, "CDC Ethernet", }, - { STRING_ETHADDR, ethaddr, }, { STRING_CONTROL, "CDC Communications Control", }, #endif #ifdef DEV_CONFIG_SUBSET @@ -986,10 +1052,10 @@ set_ether_config (struct eth_dev *dev, gfp_t gfp_flags) } #endif - dev->in = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); + dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc); dev->in_ep->driver_data = dev; - dev->out = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); + dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); dev->out_ep->driver_data = dev; /* With CDC, the host isn't allowed to use these two data @@ -2278,10 +2344,10 @@ eth_bind (struct usb_gadget *gadget) "RNDIS/%s", driver_desc); /* CDC subset ... recognized by Linux since 2.4.10, but Windows - * drivers aren't widely available. + * drivers aren't widely available. (That may be improved by + * supporting one submode of the "SAFE" variant of MDLM.) */ } else if (!cdc) { - device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; device_desc.idVendor = __constant_cpu_to_le16(SIMPLE_VENDOR_NUM); device_desc.idProduct = @@ -2352,6 +2418,10 @@ autoconf_fail: if (!cdc) { eth_config.bNumInterfaces = 1; eth_config.iConfiguration = STRING_SUBSET; + + /* use functions to set these up, in case we're built to work + * with multiple controllers and must override CDC Ethernet. + */ fs_subset_descriptors(); hs_subset_descriptors(); } @@ -2415,22 +2485,20 @@ autoconf_fail: /* Module params for these addresses should come from ID proms. * The host side address is used with CDC and RNDIS, and commonly - * ends up in a persistent config database. + * ends up in a persistent config database. It's not clear if + * host side code for the SAFE thing cares -- its original BLAN + * thing didn't, Sharp never assigned those addresses on Zaurii. */ if (get_ether_addr(dev_addr, net->dev_addr)) dev_warn(&gadget->dev, "using random %s ethernet address\n", "self"); - if (cdc || rndis) { - if (get_ether_addr(host_addr, dev->host_mac)) - dev_warn(&gadget->dev, - "using random %s ethernet address\n", "host"); -#ifdef DEV_CONFIG_CDC - snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", - dev->host_mac [0], dev->host_mac [1], - dev->host_mac [2], dev->host_mac [3], - dev->host_mac [4], dev->host_mac [5]); -#endif - } + if (get_ether_addr(host_addr, dev->host_mac)) + dev_warn(&gadget->dev, + "using random %s ethernet address\n", "host"); + snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", + dev->host_mac [0], dev->host_mac [1], + dev->host_mac [2], dev->host_mac [3], + dev->host_mac [4], dev->host_mac [5]); if (rndis) { status = rndis_init(); diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index c98316ce838..f04a29a4664 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -253,7 +253,7 @@ #include <linux/freezer.h> #include <linux/utsname.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include "gadget_chips.h" @@ -1148,7 +1148,7 @@ static int ep0_queue(struct fsg_dev *fsg) static void ep0_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; + struct fsg_dev *fsg = ep->driver_data; if (req->actual > 0) dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); @@ -1170,8 +1170,8 @@ static void ep0_complete(struct usb_ep *ep, struct usb_request *req) static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; - struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + struct fsg_dev *fsg = ep->driver_data; + struct fsg_buffhd *bh = req->context; if (req->status || req->actual != req->length) DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, @@ -1190,8 +1190,8 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; - struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + struct fsg_dev *fsg = ep->driver_data; + struct fsg_buffhd *bh = req->context; dump_msg(fsg, "bulk-out", req->buf, req->actual); if (req->status || req->actual != bh->bulk_out_intended_length) @@ -1214,8 +1214,8 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) #ifdef CONFIG_USB_FILE_STORAGE_TEST static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) { - struct fsg_dev *fsg = (struct fsg_dev *) ep->driver_data; - struct fsg_buffhd *bh = (struct fsg_buffhd *) req->context; + struct fsg_dev *fsg = ep->driver_data; + struct fsg_buffhd *bh = req->context; if (req->status || req->actual != req->length) DBG(fsg, "%s --> %d, %u/%u\n", __FUNCTION__, @@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun) if (!filp->f_op->fsync) return -EINVAL; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); rc = filemap_fdatawrite(inode->i_mapping); - err = filp->f_op->fsync(filp, filp->f_dentry, 1); + err = filp->f_op->fsync(filp, filp->f_path.dentry, 1); if (!rc) rc = err; err = filemap_fdatawait(inode->i_mapping); @@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg) static void invalidate_sub(struct lun *curlun) { struct file *filp = curlun->filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; unsigned long rc; rc = invalidate_inode_pages(inode->i_mapping); @@ -2577,7 +2577,7 @@ static int send_status(struct fsg_dev *fsg) } if (transport_is_bbb()) { - struct bulk_cs_wrap *csw = (struct bulk_cs_wrap *) bh->buf; + struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); @@ -2596,8 +2596,7 @@ static int send_status(struct fsg_dev *fsg) return 0; } else { // USB_PR_CBI - struct interrupt_data *buf = (struct interrupt_data *) - bh->buf; + struct interrupt_data *buf = bh->buf; /* Store and send the Interrupt data. UFI sends the ASC * and ASCQ bytes. Everything else sends a Type (which @@ -2982,7 +2981,7 @@ static int do_scsi_command(struct fsg_dev *fsg) static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) { struct usb_request *req = bh->outreq; - struct bulk_cb_wrap *cbw = (struct bulk_cb_wrap *) req->buf; + struct bulk_cb_wrap *cbw = req->buf; /* Was this a real packet? */ if (req->status) @@ -3428,7 +3427,7 @@ static void handle_exception(struct fsg_dev *fsg) static int fsg_main_thread(void *fsg_) { - struct fsg_dev *fsg = (struct fsg_dev *) fsg_; + struct fsg_dev *fsg = fsg_; /* Allow the thread to be killed by a signal, but set the signal mask * to block everything but INT, TERM, KILL, and USR1. */ @@ -3526,8 +3525,8 @@ static int open_backing_file(struct lun *curlun, const char *filename) if (!(filp->f_mode & FMODE_WRITE)) ro = 1; - if (filp->f_dentry) - inode = filp->f_dentry->d_inode; + if (filp->f_path.dentry) + inode = filp->f_path.dentry->d_inode; if (inode && S_ISBLK(inode->i_mode)) { if (bdev_read_only(inode->i_bdev)) ro = 1; @@ -3600,13 +3599,13 @@ static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char * static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf) { struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + struct fsg_dev *fsg = dev_get_drvdata(dev); char *p; ssize_t rc; down_read(&fsg->filesem); if (backing_file_is_open(curlun)) { // Get the complete pathname - p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1); if (IS_ERR(p)) rc = PTR_ERR(p); @@ -3629,7 +3628,7 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const { ssize_t rc = count; struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + struct fsg_dev *fsg = dev_get_drvdata(dev); int i; if (sscanf(buf, "%d", &i) != 1) @@ -3652,7 +3651,7 @@ static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct lun *curlun = dev_to_lun(dev); - struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + struct fsg_dev *fsg = dev_get_drvdata(dev); int rc = 0; if (curlun->prevent_medium_removal && backing_file_is_open(curlun)) { @@ -3700,7 +3699,7 @@ static void fsg_release(struct kref *ref) static void lun_release(struct device *dev) { - struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev); + struct fsg_dev *fsg = dev_get_drvdata(dev); kref_put(&fsg->ref, fsg_release); } @@ -4030,8 +4029,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) if (backing_file_is_open(curlun)) { p = NULL; if (pathbuf) { - p = d_path(curlun->filp->f_dentry, - curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, + curlun->filp->f_path.mnt, pathbuf, PATH_MAX); if (IS_ERR(p)) p = NULL; @@ -4100,7 +4099,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/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index aa80f091072..2e3d6620d21 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -75,6 +75,12 @@ #define gadget_is_pxa27x(g) 0 #endif +#ifdef CONFIG_USB_GADGET_HUSB2DEV +#define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name) +#else +#define gadget_is_husb2dev(g) 0 +#endif + #ifdef CONFIG_USB_GADGET_S3C2410 #define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name) #else @@ -169,5 +175,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x16; else if (gadget_is_mpc8272(gadget)) return 0x17; + else if (gadget_is_husb2dev(gadget)) + return 0x18; return -ENOENT; } diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 31351826f2b..d08a8d0e642 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -35,7 +35,7 @@ #include <sound/initval.h> #include <sound/rawmidi.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <linux/usb/audio.h> #include <linux/usb/midi.h> @@ -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..e873cf48824 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -39,7 +39,7 @@ #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/device.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <asm/byteorder.h> @@ -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/inode.c b/drivers/usb/gadget/inode.c index 3fb1044a4db..34296e79edc 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -20,7 +20,7 @@ */ -// #define DEBUG /* data to help fault diagnosis */ +// #define DEBUG /* data to help fault diagnosis */ // #define VERBOSE /* extra debug messages (success too) */ #include <linux/init.h> @@ -59,11 +59,11 @@ * may serve as a source of device events, used to handle all control * requests other than basic enumeration. * - * - Then either immediately, or after a SET_CONFIGURATION control request, - * ep_config() is called when each /dev/gadget/ep* file is configured - * (by writing endpoint descriptors). Afterwards these files are used - * to write() IN data or to read() OUT data. To halt the endpoint, a - * "wrong direction" request is issued (like reading an IN endpoint). + * - Then, after a SET_CONFIGURATION control request, ep_config() is + * called when each /dev/gadget/ep* file is configured (by writing + * endpoint descriptors). Afterwards these files are used to write() + * IN data or to read() OUT data. To halt the endpoint, a "wrong + * direction" request is issued (like reading an IN endpoint). * * Unlike "usbfs" the only ioctl()s are for things that are rare, and maybe * not possible on all hardware. For example, precise fault handling with @@ -98,16 +98,16 @@ enum ep0_state { * must always write descriptors to initialize the device, then * the device becomes UNCONNECTED until enumeration. */ - STATE_OPENED, + STATE_DEV_OPENED, /* From then on, ep0 fd is in either of two basic modes: * - (UN)CONNECTED: read usb_gadgetfs_event(s) from it * - SETUP: read/write will transfer control data and succeed; * or if "wrong direction", performs protocol stall */ - STATE_UNCONNECTED, - STATE_CONNECTED, - STATE_SETUP, + STATE_DEV_UNCONNECTED, + STATE_DEV_CONNECTED, + STATE_DEV_SETUP, /* UNBOUND means the driver closed ep0, so the device won't be * accessible again (DEV_DISABLED) until all fds are closed. @@ -121,7 +121,7 @@ enum ep0_state { struct dev_data { spinlock_t lock; atomic_t count; - enum ep0_state state; + enum ep0_state state; /* P: lock */ struct usb_gadgetfs_event event [N_EVENT]; unsigned ev_next; struct fasync_struct *fasync; @@ -188,7 +188,6 @@ static struct dev_data *dev_new (void) enum ep_state { STATE_EP_DISABLED = 0, STATE_EP_READY, - STATE_EP_DEFER_ENABLE, STATE_EP_ENABLED, STATE_EP_UNBOUND, }; @@ -313,18 +312,10 @@ nonblock: if ((val = down_interruptible (&epdata->lock)) < 0) return val; -newstate: + switch (epdata->state) { case STATE_EP_ENABLED: break; - case STATE_EP_DEFER_ENABLE: - DBG (epdata->dev, "%s wait for host\n", epdata->name); - if ((val = wait_event_interruptible (epdata->wait, - epdata->state != STATE_EP_DEFER_ENABLE - || epdata->dev->state == STATE_DEV_UNBOUND - )) < 0) - goto fail; - goto newstate; // case STATE_EP_DISABLED: /* "can't happen" */ // case STATE_EP_READY: /* "can't happen" */ default: /* error! */ @@ -333,7 +324,6 @@ newstate: // FALLTHROUGH case STATE_EP_UNBOUND: /* clean disconnect */ val = -ENODEV; -fail: up (&epdata->lock); } return val; @@ -565,29 +555,28 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ssize_t len, total; int i; - /* we "retry" to get the right mm context for this: */ - - /* copy stuff into user buffers */ - total = priv->actual; - len = 0; - for (i=0; i < priv->nr_segs; i++) { - ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); - - if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { - if (len == 0) - len = -EFAULT; - break; - } - - total -= this; - len += this; - if (total == 0) - break; - } - kfree(priv->buf); - kfree(priv); - aio_put_req(iocb); - return len; + /* we "retry" to get the right mm context for this: */ + + /* copy stuff into user buffers */ + total = priv->actual; + len = 0; + for (i=0; i < priv->nr_segs; i++) { + ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total); + + if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) { + if (len == 0) + len = -EFAULT; + break; + } + + total -= this; + len += this; + if (total == 0) + break; + } + kfree(priv->buf); + kfree(priv); + return len; } static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) @@ -600,18 +589,17 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) spin_lock(&epdata->dev->lock); priv->req = NULL; priv->epdata = NULL; - if (priv->iv == NULL - || unlikely(req->actual == 0) - || unlikely(kiocbIsCancelled(iocb))) { + + /* if this was a write or a read returning no data then we + * don't need to copy anything to userspace, so we can + * complete the aio request immediately. + */ + if (priv->iv == NULL || unlikely(req->actual == 0)) { kfree(req->buf); kfree(priv); iocb->private = NULL; /* aio_complete() reports bytes-transferred _and_ faults */ - if (unlikely(kiocbIsCancelled(iocb))) - aio_put_req(iocb); - else - aio_complete(iocb, - req->actual ? req->actual : req->status, + aio_complete(iocb, req->actual ? req->actual : req->status, req->status); } else { /* retry() won't report both; so we hide some faults */ @@ -636,7 +624,7 @@ ep_aio_rwtail( size_t len, struct ep_data *epdata, const struct iovec *iv, - unsigned long nr_segs + unsigned long nr_segs ) { struct kiocb_priv *priv; @@ -852,9 +840,9 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) break; #endif default: - DBG (data->dev, "unconnected, %s init deferred\n", + DBG(data->dev, "unconnected, %s init abandoned\n", data->name); - data->state = STATE_EP_DEFER_ENABLE; + value = -EINVAL; } if (value == 0) { fd->f_op = &ep_io_operations; @@ -943,22 +931,24 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req) static void ep0_complete (struct usb_ep *ep, struct usb_request *req) { struct dev_data *dev = ep->driver_data; + unsigned long flags; int free = 1; /* for control OUT, data must still get to userspace */ + spin_lock_irqsave(&dev->lock, flags); if (!dev->setup_in) { dev->setup_out_error = (req->status != 0); if (!dev->setup_out_error) free = 0; dev->setup_out_ready = 1; ep0_readable (dev); - } else if (dev->state == STATE_SETUP) - dev->state = STATE_CONNECTED; + } /* clean up as appropriate */ if (free && req->buf != &dev->rbuf) clean_req (ep, req); req->complete = epio_complete; + spin_unlock_irqrestore(&dev->lock, flags); } static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) @@ -998,13 +988,13 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) } /* control DATA stage */ - if ((state = dev->state) == STATE_SETUP) { + if ((state = dev->state) == STATE_DEV_SETUP) { if (dev->setup_in) { /* stall IN */ VDEBUG(dev, "ep0in stall\n"); (void) usb_ep_set_halt (dev->gadget->ep0); retval = -EL2HLT; - dev->state = STATE_CONNECTED; + dev->state = STATE_DEV_CONNECTED; } else if (len == 0) { /* ack SET_CONFIGURATION etc */ struct usb_ep *ep = dev->gadget->ep0; @@ -1012,7 +1002,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) if ((retval = setup_req (ep, req, 0)) == 0) retval = usb_ep_queue (ep, req, GFP_ATOMIC); - dev->state = STATE_CONNECTED; + dev->state = STATE_DEV_CONNECTED; /* assume that was SET_CONFIGURATION */ if (dev->current_config) { @@ -1040,6 +1030,13 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) spin_lock_irq (&dev->lock); if (retval) goto done; + + if (dev->state != STATE_DEV_SETUP) { + retval = -ECANCELED; + goto done; + } + dev->state = STATE_DEV_CONNECTED; + if (dev->setup_out_error) retval = -EIO; else { @@ -1066,39 +1063,36 @@ scan: /* return queued events right away */ if (dev->ev_next != 0) { unsigned i, n; - int tmp = dev->ev_next; - len = min (len, tmp * sizeof (struct usb_gadgetfs_event)); n = len / sizeof (struct usb_gadgetfs_event); + if (dev->ev_next < n) + n = dev->ev_next; - /* ep0 can't deliver events when STATE_SETUP */ + /* ep0 i/o has special semantics during STATE_DEV_SETUP */ for (i = 0; i < n; i++) { if (dev->event [i].type == GADGETFS_SETUP) { - len = i + 1; - len *= sizeof (struct usb_gadgetfs_event); - n = 0; + dev->state = STATE_DEV_SETUP; + n = i + 1; break; } } spin_unlock_irq (&dev->lock); + len = n * sizeof (struct usb_gadgetfs_event); if (copy_to_user (buf, &dev->event, len)) retval = -EFAULT; else retval = len; if (len > 0) { - len /= sizeof (struct usb_gadgetfs_event); - /* NOTE this doesn't guard against broken drivers; * concurrent ep0 readers may lose events. */ spin_lock_irq (&dev->lock); - dev->ev_next -= len; - if (dev->ev_next != 0) - memmove (&dev->event, &dev->event [len], + if (dev->ev_next > n) { + memmove(&dev->event[0], &dev->event[n], sizeof (struct usb_gadgetfs_event) - * (tmp - len)); - if (n == 0) - dev->state = STATE_SETUP; + * (dev->ev_next - n)); + } + dev->ev_next -= n; spin_unlock_irq (&dev->lock); } return retval; @@ -1113,8 +1107,8 @@ scan: DBG (dev, "fail %s, state %d\n", __FUNCTION__, state); retval = -ESRCH; break; - case STATE_UNCONNECTED: - case STATE_CONNECTED: + case STATE_DEV_UNCONNECTED: + case STATE_DEV_CONNECTED: spin_unlock_irq (&dev->lock); DBG (dev, "%s wait\n", __FUNCTION__); @@ -1141,7 +1135,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) switch (type) { /* these events purge the queue */ case GADGETFS_DISCONNECT: - if (dev->state == STATE_SETUP) + if (dev->state == STATE_DEV_SETUP) dev->setup_abort = 1; // FALL THROUGH case GADGETFS_CONNECT: @@ -1153,7 +1147,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) for (i = 0; i != dev->ev_next; i++) { if (dev->event [i].type != type) continue; - DBG (dev, "discard old event %d\n", type); + DBG(dev, "discard old event[%d] %d\n", i, type); dev->ev_next--; if (i == dev->ev_next) break; @@ -1166,9 +1160,9 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) default: BUG (); } + VDEBUG(dev, "event[%d] = %d\n", dev->ev_next, type); event = &dev->event [dev->ev_next++]; BUG_ON (dev->ev_next > N_EVENT); - VDEBUG (dev, "ev %d, next %d\n", type, dev->ev_next); memset (event, 0, sizeof *event); event->type = type; return event; @@ -1188,12 +1182,13 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) retval = -EIDRM; /* data and/or status stage for control request */ - } else if (dev->state == STATE_SETUP) { + } else if (dev->state == STATE_DEV_SETUP) { /* IN DATA+STATUS caller makes len <= wLength */ if (dev->setup_in) { retval = setup_req (dev->gadget->ep0, dev->req, len); if (retval == 0) { + dev->state = STATE_DEV_CONNECTED; spin_unlock_irq (&dev->lock); if (copy_from_user (dev->req->buf, buf, len)) retval = -EFAULT; @@ -1219,7 +1214,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) VDEBUG(dev, "ep0out stall\n"); (void) usb_ep_set_halt (dev->gadget->ep0); retval = -EL2HLT; - dev->state = STATE_CONNECTED; + dev->state = STATE_DEV_CONNECTED; } else { DBG(dev, "bogus ep0out stall!\n"); } @@ -1261,7 +1256,9 @@ dev_release (struct inode *inode, struct file *fd) put_dev (dev); /* other endpoints were all decoupled from this device */ + spin_lock_irq(&dev->lock); dev->state = STATE_DEV_DISABLED; + spin_unlock_irq(&dev->lock); return 0; } @@ -1282,7 +1279,7 @@ ep0_poll (struct file *fd, poll_table *wait) goto out; } - if (dev->state == STATE_SETUP) { + if (dev->state == STATE_DEV_SETUP) { if (dev->setup_in || dev->setup_can_stall) mask = POLLOUT; } else { @@ -1392,52 +1389,29 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) spin_lock (&dev->lock); dev->setup_abort = 0; - if (dev->state == STATE_UNCONNECTED) { - struct usb_ep *ep; - struct ep_data *data; - - dev->state = STATE_CONNECTED; - dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; - + if (dev->state == STATE_DEV_UNCONNECTED) { #ifdef CONFIG_USB_GADGET_DUALSPEED if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) { + spin_unlock(&dev->lock); ERROR (dev, "no high speed config??\n"); return -EINVAL; } #endif /* CONFIG_USB_GADGET_DUALSPEED */ + dev->state = STATE_DEV_CONNECTED; + dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket; + INFO (dev, "connected\n"); event = next_event (dev, GADGETFS_CONNECT); event->u.speed = gadget->speed; ep0_readable (dev); - list_for_each_entry (ep, &gadget->ep_list, ep_list) { - data = ep->driver_data; - /* ... down_trylock (&data->lock) ... */ - if (data->state != STATE_EP_DEFER_ENABLE) - continue; -#ifdef CONFIG_USB_GADGET_DUALSPEED - if (gadget->speed == USB_SPEED_HIGH) - value = usb_ep_enable (ep, &data->hs_desc); - else -#endif /* CONFIG_USB_GADGET_DUALSPEED */ - value = usb_ep_enable (ep, &data->desc); - if (value) { - ERROR (dev, "deferred %s enable --> %d\n", - data->name, value); - continue; - } - data->state = STATE_EP_ENABLED; - wake_up (&data->wait); - DBG (dev, "woke up %s waiters\n", data->name); - } - /* host may have given up waiting for response. we can miss control * requests handled lower down (device/endpoint status and features); * then ep0_{read,write} will report the wrong status. controller * driver will have aborted pending i/o. */ - } else if (dev->state == STATE_SETUP) + } else if (dev->state == STATE_DEV_SETUP) dev->setup_abort = 1; req->buf = dev->rbuf; @@ -1583,7 +1557,7 @@ delegate: } /* proceed with data transfer and status phases? */ - if (value >= 0 && dev->state != STATE_SETUP) { + if (value >= 0 && dev->state != STATE_DEV_SETUP) { req->length = value; req->zero = value < w_length; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); @@ -1747,7 +1721,9 @@ gadgetfs_bind (struct usb_gadget *gadget) goto enomem; INFO (dev, "bound to %s driver\n", gadget->name); - dev->state = STATE_UNCONNECTED; + spin_lock_irq(&dev->lock); + dev->state = STATE_DEV_UNCONNECTED; + spin_unlock_irq(&dev->lock); get_dev (dev); return 0; @@ -1762,11 +1738,9 @@ gadgetfs_disconnect (struct usb_gadget *gadget) struct dev_data *dev = get_gadget_data (gadget); spin_lock (&dev->lock); - if (dev->state == STATE_UNCONNECTED) { - DBG (dev, "already unconnected\n"); + if (dev->state == STATE_DEV_UNCONNECTED) goto exit; - } - dev->state = STATE_UNCONNECTED; + dev->state = STATE_DEV_UNCONNECTED; INFO (dev, "disconnected\n"); next_event (dev, GADGETFS_DISCONNECT); @@ -1783,9 +1757,9 @@ gadgetfs_suspend (struct usb_gadget *gadget) INFO (dev, "suspended from state %d\n", dev->state); spin_lock (&dev->lock); switch (dev->state) { - case STATE_SETUP: // VERY odd... host died?? - case STATE_CONNECTED: - case STATE_UNCONNECTED: + case STATE_DEV_SETUP: // VERY odd... host died?? + case STATE_DEV_CONNECTED: + case STATE_DEV_UNCONNECTED: next_event (dev, GADGETFS_SUSPEND); ep0_readable (dev); /* FALLTHROUGH */ @@ -1808,7 +1782,7 @@ static struct usb_gadget_driver gadgetfs_driver = { .disconnect = gadgetfs_disconnect, .suspend = gadgetfs_suspend, - .driver = { + .driver = { .name = (char *) shortname, }, }; @@ -1829,7 +1803,7 @@ static struct usb_gadget_driver probe_driver = { .unbind = gadgetfs_nop, .setup = (void *)gadgetfs_nop, .disconnect = gadgetfs_nop, - .driver = { + .driver = { .name = "nop", }, }; @@ -1849,19 +1823,16 @@ static struct usb_gadget_driver probe_driver = { * . full/low speed config ... all wTotalLength bytes (with interface, * class, altsetting, endpoint, and other descriptors) * . high speed config ... all descriptors, for high speed operation; - * this one's optional except for high-speed hardware + * this one's optional except for high-speed hardware * . device descriptor * - * Endpoints are not yet enabled. Drivers may want to immediately - * initialize them, using the /dev/gadget/ep* files that are available - * as soon as the kernel sees the configuration, or they can wait - * until device configuration and interface altsetting changes create + * Endpoints are not yet enabled. Drivers must wait until device + * configuration and interface altsetting changes create * the need to configure (or unconfigure) them. * * After initialization, the device stays active for as long as that - * $CHIP file is open. Events may then be read from that descriptor, - * such as configuration notifications. More complex drivers will handle - * some control requests in user space. + * $CHIP file is open. Events must then be read from that descriptor, + * such as configuration notifications. */ static int is_valid_config (struct usb_config_descriptor *config) @@ -1884,9 +1855,6 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) u32 tag; char *kbuf; - if (dev->state != STATE_OPENED) - return -EEXIST; - if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) return -EINVAL; @@ -1978,13 +1946,15 @@ dev_open (struct inode *inode, struct file *fd) struct dev_data *dev = inode->i_private; int value = -EBUSY; + spin_lock_irq(&dev->lock); if (dev->state == STATE_DEV_DISABLED) { dev->ev_next = 0; - dev->state = STATE_OPENED; + dev->state = STATE_DEV_OPENED; fd->private_data = dev; get_dev (dev); value = 0; } + spin_unlock_irq(&dev->lock); return value; } 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/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h index e3bb78524c8..b3fe197e1ee 100644 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ b/drivers/usb/gadget/lh7a40x_udc.h @@ -49,7 +49,7 @@ #include <asm/unaligned.h> #include <asm/hardware.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> /* diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3024c679e38..7617ff7bd5a 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -63,7 +63,7 @@ #include <linux/interrupt.h> #include <linux/moduleparam.h> #include <linux/device.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <asm/byteorder.h> @@ -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..140104341db 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -38,10 +38,11 @@ #include <linux/mm.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <linux/usb/otg.h> #include <linux/dma-mapping.h> +#include <linux/clk.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -60,6 +61,11 @@ /* bulk DMA seems to be behaving for both IN and OUT */ #define USE_DMA +/* FIXME: OMAP2 currently has some problem in DMA mode */ +#ifdef CONFIG_ARCH_OMAP2 +#undef USE_DMA +#endif + /* ISO too */ #define USE_ISO @@ -99,7 +105,7 @@ static unsigned fifo_mode = 0; * boot parameter "omap_udc:fifo_mode=42" */ module_param (fifo_mode, uint, 0); -MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)"); +MODULE_PARM_DESC (fifo_mode, "endpoint configuration"); #ifdef USE_DMA static unsigned use_dma = 1; @@ -122,7 +128,7 @@ static const char driver_desc [] = DRIVER_DESC; /*-------------------------------------------------------------------------*/ /* there's a notion of "current endpoint" for modifying endpoint - * state, and PIO access to its FIFO. + * state, and PIO access to its FIFO. */ static void use_ep(struct omap_ep *ep, u16 select) @@ -391,7 +397,7 @@ done(struct omap_ep *ep, struct omap_req *req, int status) #define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY) #define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY) -static inline int +static inline int write_packet(u8 *buf, struct omap_req *req, unsigned max) { unsigned len; @@ -456,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req) return is_last; } -static inline int +static inline int read_packet(u8 *buf, struct omap_req *req, unsigned avail) { unsigned len; @@ -542,9 +548,9 @@ static inline dma_addr_t dma_csac(unsigned lch) /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ - csac = omap_readw(OMAP_DMA_CSAC(lch)); + csac = OMAP_DMA_CSAC_REG(lch); if (csac == 0) - csac = omap_readw(OMAP_DMA_CSAC(lch)); + csac = OMAP_DMA_CSAC_REG(lch); return csac; } @@ -555,9 +561,9 @@ static inline dma_addr_t dma_cdac(unsigned lch) /* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ - cdac = omap_readw(OMAP_DMA_CDAC(lch)); + cdac = OMAP_DMA_CDAC_REG(lch); if (cdac == 0) - cdac = omap_readw(OMAP_DMA_CDAC(lch)); + cdac = OMAP_DMA_CDAC_REG(lch); return cdac; } @@ -582,7 +588,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start) } #define DMA_DEST_LAST(x) (cpu_is_omap15xx() \ - ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \ + ? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \ : dma_cdac(x)) static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start) @@ -620,17 +626,19 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req) || (cpu_is_omap15xx() && length < ep->maxpacket)) { txdma_ctrl = UDC_TXN_EOT | length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8, - length, 1, sync_mode); + length, 1, sync_mode, 0, 0); } else { length = min(length / ep->maxpacket, (unsigned) UDC_TXN_TSC + 1); - txdma_ctrl = length; + txdma_ctrl = length; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, - ep->ep.maxpacket >> 1, length, sync_mode); + ep->ep.maxpacket >> 1, length, sync_mode, + 0, 0); length *= ep->maxpacket; } omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); + OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, + 0, 0); omap_start_dma(ep->lch); ep->dma_counter = dma_csac(ep->lch); @@ -675,9 +683,11 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req) req->dma_bytes = packets * ep->ep.maxpacket; omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16, ep->ep.maxpacket >> 1, packets, - OMAP_DMA_SYNC_ELEMENT); + OMAP_DMA_SYNC_ELEMENT, + 0, 0); omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF, - OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual); + OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual, + 0, 0); ep->dma_counter = DMA_DEST_LAST(ep->lch); UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1); @@ -820,7 +830,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); + (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG), + 0, 0); } } else { status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel, @@ -831,7 +842,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_TIPB, OMAP_DMA_AMODE_CONSTANT, - (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG)); + (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG), + 0, 0); /* EMIFF */ omap_set_dma_dest_burst_mode(ep->lch, OMAP_DMA_DATA_BURST_4); @@ -846,7 +858,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel) /* channel type P: hw synch (fifo) */ if (!cpu_is_omap15xx()) - omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch)); + OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2; } just_restart: @@ -893,7 +905,7 @@ static void dma_channel_release(struct omap_ep *ep) else req = NULL; - active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0; + active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0; DBG("%s release %s %cxdma%d %p\n", ep->ep.name, active ? "active" : "idle", @@ -1117,7 +1129,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) */ dma_channel_release(ep); dma_channel_claim(ep, channel); - } else + } else done(ep, req, -ECONNRESET); spin_unlock_irqrestore(&ep->udc->lock, flags); return 0; @@ -1153,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value) /* IN endpoints must already be idle */ if ((ep->bEndpointAddress & USB_DIR_IN) - && !list_empty(&ep->queue)) { + && !list_empty(&ep->queue)) { status = -EAGAIN; goto done; } @@ -1298,6 +1310,23 @@ static void pullup_disable(struct omap_udc *udc) UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; } +static struct omap_udc *udc; + +static void omap_udc_enable_clock(int enable) +{ + if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL) + return; + + if (enable) { + clk_enable(udc->dc_clk); + clk_enable(udc->hhc_clk); + udelay(100); + } else { + clk_disable(udc->hhc_clk); + clk_disable(udc->dc_clk); + } +} + /* * Called by whatever detects VBUS sessions: external transceiver * driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock. @@ -1318,10 +1347,22 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) else FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510; } + if (udc->dc_clk != NULL && is_active) { + if (!udc->clk_requested) { + omap_udc_enable_clock(1); + udc->clk_requested = 1; + } + } if (can_pullup(udc)) pullup_enable(udc); else pullup_disable(udc); + if (udc->dc_clk != NULL && !is_active) { + if (udc->clk_requested) { + omap_udc_enable_clock(0); + udc->clk_requested = 0; + } + } spin_unlock_irqrestore(&udc->lock, flags); return 0; } @@ -1441,7 +1482,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) } } - /* IN/OUT packets mean we're in the DATA or STATUS stage. + /* IN/OUT packets mean we're in the DATA or STATUS stage. * This driver uses only uses protocol stalls (ep0 never halts), * and if we got this far the gadget driver already had a * chance to stall. Tries to be forgiving of host oddities. @@ -1509,7 +1550,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) } else if (stat == 0) UDC_CTRL_REG = UDC_SET_FIFO_EN; UDC_EP_NUM_REG = 0; - + /* activate status stage */ if (stat == 1) { done(ep0, req, 0); @@ -1866,7 +1907,7 @@ static void pio_out_timer(unsigned long _ep) spin_lock_irqsave(&ep->udc->lock, flags); if (!list_empty(&ep->queue) && ep->ackwait) { - use_ep(ep, 0); + use_ep(ep, UDC_EP_SEL); stat_flg = UDC_STAT_FLG_REG; if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN) @@ -1876,12 +1917,12 @@ static void pio_out_timer(unsigned long _ep) VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg); req = container_of(ep->queue.next, struct omap_req, queue); - UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL; (void) read_fifo(ep, req); UDC_EP_NUM_REG = ep->bEndpointAddress; UDC_CTRL_REG = UDC_SET_FIFO_EN; ep->ackwait = 1 + ep->double_buf; - } + } else + deselect_ep(); } mod_timer(&ep->timer, PIO_OUT_TIMEOUT); spin_unlock_irqrestore(&ep->udc->lock, flags); @@ -2028,7 +2069,17 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) /*-------------------------------------------------------------------------*/ -static struct omap_udc *udc; +static inline int machine_needs_vbus_session(void) +{ + return (machine_is_omap_innovator() + || machine_is_omap_osk() + || machine_is_omap_apollon() +#ifndef CONFIG_MACH_OMAP_H4_OTG + || machine_is_omap_h4() +#endif + || machine_is_sx1() + ); +} int usb_gadget_register_driver (struct usb_gadget_driver *driver) { @@ -2043,7 +2094,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; @@ -2071,6 +2121,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(&udc->lock, flags); + if (udc->dc_clk != NULL) + omap_udc_enable_clock(1); + status = driver->bind (&udc->gadget); if (status) { DBG("bind to %s --> %d\n", driver->driver.name, status); @@ -2087,9 +2140,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 { @@ -2102,10 +2157,12 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) /* boards that don't have VBUS sensing can't autogate 48MHz; * can't enter deep sleep while a gadget driver is active. */ - if (machine_is_omap_innovator() || machine_is_omap_osk()) + if (machine_needs_vbus_session()) omap_vbus_session(&udc->gadget, 1); done: + if (udc->dc_clk != NULL) + omap_udc_enable_clock(0); return status; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -2117,10 +2174,13 @@ 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()) + if (udc->dc_clk != NULL) + omap_udc_enable_clock(1); + + if (machine_needs_vbus_session()) omap_vbus_session(&udc->gadget, 0); if (udc->transceiver) @@ -2136,6 +2196,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) udc->gadget.dev.driver = NULL; udc->driver = NULL; + if (udc->dc_clk != NULL) + omap_udc_enable_clock(0); DBG("unregistered driver '%s'\n", driver->driver.name); return status; } @@ -2218,7 +2280,7 @@ static char *trx_mode(unsigned m, int enabled) case 0: return enabled ? "*6wire" : "unused"; case 1: return "4wire"; case 2: return "3wire"; - case 3: return "6wire"; + case 3: return "6wire"; default: return "unknown"; } } @@ -2227,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s) { u32 tmp; u32 trans; + char *ctrl_name; tmp = OTG_REV_REG; - trans = USB_TRANSCEIVER_CTRL_REG; - seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n", - tmp >> 4, tmp & 0xf, trans); + if (cpu_is_omap24xx()) { + ctrl_name = "control_devconf"; + trans = CONTROL_DEVCONF_REG; + } else { + ctrl_name = "tranceiver_ctrl"; + trans = USB_TRANSCEIVER_CTRL_REG; + } + seq_printf(s, "\nOTG rev %d.%d, %s %05x\n", + tmp >> 4, tmp & 0xf, ctrl_name, trans); tmp = OTG_SYSCON_1_REG; seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s," FOURBITS "\n", tmp, @@ -2306,7 +2375,7 @@ static int proc_udc_show(struct seq_file *s, void *_) driver_desc, use_dma ? " (dma)" : ""); - tmp = UDC_REV_REG & 0xff; + tmp = UDC_REV_REG & 0xff; seq_printf(s, "UDC rev %d.%d, fifo mode %d, gadget %s\n" "hmc %d, transceiver %s\n", @@ -2314,11 +2383,16 @@ static int proc_udc_show(struct seq_file *s, void *_) fifo_mode, udc->driver ? udc->driver->driver.name : "(none)", HMC, - udc->transceiver ? udc->transceiver->label : "(none)"); - seq_printf(s, "ULPD control %04x req %04x status %04x\n", - __REG16(ULPD_CLOCK_CTRL), - __REG16(ULPD_SOFT_REQ), - __REG16(ULPD_STATUS_REQ)); + udc->transceiver + ? udc->transceiver->label + : ((cpu_is_omap1710() || cpu_is_omap24xx()) + ? "external" : "(none)")); + if (cpu_class_is_omap1()) { + seq_printf(s, "ULPD control %04x req %04x status %04x\n", + __REG16(ULPD_CLOCK_CTRL), + __REG16(ULPD_SOFT_REQ), + __REG16(ULPD_STATUS_REQ)); + } /* OTG controller registers */ if (!cpu_is_omap15xx()) @@ -2503,9 +2577,10 @@ omap_ep_setup(char *name, u8 addr, u8 type, dbuf = 1; } else { /* double-buffering "not supported" on 15xx, - * and ignored for PIO-IN on 16xx + * and ignored for PIO-IN on newer chips + * (for more reliable behavior) */ - if (!use_dma || cpu_is_omap15xx()) + if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx()) dbuf = 0; switch (maxp) { @@ -2548,7 +2623,7 @@ omap_ep_setup(char *name, u8 addr, u8 type, ep->bEndpointAddress = addr; ep->bmAttributes = type; ep->double_buf = dbuf; - ep->udc = udc; + ep->udc = udc; ep->ep.name = ep->name; ep->ep.ops = &omap_ep_ops; @@ -2708,15 +2783,37 @@ static int __init omap_udc_probe(struct platform_device *pdev) struct otg_transceiver *xceiv = NULL; const char *type = NULL; struct omap_usb_config *config = pdev->dev.platform_data; + struct clk *dc_clk; + struct clk *hhc_clk; /* NOTE: "knows" the order of the resources! */ - if (!request_mem_region(pdev->resource[0].start, + if (!request_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1, driver_name)) { DBG("request_mem_region failed\n"); return -EBUSY; } + if (cpu_is_omap16xx()) { + dc_clk = clk_get(&pdev->dev, "usb_dc_ck"); + hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck"); + BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); + /* can't use omap_udc_enable_clock yet */ + clk_enable(dc_clk); + clk_enable(hhc_clk); + udelay(100); + } + + if (cpu_is_omap24xx()) { + dc_clk = clk_get(&pdev->dev, "usb_fck"); + hhc_clk = clk_get(&pdev->dev, "usb_l4_ick"); + BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); + /* can't use omap_udc_enable_clock yet */ + clk_enable(dc_clk); + clk_enable(hhc_clk); + udelay(100); + } + INFO("OMAP UDC rev %d.%d%s\n", UDC_REV_REG >> 4, UDC_REV_REG & 0xf, config->otg ? ", Mini-AB" : ""); @@ -2726,7 +2823,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) hmc = HMC_1510; type = "(unknown)"; - if (machine_is_omap_innovator()) { + if (machine_is_omap_innovator() || machine_is_sx1()) { /* just set up software VBUS detect, and then * later rig it so we always report VBUS. * FIXME without really sensing VBUS, we can't @@ -2755,6 +2852,15 @@ static int __init omap_udc_probe(struct platform_device *pdev) } hmc = HMC_1610; + + if (cpu_is_omap24xx()) { + /* this could be transceiverless in one of the + * "we don't need to know" modes. + */ + type = "external"; + goto known; + } + switch (hmc) { case 0: /* POWERUP DEFAULT == 0 */ case 4: @@ -2793,6 +2899,7 @@ bad_on_1710: goto cleanup0; } } +known: INFO("hmc mode %d, %s transceiver\n", hmc, type); /* a "gadget" abstracts/virtualizes the controller */ @@ -2817,8 +2924,8 @@ bad_on_1710: status = request_irq(pdev->resource[1].start, omap_udc_irq, IRQF_SAMPLE_RANDOM, driver_name, udc); if (status != 0) { - ERR( "can't get irq %ld, err %d\n", - pdev->resource[1].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[1].start, status); goto cleanup1; } @@ -2826,24 +2933,41 @@ bad_on_1710: status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, IRQF_SAMPLE_RANDOM, "omap_udc pio", udc); if (status != 0) { - ERR( "can't get irq %ld, err %d\n", - pdev->resource[2].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[2].start, status); goto cleanup2; } #ifdef USE_ISO status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, IRQF_DISABLED, "omap_udc iso", udc); if (status != 0) { - ERR("can't get irq %ld, err %d\n", - pdev->resource[3].start, status); + ERR("can't get irq %d, err %d\n", + (int) pdev->resource[3].start, status); goto cleanup3; } #endif + if (cpu_is_omap16xx()) { + udc->dc_clk = dc_clk; + udc->hhc_clk = hhc_clk; + clk_disable(hhc_clk); + clk_disable(dc_clk); + } + + if (cpu_is_omap24xx()) { + udc->dc_clk = dc_clk; + udc->hhc_clk = hhc_clk; + /* FIXME OMAP2 don't release hhc & dc clock */ +#if 0 + clk_disable(hhc_clk); + clk_disable(dc_clk); +#endif + } create_proc_file(); - device_add(&udc->gadget.dev); - return 0; - + status = device_add(&udc->gadget.dev); + if (!status) + return status; + /* If fail, fall through */ #ifdef USE_ISO cleanup3: free_irq(pdev->resource[2].start, udc); @@ -2859,8 +2983,17 @@ cleanup1: cleanup0: if (xceiv) put_device(xceiv->dev); + + if (cpu_is_omap16xx() || cpu_is_omap24xx()) { + clk_disable(hhc_clk); + clk_disable(dc_clk); + clk_put(hhc_clk); + clk_put(dc_clk); + } + release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); + return status; } @@ -2870,6 +3003,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev) if (!udc) return -ENODEV; + if (udc->driver) + return -EBUSY; udc->done = &done; @@ -2888,6 +3023,13 @@ static int __exit omap_udc_remove(struct platform_device *pdev) free_irq(pdev->resource[2].start, udc); free_irq(pdev->resource[1].start, udc); + if (udc->dc_clk) { + if (udc->clk_requested) + omap_udc_enable_clock(0); + clk_put(udc->hhc_clk); + clk_put(udc->dc_clk); + } + release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h index 652ee462734..1dc398bb9ab 100644 --- a/drivers/usb/gadget/omap_udc.h +++ b/drivers/usb/gadget/omap_udc.h @@ -175,6 +175,9 @@ struct omap_udc { unsigned ep0_reset_config:1; unsigned ep0_setup:1; struct completion *done; + struct clk *dc_clk; + struct clk *hhc_clk; + unsigned clk_requested:1; }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 1ed506e9598..0d225369847 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -56,7 +56,7 @@ #include <asm/arch/pxa-regs.h> #endif -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <asm/arch/udc.h> @@ -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 208e55a667a..6c742a90922 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -43,7 +43,7 @@ #include <asm/unaligned.h> #include <asm/uaccess.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb/cdc.h> #include <linux/usb_gadget.h> @@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty); static void gs_break(struct tty_struct *tty, int break_state); static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void gs_set_termios(struct tty_struct *tty, struct termios *old); +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, @@ -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 = { @@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, /* * gs_set_termios */ -static void gs_set_termios(struct tty_struct *tty, struct termios *old) +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } @@ -2195,7 +2195,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) if (size == 0) return NULL; - gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags); + gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags); if (gb == NULL) return NULL; diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index b1735767660..3459ea6c6c0 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c @@ -14,7 +14,7 @@ #include <linux/device.h> #include <linux/init.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include <asm/unaligned.h> diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 40710ea1b49..ebe04e0d287 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -84,7 +84,7 @@ #include <asm/system.h> #include <asm/unaligned.h> -#include <linux/usb_ch9.h> +#include <linux/usb/ch9.h> #include <linux/usb_gadget.h> #include "gadget_chips.h" |