mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-25 15:53:58 +00:00
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
This commit is contained in:
commit
18fbb93fbe
21 changed files with 580 additions and 142 deletions
|
@ -157,6 +157,7 @@ config USB_FSL_USB2
|
||||||
|
|
||||||
config USB_FUSB300
|
config USB_FUSB300
|
||||||
tristate "Faraday FUSB300 USB Peripheral Controller"
|
tristate "Faraday FUSB300 USB Peripheral Controller"
|
||||||
|
depends on !PHYS_ADDR_T_64BIT
|
||||||
select USB_GADGET_DUALSPEED
|
select USB_GADGET_DUALSPEED
|
||||||
help
|
help
|
||||||
Faraday usb device controller FUSB300 driver
|
Faraday usb device controller FUSB300 driver
|
||||||
|
@ -427,6 +428,7 @@ config USB_GOKU
|
||||||
config USB_LANGWELL
|
config USB_LANGWELL
|
||||||
tristate "Intel Langwell USB Device Controller"
|
tristate "Intel Langwell USB Device Controller"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
depends on !PHYS_ADDR_T_64BIT
|
||||||
select USB_GADGET_DUALSPEED
|
select USB_GADGET_DUALSPEED
|
||||||
help
|
help
|
||||||
Intel Langwell USB Device Controller is a High-Speed USB
|
Intel Langwell USB Device Controller is a High-Speed USB
|
||||||
|
|
|
@ -1214,12 +1214,13 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
|
||||||
*
|
*
|
||||||
* Check "device.h" for details
|
* Check "device.h" for details
|
||||||
*/
|
*/
|
||||||
|
#define DUMP_ENTRIES 512
|
||||||
static ssize_t show_registers(struct device *dev,
|
static ssize_t show_registers(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
|
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 dump[512];
|
u32 *dump;
|
||||||
unsigned i, k, n = 0;
|
unsigned i, k, n = 0;
|
||||||
|
|
||||||
dbg_trace("[%s] %p\n", __func__, buf);
|
dbg_trace("[%s] %p\n", __func__, buf);
|
||||||
|
@ -1228,8 +1229,14 @@ static ssize_t show_registers(struct device *dev,
|
||||||
return 0;
|
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);
|
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);
|
spin_unlock_irqrestore(udc->lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < k; i++) {
|
for (i = 0; i < k; i++) {
|
||||||
|
@ -1237,6 +1244,7 @@ static ssize_t show_registers(struct device *dev,
|
||||||
"reg[0x%04X] = 0x%08X\n",
|
"reg[0x%04X] = 0x%08X\n",
|
||||||
i * (unsigned)sizeof(u32), dump[i]);
|
i * (unsigned)sizeof(u32), dump[i]);
|
||||||
}
|
}
|
||||||
|
kfree(dump);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
|
@ -401,7 +401,7 @@ static struct usb_composite_driver eth_driver = {
|
||||||
.name = "g_ether",
|
.name = "g_ether",
|
||||||
.dev = &device_desc,
|
.dev = &device_desc,
|
||||||
.strings = dev_strings,
|
.strings = dev_strings,
|
||||||
.max_speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_SUPER,
|
||||||
.unbind = __exit_p(eth_unbind),
|
.unbind = __exit_p(eth_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
/* peak (theoretical) bulk transfer rate in bits-per-second */
|
||||||
static inline unsigned ecm_bitrate(struct usb_gadget *g)
|
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;
|
return 13 * 512 * 8 * 1000 * 8;
|
||||||
else
|
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_header_desc,
|
||||||
(struct usb_descriptor_header *) &ecm_union_desc,
|
(struct usb_descriptor_header *) &ecm_union_desc,
|
||||||
(struct usb_descriptor_header *) &ecm_desc,
|
(struct usb_descriptor_header *) &ecm_desc,
|
||||||
|
|
||||||
/* NOTE: status endpoint might need to be removed */
|
/* NOTE: status endpoint might need to be removed */
|
||||||
(struct usb_descriptor_header *) &fs_ecm_notify_desc,
|
(struct usb_descriptor_header *) &fs_ecm_notify_desc,
|
||||||
|
|
||||||
/* data interface, altsettings 0 and 1 */
|
/* data interface, altsettings 0 and 1 */
|
||||||
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
||||||
(struct usb_descriptor_header *) &ecm_data_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),
|
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
|
||||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
|
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.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_header_desc,
|
||||||
(struct usb_descriptor_header *) &ecm_union_desc,
|
(struct usb_descriptor_header *) &ecm_union_desc,
|
||||||
(struct usb_descriptor_header *) &ecm_desc,
|
(struct usb_descriptor_header *) &ecm_desc,
|
||||||
|
|
||||||
/* NOTE: status endpoint might need to be removed */
|
/* NOTE: status endpoint might need to be removed */
|
||||||
(struct usb_descriptor_header *) &hs_ecm_notify_desc,
|
(struct usb_descriptor_header *) &hs_ecm_notify_desc,
|
||||||
|
|
||||||
/* data interface, altsettings 0 and 1 */
|
/* data interface, altsettings 0 and 1 */
|
||||||
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
(struct usb_descriptor_header *) &ecm_data_nop_intf,
|
||||||
(struct usb_descriptor_header *) &ecm_data_intf,
|
(struct usb_descriptor_header *) &ecm_data_intf,
|
||||||
|
@ -265,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
|
||||||
NULL,
|
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: */
|
/* string descriptors: */
|
||||||
|
|
||||||
static struct usb_string ecm_string_defs[] = {
|
static struct usb_string ecm_string_defs[] = {
|
||||||
|
@ -679,6 +756,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
goto fail;
|
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
|
/* NOTE: all that is done without knowing or caring about
|
||||||
* the network link ... which is unavailable to this code
|
* the network link ... which is unavailable to this code
|
||||||
* until we're activated via set_alt().
|
* 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;
|
ecm->port.close = ecm_close;
|
||||||
|
|
||||||
DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
|
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",
|
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||||
ecm->port.in_ep->name, ecm->port.out_ep->name,
|
ecm->port.in_ep->name, ecm->port.out_ep->name,
|
||||||
ecm->notify->name);
|
ecm->notify->name);
|
||||||
|
@ -696,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
fail:
|
fail:
|
||||||
if (f->descriptors)
|
if (f->descriptors)
|
||||||
usb_free_descriptors(f->descriptors);
|
usb_free_descriptors(f->descriptors);
|
||||||
|
if (f->hs_descriptors)
|
||||||
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
|
|
||||||
if (ecm->notify_req) {
|
if (ecm->notify_req) {
|
||||||
kfree(ecm->notify_req->buf);
|
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");
|
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))
|
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
usb_free_descriptors(f->descriptors);
|
usb_free_descriptors(f->descriptors);
|
||||||
|
|
|
@ -115,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = {
|
||||||
NULL,
|
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: */
|
/* string descriptors: */
|
||||||
|
|
||||||
static struct usb_string eem_string_defs[] = {
|
static struct usb_string eem_string_defs[] = {
|
||||||
|
@ -265,7 +304,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
goto fail;
|
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",
|
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",
|
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||||
eem->port.in_ep->name, eem->port.out_ep->name);
|
eem->port.in_ep->name, eem->port.out_ep->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -273,6 +325,8 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
fail:
|
fail:
|
||||||
if (f->descriptors)
|
if (f->descriptors)
|
||||||
usb_free_descriptors(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 */
|
/* we might as well release our claims on endpoints */
|
||||||
if (eem->port.out_ep->desc)
|
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");
|
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))
|
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
usb_free_descriptors(f->descriptors);
|
usb_free_descriptors(f->descriptors);
|
||||||
|
|
|
@ -118,6 +118,49 @@ static struct usb_descriptor_header *hs_loopback_descs[] = {
|
||||||
NULL,
|
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: */
|
/* function-specific strings: */
|
||||||
|
|
||||||
static struct usb_string strings_loopback[] = {
|
static struct usb_string strings_loopback[] = {
|
||||||
|
@ -175,8 +218,18 @@ autoconf_fail:
|
||||||
f->hs_descriptors = hs_loopback_descs;
|
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",
|
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);
|
f->name, loop->in_ep->name, loop->out_ep->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
/* peak (theoretical) bulk transfer rate in bits-per-second */
|
||||||
static unsigned int bitrate(struct usb_gadget *g)
|
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;
|
return 13 * 512 * 8 * 1000 * 8;
|
||||||
else
|
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[] = {
|
static struct usb_descriptor_header *eth_fs_function[] = {
|
||||||
(struct usb_descriptor_header *) &rndis_iad_descriptor,
|
(struct usb_descriptor_header *) &rndis_iad_descriptor,
|
||||||
|
|
||||||
/* control interface matches ACM, not Ethernet */
|
/* control interface matches ACM, not Ethernet */
|
||||||
(struct usb_descriptor_header *) &rndis_control_intf,
|
(struct usb_descriptor_header *) &rndis_control_intf,
|
||||||
(struct usb_descriptor_header *) &header_desc,
|
(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_acm_descriptor,
|
||||||
(struct usb_descriptor_header *) &rndis_union_desc,
|
(struct usb_descriptor_header *) &rndis_union_desc,
|
||||||
(struct usb_descriptor_header *) &fs_notify_desc,
|
(struct usb_descriptor_header *) &fs_notify_desc,
|
||||||
|
|
||||||
/* data interface has no altsetting */
|
/* data interface has no altsetting */
|
||||||
(struct usb_descriptor_header *) &rndis_data_intf,
|
(struct usb_descriptor_header *) &rndis_data_intf,
|
||||||
(struct usb_descriptor_header *) &fs_in_desc,
|
(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),
|
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
|
||||||
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_endpoint_descriptor hs_in_desc = {
|
static struct usb_endpoint_descriptor hs_in_desc = {
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
@ -261,6 +266,7 @@ static struct usb_endpoint_descriptor hs_out_desc = {
|
||||||
|
|
||||||
static struct usb_descriptor_header *eth_hs_function[] = {
|
static struct usb_descriptor_header *eth_hs_function[] = {
|
||||||
(struct usb_descriptor_header *) &rndis_iad_descriptor,
|
(struct usb_descriptor_header *) &rndis_iad_descriptor,
|
||||||
|
|
||||||
/* control interface matches ACM, not Ethernet */
|
/* control interface matches ACM, not Ethernet */
|
||||||
(struct usb_descriptor_header *) &rndis_control_intf,
|
(struct usb_descriptor_header *) &rndis_control_intf,
|
||||||
(struct usb_descriptor_header *) &header_desc,
|
(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_acm_descriptor,
|
||||||
(struct usb_descriptor_header *) &rndis_union_desc,
|
(struct usb_descriptor_header *) &rndis_union_desc,
|
||||||
(struct usb_descriptor_header *) &hs_notify_desc,
|
(struct usb_descriptor_header *) &hs_notify_desc,
|
||||||
|
|
||||||
/* data interface has no altsetting */
|
/* data interface has no altsetting */
|
||||||
(struct usb_descriptor_header *) &rndis_data_intf,
|
(struct usb_descriptor_header *) &rndis_data_intf,
|
||||||
(struct usb_descriptor_header *) &hs_in_desc,
|
(struct usb_descriptor_header *) &hs_in_desc,
|
||||||
|
@ -275,6 +282,76 @@ static struct usb_descriptor_header *eth_hs_function[] = {
|
||||||
NULL,
|
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: */
|
/* string descriptors: */
|
||||||
|
|
||||||
static struct usb_string rndis_string_defs[] = {
|
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 */
|
/* copy descriptors, and track endpoint copies */
|
||||||
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
|
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
|
||||||
|
|
||||||
if (!f->hs_descriptors)
|
if (!f->hs_descriptors)
|
||||||
goto fail;
|
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.open = rndis_open;
|
||||||
rndis->port.close = rndis_close;
|
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",
|
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",
|
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||||
rndis->port.in_ep->name, rndis->port.out_ep->name,
|
rndis->port.in_ep->name, rndis->port.out_ep->name,
|
||||||
rndis->notify->name);
|
rndis->notify->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
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)
|
if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
if (f->descriptors)
|
if (f->descriptors)
|
||||||
|
@ -736,6 +829,8 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||||
rndis_deregister(rndis->config);
|
rndis_deregister(rndis->config);
|
||||||
rndis_exit();
|
rndis_exit();
|
||||||
|
|
||||||
|
if (gadget_is_superspeed(c->cdev->gadget))
|
||||||
|
usb_free_descriptors(f->ss_descriptors);
|
||||||
if (gadget_is_dualspeed(c->cdev->gadget))
|
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
usb_free_descriptors(f->descriptors);
|
usb_free_descriptors(f->descriptors);
|
||||||
|
|
|
@ -131,6 +131,49 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = {
|
||||||
NULL,
|
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: */
|
/* function-specific strings: */
|
||||||
|
|
||||||
static struct usb_string strings_sourcesink[] = {
|
static struct usb_string strings_sourcesink[] = {
|
||||||
|
@ -187,8 +230,18 @@ autoconf_fail:
|
||||||
f->hs_descriptors = hs_source_sink_descs;
|
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",
|
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);
|
f->name, ss->in_ep->name, ss->out_ep->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,46 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = {
|
||||||
NULL,
|
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: */
|
/* string descriptors: */
|
||||||
|
|
||||||
static struct usb_string geth_string_defs[] = {
|
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 */
|
/* copy descriptors, and track endpoint copies */
|
||||||
f->descriptors = usb_copy_descriptors(fs_eth_function);
|
f->descriptors = usb_copy_descriptors(fs_eth_function);
|
||||||
|
if (!f->descriptors)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* support all relevant hardware speeds... we expect that when
|
/* support all relevant hardware speeds... we expect that when
|
||||||
* hardware is dual speed, all bulk-capable endpoints work at
|
* 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 */
|
/* copy descriptors, and track endpoint copies */
|
||||||
f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
|
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
|
/* 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",
|
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",
|
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||||
geth->port.in_ep->name, geth->port.out_ep->name);
|
geth->port.in_ep->name, geth->port.out_ep->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
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 */
|
/* we might as well release our claims on endpoints */
|
||||||
if (geth->port.out_ep->desc)
|
if (geth->port.out_ep->desc)
|
||||||
geth->port.out_ep->driver_data = NULL;
|
geth->port.out_ep->driver_data = NULL;
|
||||||
|
@ -330,6 +392,8 @@ fail:
|
||||||
static void
|
static void
|
||||||
geth_unbind(struct usb_configuration *c, struct usb_function *f)
|
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))
|
if (gadget_is_dualspeed(c->cdev->gadget))
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_descriptors(f->hs_descriptors);
|
||||||
usb_free_descriptors(f->descriptors);
|
usb_free_descriptors(f->descriptors);
|
||||||
|
|
|
@ -767,56 +767,6 @@ static void fusb300_rdfifo(struct fusb300_ep *ep,
|
||||||
} while (!reg);
|
} 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)
|
static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
|
||||||
{
|
{
|
||||||
u8 value;
|
u8 value;
|
||||||
|
@ -1024,17 +974,6 @@ static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
|
||||||
return ret;
|
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,
|
static void done(struct fusb300_ep *ep, struct fusb300_request *req,
|
||||||
int status)
|
int status)
|
||||||
{
|
{
|
||||||
|
@ -1058,8 +997,8 @@ static void done(struct fusb300_ep *ep, struct fusb300_request *req,
|
||||||
fusb300_set_cxdone(ep->fusb300);
|
fusb300_set_cxdone(ep->fusb300);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
|
static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d,
|
||||||
struct fusb300_request *req)
|
u32 len)
|
||||||
{
|
{
|
||||||
u32 value;
|
u32 value;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
@ -1071,10 +1010,9 @@ void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
|
||||||
reg &= FUSB300_EPPRD0_H;
|
reg &= FUSB300_EPPRD0_H;
|
||||||
} while (reg);
|
} while (reg);
|
||||||
|
|
||||||
iowrite32((u32) req->req.buf, ep->fusb300->reg +
|
iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum));
|
||||||
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;
|
FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
|
||||||
iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
|
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)
|
struct fusb300_request *req)
|
||||||
{
|
{
|
||||||
dma_addr_t d;
|
dma_addr_t d;
|
||||||
u8 *tmp = NULL;
|
|
||||||
|
|
||||||
d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
|
d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (dma_mapping_error(NULL, d)) {
|
if (dma_mapping_error(NULL, d)) {
|
||||||
kfree(req->req.buf);
|
|
||||||
printk(KERN_DEBUG "dma_mapping_error\n");
|
printk(KERN_DEBUG "dma_mapping_error\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
|
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_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
|
||||||
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
|
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
|
||||||
|
|
||||||
tmp = req->req.buf;
|
fusb300_fill_idma_prdtbl(ep, d, req->req.length);
|
||||||
req->req.buf = (u8 *)d;
|
|
||||||
|
|
||||||
fusb300_fill_idma_prdtbl(ep, req);
|
|
||||||
/* check idma is done */
|
/* check idma is done */
|
||||||
fusb300_wait_idma_finished(ep);
|
fusb300_wait_idma_finished(ep);
|
||||||
|
|
||||||
req->req.buf = tmp;
|
dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (d)
|
|
||||||
dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void in_ep_fifo_handler(struct fusb300_ep *ep)
|
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 *req = list_entry(ep->queue.next,
|
||||||
struct fusb300_request, queue);
|
struct fusb300_request, queue);
|
||||||
|
|
||||||
if (req->req.length) {
|
if (req->req.length)
|
||||||
#if 0
|
|
||||||
fusb300_set_ep_bycnt(ep, req->req.length);
|
|
||||||
fusb300_wrfifo(ep, req);
|
|
||||||
#else
|
|
||||||
fusb300_set_idma(ep, req);
|
fusb300_set_idma(ep, req);
|
||||||
#endif
|
|
||||||
}
|
|
||||||
done(ep, req, 0);
|
done(ep, req, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -593,8 +593,8 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req)
|
||||||
/* ep0 */
|
/* ep0 */
|
||||||
dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
|
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",
|
dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n",
|
||||||
i, (u32)&(dev->ep_dqh[i]));
|
i, &(dev->ep_dqh[i]));
|
||||||
|
|
||||||
bit_mask = is_in(ep) ?
|
bit_mask = is_in(ep) ?
|
||||||
(1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
|
(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 */
|
/* allocate device dQH memory */
|
||||||
size = dev->ep_max * sizeof(struct langwell_dqh);
|
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)
|
if (size < DQH_ALIGNMENT)
|
||||||
size = DQH_ALIGNMENT;
|
size = DQH_ALIGNMENT;
|
||||||
else if ((size % DQH_ALIGNMENT) != 0) {
|
else if ((size % DQH_ALIGNMENT) != 0) {
|
||||||
|
@ -3286,7 +3286,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
dev->ep_dqh_size = size;
|
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 */
|
/* initialize ep0 status request structure */
|
||||||
dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
|
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 */
|
/* allocate device dQH memory */
|
||||||
size = dev->ep_max * sizeof(struct langwell_dqh);
|
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)
|
if (size < DQH_ALIGNMENT)
|
||||||
size = DQH_ALIGNMENT;
|
size = DQH_ALIGNMENT;
|
||||||
else if ((size % DQH_ALIGNMENT) != 0) {
|
else if ((size % DQH_ALIGNMENT) != 0) {
|
||||||
|
@ -3484,7 +3484,7 @@ static int langwell_udc_resume(struct pci_dev *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
dev->ep_dqh_size = size;
|
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 */
|
/* create dTD dma_pool resource */
|
||||||
dev->dtd_pool = dma_pool_create("langwell_dtd",
|
dev->dtd_pool = dma_pool_create("langwell_dtd",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2007 Renesas Solutions Corp.
|
* 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
|
* 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
|
* 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)
|
static void disable_controller(struct m66592 *m66592)
|
||||||
{
|
{
|
||||||
|
m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
|
||||||
if (!m66592->pdata->on_chip) {
|
if (!m66592->pdata->on_chip) {
|
||||||
m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
|
m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
@ -780,7 +781,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
|
||||||
/* write fifo */
|
/* write fifo */
|
||||||
if (req->req.buf) {
|
if (req->req.buf) {
|
||||||
if (size > 0)
|
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))
|
if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
|
||||||
m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
|
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 */
|
/* write fifo */
|
||||||
if (req->req.buf) {
|
if (req->req.buf) {
|
||||||
m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
|
m66592_write_fifo(m66592, ep, buf, size);
|
||||||
if ((size == 0)
|
if ((size == 0)
|
||||||
|| ((size % ep->ep.maxpacket) != 0)
|
|| ((size % ep->ep.maxpacket) != 0)
|
||||||
|| ((bufsize != ep->ep.maxpacket)
|
|| ((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)
|
static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
|
||||||
{
|
{
|
||||||
|
u16 tmp;
|
||||||
|
int timeout = 3000;
|
||||||
|
|
||||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||||
case USB_RECIP_DEVICE:
|
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;
|
break;
|
||||||
case USB_RECIP_INTERFACE:
|
case USB_RECIP_INTERFACE:
|
||||||
control_end(m66592, 1);
|
control_end(m66592, 1);
|
||||||
|
@ -1540,10 +1561,26 @@ static int m66592_get_frame(struct usb_gadget *_gadget)
|
||||||
return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
|
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 = {
|
static struct usb_gadget_ops m66592_gadget_ops = {
|
||||||
.get_frame = m66592_get_frame,
|
.get_frame = m66592_get_frame,
|
||||||
.start = m66592_start,
|
.start = m66592_start,
|
||||||
.stop = m66592_stop,
|
.stop = m66592_stop,
|
||||||
|
.pullup = m66592_pullup,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __exit m66592_remove(struct platform_device *pdev)
|
static int __exit m66592_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2007 Renesas Solutions Corp.
|
* 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
|
* 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
|
* 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);
|
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,
|
static inline void m66592_write_fifo(struct m66592 *m66592,
|
||||||
unsigned long offset,
|
struct m66592_ep *ep,
|
||||||
void *buf, unsigned long len)
|
void *buf, unsigned long len)
|
||||||
{
|
{
|
||||||
void __iomem *fifoaddr = m66592->reg + offset;
|
void __iomem *fifoaddr = m66592->reg + ep->fifoaddr;
|
||||||
|
|
||||||
if (m66592->pdata->on_chip) {
|
if (m66592->pdata->on_chip) {
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
|
@ -591,26 +606,15 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
|
||||||
iowrite16_rep(fifoaddr, buf, len);
|
iowrite16_rep(fifoaddr, buf, len);
|
||||||
if (odd) {
|
if (odd) {
|
||||||
unsigned char *p = buf + len*2;
|
unsigned char *p = buf + len*2;
|
||||||
|
if (m66592->pdata->wr0_shorted_to_wr1)
|
||||||
|
m66592_bclr(m66592, M66592_MBW_16, ep->fifosel);
|
||||||
iowrite8(*p, fifoaddr);
|
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__ */
|
#endif /* ifndef __M66592_UDC_H__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -737,8 +737,8 @@ net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req)
|
||||||
if (req->req.length & 1)
|
if (req->req.length & 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08x\n",
|
dev_vdbg(ep->dev->dev, "kick_dma %s req %p dma %08llx\n",
|
||||||
ep->ep.name, req, req->req.dma);
|
ep->ep.name, req, (unsigned long long) req->req.dma);
|
||||||
|
|
||||||
net2272_ep_write(ep, EP_RSPSET, 1 << ALT_NAK_OUT_PACKETS);
|
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;
|
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,
|
_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);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2009 Renesas Solutions Corp.
|
* 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
|
* 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
|
* 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;
|
u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
|
||||||
|
|
||||||
if (r8a66597->pdata->on_chip) {
|
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_bset(r8a66597, HSE, SYSCFG0);
|
||||||
|
|
||||||
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
||||||
|
@ -618,6 +622,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
|
||||||
{
|
{
|
||||||
if (r8a66597->pdata->on_chip) {
|
if (r8a66597->pdata->on_chip) {
|
||||||
r8a66597_bset(r8a66597, SCKE, SYSCFG0);
|
r8a66597_bset(r8a66597, SCKE, SYSCFG0);
|
||||||
|
r8a66597_bclr(r8a66597, UTST, TESTMODE);
|
||||||
|
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
r8a66597_write(r8a66597, 0, INTENB0);
|
r8a66597_write(r8a66597, 0, INTENB0);
|
||||||
|
@ -635,6 +640,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
|
||||||
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
|
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
r8a66597_bclr(r8a66597, UTST, TESTMODE);
|
||||||
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
|
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
|
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)
|
static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
|
||||||
{
|
{
|
||||||
|
u16 tmp;
|
||||||
|
int timeout = 3000;
|
||||||
|
|
||||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||||
case USB_RECIP_DEVICE:
|
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;
|
break;
|
||||||
case USB_RECIP_INTERFACE:
|
case USB_RECIP_INTERFACE:
|
||||||
control_end(r8a66597, 1);
|
control_end(r8a66597, 1);
|
||||||
|
@ -1444,6 +1469,7 @@ static int r8a66597_start(struct usb_gadget_driver *driver,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_controller(r8a66597);
|
||||||
r8a66597_bset(r8a66597, VBSE, INTENB0);
|
r8a66597_bset(r8a66597, VBSE, INTENB0);
|
||||||
if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
|
if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
|
||||||
r8a66597_start_xclock(r8a66597);
|
r8a66597_start_xclock(r8a66597);
|
||||||
|
@ -1474,15 +1500,12 @@ static int r8a66597_stop(struct usb_gadget_driver *driver)
|
||||||
spin_lock_irqsave(&r8a66597->lock, flags);
|
spin_lock_irqsave(&r8a66597->lock, flags);
|
||||||
if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN)
|
if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN)
|
||||||
r8a66597_usb_disconnect(r8a66597);
|
r8a66597_usb_disconnect(r8a66597);
|
||||||
|
r8a66597_bclr(r8a66597, VBSE, INTENB0);
|
||||||
|
disable_controller(r8a66597);
|
||||||
spin_unlock_irqrestore(&r8a66597->lock, flags);
|
spin_unlock_irqrestore(&r8a66597->lock, flags);
|
||||||
|
|
||||||
r8a66597_bclr(r8a66597, VBSE, INTENB0);
|
|
||||||
|
|
||||||
driver->unbind(&r8a66597->gadget);
|
driver->unbind(&r8a66597->gadget);
|
||||||
|
|
||||||
init_controller(r8a66597);
|
|
||||||
disable_controller(r8a66597);
|
|
||||||
|
|
||||||
device_del(&r8a66597->gadget.dev);
|
device_del(&r8a66597->gadget.dev);
|
||||||
r8a66597->driver = NULL;
|
r8a66597->driver = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1495,10 +1518,26 @@ static int r8a66597_get_frame(struct usb_gadget *_gadget)
|
||||||
return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
|
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 = {
|
static struct usb_gadget_ops r8a66597_gadget_ops = {
|
||||||
.get_frame = r8a66597_get_frame,
|
.get_frame = r8a66597_get_frame,
|
||||||
.start = r8a66597_start,
|
.start = r8a66597_start,
|
||||||
.stop = r8a66597_stop,
|
.stop = r8a66597_stop,
|
||||||
|
.pullup = r8a66597_pullup,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __exit r8a66597_remove(struct platform_device *pdev)
|
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;
|
goto clean_up3;
|
||||||
r8a66597->ep0_req->complete = nop_completion;
|
r8a66597->ep0_req->complete = nop_completion;
|
||||||
|
|
||||||
init_controller(r8a66597);
|
|
||||||
|
|
||||||
ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
|
ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_add_udc;
|
goto err_add_udc;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009 Renesas Solutions Corp.
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -97,16 +97,17 @@ struct eth_dev {
|
||||||
|
|
||||||
static unsigned qmult = 5;
|
static unsigned qmult = 5;
|
||||||
module_param(qmult, uint, S_IRUGO|S_IWUSR);
|
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) */
|
#else /* full speed (low speed doesn't do bulk) */
|
||||||
#define qmult 1
|
#define qmult 1
|
||||||
#endif
|
#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)
|
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;
|
return qmult * DEFAULT_QLEN;
|
||||||
else
|
else
|
||||||
return DEFAULT_QLEN;
|
return DEFAULT_QLEN;
|
||||||
|
@ -598,9 +599,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
||||||
|
|
||||||
req->length = length;
|
req->length = length;
|
||||||
|
|
||||||
/* throttle highspeed IRQ rate back slightly */
|
/* throttle high/super speed IRQ rate back slightly */
|
||||||
if (gadget_is_dualspeed(dev->gadget))
|
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)
|
? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@ static struct usb_composite_driver zero_driver = {
|
||||||
.name = "zero",
|
.name = "zero",
|
||||||
.dev = &device_desc,
|
.dev = &device_desc,
|
||||||
.strings = dev_strings,
|
.strings = dev_strings,
|
||||||
.max_speed = USB_SPEED_HIGH,
|
.max_speed = USB_SPEED_SUPER,
|
||||||
.unbind = zero_unbind,
|
.unbind = zero_unbind,
|
||||||
.suspend = zero_suspend,
|
.suspend = zero_suspend,
|
||||||
.resume = zero_resume,
|
.resume = zero_resume,
|
||||||
|
|
|
@ -2282,6 +2282,7 @@ static void musb_restore_context(struct musb *musb)
|
||||||
musb->context.index_regs[i].rxhubport);
|
musb->context.index_regs[i].rxhubport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
musb_writeb(musb_base, MUSB_INDEX, musb->context.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int musb_suspend(struct device *dev)
|
static int musb_suspend(struct device *dev)
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct m66592_platdata {
|
||||||
/* (external controller only) one = 3.3V, zero = 1.5V */
|
/* (external controller only) one = 3.3V, zero = 1.5V */
|
||||||
unsigned vif:1;
|
unsigned vif:1;
|
||||||
|
|
||||||
|
/* (external controller only) set one = WR0_N shorted to WR1_N */
|
||||||
|
unsigned wr0_shorted_to_wr1:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __LINUX_USB_M66592_H */
|
#endif /* __LINUX_USB_M66592_H */
|
||||||
|
|
|
@ -31,6 +31,9 @@ struct r8a66597_platdata {
|
||||||
/* This callback can control port power instead of DVSTCTR register. */
|
/* This callback can control port power instead of DVSTCTR register. */
|
||||||
void (*port_power)(int port, int power);
|
void (*port_power)(int port, int power);
|
||||||
|
|
||||||
|
/* This parameter is for BUSWAIT */
|
||||||
|
u16 buswait;
|
||||||
|
|
||||||
/* set one = on chip controller, set zero = external controller */
|
/* set one = on chip controller, set zero = external controller */
|
||||||
unsigned on_chip:1;
|
unsigned on_chip:1;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue