diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-07-08 22:30:22 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-07-08 22:30:55 (GMT) |
commit | 18fbb93fbec3cfd6acf46f60990f7ab21c4221dd (patch) | |
tree | 19599d4a2d402422b109e720e988ad16bc6e8ab4 /drivers/usb/gadget | |
parent | 3b87218829a4182850cc62f8c0c28abcecfdf8e6 (diff) | |
parent | 156833dc3ca3b730127c4b3045c466cca46c2767 (diff) | |
download | linux-fsl-qoriq-18fbb93fbec3cfd6acf46f60990f7ab21c4221dd.tar.xz |
Merge branch 'for-next' of master.kernel.org:/pub/scm/linux/kernel/git/balbi/usb into usb-next
* 'for-next' of master.kernel.org:/pub/scm/linux/kernel/git/balbi/usb:
usb: gadget: m66592-udc: add pullup function
usb: gadget: m66592-udc: add function for external controller
usb: gadget: r8a66597-udc: add pullup function
usb: gadget: zero: add superspeed support
usb: gadget: add SS descriptors to Ethernet gadget
usb: gadget: r8a66597-udc: add support for TEST_MODE
usb: gadget: m66592-udc: add support for TEST_MODE
usb: gadget: r8a66597-udc: Make BUSWAIT configurable through platform data
usb: gadget: r8a66597-udc: fix cannot connect after rmmod gadget driver
usb: update email address in r8a66597-udc and m66592-udc
usb: musb: restore INDEX register in resume path
usb: gadget: fix up depencies
usb: gadget: fusb300_udc: fix compile warnings
usb: gadget: ci13xx_udc.c: fix compile warning
usb: gadget: net2272: fix compile warnings
usb: gadget: langwell_udc: fix compile warnings
usb: gadget: fusb300_udc: drop dead code
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/ci13xxx_udc.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/ether.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/f_ecm.c | 100 | ||||
-rw-r--r-- | drivers/usb/gadget/f_eem.c | 56 | ||||
-rw-r--r-- | drivers/usb/gadget/f_loopback.c | 55 | ||||
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 101 | ||||
-rw-r--r-- | drivers/usb/gadget/f_sourcesink.c | 55 | ||||
-rw-r--r-- | drivers/usb/gadget/f_subset.c | 64 | ||||
-rw-r--r-- | drivers/usb/gadget/fusb300_udc.c | 91 | ||||
-rw-r--r-- | drivers/usb/gadget/langwell_udc.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/m66592-udc.c | 45 | ||||
-rw-r--r-- | drivers/usb/gadget/m66592-udc.h | 40 | ||||
-rw-r--r-- | drivers/usb/gadget/net2272.c | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/r8a66597-udc.c | 57 | ||||
-rw-r--r-- | drivers/usb/gadget/r8a66597-udc.h | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/u_ether.c | 12 | ||||
-rw-r--r-- | drivers/usb/gadget/zero.c | 2 |
18 files changed, 574 insertions, 142 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b5b8d67..44b6b40 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -157,6 +157,7 @@ config USB_FSL_USB2 config USB_FUSB300 tristate "Faraday FUSB300 USB Peripheral Controller" + depends on !PHYS_ADDR_T_64BIT select USB_GADGET_DUALSPEED help Faraday usb device controller FUSB300 driver @@ -427,6 +428,7 @@ config USB_GOKU config USB_LANGWELL tristate "Intel Langwell USB Device Controller" depends on PCI + depends on !PHYS_ADDR_T_64BIT select USB_GADGET_DUALSPEED help Intel Langwell USB Device Controller is a High-Speed USB diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 0824716..1265a85 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -1214,12 +1214,13 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); * * Check "device.h" for details */ +#define DUMP_ENTRIES 512 static ssize_t show_registers(struct device *dev, struct device_attribute *attr, char *buf) { struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); unsigned long flags; - u32 dump[512]; + u32 *dump; unsigned i, k, n = 0; dbg_trace("[%s] %p\n", __func__, buf); @@ -1228,8 +1229,14 @@ static ssize_t show_registers(struct device *dev, return 0; } + dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL); + if (!dump) { + dev_err(dev, "%s: out of memory\n", __func__); + return 0; + } + spin_lock_irqsave(udc->lock, flags); - k = hw_register_read(dump, sizeof(dump)/sizeof(u32)); + k = hw_register_read(dump, DUMP_ENTRIES); spin_unlock_irqrestore(udc->lock, flags); for (i = 0; i < k; i++) { @@ -1237,6 +1244,7 @@ static ssize_t show_registers(struct device *dev, "reg[0x%04X] = 0x%08X\n", i * (unsigned)sizeof(u32), dump[i]); } + kfree(dump); return n; } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index ac41858..aafc84f 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -401,7 +401,7 @@ static struct usb_composite_driver eth_driver = { .name = "g_ether", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .unbind = __exit_p(eth_unbind), }; diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index ddedbc83..3691a0c 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -77,10 +77,12 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f) /* peak (theoretical) bulk transfer rate in bits-per-second */ static inline unsigned ecm_bitrate(struct usb_gadget *g) { - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return 13 * 1024 * 8 * 1000 * 8; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return 13 * 512 * 8 * 1000 * 8; else - return 19 * 64 * 1 * 1000 * 8; + return 19 * 64 * 1 * 1000 * 8; } /*-------------------------------------------------------------------------*/ @@ -210,8 +212,10 @@ static struct usb_descriptor_header *ecm_fs_function[] = { (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, (struct usb_descriptor_header *) &ecm_desc, + /* NOTE: status endpoint might need to be removed */ (struct usb_descriptor_header *) &fs_ecm_notify_desc, + /* data interface, altsettings 0 and 1 */ (struct usb_descriptor_header *) &ecm_data_nop_intf, (struct usb_descriptor_header *) &ecm_data_intf, @@ -231,6 +235,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = { .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; + static struct usb_endpoint_descriptor hs_ecm_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -255,8 +260,10 @@ static struct usb_descriptor_header *ecm_hs_function[] = { (struct usb_descriptor_header *) &ecm_header_desc, (struct usb_descriptor_header *) &ecm_union_desc, (struct usb_descriptor_header *) &ecm_desc, + /* NOTE: status endpoint might need to be removed */ (struct usb_descriptor_header *) &hs_ecm_notify_desc, + /* data interface, altsettings 0 and 1 */ (struct usb_descriptor_header *) &ecm_data_nop_intf, (struct usb_descriptor_header *) &ecm_data_intf, @@ -265,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_ecm_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; + +static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = { + .bLength = sizeof ss_ecm_intr_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 3 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ + .wBytesPerInterval = cpu_to_le16(ECM_STATUS_BYTECOUNT), +}; + +static struct usb_endpoint_descriptor ss_ecm_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_ecm_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = { + .bLength = sizeof ss_ecm_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 2 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ +}; + +static struct usb_descriptor_header *ecm_ss_function[] = { + /* CDC ECM control descriptors */ + (struct usb_descriptor_header *) &ecm_control_intf, + (struct usb_descriptor_header *) &ecm_header_desc, + (struct usb_descriptor_header *) &ecm_union_desc, + (struct usb_descriptor_header *) &ecm_desc, + + /* NOTE: status endpoint might need to be removed */ + (struct usb_descriptor_header *) &ss_ecm_notify_desc, + (struct usb_descriptor_header *) &ss_ecm_intr_comp_desc, + + /* data interface, altsettings 0 and 1 */ + (struct usb_descriptor_header *) &ecm_data_nop_intf, + (struct usb_descriptor_header *) &ecm_data_intf, + (struct usb_descriptor_header *) &ss_ecm_in_desc, + (struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc, + (struct usb_descriptor_header *) &ss_ecm_out_desc, + (struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ static struct usb_string ecm_string_defs[] = { @@ -679,6 +756,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) goto fail; } + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_ecm_in_desc.bEndpointAddress = + fs_ecm_in_desc.bEndpointAddress; + ss_ecm_out_desc.bEndpointAddress = + fs_ecm_out_desc.bEndpointAddress; + ss_ecm_notify_desc.bEndpointAddress = + fs_ecm_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(ecm_ss_function); + if (!f->ss_descriptors) + goto fail; + } + /* NOTE: all that is done without knowing or caring about * the network link ... which is unavailable to this code * until we're activated via set_alt(). @@ -688,6 +779,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) ecm->port.close = ecm_close; DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n", + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", ecm->port.in_ep->name, ecm->port.out_ep->name, ecm->notify->name); @@ -696,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) fail: if (f->descriptors) usb_free_descriptors(f->descriptors); + if (f->hs_descriptors) + usb_free_descriptors(f->hs_descriptors); if (ecm->notify_req) { kfree(ecm->notify_req->buf); @@ -722,6 +816,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f) DBG(c->cdev, "ecm unbind\n"); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 3e41274..046c6d0 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -115,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { + .bLength = sizeof eem_ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 2 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ +}; + +static struct usb_descriptor_header *eem_ss_function[] __initdata = { + /* CDC EEM control descriptors */ + (struct usb_descriptor_header *) &eem_intf, + (struct usb_descriptor_header *) &eem_ss_in_desc, + (struct usb_descriptor_header *) &eem_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &eem_ss_out_desc, + (struct usb_descriptor_header *) &eem_ss_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ static struct usb_string eem_string_defs[] = { @@ -265,7 +304,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) goto fail; } + if (gadget_is_superspeed(c->cdev->gadget)) { + eem_ss_in_desc.bEndpointAddress = + eem_fs_in_desc.bEndpointAddress; + eem_ss_out_desc.bEndpointAddress = + eem_fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(eem_ss_function); + if (!f->ss_descriptors) + goto fail; + } + DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n", + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", eem->port.in_ep->name, eem->port.out_ep->name); return 0; @@ -273,6 +325,8 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) fail: if (f->descriptors) usb_free_descriptors(f->descriptors); + if (f->hs_descriptors) + usb_free_descriptors(f->hs_descriptors); /* we might as well release our claims on endpoints */ if (eem->port.out_ep->desc) @@ -292,6 +346,8 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f) DBG(c->cdev, "eem unbind\n"); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 3756326..ca660d4 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -118,6 +118,49 @@ static struct usb_descriptor_header *hs_loopback_descs[] = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_loop_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, +}; + +static struct usb_endpoint_descriptor ss_loop_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, +}; + +static struct usb_descriptor_header *ss_loopback_descs[] = { + (struct usb_descriptor_header *) &loopback_intf, + (struct usb_descriptor_header *) &ss_loop_source_desc, + (struct usb_descriptor_header *) &ss_loop_source_comp_desc, + (struct usb_descriptor_header *) &ss_loop_sink_desc, + (struct usb_descriptor_header *) &ss_loop_sink_comp_desc, + NULL, +}; + /* function-specific strings: */ static struct usb_string strings_loopback[] = { @@ -175,8 +218,18 @@ autoconf_fail: f->hs_descriptors = hs_loopback_descs; } + /* support super speed hardware */ + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_loop_source_desc.bEndpointAddress = + fs_loop_source_desc.bEndpointAddress; + ss_loop_sink_desc.bEndpointAddress = + fs_loop_sink_desc.bEndpointAddress; + f->ss_descriptors = ss_loopback_descs; + } + DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", - gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + (gadget_is_superspeed(c->cdev->gadget) ? "super" : + (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), f->name, loop->in_ep->name, loop->out_ep->name); return 0; } diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index b324efa..8f3eae9 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -95,10 +95,12 @@ static inline struct f_rndis *func_to_rndis(struct usb_function *f) /* peak (theoretical) bulk transfer rate in bits-per-second */ static unsigned int bitrate(struct usb_gadget *g) { - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return 13 * 1024 * 8 * 1000 * 8; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return 13 * 512 * 8 * 1000 * 8; else - return 19 * 64 * 1 * 1000 * 8; + return 19 * 64 * 1 * 1000 * 8; } /*-------------------------------------------------------------------------*/ @@ -216,6 +218,7 @@ static struct usb_endpoint_descriptor fs_out_desc = { static struct usb_descriptor_header *eth_fs_function[] = { (struct usb_descriptor_header *) &rndis_iad_descriptor, + /* control interface matches ACM, not Ethernet */ (struct usb_descriptor_header *) &rndis_control_intf, (struct usb_descriptor_header *) &header_desc, @@ -223,6 +226,7 @@ static struct usb_descriptor_header *eth_fs_function[] = { (struct usb_descriptor_header *) &rndis_acm_descriptor, (struct usb_descriptor_header *) &rndis_union_desc, (struct usb_descriptor_header *) &fs_notify_desc, + /* data interface has no altsetting */ (struct usb_descriptor_header *) &rndis_data_intf, (struct usb_descriptor_header *) &fs_in_desc, @@ -241,6 +245,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = { .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; + static struct usb_endpoint_descriptor hs_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -261,6 +266,7 @@ static struct usb_endpoint_descriptor hs_out_desc = { static struct usb_descriptor_header *eth_hs_function[] = { (struct usb_descriptor_header *) &rndis_iad_descriptor, + /* control interface matches ACM, not Ethernet */ (struct usb_descriptor_header *) &rndis_control_intf, (struct usb_descriptor_header *) &header_desc, @@ -268,6 +274,7 @@ static struct usb_descriptor_header *eth_hs_function[] = { (struct usb_descriptor_header *) &rndis_acm_descriptor, (struct usb_descriptor_header *) &rndis_union_desc, (struct usb_descriptor_header *) &hs_notify_desc, + /* data interface has no altsetting */ (struct usb_descriptor_header *) &rndis_data_intf, (struct usb_descriptor_header *) &hs_in_desc, @@ -275,6 +282,76 @@ static struct usb_descriptor_header *eth_hs_function[] = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; + +static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = { + .bLength = sizeof ss_intr_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 3 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ + .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), +}; + +static struct usb_endpoint_descriptor ss_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = { + .bLength = sizeof ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 2 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ +}; + +static struct usb_descriptor_header *eth_ss_function[] = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, + + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &ss_notify_desc, + (struct usb_descriptor_header *) &ss_intr_comp_desc, + + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &ss_in_desc, + (struct usb_descriptor_header *) &ss_bulk_comp_desc, + (struct usb_descriptor_header *) &ss_out_desc, + (struct usb_descriptor_header *) &ss_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ static struct usb_string rndis_string_defs[] = { @@ -670,11 +747,24 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(eth_hs_function); - if (!f->hs_descriptors) goto fail; } + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + ss_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + ss_notify_desc.bEndpointAddress = + fs_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(eth_ss_function); + if (!f->ss_descriptors) + goto fail; + } + rndis->port.open = rndis_open; rndis->port.close = rndis_close; @@ -699,12 +789,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) */ DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n", + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", rndis->port.in_ep->name, rndis->port.out_ep->name, rndis->notify->name); return 0; fail: + if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors) + usb_free_descriptors(f->ss_descriptors); if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors) usb_free_descriptors(f->hs_descriptors); if (f->descriptors) @@ -736,6 +829,8 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f) rndis_deregister(rndis->config); rndis_exit(); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 5a92883..e18b4f5 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -131,6 +131,49 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +struct usb_ss_ep_comp_descriptor ss_source_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, +}; + +static struct usb_endpoint_descriptor ss_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = { + .bLength = USB_DT_SS_EP_COMP_SIZE, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = 0, +}; + +static struct usb_descriptor_header *ss_source_sink_descs[] = { + (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &ss_source_desc, + (struct usb_descriptor_header *) &ss_source_comp_desc, + (struct usb_descriptor_header *) &ss_sink_desc, + (struct usb_descriptor_header *) &ss_sink_comp_desc, + NULL, +}; + /* function-specific strings: */ static struct usb_string strings_sourcesink[] = { @@ -187,8 +230,18 @@ autoconf_fail: f->hs_descriptors = hs_source_sink_descs; } + /* support super speed hardware */ + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_source_desc.bEndpointAddress = + fs_source_desc.bEndpointAddress; + ss_sink_desc.bEndpointAddress = + fs_sink_desc.bEndpointAddress; + f->ss_descriptors = ss_source_sink_descs; + } + DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", - gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + (gadget_is_superspeed(c->cdev->gadget) ? "super" : + (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), f->name, ss->in_ep->name, ss->out_ep->name); return 0; } diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 93bf676..3dc5375 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -201,6 +201,46 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = { NULL, }; +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = { + .bLength = sizeof ss_subset_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 2 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ +}; + +static struct usb_descriptor_header *ss_eth_function[] __initdata = { + (struct usb_descriptor_header *) &subset_data_intf, + (struct usb_descriptor_header *) &mdlm_header_desc, + (struct usb_descriptor_header *) &mdlm_desc, + (struct usb_descriptor_header *) &mdlm_detail_desc, + (struct usb_descriptor_header *) ðer_desc, + (struct usb_descriptor_header *) &ss_subset_in_desc, + (struct usb_descriptor_header *) &ss_subset_bulk_comp_desc, + (struct usb_descriptor_header *) &ss_subset_out_desc, + (struct usb_descriptor_header *) &ss_subset_bulk_comp_desc, + NULL, +}; + /* string descriptors: */ static struct usb_string geth_string_defs[] = { @@ -290,6 +330,8 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) /* copy descriptors, and track endpoint copies */ f->descriptors = usb_copy_descriptors(fs_eth_function); + if (!f->descriptors) + goto fail; /* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at @@ -303,6 +345,20 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(hs_eth_function); + if (!f->hs_descriptors) + goto fail; + } + + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_subset_in_desc.bEndpointAddress = + fs_subset_in_desc.bEndpointAddress; + ss_subset_out_desc.bEndpointAddress = + fs_subset_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(ss_eth_function); + if (!f->ss_descriptors) + goto fail; } /* NOTE: all that is done without knowing or caring about @@ -311,11 +367,17 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) */ DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n", + gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", geth->port.in_ep->name, geth->port.out_ep->name); return 0; fail: + if (f->descriptors) + usb_free_descriptors(f->descriptors); + if (f->hs_descriptors) + usb_free_descriptors(f->hs_descriptors); + /* we might as well release our claims on endpoints */ if (geth->port.out_ep->desc) geth->port.out_ep->driver_data = NULL; @@ -330,6 +392,8 @@ fail: static void geth_unbind(struct usb_configuration *c, struct usb_function *f) { + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_descriptors(f->hs_descriptors); usb_free_descriptors(f->descriptors); diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 06353e7..24a9243 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -767,56 +767,6 @@ static void fusb300_rdfifo(struct fusb300_ep *ep, } while (!reg); } -/* write data to fifo */ -static void fusb300_wrfifo(struct fusb300_ep *ep, - struct fusb300_request *req) -{ - int i = 0; - u8 *tmp; - u32 data, reg; - struct fusb300 *fusb300 = ep->fusb300; - - tmp = req->req.buf; - req->req.actual = req->req.length; - - for (i = (req->req.length >> 2); i > 0; i--) { - data = *tmp | *(tmp + 1) << 8 | - *(tmp + 2) << 16 | *(tmp + 3) << 24; - - iowrite32(data, fusb300->reg + - FUSB300_OFFSET_EPPORT(ep->epnum)); - tmp += 4; - } - - switch (req->req.length % 4) { - case 1: - data = *tmp; - iowrite32(data, fusb300->reg + - FUSB300_OFFSET_EPPORT(ep->epnum)); - break; - case 2: - data = *tmp | *(tmp + 1) << 8; - iowrite32(data, fusb300->reg + - FUSB300_OFFSET_EPPORT(ep->epnum)); - break; - case 3: - data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16; - iowrite32(data, fusb300->reg + - FUSB300_OFFSET_EPPORT(ep->epnum)); - break; - default: - break; - } - - do { - reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1); - reg &= FUSB300_IGR1_SYNF0_EMPTY_INT; - if (i) - printk(KERN_INFO"sync fifo is not empty!\n"); - i++; - } while (!reg); -} - static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep) { u8 value; @@ -1024,17 +974,6 @@ static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl) return ret; } -static void fusb300_set_ep_bycnt(struct fusb300_ep *ep, u32 bycnt) -{ - struct fusb300 *fusb300 = ep->fusb300; - u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum)); - - reg &= ~FUSB300_FFR_BYCNT; - reg |= bycnt & FUSB300_FFR_BYCNT; - - iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum)); -} - static void done(struct fusb300_ep *ep, struct fusb300_request *req, int status) { @@ -1058,8 +997,8 @@ static void done(struct fusb300_ep *ep, struct fusb300_request *req, fusb300_set_cxdone(ep->fusb300); } -void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, - struct fusb300_request *req) +static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d, + u32 len) { u32 value; u32 reg; @@ -1071,10 +1010,9 @@ void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, reg &= FUSB300_EPPRD0_H; } while (reg); - iowrite32((u32) req->req.buf, ep->fusb300->reg + - FUSB300_OFFSET_EPPRD_W1(ep->epnum)); + iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum)); - value = FUSB300_EPPRD0_BTC(req->req.length) | FUSB300_EPPRD0_H | + value = FUSB300_EPPRD0_BTC(len) | FUSB300_EPPRD0_H | FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I; iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum)); @@ -1111,13 +1049,12 @@ static void fusb300_set_idma(struct fusb300_ep *ep, struct fusb300_request *req) { dma_addr_t d; - u8 *tmp = NULL; d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE); if (dma_mapping_error(NULL, d)) { - kfree(req->req.buf); printk(KERN_DEBUG "dma_mapping_error\n"); + return; } dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE); @@ -1125,17 +1062,11 @@ static void fusb300_set_idma(struct fusb300_ep *ep, fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0, FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); - tmp = req->req.buf; - req->req.buf = (u8 *)d; - - fusb300_fill_idma_prdtbl(ep, req); + fusb300_fill_idma_prdtbl(ep, d, req->req.length); /* check idma is done */ fusb300_wait_idma_finished(ep); - req->req.buf = tmp; - - if (d) - dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE); + dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE); } static void in_ep_fifo_handler(struct fusb300_ep *ep) @@ -1143,14 +1074,8 @@ static void in_ep_fifo_handler(struct fusb300_ep *ep) struct fusb300_request *req = list_entry(ep->queue.next, struct fusb300_request, queue); - if (req->req.length) { -#if 0 - fusb300_set_ep_bycnt(ep, req->req.length); - fusb300_wrfifo(ep, req); -#else + if (req->req.length) fusb300_set_idma(ep, req); -#endif - } done(ep, req, 0); } diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index d8403ae..a06e2c2 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -593,8 +593,8 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req) /* ep0 */ dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep)); - dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n", - i, (u32)&(dev->ep_dqh[i])); + dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n", + i, &(dev->ep_dqh[i])); bit_mask = is_in(ep) ? (1 << (ep->ep_num + 16)) : (1 << (ep->ep_num)); @@ -3271,7 +3271,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, /* allocate device dQH memory */ size = dev->ep_max * sizeof(struct langwell_dqh); - dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); + dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size); if (size < DQH_ALIGNMENT) size = DQH_ALIGNMENT; else if ((size % DQH_ALIGNMENT) != 0) { @@ -3286,7 +3286,7 @@ static int langwell_udc_probe(struct pci_dev *pdev, goto error; } dev->ep_dqh_size = size; - dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size); /* initialize ep0 status request structure */ dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL); @@ -3470,7 +3470,7 @@ static int langwell_udc_resume(struct pci_dev *pdev) /* allocate device dQH memory */ size = dev->ep_max * sizeof(struct langwell_dqh); - dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); + dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size); if (size < DQH_ALIGNMENT) size = DQH_ALIGNMENT; else if ((size % DQH_ALIGNMENT) != 0) { @@ -3484,7 +3484,7 @@ static int langwell_udc_resume(struct pci_dev *pdev) return -ENOMEM; } dev->ep_dqh_size = size; - dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size); /* create dTD dma_pool resource */ dev->dtd_pool = dma_pool_create("langwell_dtd", diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 11d3782..491f825 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -3,7 +3,7 @@ * * Copyright (C) 2006-2007 Renesas Solutions Corp. * - * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> + * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -691,6 +691,7 @@ static void init_controller(struct m66592 *m66592) static void disable_controller(struct m66592 *m66592) { + m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE); if (!m66592->pdata->on_chip) { m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); udelay(1); @@ -780,7 +781,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req) /* write fifo */ if (req->req.buf) { if (size > 0) - m66592_write_fifo(m66592, ep->fifoaddr, buf, size); + m66592_write_fifo(m66592, ep, buf, size); if ((size == 0) || ((size % ep->ep.maxpacket) != 0)) m66592_bset(m66592, M66592_BVAL, ep->fifoctr); } @@ -826,7 +827,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req) /* write fifo */ if (req->req.buf) { - m66592_write_fifo(m66592, ep->fifoaddr, buf, size); + m66592_write_fifo(m66592, ep, buf, size); if ((size == 0) || ((size % ep->ep.maxpacket) != 0) || ((bufsize != ep->ep.maxpacket) @@ -1048,10 +1049,30 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) { + u16 tmp; + int timeout = 3000; switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - control_end(m66592, 1); + switch (le16_to_cpu(ctrl->wValue)) { + case USB_DEVICE_TEST_MODE: + control_end(m66592, 1); + /* Wait for the completion of status stage */ + do { + tmp = m66592_read(m66592, M66592_INTSTS0) & + M66592_CTSQ; + udelay(1); + } while (tmp != M66592_CS_IDST || timeout-- > 0); + + if (tmp == M66592_CS_IDST) + m66592_bset(m66592, + le16_to_cpu(ctrl->wIndex >> 8), + M66592_TESTMODE); + break; + default: + pipe_stall(m66592, 0); + break; + } break; case USB_RECIP_INTERFACE: control_end(m66592, 1); @@ -1540,10 +1561,26 @@ static int m66592_get_frame(struct usb_gadget *_gadget) return m66592_read(m66592, M66592_FRMNUM) & 0x03FF; } +static int m66592_pullup(struct usb_gadget *gadget, int is_on) +{ + struct m66592 *m66592 = gadget_to_m66592(gadget); + unsigned long flags; + + spin_lock_irqsave(&m66592->lock, flags); + if (is_on) + m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG); + else + m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); + spin_unlock_irqrestore(&m66592->lock, flags); + + return 0; +} + static struct usb_gadget_ops m66592_gadget_ops = { .get_frame = m66592_get_frame, .start = m66592_start, .stop = m66592_stop, + .pullup = m66592_pullup, }; static int __exit m66592_remove(struct platform_device *pdev) diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index c3caf1a..7b93d57 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -3,7 +3,7 @@ * * Copyright (C) 2006-2007 Renesas Solutions Corp. * - * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> + * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -561,11 +561,26 @@ static inline void m66592_write(struct m66592 *m66592, u16 val, iowrite16(val, m66592->reg + offset); } +static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, + unsigned long offset) +{ + u16 tmp; + tmp = m66592_read(m66592, offset); + tmp = tmp & (~pat); + tmp = tmp | val; + m66592_write(m66592, tmp, offset); +} + +#define m66592_bclr(m66592, val, offset) \ + m66592_mdfy(m66592, 0, val, offset) +#define m66592_bset(m66592, val, offset) \ + m66592_mdfy(m66592, val, 0, offset) + static inline void m66592_write_fifo(struct m66592 *m66592, - unsigned long offset, + struct m66592_ep *ep, void *buf, unsigned long len) { - void __iomem *fifoaddr = m66592->reg + offset; + void __iomem *fifoaddr = m66592->reg + ep->fifoaddr; if (m66592->pdata->on_chip) { unsigned long count; @@ -591,26 +606,15 @@ static inline void m66592_write_fifo(struct m66592 *m66592, iowrite16_rep(fifoaddr, buf, len); if (odd) { unsigned char *p = buf + len*2; + if (m66592->pdata->wr0_shorted_to_wr1) + m66592_bclr(m66592, M66592_MBW_16, ep->fifosel); iowrite8(*p, fifoaddr); + if (m66592->pdata->wr0_shorted_to_wr1) + m66592_bset(m66592, M66592_MBW_16, ep->fifosel); } } } -static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, - unsigned long offset) -{ - u16 tmp; - tmp = m66592_read(m66592, offset); - tmp = tmp & (~pat); - tmp = tmp | val; - m66592_write(m66592, tmp, offset); -} - -#define m66592_bclr(m66592, val, offset) \ - m66592_mdfy(m66592, 0, val, offset) -#define m66592_bset(m66592, val, offset) \ - m66592_mdfy(m66592, val, 0, offset) - #endif /* ifndef __M66592_UDC_H__ */ diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 6065bdf..7c7b0e1 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -737,8 +737,8 @@ net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req) if (req->req.length & 1) return -EINVAL; - dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08x\n", - ep->ep.name, req, req->req.dma); + dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08llx\n", + ep->ep.name, req, (unsigned long long) req->req.dma); net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS); @@ -856,9 +856,9 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->mapped = 1; } - dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08x %s\n", + dev_vdbg(dev->dev, "%s queue req %p, len %d buf %p dma %08llx %s\n", _ep->name, _req, _req->length, _req->buf, - _req->dma, _req->zero ? "zero" : "!zero"); + (unsigned long long) _req->dma, _req->zero ? "zero" : "!zero"); spin_lock_irqsave(&dev->lock, flags); diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index db7a6de..50991e5 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -3,7 +3,7 @@ * * Copyright (C) 2006-2009 Renesas Solutions Corp. * - * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> + * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -576,7 +576,11 @@ static void init_controller(struct r8a66597 *r8a66597) u16 endian = r8a66597->pdata->endian ? BIGEND : 0; if (r8a66597->pdata->on_chip) { - r8a66597_bset(r8a66597, 0x04, SYSCFG1); + if (r8a66597->pdata->buswait) + r8a66597_write(r8a66597, r8a66597->pdata->buswait, + SYSCFG1); + else + r8a66597_write(r8a66597, 0x0f, SYSCFG1); r8a66597_bset(r8a66597, HSE, SYSCFG0); r8a66597_bclr(r8a66597, USBE, SYSCFG0); @@ -618,6 +622,7 @@ static void disable_controller(struct r8a66597 *r8a66597) { if (r8a66597->pdata->on_chip) { r8a66597_bset(r8a66597, SCKE, SYSCFG0); + r8a66597_bclr(r8a66597, UTST, TESTMODE); /* disable interrupts */ r8a66597_write(r8a66597, 0, INTENB0); @@ -635,6 +640,7 @@ static void disable_controller(struct r8a66597 *r8a66597) r8a66597_bclr(r8a66597, SCKE, SYSCFG0); } else { + r8a66597_bclr(r8a66597, UTST, TESTMODE); r8a66597_bclr(r8a66597, SCKE, SYSCFG0); udelay(1); r8a66597_bclr(r8a66597, PLLC, SYSCFG0); @@ -999,10 +1005,29 @@ static void clear_feature(struct r8a66597 *r8a66597, static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl) { + u16 tmp; + int timeout = 3000; switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - control_end(r8a66597, 1); + switch (le16_to_cpu(ctrl->wValue)) { + case USB_DEVICE_TEST_MODE: + control_end(r8a66597, 1); + /* Wait for the completion of status stage */ + do { + tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ; + udelay(1); + } while (tmp != CS_IDST || timeout-- > 0); + + if (tmp == CS_IDST) + r8a66597_bset(r8a66597, + le16_to_cpu(ctrl->wIndex >> 8), + TESTMODE); + break; + default: + pipe_stall(r8a66597, 0); + break; + } break; case USB_RECIP_INTERFACE: control_end(r8a66597, 1); @@ -1444,6 +1469,7 @@ static int r8a66597_start(struct usb_gadget_driver *driver, goto error; } + init_controller(r8a66597); r8a66597_bset(r8a66597, VBSE, INTENB0); if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) { r8a66597_start_xclock(r8a66597); @@ -1474,15 +1500,12 @@ static int r8a66597_stop(struct usb_gadget_driver *driver) spin_lock_irqsave(&r8a66597->lock, flags); if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN) r8a66597_usb_disconnect(r8a66597); - spin_unlock_irqrestore(&r8a66597->lock, flags); - r8a66597_bclr(r8a66597, VBSE, INTENB0); + disable_controller(r8a66597); + spin_unlock_irqrestore(&r8a66597->lock, flags); driver->unbind(&r8a66597->gadget); - init_controller(r8a66597); - disable_controller(r8a66597); - device_del(&r8a66597->gadget.dev); r8a66597->driver = NULL; return 0; @@ -1495,10 +1518,26 @@ static int r8a66597_get_frame(struct usb_gadget *_gadget) return r8a66597_read(r8a66597, FRMNUM) & 0x03FF; } +static int r8a66597_pullup(struct usb_gadget *gadget, int is_on) +{ + struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); + unsigned long flags; + + spin_lock_irqsave(&r8a66597->lock, flags); + if (is_on) + r8a66597_bset(r8a66597, DPRPU, SYSCFG0); + else + r8a66597_bclr(r8a66597, DPRPU, SYSCFG0); + spin_unlock_irqrestore(&r8a66597->lock, flags); + + return 0; +} + static struct usb_gadget_ops r8a66597_gadget_ops = { .get_frame = r8a66597_get_frame, .start = r8a66597_start, .stop = r8a66597_stop, + .pullup = r8a66597_pullup, }; static int __exit r8a66597_remove(struct platform_device *pdev) @@ -1646,8 +1685,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) goto clean_up3; r8a66597->ep0_req->complete = nop_completion; - init_controller(r8a66597); - ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget); if (ret) goto err_add_udc; diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 5fc22e0..503f766 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -3,7 +3,7 @@ * * Copyright (C) 2007-2009 Renesas Solutions Corp. * - * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> + * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index b91363e..dfed4c1 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -97,16 +97,17 @@ struct eth_dev { static unsigned qmult = 5; module_param(qmult, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(qmult, "queue length multiplier at high speed"); +MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed"); #else /* full speed (low speed doesn't do bulk) */ #define qmult 1 #endif -/* for dual-speed hardware, use deeper queues at highspeed */ +/* for dual-speed hardware, use deeper queues at high/super speed */ static inline int qlen(struct usb_gadget *gadget) { - if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH) + if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || + gadget->speed == USB_SPEED_SUPER)) return qmult * DEFAULT_QLEN; else return DEFAULT_QLEN; @@ -598,9 +599,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, req->length = length; - /* throttle highspeed IRQ rate back slightly */ + /* throttle high/super speed IRQ rate back slightly */ if (gadget_is_dualspeed(dev->gadget)) - req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) + req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH || + dev->gadget->speed == USB_SPEED_SUPER) ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) : 0; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index af7e7c3..00e2fd2 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -340,7 +340,7 @@ static struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .unbind = zero_unbind, .suspend = zero_suspend, .resume = zero_resume, |