Commit 959ab1dc authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/usb-2.6
parents 01477f1c 6afd2055
...@@ -7,7 +7,7 @@ menu "USB support" ...@@ -7,7 +7,7 @@ menu "USB support"
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB config USB
tristate "Support for USB" tristate "Support for USB"
depends on PCI || SA1111 depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
---help--- ---help---
Universal Serial Bus (USB) is a specification for a serial bus Universal Serial Bus (USB) is a specification for a serial bus
subsystem which offers higher speeds and more features than the subsystem which offers higher speeds and more features than the
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "usb.h"
#include "hcd.h" #include "hcd.h"
#include "hub.h" #include "hub.h"
...@@ -1316,8 +1317,8 @@ int usb_physical_reset_device(struct usb_device *dev) ...@@ -1316,8 +1317,8 @@ int usb_physical_reset_device(struct usb_device *dev)
kfree(descriptor); kfree(descriptor);
usb_destroy_configuration(dev); usb_destroy_configuration(dev);
ret = usb_get_device_descriptor(dev); ret = usb_get_device_descriptor(dev, sizeof(dev->descriptor));
if (ret < sizeof(dev->descriptor)) { if (ret != sizeof(dev->descriptor)) {
if (ret < 0) if (ret < 0)
err("unable to get device %s descriptor " err("unable to get device %s descriptor "
"(error=%d)", dev->devpath, ret); "(error=%d)", dev->devpath, ret);
......
...@@ -546,10 +546,10 @@ void usb_sg_cancel (struct usb_sg_request *io) ...@@ -546,10 +546,10 @@ void usb_sg_cancel (struct usb_sg_request *io)
* *
* Gets a USB descriptor. Convenience functions exist to simplify * Gets a USB descriptor. Convenience functions exist to simplify
* getting some types of descriptors. Use * getting some types of descriptors. Use
* usb_get_device_descriptor() for USB_DT_DEVICE, * usb_get_device_descriptor() for USB_DT_DEVICE (not exported),
* and usb_get_string() or usb_string() for USB_DT_STRING. * and usb_get_string() or usb_string() for USB_DT_STRING.
* Configuration descriptors (USB_DT_CONFIG) are part of the device * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
* structure, at least for the current configuration. * are part of the device structure.
* In addition to a number of USB-standard descriptors, some * In addition to a number of USB-standard descriptors, some
* devices also use class-specific or vendor-specific descriptors. * devices also use class-specific or vendor-specific descriptors.
* *
...@@ -610,6 +610,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char ...@@ -610,6 +610,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
/** /**
* usb_get_device_descriptor - (re)reads the device descriptor * usb_get_device_descriptor - (re)reads the device descriptor
* @dev: the device whose device descriptor is being updated * @dev: the device whose device descriptor is being updated
* @size: how much of the descriptor to read
* Context: !in_interrupt () * Context: !in_interrupt ()
* *
* Updates the copy of the device descriptor stored in the device structure, * Updates the copy of the device descriptor stored in the device structure,
...@@ -618,24 +619,35 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char ...@@ -618,24 +619,35 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
* vendors product and version fields (idVendor, idProduct, and bcdDevice). * vendors product and version fields (idVendor, idProduct, and bcdDevice).
* That lets device drivers compare against non-byteswapped constants. * That lets device drivers compare against non-byteswapped constants.
* *
* There's normally no need to use this call, although some devices * Not exported, only for use by the core. If drivers really want to read
* will change their descriptors after events like updating firmware. * the device descriptor directly, they can call usb_get_descriptor() with
* type = USB_DT_DEVICE and index = 0.
* *
* This call is synchronous, and may not be used in an interrupt context. * This call is synchronous, and may not be used in an interrupt context.
* *
* Returns the number of bytes received on success, or else the status code * Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call. * returned by the underlying usb_control_msg() call.
*/ */
int usb_get_device_descriptor(struct usb_device *dev) int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
{ {
int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, struct usb_device_descriptor *desc;
sizeof(dev->descriptor)); int ret;
if (size > sizeof(*desc))
return -EINVAL;
desc = kmalloc(sizeof(*desc), GFP_NOIO);
if (!desc)
return -ENOMEM;
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
if (ret >= 0) { if (ret >= 0) {
le16_to_cpus(&dev->descriptor.bcdUSB); le16_to_cpus(&desc->bcdUSB);
le16_to_cpus(&dev->descriptor.idVendor); le16_to_cpus(&desc->idVendor);
le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&desc->idProduct);
le16_to_cpus(&dev->descriptor.bcdDevice); le16_to_cpus(&desc->bcdDevice);
memcpy(&dev->descriptor, desc, size);
} }
kfree(desc);
return ret; return ret;
} }
...@@ -1241,7 +1253,6 @@ EXPORT_SYMBOL(usb_sg_wait); ...@@ -1241,7 +1253,6 @@ EXPORT_SYMBOL(usb_sg_wait);
// synchronous control message convenience routines // synchronous control message convenience routines
EXPORT_SYMBOL(usb_get_descriptor); EXPORT_SYMBOL(usb_get_descriptor);
EXPORT_SYMBOL(usb_get_device_descriptor);
EXPORT_SYMBOL(usb_get_status); EXPORT_SYMBOL(usb_get_status);
EXPORT_SYMBOL(usb_get_string); EXPORT_SYMBOL(usb_get_string);
EXPORT_SYMBOL(usb_string); EXPORT_SYMBOL(usb_string);
......
...@@ -206,12 +206,15 @@ void usb_deregister(struct usb_driver *driver) ...@@ -206,12 +206,15 @@ void usb_deregister(struct usb_driver *driver)
*/ */
struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
{ {
struct usb_host_config *config = dev->actconfig;
int i; int i;
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) if (!config)
if (dev->actconfig->interface[i]->altsetting[0] return NULL;
for (i = 0; i < config->desc.bNumInterfaces; i++)
if (config->interface[i]->altsetting[0]
.desc.bInterfaceNumber == ifnum) .desc.bInterfaceNumber == ifnum)
return dev->actconfig->interface[i]; return config->interface[i];
return NULL; return NULL;
} }
...@@ -233,14 +236,17 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) ...@@ -233,14 +236,17 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
struct usb_endpoint_descriptor * struct usb_endpoint_descriptor *
usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
{ {
struct usb_host_config *config = dev->actconfig;
int i, k; int i, k;
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { if (!config)
return NULL;
for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf; struct usb_interface *intf;
struct usb_host_interface *alt; struct usb_host_interface *alt;
/* only endpoints in current altseting are active */ /* only endpoints in current altsetting are active */
intf = dev->actconfig->interface[i]; intf = config->interface[i];
alt = intf->altsetting + intf->act_altsetting; alt = intf->altsetting + intf->act_altsetting;
for (k = 0; k < alt->desc.bNumEndpoints; k++) for (k = 0; k < alt->desc.bNumEndpoints; k++)
...@@ -1059,7 +1065,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1059,7 +1065,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
wait_ms(10); /* Let the SET_ADDRESS settle */ wait_ms(10); /* Let the SET_ADDRESS settle */
/* high and low speed devices don't need this... */ /* high and low speed devices don't need this... */
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); err = usb_get_device_descriptor(dev, 8);
if (err >= 8) if (err >= 8)
break; break;
wait_ms(100); wait_ms(100);
...@@ -1079,8 +1085,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent) ...@@ -1079,8 +1085,8 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
/* USB device state == addressed ... still not usable */ /* USB device state == addressed ... still not usable */
err = usb_get_device_descriptor(dev); err = usb_get_device_descriptor(dev, sizeof(dev->descriptor));
if (err < (signed)sizeof(dev->descriptor)) { if (err != (signed)sizeof(dev->descriptor)) {
dev_err(&dev->dev, "device descriptor read/all, error %d\n", err); dev_err(&dev->dev, "device descriptor read/all, error %d\n", err);
goto fail; goto fail;
} }
......
...@@ -14,3 +14,6 @@ extern void usb_enable_endpoint (struct usb_device *dev, ...@@ -14,3 +14,6 @@ extern void usb_enable_endpoint (struct usb_device *dev,
struct usb_endpoint_descriptor *epd); struct usb_endpoint_descriptor *epd);
extern void usb_enable_interface (struct usb_device *dev, extern void usb_enable_interface (struct usb_device *dev,
struct usb_interface *intf); struct usb_interface *intf);
extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
...@@ -3,12 +3,10 @@ ...@@ -3,12 +3,10 @@
# (a) a peripheral controller, and # (a) a peripheral controller, and
# (b) the gadget driver using it. # (b) the gadget driver using it.
# #
# for 2.5 kbuild, drivers/usb/gadget/Kconfig menu "USB Gadget Support"
# source this at the end of drivers/usb/Kconfig
# config USB_GADGET
menuconfig USB_GADGET
tristate "Support for USB Gadgets" tristate "Support for USB Gadgets"
depends on EXPERIMENTAL
help help
USB is a master/slave protocol, organized with one master USB is a master/slave protocol, organized with one master
host (such as a PC) controlling up to 127 peripheral devices. host (such as a PC) controlling up to 127 peripheral devices.
...@@ -36,12 +34,15 @@ menuconfig USB_GADGET ...@@ -36,12 +34,15 @@ menuconfig USB_GADGET
# USB Peripheral Controller Support # USB Peripheral Controller Support
# #
choice choice
prompt "USB Peripheral Controller Support" prompt "USB Peripheral Controller"
depends on USB_GADGET depends on USB_GADGET
help
A USB device uses a controller to talk to its host.
Systems should have only one such upstream link.
config USB_NET2280 config USB_GADGET_NET2280
tristate "NetChip 2280 USB Peripheral Controller" boolean "NetChip 2280"
depends on PCI && USB_GADGET depends on PCI
help help
NetChip 2280 is a PCI based USB peripheral controller which NetChip 2280 is a PCI based USB peripheral controller which
supports both full and high speed USB 2.0 data transfers. supports both full and high speed USB 2.0 data transfers.
...@@ -54,21 +55,118 @@ config USB_NET2280 ...@@ -54,21 +55,118 @@ config USB_NET2280
dynamically linked module called "net2280" and force all dynamically linked module called "net2280" and force all
gadget drivers to also be dynamically linked. gadget drivers to also be dynamically linked.
config USB_NET2280
tristate
depends on USB_GADGET_NET2280
default USB_GADGET
config USB_GADGET_PXA2XX
boolean "PXA 2xx or IXP 42x"
depends on ARCH_PXA || ARCH_IXP425
help
Intel's PXA 2xx series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The
controller in the IXP 4xx series is register-compatible.
It has fifteen fixed-function endpoints, as well as endpoint
zero (for control transfers).
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "pxa2xx_udc" and force all
gadget drivers to also be dynamically linked.
config USB_PXA2XX
tristate
depends on USB_GADGET_PXA2XX
default USB_GADGET
# if there's only one gadget driver, using only two bulk endpoints,
# don't waste memory for the other endpoints
config USB_PXA2XX_SMALL
depends on USB_GADGET_PXA2XX
bool
default y if USB_ZERO
default y if USB_ETH
default y if USB_G_SERIAL
config USB_GADGET_GOKU
boolean "Toshiba TC86C001 'Goku-S'"
depends on PCI
help
The Toshiba TC86C001 is a PCI device which includes controllers
for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
The device controller has three configurable (bulk or interrupt)
endpoints, plus endpoint zero (for control transfers).
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "goku_udc" and to force all
gadget drivers to also be dynamically linked.
config USB_GOKU
tristate
depends on USB_GADGET_GOKU
default USB_GADGET
# this could be built elsewhere (doesn't yet exist)
config USB_GADGET_SA1100
boolean "SA 1100"
depends on ARCH_SA1100
help
Intel's SA-1100 is an ARM-4 processor with an integrated
full speed USB 1.1 device controller.
It has two fixed-function endpoints, as well as endpoint
zero (for control transfers).
config USB_SA1100
tristate
depends on USB_GADGET_SA1100
default USB_GADGET
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
depends on USB
help
This host controller driver emulates USB, looping all data transfer
requests back to a USB "gadget driver" in the same host. The host
side is the master; the gadget side is the slave. Gadget drivers
can be high, full, or low speed; and they have access to endpoints
like those from NET2280, PXA2xx, or SA1100 hardware.
This may help in some stages of creating a driver to embed in a
Linux device, since it lets you debug several parts of the gadget
driver without its hardware or drivers being involved.
Since such a gadget side driver needs to interoperate with a host
side Linux-USB device driver, this may help to debug both sides
of a USB protocol stack.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "dummy_hcd" and force all
gadget drivers to also be dynamically linked.
config USB_DUMMY_HCD
tristate
depends on USB_GADGET_DUMMY_HCD
default USB_GADGET
endchoice endchoice
# #
# USB Gadget Drivers # USB Gadget Drivers
# #
choice choice
prompt "USB Gadget Drivers" tristate "USB Gadget Drivers"
depends on USB_GADGET depends on USB_GADGET
default USB_ETH default USB_ETH
# FIXME want a cleaner dependency/config approach for drivers. # this first set of drivers all depend on bulk-capable hardware.
config USB_ZERO config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)" tristate "Gadget Zero (DEVELOPMENT)"
depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) depends on EXPERIMENTAL
help help
Gadget Zero is a two-configuration device. It either sinks and Gadget Zero is a two-configuration device. It either sinks and
sources bulk data; or it loops back a configurable number of sources bulk data; or it loops back a configurable number of
...@@ -91,26 +189,9 @@ config USB_ZERO ...@@ -91,26 +189,9 @@ config USB_ZERO
Say "y" to link the driver statically, or "m" to build a Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_zero". dynamically linked module called "g_zero".
config USB_ZERO_NET2280
bool
# for now, treat the "dummy" hcd as if it were a net2280
depends on USB_ZERO && (USB_NET2280 || USB_DUMMY_HCD)
default y
config USB_ZERO_PXA2XX
bool
depends on USB_ZERO && USB_PXA2XX
default y
config USB_ZERO_SA1100
bool
depends on USB_ZERO && USB_SA1100
default y
config USB_ETH config USB_ETH
tristate "Ethernet Gadget" tristate "Ethernet Gadget"
depends on USB_GADGET && NET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX || USB_SA1100) depends on NET
help help
This driver implements Ethernet style communication, in either This driver implements Ethernet style communication, in either
of two ways: of two ways:
...@@ -136,26 +217,9 @@ config USB_ETH ...@@ -136,26 +217,9 @@ config USB_ETH
Say "y" to link the driver statically, or "m" to build a Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_ether". dynamically linked module called "g_ether".
config USB_ETH_NET2280
bool
# for now, treat the "dummy" hcd as if it were a net2280
depends on USB_ETH && (USB_NET2280 || USB_DUMMY_HCD)
default y
config USB_ETH_PXA2XX
bool
depends on USB_ETH && USB_PXA2XX
default y
config USB_ETH_SA1100
bool
depends on USB_ETH && USB_SA1100
default y
config USB_GADGETFS config USB_GADGETFS
tristate "Gadget Filesystem (EXPERIMENTAL)" tristate "Gadget Filesystem (EXPERIMENTAL)"
depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA2XX) && EXPERIMENTAL depends on EXPERIMENTAL
help help
This driver provides a filesystem based API that lets user mode This driver provides a filesystem based API that lets user mode
programs implement a single-configuration USB device, including programs implement a single-configuration USB device, including
...@@ -166,16 +230,43 @@ config USB_GADGETFS ...@@ -166,16 +230,43 @@ config USB_GADGETFS
Say "y" to link the driver statically, or "m" to build a Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "gadgetfs". dynamically linked module called "gadgetfs".
config USB_GADGETFS_NET2280 config USB_FILE_STORAGE
bool tristate "File-backed Storage Gadget (DEVELOPMENT)"
# for now, treat the "dummy" hcd as if it were a net2280 # we don't support the SA1100 because of its limitations
depends on USB_GADGETFS && (USB_NET2280 || USB_DUMMY_HCD) depends on USB_GADGET_SA1100 = n
default y help
The File-backed Storage Gadget acts as a USB Mass Storage
disk drive. As its storage repository it can use a regular
file or a block device (in much the same way as the "loop"
device driver), specified as a module parameter.
config USB_GADGETFS_PXA2XX Say "y" to link the driver statically, or "m" to build a
bool dynamically linked module called "g_file_storage".
depends on USB_GADGETFS && USB_PXA2XX
default y config USB_FILE_STORAGE_TEST
bool "File-backed Storage Gadget test version"
depends on USB_FILE_STORAGE
default n
help
Say "y" to generate the larger testing version of the
File-backed Storage Gadget, useful for probing the
behavior of USB Mass Storage hosts. Not needed for
normal operation.
config USB_G_SERIAL
tristate "Serial Gadget"
help
The Serial Gadget talks to the Linux-USB generic serial driver.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_serial".
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
# - none yet
config USB_G_SERIAL config USB_G_SERIAL
tristate "serial Gadget" tristate "serial Gadget"
...@@ -200,4 +291,4 @@ config USB_G_SERIAL_SA1100 ...@@ -200,4 +291,4 @@ config USB_G_SERIAL_SA1100
endchoice endchoice
# endmenuconfig endmenu
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# USB peripheral controller drivers # USB peripheral controller drivers
# #
obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
# #
# USB gadget drivers # USB gadget drivers
...@@ -10,8 +12,11 @@ g_zero-objs := zero.o usbstring.o ...@@ -10,8 +12,11 @@ g_zero-objs := zero.o usbstring.o
g_ether-objs := ether.o usbstring.o g_ether-objs := ether.o usbstring.o
g_serial-objs := serial.o usbstring.o g_serial-objs := serial.o usbstring.o
gadgetfs-objs := inode.o usbstring.o gadgetfs-objs := inode.o usbstring.o
g_file_storage-objs := file_storage.o usbstring.o
obj-$(CONFIG_USB_ZERO) += g_zero.o obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_ETH) += g_ether.o obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
...@@ -122,12 +122,9 @@ struct eth_dev { ...@@ -122,12 +122,9 @@ struct eth_dev {
* *
* CHIP ... hardware identifier * CHIP ... hardware identifier
* DRIVER_VERSION_NUM ... alerts the host side driver to differences * DRIVER_VERSION_NUM ... alerts the host side driver to differences
* EP0_MAXPACKET ... controls packetization of control requests
* EP_*_NAME ... which endpoints do we use for which purpose? * EP_*_NAME ... which endpoints do we use for which purpose?
* EP_*_NUM ... numbers for them (often limited by hardware) * EP_*_NUM ... numbers for them (often limited by hardware)
* HIGHSPEED ... define if ep0 and descriptors need high speed support * HIGHSPEED ... define if ep0 and descriptors need high speed support
* MAX_USB_POWER ... define if we use other than 100 mA bus current
* SELFPOWER ... unless we can run on bus power, USB_CONFIG_ATT_SELFPOWER
* WAKEUP ... if hardware supports remote wakeup AND we will issue the * WAKEUP ... if hardware supports remote wakeup AND we will issue the
* usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
* *
...@@ -143,6 +140,9 @@ struct eth_dev { ...@@ -143,6 +140,9 @@ struct eth_dev {
/* #undef on hardware that can't implement CDC */ /* #undef on hardware that can't implement CDC */
#define DEV_CONFIG_CDC #define DEV_CONFIG_CDC
/* undef on bus-powered hardware, and #define MAX_USB_POWER */
#define SELFPOWER
/* /*
* NetChip 2280, PCI based. * NetChip 2280, PCI based.
* *
...@@ -152,11 +152,10 @@ struct eth_dev { ...@@ -152,11 +152,10 @@ struct eth_dev {
* performance note: only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f) * performance note: only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f)
* otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help. * otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help.
*/ */
#ifdef CONFIG_USB_ETH_NET2280 #ifdef CONFIG_USB_GADGET_NET2280
#define CHIP "net2280" #define CHIP "net2280"
#define DEFAULT_QLEN 4 /* has dma chaining */ #define DEFAULT_QLEN 4 /* has dma chaining */
#define DRIVER_VERSION_NUM 0x0101 #define DRIVER_VERSION_NUM 0x0101
#define EP0_MAXPACKET 64
static const char EP_OUT_NAME [] = "ep-a"; static const char EP_OUT_NAME [] = "ep-a";
#define EP_OUT_NUM 1 #define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep-b"; static const char EP_IN_NAME [] = "ep-b";
...@@ -164,8 +163,6 @@ static const char EP_IN_NAME [] = "ep-b"; ...@@ -164,8 +163,6 @@ static const char EP_IN_NAME [] = "ep-b";
static const char EP_STATUS_NAME [] = "ep-f"; static const char EP_STATUS_NAME [] = "ep-f";
#define EP_STATUS_NUM 3 #define EP_STATUS_NUM 3
#define HIGHSPEED #define HIGHSPEED
/* specific hardware configs could be bus-powered */
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* supports remote wakeup, but this driver doesn't */ /* supports remote wakeup, but this driver doesn't */
extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
...@@ -186,17 +183,14 @@ static inline void hw_optimize (struct usb_gadget *gadget) ...@@ -186,17 +183,14 @@ static inline void hw_optimize (struct usb_gadget *gadget)
* multiple interfaces (or altsettings) aren't usable. so this hardware * multiple interfaces (or altsettings) aren't usable. so this hardware
* can't implement CDC, which needs both capabilities. * can't implement CDC, which needs both capabilities.
*/ */
#ifdef CONFIG_USB_ETH_PXA2XX #ifdef CONFIG_USB_GADGET_PXA2XX
#undef DEV_CONFIG_CDC #undef DEV_CONFIG_CDC
#define CHIP "pxa2xx" #define CHIP "pxa2xx"
#define DRIVER_VERSION_NUM 0x0103 #define DRIVER_VERSION_NUM 0x0103
#define EP0_MAXPACKET 16
static const char EP_OUT_NAME [] = "ep2out-bulk"; static const char EP_OUT_NAME [] = "ep2out-bulk";
#define EP_OUT_NUM 2 #define EP_OUT_NUM 2
static const char EP_IN_NAME [] = "ep1in-bulk"; static const char EP_IN_NAME [] = "ep1in-bulk";
#define EP_IN_NUM 1 #define EP_IN_NUM 1
/* doesn't support bus-powered operation */
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* supports remote wakeup, but this driver doesn't */ /* supports remote wakeup, but this driver doesn't */
/* no hw optimizations to apply */ /* no hw optimizations to apply */
...@@ -209,17 +203,14 @@ static const char EP_IN_NAME [] = "ep1in-bulk"; ...@@ -209,17 +203,14 @@ static const char EP_IN_NAME [] = "ep1in-bulk";
* can't have a notification endpoint, since there are only the two * can't have a notification endpoint, since there are only the two
* bulk-capable ones. the CDC spec allows that. * bulk-capable ones. the CDC spec allows that.
*/ */
#ifdef CONFIG_USB_ETH_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100" #define CHIP "sa1100"
#define DRIVER_VERSION_NUM 0x0105 #define DRIVER_VERSION_NUM 0x0105
#define EP0_MAXPACKET 8
static const char EP_OUT_NAME [] = "ep1out-bulk"; static const char EP_OUT_NAME [] = "ep1out-bulk";
#define EP_OUT_NUM 1 #define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2in-bulk"; static const char EP_IN_NAME [] = "ep2in-bulk";
#define EP_IN_NUM 2 #define EP_IN_NUM 2
// EP_STATUS_NUM is undefined // EP_STATUS_NUM is undefined
/* doesn't support bus-powered operation */
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* doesn't support remote wakeup? */ /* doesn't support remote wakeup? */
/* no hw optimizations to apply */ /* no hw optimizations to apply */
...@@ -231,25 +222,43 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -231,25 +222,43 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
* *
* This has three semi-configurable full speed bulk/interrupt endpoints. * This has three semi-configurable full speed bulk/interrupt endpoints.
*/ */
#ifdef CONFIG_USB_ETH_GOKU #ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku" #define CHIP "goku"
#define DRIVER_VERSION_NUM 0x0106 #define DRIVER_VERSION_NUM 0x0106
#define EP0_MAXPACKET 8
static const char EP_OUT_NAME [] = "ep1-bulk"; static const char EP_OUT_NAME [] = "ep1-bulk";
#define EP_OUT_NUM 1 #define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2-bulk"; static const char EP_IN_NAME [] = "ep2-bulk";
#define EP_IN_NUM 2 #define EP_IN_NUM 2
static const char EP_STATUS_NAME [] = "ep3-bulk"; static const char EP_STATUS_NAME [] = "ep3-bulk";
#define EP_STATUS_NUM 3 #define EP_STATUS_NUM 3
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* doesn't support remote wakeup */ /* doesn't support remote wakeup */
#define hw_optimize(g) do {} while (0) #define hw_optimize(g) do {} while (0)
#endif #endif
/*
* SuperH UDC: UDC built-in to some Renesas SH processors.
*
* This has three semi-configurable full speed bulk/interrupt endpoints.
*
* Only one configuration and interface is supported. So this hardware
* can't implement CDC.
*/
#ifdef CONFIG_USB_GADGET_SUPERH
#undef DEV_CONFIG_CDC
#define CHIP "superh"
#define DRIVER_VERSION_NUM 0x0107
static const char EP_OUT_NAME[] = "ep1out-bulk";
#define EP_OUT_NUM 1
static const char EP_IN_NAME[] = "ep2in-bulk";
#define EP_IN_NUM 2
#define hw_optimize(g) do {} while (0)
#endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#ifndef EP0_MAXPACKET #ifndef CHIP
# error Configure some USB peripheral controller driver! # error Configure some USB peripheral controller driver!
#endif #endif
...@@ -280,19 +289,15 @@ static const char EP_STATUS_NAME [] = "ep3-bulk"; ...@@ -280,19 +289,15 @@ static const char EP_STATUS_NAME [] = "ep3-bulk";
* hardware that supports remote wakeup defaults to disabling it. * hardware that supports remote wakeup defaults to disabling it.
*/ */
#ifndef SELFPOWER
/* default: say we rely on bus power */
#define SELFPOWER 0
/* else:
* - SELFPOWER value must be USB_CONFIG_ATT_SELFPOWER
* - MAX_USB_POWER may be nonzero.
*/
#endif
#ifndef MAX_USB_POWER #ifndef MAX_USB_POWER
/* any hub supports this steady state bus power consumption */ #ifdef SELFPOWER
#define MAX_USB_POWER 100 /* mA */ /* some hosts are confused by 0mA */
#define MAX_USB_POWER 2 /* mA */
#else
/* bus powered */
#error Define your bus power consumption!
#endif #endif
#endif /* MAX_USB_POWER */
#ifndef WAKEUP #ifndef WAKEUP
/* default: this driver won't do remote wakeup */ /* default: this driver won't do remote wakeup */
...@@ -376,7 +381,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); ...@@ -376,7 +381,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
/* /*
* This device advertises one configuration. * This device advertises one configuration.
*/ */
static const struct usb_device_descriptor static struct usb_device_descriptor
device_desc = { device_desc = {
.bLength = sizeof device_desc, .bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE, .bDescriptorType = USB_DT_DEVICE,
...@@ -386,7 +391,6 @@ device_desc = { ...@@ -386,7 +391,6 @@ device_desc = {
.bDeviceClass = DEV_CONFIG_CLASS, .bDeviceClass = DEV_CONFIG_CLASS,
.bDeviceSubClass = 0, .bDeviceSubClass = 0,
.bDeviceProtocol = 0, .bDeviceProtocol = 0,
.bMaxPacketSize0 = EP0_MAXPACKET,
.idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
...@@ -396,7 +400,7 @@ device_desc = { ...@@ -396,7 +400,7 @@ device_desc = {
.bNumConfigurations = 1, .bNumConfigurations = 1,
}; };
static const struct usb_config_descriptor static struct usb_config_descriptor
eth_config = { eth_config = {
.bLength = sizeof eth_config, .bLength = sizeof eth_config,
.bDescriptorType = USB_DT_CONFIG, .bDescriptorType = USB_DT_CONFIG,
...@@ -409,7 +413,7 @@ eth_config = { ...@@ -409,7 +413,7 @@ eth_config = {
#endif #endif
.bConfigurationValue = DEV_CONFIG_VALUE, .bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = STRING_PRODUCT, .iConfiguration = STRING_PRODUCT,
.bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, .bmAttributes = USB_CONFIG_ATT_ONE | WAKEUP,
.bMaxPower = (MAX_USB_POWER + 1) / 2, .bMaxPower = (MAX_USB_POWER + 1) / 2,
}; };
...@@ -645,7 +649,7 @@ hs_sink_desc = { ...@@ -645,7 +649,7 @@ hs_sink_desc = {
.bInterval = 1, .bInterval = 1,
}; };
static const struct usb_qualifier_descriptor static struct usb_qualifier_descriptor
dev_qualifier = { dev_qualifier = {
.bLength = sizeof dev_qualifier, .bLength = sizeof dev_qualifier,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER, .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
...@@ -653,12 +657,10 @@ dev_qualifier = { ...@@ -653,12 +657,10 @@ dev_qualifier = {
.bcdUSB = __constant_cpu_to_le16 (0x0200), .bcdUSB = __constant_cpu_to_le16 (0x0200),
.bDeviceClass = DEV_CONFIG_CLASS, .bDeviceClass = DEV_CONFIG_CLASS,
/* assumes ep0 uses the same value for both speeds ... */
.bMaxPacketSize0 = EP0_MAXPACKET,
.bNumConfigurations = 1, .bNumConfigurations = 1,
}; };
/* maxpacket and other transfer characteristics vary by speed. */ /* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
...@@ -959,7 +961,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) ...@@ -959,7 +961,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
if (number == dev->config) if (number == dev->config)
return 0; return 0;
#ifdef CONFIG_USB_ETH_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
if (dev->config && atomic_read (&dev->tx_qlen) != 0) { if (dev->config && atomic_read (&dev->tx_qlen) != 0) {
/* tx fifo is full, but we can't clear it...*/ /* tx fifo is full, but we can't clear it...*/
INFO (dev, "can't change configurations\n"); INFO (dev, "can't change configurations\n");
...@@ -1006,6 +1008,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) ...@@ -1006,6 +1008,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
/* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications */ /* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications */
#define CDC_NOTIFY_NETWORK_CONNECTION 0x00 /* required; 6.3.1 */ #define CDC_NOTIFY_NETWORK_CONNECTION 0x00 /* required; 6.3.1 */
#define CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 /* optional; 6.3.2 */
#define CDC_NOTIFY_SPEED_CHANGE 0x2a /* required; 6.3.8 */ #define CDC_NOTIFY_SPEED_CHANGE 0x2a /* required; 6.3.8 */
struct cdc_notification { struct cdc_notification {
...@@ -1123,6 +1126,8 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -1123,6 +1126,8 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
/* see section 3.8.2 table 10 of the CDC spec for more ethernet /* see section 3.8.2 table 10 of the CDC spec for more ethernet
* requests, mostly for filters (multicast, pm) and statistics * requests, mostly for filters (multicast, pm) and statistics
*/ */
#define CDC_SEND_ENCAPSULATED_REQUEST 0x00 /* optional */
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 /* optional */
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */ #define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */
/* /*
...@@ -1188,7 +1193,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1188,7 +1193,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC); value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
spin_unlock (&dev->lock); spin_unlock (&dev->lock);
break; break;
#ifdef CONFIG_USB_ETH_PXA2XX #ifdef CONFIG_USB_GADGET_PXA2XX
/* PXA UDC prevents us from using SET_INTERFACE in normal ways. /* PXA UDC prevents us from using SET_INTERFACE in normal ways.
* And it hides GET_CONFIGURATION and GET_INTERFACE too. * And it hides GET_CONFIGURATION and GET_INTERFACE too.
*/ */
...@@ -1638,7 +1643,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) ...@@ -1638,7 +1643,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
req->context = skb; req->context = skb;
req->complete = tx_complete; req->complete = tx_complete;
#ifdef CONFIG_USB_ETH_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
/* don't demand zlp (req->zero) support from all hardware */ /* don't demand zlp (req->zero) support from all hardware */
if ((length % dev->in_ep->maxpacket) == 0) if ((length % dev->in_ep->maxpacket) == 0)
length++; length++;
...@@ -1770,6 +1775,17 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1770,6 +1775,17 @@ eth_bind (struct usb_gadget *gadget)
return -ENODEV; return -ENODEV;
#endif #endif
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
#ifdef HIGHSPEED
/* assumes ep0 uses the same value for both speeds ... */
dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
#endif
#ifdef SELFPOWERED
eth_config.bmAttributes |= USB_CONFIG_ATT_SELFPOWERED;
usb_gadget_set_selfpowered (gadget);
#endif
net = alloc_etherdev (sizeof *dev); net = alloc_etherdev (sizeof *dev);
if (!net) if (!net)
return status; return status;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
* rev1 chips. Rev1a silicon (0110) fixes almost all of them. * rev1 chips. Rev1a silicon (0110) fixes almost all of them.
*/ */
#define USE_DMA_CHAINING
/* /*
* Copyright (C) 2003 David Brownell * Copyright (C) 2003 David Brownell
* Copyright (C) 2003 NetChip Technologies * Copyright (C) 2003 NetChip Technologies
...@@ -47,8 +44,8 @@ ...@@ -47,8 +44,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define DEBUG 1 #undef DEBUG /* messages on error and most fault paths */
// #define VERBOSE /* extra debug messages (success too) */ #undef VERBOSE /* extra debug messages (success too) */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -77,7 +74,7 @@ ...@@ -77,7 +74,7 @@
#define DRIVER_DESC "NetChip 2280 USB Peripheral Controller" #define DRIVER_DESC "NetChip 2280 USB Peripheral Controller"
#define DRIVER_VERSION "Bastille Day 2003" #define DRIVER_VERSION "2004 Jan 14"
#define DMA_ADDR_INVALID (~(dma_addr_t)0) #define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */ #define EP_DONTUSE 13 /* nonzero */
...@@ -96,10 +93,21 @@ static const char *ep_name [] = { ...@@ -96,10 +93,21 @@ static const char *ep_name [] = {
"ep-e", "ep-f", "ep-e", "ep-f",
}; };
/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO)
* use_dma_chaining -- dma descriptor queueing gives even more irq reduction
*
* The net2280 DMA engines are not tightly integrated with their FIFOs;
* not all cases are (yet) handled well in this driver or the silicon.
* Some gadget drivers work better with the dma support here than others.
* These two parameters let you use PIO or more aggressive DMA.
*/
static int use_dma = 1; static int use_dma = 1;
static int use_dma_chaining = 0;
/* "modprobe net2280 use_dma=n" etc */ /* "modprobe net2280 use_dma=n" etc */
module_param (use_dma, bool, S_IRUGO|S_IWUSR); module_param (use_dma, bool, S_IRUGO);
module_param (use_dma_chaining, bool, S_IRUGO);
/* mode 0 == ep-{a,b,c,d} 1K fifo each /* mode 0 == ep-{a,b,c,d} 1K fifo each
* mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
...@@ -110,6 +118,7 @@ static ushort fifo_mode = 0; ...@@ -110,6 +118,7 @@ static ushort fifo_mode = 0;
/* "modprobe net2280 fifo_mode=1" etc */ /* "modprobe net2280 fifo_mode=1" etc */
module_param (fifo_mode, ushort, 0644); module_param (fifo_mode, ushort, 0644);
#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") #define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
#if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG) #if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG)
...@@ -162,6 +171,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -162,6 +171,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* ep_reset() has already been called */ /* ep_reset() has already been called */
ep->stopped = 0; ep->stopped = 0;
ep->out_overflow = 0;
/* set speed-dependent max packet; may kick in high bandwidth */ /* set speed-dependent max packet; may kick in high bandwidth */
set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max); set_idx_reg (dev->regs, REG_EP_MAXPKT (dev, ep->num), max);
...@@ -169,8 +179,8 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -169,8 +179,8 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* FIFO lines can't go to different packets. PIO is ok, so /* FIFO lines can't go to different packets. PIO is ok, so
* use it instead of troublesome (non-bulk) multi-packet DMA. * use it instead of troublesome (non-bulk) multi-packet DMA.
*/ */
if (ep->is_in && ep->dma && (max % 4) != 0) { if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
DEBUG (ep->dev, "%s, no IN dma for maxpacket %d\n", DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
ep->ep.name, ep->ep.maxpacket); ep->ep.name, ep->ep.maxpacket);
ep->dma = 0; ep->dma = 0;
} }
...@@ -179,17 +189,21 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -179,17 +189,21 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat); writel ((1 << FIFO_FLUSH), &ep->regs->ep_stat);
tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
if (tmp == USB_ENDPOINT_XFER_INT) { if (tmp == USB_ENDPOINT_XFER_INT) {
/* not just because of erratum 0105; avoid ever /* erratum 0105 workaround prevents hs NYET */
* kicking in the "toggle-irrelevant" mode. if (dev->chiprev == 0100
*/ && dev->gadget.speed == USB_SPEED_HIGH
tmp = USB_ENDPOINT_XFER_BULK; && !(desc->bEndpointAddress & USB_DIR_IN))
writel ((1 << CLEAR_NAK_OUT_PACKETS_MODE),
&ep->regs->ep_rsp);
} else if (tmp == USB_ENDPOINT_XFER_BULK) { } else if (tmp == USB_ENDPOINT_XFER_BULK) {
/* catch some particularly blatant driver bugs */ /* catch some particularly blatant driver bugs */
if ((dev->gadget.speed == USB_SPEED_HIGH if ((dev->gadget.speed == USB_SPEED_HIGH
&& max != 512) && max != 512)
|| (dev->gadget.speed == USB_SPEED_FULL || (dev->gadget.speed == USB_SPEED_FULL
&& max > 64)) && max > 64)) {
spin_unlock_irqrestore (&dev->lock, flags);
return -ERANGE; return -ERANGE;
}
} }
ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0; ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0;
tmp <<= ENDPOINT_TYPE; tmp <<= ENDPOINT_TYPE;
...@@ -205,11 +219,6 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -205,11 +219,6 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
writel (tmp, &ep->regs->ep_cfg); writel (tmp, &ep->regs->ep_cfg);
#ifdef NET2280_DMA_OUT_WORKAROUND
if (!ep->is_in)
ep->dma = 0;
#endif
/* enable irqs */ /* enable irqs */
if (!ep->dma) { /* pio, per-packet */ if (!ep->dma) { /* pio, per-packet */
tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0); tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0);
...@@ -388,6 +397,7 @@ net2280_alloc_request (struct usb_ep *_ep, int gfp_flags) ...@@ -388,6 +397,7 @@ net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
} }
td->dmacount = 0; /* not VALID */ td->dmacount = 0; /* not VALID */
td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
req->td = td; req->td = td;
} }
return &req->req; return &req->req;
...@@ -541,8 +551,11 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req) ...@@ -541,8 +551,11 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
count -= 4; count -= 4;
} }
/* last fifo entry is "short" unless we wrote a full packet */ /* last fifo entry is "short" unless we wrote a full packet.
if (total < ep->ep.maxpacket) { * also explicitly validate last word in (periodic) transfers
* when maxpacket is not a multiple of 4 bytes.
*/
if (count || total < ep->ep.maxpacket) {
tmp = count ? get_unaligned ((u32 *)buf) : count; tmp = count ? get_unaligned ((u32 *)buf) : count;
cpu_to_le32s (&tmp); cpu_to_le32s (&tmp);
set_fifo_bytecount (ep, count & 0x03); set_fifo_bytecount (ep, count & 0x03);
...@@ -555,6 +568,9 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req) ...@@ -555,6 +568,9 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
/* work around erratum 0106: PCI and USB race over the OUT fifo. /* work around erratum 0106: PCI and USB race over the OUT fifo.
* caller guarantees chiprev 0100, out endpoint is NAKing, and * caller guarantees chiprev 0100, out endpoint is NAKing, and
* there's no real data in the fifo. * there's no real data in the fifo.
*
* NOTE: also used in cases where that erratum doesn't apply:
* where the host wrote "too much" data to us.
*/ */
static void out_flush (struct net2280_ep *ep) static void out_flush (struct net2280_ep *ep)
{ {
...@@ -599,13 +615,13 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req) ...@@ -599,13 +615,13 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
/* erratum 0106 ... packets coming in during fifo reads might /* erratum 0106 ... packets coming in during fifo reads might
* be incompletely rejected. not all cases have workarounds. * be incompletely rejected. not all cases have workarounds.
*/ */
if (ep->dev->chiprev == 0x0100) { if (ep->dev->chiprev == 0x0100
&& ep->dev->gadget.speed == USB_SPEED_FULL) {
udelay (1);
tmp = readl (&ep->regs->ep_stat); tmp = readl (&ep->regs->ep_stat);
if ((tmp & (1 << NAK_OUT_PACKETS))) if ((tmp & (1 << NAK_OUT_PACKETS)))
/* cleanup = 1 */; cleanup = 1;
else if ((tmp & (1 << FIFO_FULL)) else if ((tmp & (1 << FIFO_FULL))) {
/* don't break hs PING protocol ... */
|| ep->dev->gadget.speed == USB_SPEED_FULL) {
start_out_naking (ep); start_out_naking (ep);
prevent = 1; prevent = 1;
} }
...@@ -617,6 +633,15 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req) ...@@ -617,6 +633,15 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
*/ */
prefetchw (buf); prefetchw (buf);
count = readl (&regs->ep_avail); count = readl (&regs->ep_avail);
if (unlikely (count == 0)) {
udelay (1);
tmp = readl (&ep->regs->ep_stat);
count = readl (&regs->ep_avail);
/* handled that data already? */
if (count == 0 && (tmp & (1 << NAK_OUT_PACKETS)) == 0)
return 0;
}
tmp = req->req.length - req->req.actual; tmp = req->req.length - req->req.actual;
if (count > tmp) { if (count > tmp) {
/* as with DMA, data overflow gets flushed */ /* as with DMA, data overflow gets flushed */
...@@ -626,7 +651,10 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req) ...@@ -626,7 +651,10 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
ep->ep.name, count, tmp); ep->ep.name, count, tmp);
req->req.status = -EOVERFLOW; req->req.status = -EOVERFLOW;
cleanup = 1; cleanup = 1;
} /* NAK_OUT_PACKETS will be set, so flushing is safe;
* the next read will start with the next packet
*/
} /* else it's a ZLP, no worries */
count = tmp; count = tmp;
} }
req->req.actual += count; req->req.actual += count;
...@@ -665,7 +693,7 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req) ...@@ -665,7 +693,7 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
} }
/* fill out dma descriptor to match a given request */ /* fill out dma descriptor to match a given request */
static inline void static void
fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
{ {
struct net2280_dma *td = req->td; struct net2280_dma *td = req->td;
...@@ -678,15 +706,13 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) ...@@ -678,15 +706,13 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
*/ */
if (ep->is_in) if (ep->is_in)
dmacount |= (1 << DMA_DIRECTION); dmacount |= (1 << DMA_DIRECTION);
else else if ((dmacount % ep->ep.maxpacket) != 0)
dmacount |= (1 << END_OF_CHAIN); dmacount |= (1 << END_OF_CHAIN);
req->valid = valid; req->valid = valid;
if (valid) if (valid)
dmacount |= (1 << VALID_BIT); dmacount |= (1 << VALID_BIT);
#ifdef USE_DMA_CHAINING if (likely(!req->req.no_interrupt || !use_dma_chaining))
if (!req->req.no_interrupt)
#endif
dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE); dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
/* td->dmadesc = previously set by caller */ /* td->dmadesc = previously set by caller */
...@@ -698,7 +724,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) ...@@ -698,7 +724,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
} }
static const u32 dmactl_default = static const u32 dmactl_default =
(1 << DMA_CLEAR_COUNT_ENABLE) (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT)
| (1 << DMA_CLEAR_COUNT_ENABLE)
/* erratum 0116 workaround part 1 (use POLLING) */ /* erratum 0116 workaround part 1 (use POLLING) */
| (POLL_100_USEC << DESCRIPTOR_POLLING_RATE) | (POLL_100_USEC << DESCRIPTOR_POLLING_RATE)
| (1 << DMA_VALID_BIT_POLLING_ENABLE) | (1 << DMA_VALID_BIT_POLLING_ENABLE)
...@@ -714,18 +741,41 @@ static inline void spin_stop_dma (struct net2280_dma_regs *dma) ...@@ -714,18 +741,41 @@ static inline void spin_stop_dma (struct net2280_dma_regs *dma)
static inline void stop_dma (struct net2280_dma_regs *dma) static inline void stop_dma (struct net2280_dma_regs *dma)
{ {
writel (dmactl_default & ~(1 << DMA_ENABLE), &dma->dmactl); writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
spin_stop_dma (dma); spin_stop_dma (dma);
} }
static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
{
struct net2280_dma_regs *dma = ep->dma;
writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
&dma->dmacount);
writel (readl (&dma->dmastat), &dma->dmastat);
writel (td_dma, &dma->dmadesc);
writel (dmactl, &dma->dmactl);
/* erratum 0116 workaround part 3: pci arbiter away from net2280 */
(void) readl (&ep->dev->pci->pcimstctl);
writel ((1 << DMA_START), &dma->dmastat);
if (!ep->is_in)
stop_out_naking (ep);
}
static void start_dma (struct net2280_ep *ep, struct net2280_request *req) static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
{ {
u32 tmp; u32 tmp;
int clear_nak = 0;
struct net2280_dma_regs *dma = ep->dma; struct net2280_dma_regs *dma = ep->dma;
/* FIXME can't use DMA for ZLPs */ /* FIXME can't use DMA for ZLPs */
/* on this path we "know" there's no dma active (yet) */
WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
writel (0, &ep->dma->dmactl);
/* previous OUT packet might have been short */ /* previous OUT packet might have been short */
if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat)) if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
& (1 << NAK_OUT_PACKETS)) != 0) { & (1 << NAK_OUT_PACKETS)) != 0) {
...@@ -733,9 +783,9 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) ...@@ -733,9 +783,9 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
&ep->regs->ep_stat); &ep->regs->ep_stat);
tmp = readl (&ep->regs->ep_avail); tmp = readl (&ep->regs->ep_avail);
if (tmp == 0) if (tmp) {
clear_nak = 1; writel (readl (&dma->dmastat), &dma->dmastat);
else {
/* transfer all/some fifo data */ /* transfer all/some fifo data */
writel (req->req.dma, &dma->dmaaddr); writel (req->req.dma, &dma->dmaaddr);
tmp = min (tmp, req->req.length); tmp = min (tmp, req->req.length);
...@@ -744,6 +794,8 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) ...@@ -744,6 +794,8 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
req->td->dmacount = cpu_to_le32 (req->req.length - tmp); req->td->dmacount = cpu_to_le32 (req->req.length - tmp);
writel ((1 << DMA_DONE_INTERRUPT_ENABLE) writel ((1 << DMA_DONE_INTERRUPT_ENABLE)
| tmp, &dma->dmacount); | tmp, &dma->dmacount);
req->td->dmadesc = 0;
req->valid = 1;
writel ((1 << DMA_ENABLE), &dma->dmactl); writel ((1 << DMA_ENABLE), &dma->dmactl);
writel ((1 << DMA_START), &dma->dmastat); writel ((1 << DMA_START), &dma->dmastat);
...@@ -751,8 +803,6 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) ...@@ -751,8 +803,6 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
} }
} }
/* on this path we know there's no dma queue (yet) */
WARN_ON (readl (&dma->dmactl) & (1 << DMA_ENABLE));
tmp = dmactl_default; tmp = dmactl_default;
/* force packet boundaries between dma requests, but prevent the /* force packet boundaries between dma requests, but prevent the
...@@ -772,25 +822,10 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) ...@@ -772,25 +822,10 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
req->td->dmadesc = cpu_to_le32 (ep->td_dma); req->td->dmadesc = cpu_to_le32 (ep->td_dma);
fill_dma_desc (ep, req, 1); fill_dma_desc (ep, req, 1);
#ifdef USE_DMA_CHAINING if (!use_dma_chaining)
writel ( (1 << VALID_BIT) req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
| (ep->is_in << DMA_DIRECTION)
| 0, &dma->dmacount);
#else
req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
#endif
writel (req->td_dma, &dma->dmadesc);
writel (tmp, &dma->dmactl);
/* erratum 0116 workaround part 3: pci arbiter away from net2280 */ start_queue (ep, tmp, req->td_dma);
(void) readl (&ep->dev->pci->pcimstctl);
writel ((1 << DMA_START), &dma->dmastat);
/* recover from previous short read; erratum 0112 workaround #1 */
if (clear_nak)
writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
} }
static inline void static inline void
...@@ -893,7 +928,6 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags) ...@@ -893,7 +928,6 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
_req->status = -EINPROGRESS; _req->status = -EINPROGRESS;
_req->actual = 0; _req->actual = 0;
req->dma_done = 0;
/* kickstart this i/o queue? */ /* kickstart this i/o queue? */
if (list_empty (&ep->queue) && !ep->stopped) { if (list_empty (&ep->queue) && !ep->stopped) {
...@@ -977,10 +1011,11 @@ dma_done ( ...@@ -977,10 +1011,11 @@ dma_done (
) )
{ {
req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount); req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount);
rmb ();
done (ep, req, status); done (ep, req, status);
} }
static void restart_dma (struct net2280_ep *ep);
static void scan_dma_completions (struct net2280_ep *ep) static void scan_dma_completions (struct net2280_ep *ep)
{ {
/* only look at descriptors that were "naturally" retired, /* only look at descriptors that were "naturally" retired,
...@@ -1000,14 +1035,37 @@ static void scan_dma_completions (struct net2280_ep *ep) ...@@ -1000,14 +1035,37 @@ static void scan_dma_completions (struct net2280_ep *ep)
break; break;
/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short" /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
* packets, including overruns, even when the transfer was * cases where DMA must be aborted; this code handles
* exactly the length requested (dmacount now zero). * all non-abort DMA completions.
* FIXME there's an overrun case here too, where we expect
* a short packet but receive a max length one (won't NAK).
*/ */
if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) { if (unlikely (req->td->dmadesc == 0)) {
req->dma_done = 1; /* paranoia */
tmp = readl (&ep->dma->dmacount);
if (tmp & DMA_BYTE_COUNT_MASK)
break;
/* single transfer mode */
dma_done (ep, req, tmp, 0);
break; break;
} else if (!ep->is_in
&& (req->req.length % ep->ep.maxpacket) != 0) {
tmp = readl (&ep->regs->ep_stat);
/* AVOID TROUBLE HERE by not issuing short reads from
* your gadget driver. That helps avoids errata 0121,
* 0122, and 0124; not all cases trigger the warning.
*/
if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
WARN (ep->dev, "%s lost packet sync!\n",
ep->ep.name);
req->req.status = -EOVERFLOW;
} else if ((tmp = readl (&ep->regs->ep_avail)) != 0) {
/* fifo gets flushed later */
ep->out_overflow = 1;
DEBUG (ep->dev, "%s dma, discard %d len %d\n",
ep->ep.name, tmp,
req->req.length);
req->req.status = -EOVERFLOW;
}
} }
dma_done (ep, req, tmp, 0); dma_done (ep, req, tmp, 0);
} }
...@@ -1016,41 +1074,50 @@ static void scan_dma_completions (struct net2280_ep *ep) ...@@ -1016,41 +1074,50 @@ static void scan_dma_completions (struct net2280_ep *ep)
static void restart_dma (struct net2280_ep *ep) static void restart_dma (struct net2280_ep *ep)
{ {
struct net2280_request *req; struct net2280_request *req;
u32 dmactl = dmactl_default;
if (ep->stopped) if (ep->stopped)
return; return;
req = list_entry (ep->queue.next, struct net2280_request, queue); req = list_entry (ep->queue.next, struct net2280_request, queue);
#ifdef USE_DMA_CHAINING if (!use_dma_chaining) {
start_dma (ep, req);
return;
}
/* the 2280 will be processing the queue unless queue hiccups after /* the 2280 will be processing the queue unless queue hiccups after
* the previous transfer: * the previous transfer:
* IN: wanted automagic zlp, head doesn't (or vice versa) * IN: wanted automagic zlp, head doesn't (or vice versa)
* DMA_FIFO_VALIDATE doesn't init from dma descriptors.
* OUT: was "usb-short", we must restart. * OUT: was "usb-short", we must restart.
*/ */
if (!req->valid) { if (ep->is_in && !req->valid) {
struct net2280_request *entry, *prev = 0; struct net2280_request *entry, *prev = 0;
int qmode, reqmode, done = 0; int reqmode, done = 0;
DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td); DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
qmode = likely (req->req.zero ep->in_fifo_validate = likely (req->req.zero
|| (req->req.length % ep->ep.maxpacket) != 0); || (req->req.length % ep->ep.maxpacket) != 0);
if (ep->in_fifo_validate)
dmactl |= (1 << DMA_FIFO_VALIDATE);
list_for_each_entry (entry, &ep->queue, queue) { list_for_each_entry (entry, &ep->queue, queue) {
u32 dmacount; u32 dmacount;
if (entry != req) if (entry == req)
continue; continue;
dmacount = entry->td->dmacount; dmacount = entry->td->dmacount;
if (!done) { if (!done) {
reqmode = likely (entry->req.zero reqmode = likely (entry->req.zero
|| (entry->req.length || (entry->req.length
% ep->ep.maxpacket) != 0); % ep->ep.maxpacket) != 0);
if (reqmode == qmode) { if (reqmode == ep->in_fifo_validate) {
entry->valid = 1; entry->valid = 1;
dmacount |= valid_bit; dmacount |= valid_bit;
entry->td->dmacount = dmacount; entry->td->dmacount = dmacount;
prev = entry; prev = entry;
continue; continue;
} else { } else {
/* force a hiccup */
prev->td->dmacount |= dma_done_ie; prev->td->dmacount |= dma_done_ie;
done = 1; done = 1;
} }
...@@ -1062,22 +1129,21 @@ static void restart_dma (struct net2280_ep *ep) ...@@ -1062,22 +1129,21 @@ static void restart_dma (struct net2280_ep *ep)
entry->td->dmacount = dmacount; entry->td->dmacount = dmacount;
prev = entry; prev = entry;
} }
start_dma (ep, req); }
} else if (!ep->is_in
&& (readl (&ep->regs->ep_stat) writel (0, &ep->dma->dmactl);
& (1 << NAK_OUT_PACKETS)) != 0) start_queue (ep, dmactl, req->td_dma);
start_dma (ep, req);
#else
start_dma (ep, req);
#endif
} }
static inline void abort_dma (struct net2280_ep *ep) static void abort_dma (struct net2280_ep *ep)
{ {
/* abort the current transfer */ /* abort the current transfer */
writel ((1 << DMA_ABORT), &ep->dma->dmastat); if (likely (!list_empty (&ep->queue))) {
/* FIXME work around errata 0121, 0122, 0124 */
/* collect completed transfers (except the current one) */ writel ((1 << DMA_ABORT), &ep->dma->dmastat);
spin_stop_dma (ep->dma);
} else
stop_dma (ep->dma);
scan_dma_completions (ep); scan_dma_completions (ep);
} }
...@@ -1108,43 +1174,53 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) ...@@ -1108,43 +1174,53 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
int stopped; int stopped;
ep = container_of (_ep, struct net2280_ep, ep); ep = container_of (_ep, struct net2280_ep, ep);
req = container_of (_req, struct net2280_request, req);
if (!_ep || (!ep->desc && ep->num != 0) || !_req) if (!_ep || (!ep->desc && ep->num != 0) || !_req)
return -EINVAL; return -EINVAL;
spin_lock_irqsave (&ep->dev->lock, flags); spin_lock_irqsave (&ep->dev->lock, flags);
stopped = ep->stopped; stopped = ep->stopped;
/* pause dma while we scan the queue */ /* quiesce dma while we patch the queue */
dmactl = 0; dmactl = 0;
ep->stopped = 1; ep->stopped = 1;
if (ep->dma) { if (ep->dma) {
dmactl = readl (&ep->dma->dmactl); dmactl = readl (&ep->dma->dmactl);
writel (dmactl & ~(1 << DMA_ENABLE), &ep->dma->dmactl); /* WARNING erratum 0127 may kick in ... */
/* force synch, clean any completed requests */ stop_dma (ep->dma);
spin_stop_dma (ep->dma);
scan_dma_completions (ep); scan_dma_completions (ep);
} }
/* make sure it's still queued on this endpoint */
list_for_each_entry (req, &ep->queue, queue) {
if (&req->req == _req)
break;
}
if (&req->req != _req) {
spin_unlock_irqrestore (&ep->dev->lock, flags);
return -EINVAL;
}
/* queue head may be partially complete. */ /* queue head may be partially complete. */
if (ep->queue.next == &req->queue) { if (ep->queue.next == &req->queue) {
if (ep->dma) { if (ep->dma) {
DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name); DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name);
_req->status = -ECONNRESET; _req->status = -ECONNRESET;
abort_dma (ep); abort_dma (ep);
if (likely (ep->queue.next == &req->queue)) if (likely (ep->queue.next == &req->queue)) {
// NOTE: misreports single-transfer mode
req->td->dmacount = 0; /* invalidate */
dma_done (ep, req, dma_done (ep, req,
le32_to_cpup (&req->td->dmacount), readl (&ep->dma->dmacount),
-ECONNRESET); -ECONNRESET);
}
} else { } else {
DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name); DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
done (ep, req, -ECONNRESET); done (ep, req, -ECONNRESET);
} }
req = 0; req = 0;
#ifdef USE_DMA_CHAINING
/* patch up hardware chaining data */ /* patch up hardware chaining data */
} else if (ep->dma) { } else if (ep->dma && use_dma_chaining) {
if (req->queue.prev == ep->queue.next) { if (req->queue.prev == ep->queue.next) {
writel (le32_to_cpu (req->td->dmadesc), writel (le32_to_cpu (req->td->dmadesc),
&ep->dma->dmadesc); &ep->dma->dmadesc);
...@@ -1161,7 +1237,6 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) ...@@ -1161,7 +1237,6 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
if (req->td->dmacount & dma_done_ie) if (req->td->dmacount & dma_done_ie)
prev->td->dmacount |= dma_done_ie; prev->td->dmacount |= dma_done_ie;
} }
#endif
} }
if (req) if (req)
...@@ -1188,10 +1263,14 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) ...@@ -1188,10 +1263,14 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int net2280_fifo_status (struct usb_ep *_ep);
static int static int
net2280_set_halt (struct usb_ep *_ep, int value) net2280_set_halt (struct usb_ep *_ep, int value)
{ {
struct net2280_ep *ep; struct net2280_ep *ep;
unsigned long flags;
int retval = 0;
ep = container_of (_ep, struct net2280_ep, ep); ep = container_of (_ep, struct net2280_ep, ep);
if (!_ep || (!ep->desc && ep->num != 0)) if (!_ep || (!ep->desc && ep->num != 0))
...@@ -1202,19 +1281,27 @@ net2280_set_halt (struct usb_ep *_ep, int value) ...@@ -1202,19 +1281,27 @@ net2280_set_halt (struct usb_ep *_ep, int value)
== USB_ENDPOINT_XFER_ISOC) == USB_ENDPOINT_XFER_ISOC)
return -EINVAL; return -EINVAL;
VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); spin_lock_irqsave (&ep->dev->lock, flags);
if (!list_empty (&ep->queue))
/* set/clear, then synch memory views with the device */ retval = -EAGAIN;
if (value) { else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
if (ep->num == 0) retval = -EAGAIN;
ep->dev->protocol_stall = 1; else {
else VDEBUG (ep->dev, "%s %s halt\n", _ep->name,
set_halt (ep); value ? "set" : "clear");
} else /* set/clear, then synch memory views with the device */
clear_halt (ep); if (value) {
(void) readl (&ep->regs->ep_rsp); if (ep->num == 0)
ep->dev->protocol_stall = 1;
else
set_halt (ep);
} else
clear_halt (ep);
(void) readl (&ep->regs->ep_rsp);
}
spin_unlock_irqrestore (&ep->dev->lock, flags);
return 0; return retval;
} }
static int static int
...@@ -1290,21 +1377,49 @@ static int net2280_get_frame (struct usb_gadget *_gadget) ...@@ -1290,21 +1377,49 @@ static int net2280_get_frame (struct usb_gadget *_gadget)
static int net2280_wakeup (struct usb_gadget *_gadget) static int net2280_wakeup (struct usb_gadget *_gadget)
{ {
struct net2280 *dev; struct net2280 *dev;
u32 tmp;
unsigned long flags;
if (!_gadget) if (!_gadget)
return 0; return 0;
dev = container_of (_gadget, struct net2280, gadget); dev = container_of (_gadget, struct net2280, gadget);
writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
spin_lock_irqsave (&dev->lock, flags);
tmp = readl (&dev->usb->usbctl);
if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE))
writel (1 << GENERATE_RESUME, &dev->usb->usbstat);
spin_unlock_irqrestore (&dev->lock, flags);
/* pci writes may still be posted */ /* pci writes may still be posted */
return 0; return 0;
} }
static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
{
struct net2280 *dev;
u32 tmp;
unsigned long flags;
if (!_gadget)
return 0;
dev = container_of (_gadget, struct net2280, gadget);
spin_lock_irqsave (&dev->lock, flags);
tmp = readl (&dev->usb->usbctl);
if (value)
tmp |= (1 << SELF_POWERED_STATUS);
else
tmp &= ~(1 << SELF_POWERED_STATUS);
writel (tmp, &dev->usb->usbctl);
spin_unlock_irqrestore (&dev->lock, flags);
return 0;
}
static const struct usb_gadget_ops net2280_ops = { static const struct usb_gadget_ops net2280_ops = {
.get_frame = net2280_get_frame, .get_frame = net2280_get_frame,
.wakeup = net2280_wakeup, .wakeup = net2280_wakeup,
.set_selfpowered = net2280_set_selfpowered,
// .set_selfpowered = net2280_set_selfpowered,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -1348,11 +1463,14 @@ show_registers (struct device *_dev, char *buf) ...@@ -1348,11 +1463,14 @@ show_registers (struct device *_dev, char *buf)
/* Main Control Registers */ /* Main Control Registers */
t = snprintf (next, size, "%s version " DRIVER_VERSION t = snprintf (next, size, "%s version " DRIVER_VERSION
", chiprev %04x\n" ", chiprev %04x, dma %s\n\n"
"devinit %03x fifoctl %08x gadget '%s'\n" "devinit %03x fifoctl %08x gadget '%s'\n"
"pci irqenb0 %02x irqenb1 %08x " "pci irqenb0 %02x irqenb1 %08x "
"irqstat0 %04x irqstat1 %08x\n", "irqstat0 %04x irqstat1 %08x\n",
driver_name, dev->chiprev, driver_name, dev->chiprev,
use_dma
? (use_dma_chaining ? "chaining" : "enabled")
: "disabled",
readl (&dev->regs->devinit), readl (&dev->regs->devinit),
readl (&dev->regs->fifoctl), readl (&dev->regs->fifoctl),
s, s,
...@@ -1399,7 +1517,7 @@ show_registers (struct device *_dev, char *buf) ...@@ -1399,7 +1517,7 @@ show_registers (struct device *_dev, char *buf)
t1 = readl (&ep->regs->ep_cfg); t1 = readl (&ep->regs->ep_cfg);
t2 = readl (&ep->regs->ep_rsp) & 0xff; t2 = readl (&ep->regs->ep_rsp) & 0xff;
t = snprintf (next, size, t = snprintf (next, size,
"%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s"
"irqenb %02x\n", "irqenb %02x\n",
ep->ep.name, t1, t2, ep->ep.name, t1, t2,
(t2 & (1 << CLEAR_NAK_OUT_PACKETS)) (t2 & (1 << CLEAR_NAK_OUT_PACKETS))
...@@ -1453,7 +1571,7 @@ show_registers (struct device *_dev, char *buf) ...@@ -1453,7 +1571,7 @@ show_registers (struct device *_dev, char *buf)
// none yet // none yet
/* Statistics */ /* Statistics */
t = snprintf (next, size, "irqs: "); t = snprintf (next, size, "\nirqs: ");
size -= t; size -= t;
next += t; next += t;
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
...@@ -1462,7 +1580,7 @@ show_registers (struct device *_dev, char *buf) ...@@ -1462,7 +1580,7 @@ show_registers (struct device *_dev, char *buf)
ep = &dev->ep [i]; ep = &dev->ep [i];
if (i && !ep->irqs) if (i && !ep->irqs)
continue; continue;
t = snprintf (next, size, " %s/%ld", ep->ep.name, ep->irqs); t = snprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs);
size -= t; size -= t;
next += t; next += t;
...@@ -1504,7 +1622,7 @@ show_queues (struct device *_dev, char *buf) ...@@ -1504,7 +1622,7 @@ show_queues (struct device *_dev, char *buf)
continue; continue;
t = d->bEndpointAddress; t = d->bEndpointAddress;
t = snprintf (next, size, t = snprintf (next, size,
"%s (ep%d%s-%s) max %04x %s\n", "\n%s (ep%d%s-%s) max %04x %s fifo %d\n",
ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK,
(t & USB_DIR_IN) ? "in" : "out", (t & USB_DIR_IN) ? "in" : "out",
({ char *val; ({ char *val;
...@@ -1517,7 +1635,7 @@ show_queues (struct device *_dev, char *buf) ...@@ -1517,7 +1635,7 @@ show_queues (struct device *_dev, char *buf)
val = "iso"; break; val = "iso"; break;
}; val; }), }; val; }),
le16_to_cpu (d->wMaxPacketSize) & 0x1fff, le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
ep->dma ? "dma" : "pio" ep->dma ? "dma" : "pio", ep->fifo_size
); );
} else /* ep0 should only have one transfer queued */ } else /* ep0 should only have one transfer queued */
t = snprintf (next, size, "ep0 max 64 pio %s\n", t = snprintf (next, size, "ep0 max 64 pio %s\n",
...@@ -1552,6 +1670,20 @@ show_queues (struct device *_dev, char *buf) ...@@ -1552,6 +1670,20 @@ show_queues (struct device *_dev, char *buf)
goto done; goto done;
size -= t; size -= t;
next += t; next += t;
if (ep->dma) {
struct net2280_dma *td;
td = req->td;
t = snprintf (next, size, "\t td %08x "
" count %08x buf %08x desc %08x\n",
req->td_dma, td->dmacount,
td->dmaaddr, td->dmadesc);
if (t <= 0 || t > size)
goto done;
size -= t;
next += t;
}
} }
} }
...@@ -1686,8 +1818,10 @@ static void usb_reset (struct net2280 *dev) ...@@ -1686,8 +1818,10 @@ static void usb_reset (struct net2280 *dev)
/* clear old dma and irq state */ /* clear old dma and irq state */
for (tmp = 0; tmp < 4; tmp++) { for (tmp = 0; tmp < 4; tmp++) {
writel ((1 << DMA_ABORT), &dev->dma [tmp].dmastat); struct net2280_ep *ep = &dev->ep [tmp + 1];
stop_dma (&dev->dma [tmp]);
if (ep->dma)
abort_dma (ep);
} }
writel (~0, &dev->regs->irqstat0), writel (~0, &dev->regs->irqstat0),
writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1), writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1),
...@@ -1767,7 +1901,7 @@ static void ep0_start (struct net2280 *dev) ...@@ -1767,7 +1901,7 @@ static void ep0_start (struct net2280 *dev)
| (1 << SELF_POWERED_USB_DEVICE) | (1 << SELF_POWERED_USB_DEVICE)
| (1 << REMOTE_WAKEUP_SUPPORT) | (1 << REMOTE_WAKEUP_SUPPORT)
| (1 << USB_DETECT_ENABLE) | (1 << USB_DETECT_ENABLE)
| (1 << DEVICE_REMOTE_WAKEUP_ENABLE) | (1 << SELF_POWERED_STATUS)
, &dev->usb->usbctl); , &dev->usb->usbctl);
/* enable irqs so we can see ep0 and general operation */ /* enable irqs so we can see ep0 and general operation */
...@@ -1889,6 +2023,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) ...@@ -1889,6 +2023,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
spin_unlock_irqrestore (&dev->lock, flags); spin_unlock_irqrestore (&dev->lock, flags);
driver->unbind (&dev->gadget); driver->unbind (&dev->gadget);
dev->gadget.dev.driver = 0;
dev->driver = 0; dev->driver = 0;
net2280_led_active (dev, 0); net2280_led_active (dev, 0);
...@@ -1947,6 +2082,8 @@ static void handle_ep_small (struct net2280_ep *ep) ...@@ -1947,6 +2082,8 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1; ep->stopped = 1;
set_halt (ep); set_halt (ep);
} }
if (!req)
allow_status (ep);
mode = 2; mode = 2;
/* reply to extra IN data tokens with a zlp */ /* reply to extra IN data tokens with a zlp */
} else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) { } else if (t & (1 << DATA_IN_TOKEN_INTERRUPT)) {
...@@ -1987,41 +2124,62 @@ static void handle_ep_small (struct net2280_ep *ep) ...@@ -1987,41 +2124,62 @@ static void handle_ep_small (struct net2280_ep *ep)
if (likely (ep->dma != 0)) { if (likely (ep->dma != 0)) {
if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) { if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
u32 count; u32 count;
int stopped = ep->stopped;
/* TRANSFERRED works around OUT_DONE erratum 0112. /* TRANSFERRED works around OUT_DONE erratum 0112.
* we expect (N <= maxpacket) bytes; host wrote M. * we expect (N <= maxpacket) bytes; host wrote M.
* iff (M < N) we won't ever see a DMA interrupt. * iff (M < N) we won't ever see a DMA interrupt.
*/ */
count = readl (&ep->dma->dmacount); ep->stopped = 1;
count &= DMA_BYTE_COUNT_MASK; for (count = 0; ; t = readl (&ep->regs->ep_stat)) {
if (!req->dma_done) {
/* dma can finish with the FIFO non-empty, /* any preceding dma transfers must finish.
* on (M > N) errors. * dma handles (M >= N), may empty the queue
*/
scan_dma_completions (ep);
if (unlikely (list_empty (&ep->queue)
|| ep->out_overflow)) {
req = 0;
break;
}
req = list_entry (ep->queue.next,
struct net2280_request, queue);
/* here either (M < N), a "real" short rx;
* or (M == N) and the queue didn't empty
*/ */
while (count && (t & (1 << FIFO_EMPTY)) == 0) { if (likely (t & (1 << FIFO_EMPTY))) {
cpu_relax ();
t = readl (&ep->regs->ep_stat);
count = readl (&ep->dma->dmacount); count = readl (&ep->dma->dmacount);
count &= DMA_BYTE_COUNT_MASK; count &= DMA_BYTE_COUNT_MASK;
if (readl (&ep->dma->dmadesc)
!= req->td_dma)
req = 0;
break;
} }
udelay(1);
} }
/* stop DMA, leave ep NAKing */ /* stop DMA, leave ep NAKing */
writel ((1 << DMA_ABORT), &ep->dma->dmastat); writel ((1 << DMA_ABORT), &ep->dma->dmastat);
spin_stop_dma (ep->dma); spin_stop_dma (ep->dma);
/* buffer might have been too small */ if (likely (req)) {
t = readl (&ep->regs->ep_avail); req->td->dmacount = 0;
if (t != 0) t = readl (&ep->regs->ep_avail);
DEBUG (ep->dev, "%s dma, discard %d len %d\n", dma_done (ep, req, count, t);
ep->ep.name, t, count); }
dma_done (ep, req, count, t ? -EOVERFLOW : 0);
/* also flush to prevent erratum 0106 trouble */ /* also flush to prevent erratum 0106 trouble */
if (t || ep->dev->chiprev == 0x0100) if (unlikely (ep->out_overflow
|| (ep->dev->chiprev == 0x0100
&& ep->dev->gadget.speed
== USB_SPEED_FULL))) {
out_flush (ep); out_flush (ep);
ep->out_overflow = 0;
}
/* restart dma (still NAKing OUT!) if needed */ /* (re)start dma if needed, stop NAKing */
ep->stopped = stopped;
if (!list_empty (&ep->queue)) if (!list_empty (&ep->queue))
restart_dma (ep); restart_dma (ep);
} else } else
...@@ -2192,11 +2350,12 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2192,11 +2350,12 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
* that'll mean a lot less irqs for some drivers. * that'll mean a lot less irqs for some drivers.
*/ */
ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0; ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
if (ep->is_in) if (ep->is_in) {
scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT) scratch = (1 << DATA_PACKET_TRANSMITTED_INTERRUPT)
| (1 << DATA_OUT_PING_TOKEN_INTERRUPT) | (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
| (1 << DATA_IN_TOKEN_INTERRUPT); | (1 << DATA_IN_TOKEN_INTERRUPT);
else stop_out_naking (ep);
} else
scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT) scratch = (1 << DATA_PACKET_RECEIVED_INTERRUPT)
| (1 << DATA_OUT_PING_TOKEN_INTERRUPT) | (1 << DATA_OUT_PING_TOKEN_INTERRUPT)
| (1 << DATA_IN_TOKEN_INTERRUPT); | (1 << DATA_IN_TOKEN_INTERRUPT);
...@@ -2398,18 +2557,18 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) ...@@ -2398,18 +2557,18 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
tmp = readl (&dma->dmastat); tmp = readl (&dma->dmastat);
writel (tmp, &dma->dmastat); writel (tmp, &dma->dmastat);
#ifdef USE_DMA_CHAINING /* chaining should stop on abort, short OUT from fifo,
/* chaining should stop only on error (which?)
* or (stat0 codepath) short OUT transfer. * or (stat0 codepath) short OUT transfer.
*/ */
#else if (!use_dma_chaining) {
if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) == 0) { if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT))
DEBUG (ep->dev, "%s no xact done? %08x\n", == 0) {
ep->ep.name, tmp); DEBUG (ep->dev, "%s no xact done? %08x\n",
continue; ep->ep.name, tmp);
continue;
}
stop_dma (ep->dma);
} }
stop_dma (ep->dma);
#endif
/* OUT transfers terminate when the data from the /* OUT transfers terminate when the data from the
* host is in our memory. Process whatever's done. * host is in our memory. Process whatever's done.
...@@ -2425,16 +2584,14 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) ...@@ -2425,16 +2584,14 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
/* disable dma on inactive queues; else maybe restart */ /* disable dma on inactive queues; else maybe restart */
if (list_empty (&ep->queue)) { if (list_empty (&ep->queue)) {
#ifdef USE_DMA_CHAINING if (use_dma_chaining)
stop_dma (ep->dma); stop_dma (ep->dma);
#endif
} else { } else {
tmp = readl (&dma->dmactl); tmp = readl (&dma->dmactl);
if ((tmp & (1 << DMA_SCATTER_GATHER_ENABLE)) == 0 if (!use_dma_chaining
|| (tmp & (1 << DMA_ENABLE)) == 0) || (tmp & (1 << DMA_ENABLE)) == 0)
restart_dma (ep); restart_dma (ep);
#ifdef USE_DMA_CHAINING else if (ep->is_in && use_dma_chaining) {
else if (ep->desc->bEndpointAddress & USB_DIR_IN) {
struct net2280_request *req; struct net2280_request *req;
u32 dmacount; u32 dmacount;
...@@ -2449,12 +2606,9 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) ...@@ -2449,12 +2606,9 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
dmacount &= __constant_cpu_to_le32 ( dmacount &= __constant_cpu_to_le32 (
(1 << VALID_BIT) (1 << VALID_BIT)
| DMA_BYTE_COUNT_MASK); | DMA_BYTE_COUNT_MASK);
if (dmacount && (dmacount & valid_bit) == 0) { if (dmacount && (dmacount & valid_bit) == 0)
stop_dma (ep->dma);
restart_dma (ep); restart_dma (ep);
}
} }
#endif
} }
ep->irqs++; ep->irqs++;
} }
...@@ -2505,7 +2659,7 @@ static void gadget_release (struct device *_dev) ...@@ -2505,7 +2659,7 @@ static void gadget_release (struct device *_dev)
/* tear down the binding between this driver and the pci device */ /* tear down the binding between this driver and the pci device */
static void net2280_remove (struct pci_dev *pdev) static void __exit net2280_remove (struct pci_dev *pdev)
{ {
struct net2280 *dev = pci_get_drvdata (pdev); struct net2280 *dev = pci_get_drvdata (pdev);
...@@ -2665,12 +2819,14 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2665,12 +2819,14 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
} }
td->dmacount = 0; /* not VALID */ td->dmacount = 0; /* not VALID */
td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
dev->ep [i].dummy = td; dev->ep [i].dummy = td;
} }
/* enable lower-overhead pci memory bursts during DMA */ /* enable lower-overhead pci memory bursts during DMA */
writel ((1 << PCI_RETRY_ABORT_ENABLE) writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE)
| (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) // 256 write retries may not be enough...
// | (1 << PCI_RETRY_ABORT_ENABLE)
| (1 << DMA_READ_MULTIPLE_ENABLE) | (1 << DMA_READ_MULTIPLE_ENABLE)
| (1 << DMA_READ_LINE_ENABLE) | (1 << DMA_READ_LINE_ENABLE)
, &dev->pci->pcimstctl); , &dev->pci->pcimstctl);
...@@ -2686,15 +2842,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2686,15 +2842,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
INFO (dev, "%s\n", driver_desc); INFO (dev, "%s\n", driver_desc);
INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
bufp, base, dev->chiprev); bufp, base, dev->chiprev);
bufp = DRIVER_VERSION INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
#ifndef USE_DMA_CHAINING use_dma
" (no dma chain)" ? (use_dma_chaining ? "chaining" : "enabled")
#endif : "disabled");
#ifdef NET2280_DMA_OUT_WORKAROUND
" (no dma out)"
#endif
;
INFO (dev, "version: %s\n", bufp);
the_controller = dev; the_controller = dev;
device_register (&dev->gadget.dev); device_register (&dev->gadget.dev);
...@@ -2729,7 +2880,7 @@ static struct pci_driver net2280_pci_driver = { ...@@ -2729,7 +2880,7 @@ static struct pci_driver net2280_pci_driver = {
.id_table = pci_ids, .id_table = pci_ids,
.probe = net2280_probe, .probe = net2280_probe,
.remove = net2280_remove, .remove = __exit_p(net2280_remove),
/* FIXME add power management support */ /* FIXME add power management support */
}; };
...@@ -2740,6 +2891,8 @@ MODULE_LICENSE ("GPL"); ...@@ -2740,6 +2891,8 @@ MODULE_LICENSE ("GPL");
static int __init init (void) static int __init init (void)
{ {
if (!use_dma)
use_dma_chaining = 0;
return pci_module_init (&net2280_pci_driver); return pci_module_init (&net2280_pci_driver);
} }
module_init (init); module_init (init);
......
...@@ -520,6 +520,7 @@ struct net2280_ep { ...@@ -520,6 +520,7 @@ struct net2280_ep {
unsigned num : 8, unsigned num : 8,
fifo_size : 12, fifo_size : 12,
in_fifo_validate : 1, in_fifo_validate : 1,
out_overflow : 1,
stopped : 1, stopped : 1,
is_in : 1, is_in : 1,
is_iso : 1; is_iso : 1;
...@@ -529,6 +530,7 @@ static inline void allow_status (struct net2280_ep *ep) ...@@ -529,6 +530,7 @@ static inline void allow_status (struct net2280_ep *ep)
{ {
/* ep0 only */ /* ep0 only */
writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE) writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
| (1 << CLEAR_NAK_OUT_PACKETS)
| (1 << CLEAR_NAK_OUT_PACKETS_MODE) | (1 << CLEAR_NAK_OUT_PACKETS_MODE)
, &ep->regs->ep_rsp); , &ep->regs->ep_rsp);
ep->stopped = 1; ep->stopped = 1;
...@@ -546,7 +548,6 @@ struct net2280_request { ...@@ -546,7 +548,6 @@ struct net2280_request {
dma_addr_t td_dma; dma_addr_t td_dma;
struct list_head queue; struct list_head queue;
unsigned mapped : 1, unsigned mapped : 1,
dma_done : 1,
valid : 1; valid : 1;
}; };
...@@ -559,8 +560,7 @@ struct net2280 { ...@@ -559,8 +560,7 @@ struct net2280 {
unsigned enabled : 1, unsigned enabled : 1,
protocol_stall : 1, protocol_stall : 1,
got_irq : 1, got_irq : 1,
region : 1, region : 1;
selfpowered : 1;
u16 chiprev; u16 chiprev;
/* pci state used to access those endpoints */ /* pci state used to access those endpoints */
......
...@@ -135,9 +135,6 @@ do { \ ...@@ -135,9 +135,6 @@ do { \
#define GS_NUM_PORTS 16 #define GS_NUM_PORTS 16
#define GS_VENDOR_ID 0x05F9
#define GS_PRODUCT_ID 0xFFFF
#define GS_NUM_CONFIGS 1 #define GS_NUM_CONFIGS 1
#define GS_NO_CONFIG_ID 0 #define GS_NO_CONFIG_ID 0
#define GS_BULK_CONFIG_ID 2 #define GS_BULK_CONFIG_ID 2
...@@ -187,7 +184,7 @@ static int debug = G_SERIAL_DEBUG; ...@@ -187,7 +184,7 @@ static int debug = G_SERIAL_DEBUG;
* DMA channels to manage their FIFOs. It supports high speed. * DMA channels to manage their FIFOs. It supports high speed.
* Those endpoints can be arranged in any desired configuration. * Those endpoints can be arranged in any desired configuration.
*/ */
#ifdef CONFIG_USB_G_SERIAL_NET2280 #ifdef CONFIG_USB_GADGET_NET2280
#define CHIP "net2280" #define CHIP "net2280"
#define EP0_MAXPACKET 64 #define EP0_MAXPACKET 64
static const char EP_OUT_NAME[] = "ep-a"; static const char EP_OUT_NAME[] = "ep-a";
...@@ -220,13 +217,13 @@ static inline void hw_optimize(struct usb_gadget *gadget) ...@@ -220,13 +217,13 @@ static inline void hw_optimize(struct usb_gadget *gadget)
* can't use altsettings or reset the interfaces independently. * can't use altsettings or reset the interfaces independently.
* So stick to a single interface. * So stick to a single interface.
*/ */
#ifdef CONFIG_USB_G_SERIAL_PXA2XX #ifdef CONFIG_USB_GADGET_PXA2XX
#define CHIP "pxa2xx" #define CHIP "pxa2xx"
#define EP0_MAXPACKET 16 #define EP0_MAXPACKET 16
static const char EP_OUT_NAME[] = "ep12out-bulk"; static const char EP_OUT_NAME[] = "ep2out-bulk";
#define EP_OUT_NUM 12 #define EP_OUT_NUM 2
static const char EP_IN_NAME[] = "ep11in-bulk"; static const char EP_IN_NAME[] = "ep1in-bulk";
#define EP_IN_NUM 11 #define EP_IN_NUM 1
#define SELFPOWER USB_CONFIG_ATT_SELFPOWER #define SELFPOWER USB_CONFIG_ATT_SELFPOWER
/* no hw optimizations to apply */ /* no hw optimizations to apply */
...@@ -245,7 +242,7 @@ static const char EP_IN_NAME[] = "ep11in-bulk"; ...@@ -245,7 +242,7 @@ static const char EP_IN_NAME[] = "ep11in-bulk";
* in special situations. So this is a case of "choose it right * in special situations. So this is a case of "choose it right
* during enumeration" ... * during enumeration" ...
*/ */
#ifdef CONFIG_USB_G_SERIAL_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100" #define CHIP "sa1100"
#define EP0_MAXPACKET 8 #define EP0_MAXPACKET 8
static const char EP_OUT_NAME[] = "ep1out-bulk"; static const char EP_OUT_NAME[] = "ep1out-bulk";
...@@ -264,7 +261,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -264,7 +261,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
* *
* This has three semi-configurable full speed bulk/interrupt endpoints. * This has three semi-configurable full speed bulk/interrupt endpoints.
*/ */
#ifdef CONFIG_USB_G_SERIAL_GOKU #ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku" #define CHIP "goku"
#define DRIVER_VERSION_NUM 0x0116 #define DRIVER_VERSION_NUM 0x0116
#define EP0_MAXPACKET 8 #define EP0_MAXPACKET 8
...@@ -302,6 +299,14 @@ static const char EP_IN_NAME [] = "ep2-bulk"; ...@@ -302,6 +299,14 @@ static const char EP_IN_NAME [] = "ep2-bulk";
/* else value must be USB_CONFIG_ATT_WAKEUP */ /* else value must be USB_CONFIG_ATT_WAKEUP */
#endif #endif
/* Thanks to NetChip Technologies for donating this product ID.
*
* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures.
*/
#define GS_VENDOR_ID 0x0525 /* NetChip */
#define GS_PRODUCT_ID 0xa4a6 /* Linux-USB Serial Gadget */
/* Structures */ /* Structures */
......
...@@ -131,7 +131,7 @@ static const char loopback [] = "loop input to output"; ...@@ -131,7 +131,7 @@ static const char loopback [] = "loop input to output";
* DMA channels to manage their FIFOs. It supports high speed. * DMA channels to manage their FIFOs. It supports high speed.
* Those endpoints can be arranged in any desired configuration. * Those endpoints can be arranged in any desired configuration.
*/ */
#ifdef CONFIG_USB_ZERO_NET2280 #if defined(CONFIG_USB_GADGET_NET2280) || defined(CONFIG_USB_GADGET_DUMMY_HCD)
#define CHIP "net2280" #define CHIP "net2280"
#define DRIVER_VERSION_NUM 0x0101 #define DRIVER_VERSION_NUM 0x0101
static const char EP_OUT_NAME [] = "ep-a"; static const char EP_OUT_NAME [] = "ep-a";
...@@ -154,7 +154,7 @@ static const char EP_IN_NAME [] = "ep-b"; ...@@ -154,7 +154,7 @@ static const char EP_IN_NAME [] = "ep-b";
* can't use altsettings or reset the interfaces independently. * can't use altsettings or reset the interfaces independently.
* So stick to a single interface. * So stick to a single interface.
*/ */
#ifdef CONFIG_USB_ZERO_PXA2XX #ifdef CONFIG_USB_GADGET_PXA2XX
#define CHIP "pxa2xx" #define CHIP "pxa2xx"
#define DRIVER_VERSION_NUM 0x0103 #define DRIVER_VERSION_NUM 0x0103
static const char EP_OUT_NAME [] = "ep12out-bulk"; static const char EP_OUT_NAME [] = "ep12out-bulk";
...@@ -176,7 +176,7 @@ static const char EP_IN_NAME [] = "ep11in-bulk"; ...@@ -176,7 +176,7 @@ static const char EP_IN_NAME [] = "ep11in-bulk";
* in special situations. So this is a case of "choose it right * in special situations. So this is a case of "choose it right
* during enumeration" ... * during enumeration" ...
*/ */
#ifdef CONFIG_USB_ZERO_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100" #define CHIP "sa1100"
#define DRIVER_VERSION_NUM 0x0105 #define DRIVER_VERSION_NUM 0x0105
static const char EP_OUT_NAME [] = "ep1out-bulk"; static const char EP_OUT_NAME [] = "ep1out-bulk";
...@@ -192,7 +192,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk"; ...@@ -192,7 +192,7 @@ static const char EP_IN_NAME [] = "ep2in-bulk";
* *
* This has three semi-configurable full speed bulk/interrupt endpoints. * This has three semi-configurable full speed bulk/interrupt endpoints.
*/ */
#ifdef CONFIG_USB_ZERO_GOKU #ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku" #define CHIP "goku"
#define DRIVER_VERSION_NUM 0x0106 #define DRIVER_VERSION_NUM 0x0106
static const char EP_OUT_NAME [] = "ep1-bulk"; static const char EP_OUT_NAME [] = "ep1-bulk";
...@@ -936,7 +936,7 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) ...@@ -936,7 +936,7 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
if (number == dev->config) if (number == dev->config)
return 0; return 0;
#ifdef CONFIG_USB_ZERO_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
if (dev->config) { if (dev->config) {
/* tx fifo is full, but we can't clear it...*/ /* tx fifo is full, but we can't clear it...*/
INFO (dev, "can't change configurations\n"); INFO (dev, "can't change configurations\n");
......
...@@ -684,6 +684,10 @@ MODULE_LICENSE ("GPL"); ...@@ -684,6 +684,10 @@ MODULE_LICENSE ("GPL");
#include "ohci-sa1111.c" #include "ohci-sa1111.c"
#endif #endif
#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111)) #ifdef CONFIG_ARCH_OMAP
#include "ohci-omap.c"
#endif
#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP))
#error "missing bus glue for ohci-hcd" #error "missing bus glue for ohci-hcd"
#endif #endif
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
*
* OMAP Bus Glue
*
* Written by Christopher Hoover <ch@hpl.hp.com>
* Based on fragments of previous driver by Rusell King et al.
*
* Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
* Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
*
* This file is licenced under the GPL.
*/
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/arch/bus.h>
#include <asm/arch/hardware.h>
#include <asm/arch/mux.h>
#include <asm/arch/irqs.h>
#include "ohci-omap.h"
#ifndef CONFIG_ARCH_OMAP
#error "This file is OMAP bus glue. CONFIG_OMAP must be defined."
#endif
extern int usb_disabled(void);
extern int ocpi_enable(void);
/*
* Use the first port only by default. Override with hmc_mode option.
*
* NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports
* 1 & 2, so only port 0 will work. To use the OHCI on the first port, use
* the Innovator USB client cable with a client-to-client connector and modify
* either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should
* be the red lead in the cable.
*
* To mount USB hard disk as root, see the patch for do_mounts.c that tries
* remounting the root, and use root=0801 if your root is on sda1. Does not
* work with devfs.
*/
static int default_hmc_mode = 16;
static int hmc_mode = 1234;
/*
* Set the USB host pin multiplexing and the selected HMC mode
*/
static int omap_usb_set_hmc_mode(int hmc_mode)
{
unsigned int val;
switch (hmc_mode) {
case 0:
/* 0: function, 1: disabled, 2: disabled */
omap_cfg_reg(W4_USB_PUEN);
omap_cfg_reg(R18_1510_USB_GPIO0);
break;
case 4:
/* 0: function 1: host 2: host */
omap_cfg_reg(usb1_speed);
omap_cfg_reg(usb1_susp);
omap_cfg_reg(usb1_seo);
omap_cfg_reg(usb1_txen);
omap_cfg_reg(usb1_txd);
omap_cfg_reg(usb1_vp);
omap_cfg_reg(usb1_vm);
omap_cfg_reg(usb1_rcv);
omap_cfg_reg(usb2_susp);
omap_cfg_reg(usb2_seo);
omap_cfg_reg(usb2_txen);
omap_cfg_reg(usb2_txd);
omap_cfg_reg(usb2_vp);
omap_cfg_reg(usb2_vm);
omap_cfg_reg(usb2_rcv);
break;
case 16:
/* 0: host, 1: disabled, 2: disabled */
omap_cfg_reg(W9_USB0_TXEN);
omap_cfg_reg(AA9_USB0_VP);
omap_cfg_reg(Y5_USB0_RCV);
omap_cfg_reg(R9_USB0_VM);
omap_cfg_reg(V6_USB0_TXD);
omap_cfg_reg(W5_USB0_SE0);
break;
default:
printk("Unknown USB host configuration: %i\n", hmc_mode);
return -ENODEV;
}
/* Write the selected HMC mode */
val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR;
val |= (hmc_mode << 1);
writel(val, MOD_CONF_CTRL_0);
return 0;
}
/*
* OHCI clock initialization for OMAP-1510 and 1610
*/
static int omap_ohci_clock_power(int on)
{
if (on) {
if (cpu_is_omap_1510()) {
/* Use DPLL, not APLL */
writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH,
ULPD_APLL_CTRL_REG);
/* Enable DPLL */
writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE,
ULPD_DPLL_CTRL_REG);
/* Software request for USB 48MHz clock */
writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ,
ULPD_SOFT_REQ_REG);
while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK));
}
if (cpu_is_omap_1610()) {
/* Enable OHCI */
writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ,
ULPD_SOFT_REQ_REG);
/* USB host clock request if not using OTG */
writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ,
ULPD_SOFT_REQ_REG);
outl(inl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
ULPD_STATUS_REQ_REG);
}
/* Enable 48MHz clock to USB */
writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN,
ULPD_CLOCK_CTRL_REG);
writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
ARM_IDLECT2);
writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
MOD_CONF_CTRL_0);
} else {
/* Disable 48MHz clock to USB */
writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN,
ULPD_CLOCK_CTRL_REG);
/* FIXME: The DPLL stays on for now */
}
return 0;
}
/*
* Hardware specific transceiver power on/off
*/
static int omap_ohci_transceiver_power(int on)
{
if (on) {
if (omap_is_innovator())
writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20,
OMAP1510_FPGA_HOST_CTRL);
} else {
if (omap_is_innovator())
writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20,
OMAP1510_FPGA_HOST_CTRL);
}
return 0;
}
/*
* OMAP-1510 specific Local Bus clock on/off
*/
static int omap_1510_local_bus_power(int on)
{
if (on) {
writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
udelay(200);
} else {
writel(0, OMAP1510_LB_MMU_CTL);
}
return 0;
}
/*
* OMAP-1510 specific Local Bus initialization
* NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
* See also arch/mach-omap/memory.h for __virt_to_bus() and
* __bus_to_virt() which need to match with the physical
* Local Bus address below.
*/
static int omap_1510_local_bus_init(void)
{
unsigned int tlb;
unsigned long lbaddr, physaddr;
writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
OMAP1510_LB_CLOCK_DIV);
/* Configure the Local Bus MMU table */
for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
physaddr = tlb * 0x00100000 + PHYS_OFFSET;
writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
OMAP1510_LB_MMU_CAM_L);
writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
writel(tlb << 4, OMAP1510_LB_MMU_LCK);
writel(0x1, OMAP1510_LB_MMU_LD_TLB);
}
/* Enable the walking table */
writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
udelay(200);
return 0;
}
/*
* OMAP-1610 specific hardware initialization
*
* Intended to configure OMAP-1610 USB host and OTG ports depending on
* the HMC mode selected.
*
* FIXME: Currently only supports alternate ping group 2 mode, should
* be easy to modify for other configurations once there is some
* hardware to test with.
*/
static int omap_1610_usb_init(int mode)
{
u_int val = 0;
/* Configure the OMAP transceiver settings */
val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/
val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */
//val |= (1 << 3); /* Isolate integrated transceiver from port 0 */
val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */
val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */
outl(val, USB_TRANSCEIVER_CTRL);
/* Set the USB0_TRX_MODE */
val = 0;
val &= ~OTG_IDLE_EN;
val &= ~DEV_IDLE_EN;
val &= ~(7 << 16); /* Clear USB0_TRX_MODE */
val |= (3 << 16); /* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
outl(val, OTG_SYSCON_1);
/*
* Control via OTG, see TRM p 15-163
*/
val = 0;
//val |= 1; /* REVISIT: Enable OTG = 1 */
/* Control via OTG */
val &= ~HMC_PADEN;
val &= ~OTG_PADEN;
val |= UHOST_EN;
val &= ~0x3f; /* Clear HMC mode */
val |= mode; /* Set HMC mode */
val &= ~(7 << 16); /* Clear ASE0_BRST */
val |= (4 << 16); /* Must be 4 */
val |= USBX_SYNCHRO; /* Must be set */
val |= SRP_VBUS;
outl(val, OTG_SYSCON_2);
/* Enable OTG idle */
//outl(inl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
return 0;
}
/*-------------------------------------------------------------------------*/
static void omap_start_hc(struct omap_dev *dev)
{
printk(KERN_DEBUG __FILE__
": starting OMAP OHCI USB Controller\n");
/*
* Set the HMC mode for the USB ports
*/
#if 0
/* See note about the Innovator wiring above */
if (omap_is_innovator())
hmc_mode = 4; /* 0: function 1: host 2: host */
#endif
if (cpu_is_omap_1610())
ocpi_enable();
omap_usb_set_hmc_mode(hmc_mode);
omap_ohci_clock_power(1);
omap_ohci_transceiver_power(1);
if (cpu_is_omap_1510()) {
omap_1510_local_bus_power(1);
omap_1510_local_bus_init();
}
if (cpu_is_omap_1610())
omap_1610_usb_init(hmc_mode);
//omap_enable_device(dev);
}
static void omap_stop_hc(struct omap_dev *dev)
{
printk(KERN_DEBUG __FILE__
": stopping OMAP OHCI USB Controller\n");
/*
* FIXME: Put the USB host controller into reset.
*/
/*
* FIXME: Stop the USB clock.
*/
//omap_disable_device(dev);
}
/*-------------------------------------------------------------------------*/
static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
{
struct usb_hcd *hcd = __hcd;
return usb_hcd_irq(irq, hcd, r);
}
/*-------------------------------------------------------------------------*/
void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
/**
* usb_hcd_omap_probe - initialize OMAP-based HCDs
* Context: !in_interrupt()
*
* Allocates basic resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*
* Store this function in the HCD's struct pci_driver as probe().
*/
int usb_hcd_omap_probe (const struct hc_driver *driver,
struct usb_hcd **hcd_out,
struct omap_dev *dev)
{
int retval;
struct usb_hcd *hcd = 0;
if (!request_mem_region(dev->res.start,
dev->res.end - dev->res.start + 1, hcd_name)) {
dbg("request_mem_region failed");
return -EBUSY;
}
omap_start_hc(dev);
hcd = driver->hcd_alloc ();
if (hcd == NULL){
dbg ("hcd_alloc failed");
retval = -ENOMEM;
goto err1;
}
hcd->driver = (struct hc_driver *) driver;
hcd->description = driver->description;
hcd->irq = dev->irq[0];
hcd->regs = dev->mapbase;
hcd->pdev = OMAP_FAKE_PCIDEV;
hcd->self.controller = &dev->dev;
hcd->controller = hcd->self.controller;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
dbg ("pool alloc fail");
goto err1;
}
retval = request_irq (hcd->irq,
usb_hcd_omap_hcim_irq,
SA_INTERRUPT, hcd->description, hcd);
if (retval != 0) {
dbg("request_irq failed");
retval = -EBUSY;
goto err2;
}
info ("%s (OMAP) at 0x%p, irq %d\n",
hcd->description, hcd->regs, hcd->irq);
usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = "omap";
hcd->product_desc = "OMAP OHCI";
INIT_LIST_HEAD (&hcd->dev_list);
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
{
usb_hcd_omap_remove(hcd, dev);
return retval;
}
*hcd_out = hcd;
return 0;
err2:
hcd_buffer_destroy (hcd);
if (hcd)
driver->hcd_free(hcd);
err1:
omap_stop_hc(dev);
release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
return retval;
}
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
* usb_hcd_omap_remove - shutdown processing for OMAP-based HCDs
* @dev: USB Host Controller being removed
* Context: !in_interrupt()
*
* Reverses the effect of usb_hcd_omap_probe(), first invoking
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
{
struct usb_device *hub;
void *base;
info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
if (in_interrupt ())
BUG ();
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hub);
hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd);
hcd->state = USB_STATE_HALT;
free_irq (hcd->irq, hcd);
usb_deregister_bus (&hcd->self);
base = hcd->regs;
hcd->driver->hcd_free (hcd);
omap_stop_hc(dev);
release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
}
/*-------------------------------------------------------------------------*/
static int __devinit
ohci_omap_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ret;
if (hcd->pdev) {
ohci->hcca = pci_alloc_consistent (hcd->pdev,
sizeof *ohci->hcca, &ohci->hcca_dma);
if (!ohci->hcca)
return -ENOMEM;
}
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
if ((ret = ohci_mem_init (ohci)) < 0) {
ohci_stop (hcd);
return ret;
}
ohci->regs = hcd->regs;
if (hc_reset (ohci) < 0) {
ohci_stop (hcd);
return -ENODEV;
}
if (hc_start (ohci) < 0) {
err ("can't start %s", ohci->hcd.self.bus_name);
ohci_stop (hcd);
return -EBUSY;
}
create_debug_files (ohci);
#ifdef DEBUG
ohci_dump (ohci, 1);
#endif
return 0;
}
/*-------------------------------------------------------------------------*/
static const struct hc_driver ohci_omap_hc_driver = {
.description = hcd_name,
/*
* generic hardware linkage
*/
.irq = ohci_irq,
.flags = HCD_USB11,
/*
* basic lifecycle operations
*/
.start = ohci_omap_start,
#ifdef CONFIG_PM
/* suspend: ohci_omap_suspend, -- tbd */
/* resume: ohci_omap_resume, -- tbd */
#endif
.stop = ohci_stop,
/*
* memory lifecycle (except per-request)
*/
.hcd_alloc = ohci_hcd_alloc,
.hcd_free = ohci_hcd_free,
/*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
/*
* scheduling support
*/
.get_frame_number = ohci_get_frame,
/*
* root hub support
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
};
/*-------------------------------------------------------------------------*/
static int ohci_hcd_omap_drv_probe(struct omap_dev *dev)
{
struct usb_hcd *hcd = NULL;
int ret;
if (usb_disabled())
return -ENODEV;
ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev);
if (ret == 0)
omap_set_drvdata(dev, hcd);
return ret;
}
static int ohci_hcd_omap_drv_remove(struct omap_dev *dev)
{
struct usb_hcd *hcd = omap_get_drvdata(dev);
usb_hcd_omap_remove(hcd, dev);
omap_set_drvdata(dev, NULL);
return 0;
}
/*
* Driver definition to register with the OMAP bus
*/
static struct omap_driver ohci_hcd_omap_driver = {
.drv = {
.name = OMAP_OHCI_NAME,
},
.devid = OMAP_OCP_DEVID_USB,
.busid = OMAP_BUS_OCP,
.clocks = 0,
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
};
/* Any dma_mask must be set for OHCI to work */
static u64 omap_dmamask = 0xffffffffUL;
/*
* Device definition to match the driver above
*/
static struct omap_dev ohci_hcd_omap_device = {
.name = OMAP_OHCI_NAME,
.devid = OMAP_OCP_DEVID_USB,
.busid = OMAP_BUS_OCP,
.mapbase = (void *)OMAP_OHCI_BASE,
.dma_mask = &omap_dmamask, /* Needed only for OHCI */
.res = {
.start = OMAP_OHCI_BASE,
.end = OMAP_OHCI_BASE + OMAP_OHCI_SIZE,
},
.irq = {
INT_OHCI,
},
};
static int __init ohci_hcd_omap_init (void)
{
int ret;
dbg (DRIVER_INFO " (OMAP)");
dbg ("block sizes: ed %d td %d\n",
sizeof (struct ed), sizeof (struct td));
if (hmc_mode < 0 || hmc_mode > 25)
hmc_mode = default_hmc_mode;
/* Register the driver with OMAP bus */
ret = omap_driver_register(&ohci_hcd_omap_driver);
if (ret != 0)
return -ENODEV;
/* Register the device with OMAP bus */
ret = omap_device_register(&ohci_hcd_omap_device);
if (ret != 0) {
omap_driver_unregister(&ohci_hcd_omap_driver);
return -ENODEV;
}
return ret;
}
MODULE_PARM(hmc_mode, "hmc_mode");
static void __exit ohci_hcd_omap_cleanup (void)
{
omap_device_unregister(&ohci_hcd_omap_device);
omap_driver_unregister(&ohci_hcd_omap_driver);
}
module_init (ohci_hcd_omap_init);
module_exit (ohci_hcd_omap_cleanup);
/*
* linux/drivers/usb/host/ohci-omap.h
*
* OMAP OHCI USB controller specific defines
*/
/* OMAP USB OHCI common defines */
#define OMAP_OHCI_NAME "omap-ohci"
#define OMAP_OHCI_BASE 0xfffba000
#define OMAP_OHCI_SIZE 4096
#define HMC_CLEAR (0x3f << 1)
#define APLL_NDPLL_SWITCH 0x0001
#define DPLL_PLL_ENABLE 0x0010
#define DPLL_LOCK 0x0001
#define SOFT_REQ_REG_REQ 0x0001
#define USB_MCLK_EN 0x0010
#define USB_HOST_HHC_UHOST_EN 0x00000200
#define SOFT_USB_OTG_REQ (1 << 8)
#define SOFT_USB_REQ (1 << 3)
#define STATUS_REQ_REG 0xfffe0840
#define USB_HOST_DPLL_REQ (1 << 8)
#define SOFT_DPLL_REQ (1 << 0)
/* OMAP-1510 USB OHCI defines */
#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */
#define OMAP1510_LB_CLOCK_DIV 0xfffec10c
#define OMAP1510_LB_MMU_CTL 0xfffec208
#define OMAP1510_LB_MMU_LCK 0xfffec224
#define OMAP1510_LB_MMU_LD_TLB 0xfffec228
#define OMAP1510_LB_MMU_CAM_H 0xfffec22c
#define OMAP1510_LB_MMU_CAM_L 0xfffec230
#define OMAP1510_LB_MMU_RAM_H 0xfffec234
#define OMAP1510_LB_MMU_RAM_L 0xfffec238
/* OMAP-1610 USB OHCI defines */
#define USB_TRANSCEIVER_CTRL 0xfffe1064
#define OTG_REV 0xfffb0400
#define OTG_SYSCON_1 0xfffb0404
#define OTG_IDLE_EN (1 << 15)
#define DEV_IDLE_EN (1 << 13)
#define OTG_SYSCON_2 0xfffb0408
#define OTG_CTRL 0xfffb040c
#define OTG_IRQ_EN 0xfffb0410
#define OTG_IRQ_SRC 0xfffb0414
#define OTG_EN (1 << 31)
#define USBX_SYNCHRO (1 << 30)
#define SRP_VBUS (1 << 12)
#define OTG_PADEN (1 << 10)
#define HMC_PADEN (1 << 9)
#define UHOST_EN (1 << 8)
/* Hardware specific defines */
#define OMAP1510_FPGA_HOST_CTRL 0xe800020c
...@@ -781,17 +781,25 @@ static int dabusb_probe (struct usb_interface *intf, ...@@ -781,17 +781,25 @@ static int dabusb_probe (struct usb_interface *intf,
static void dabusb_disconnect (struct usb_interface *intf) static void dabusb_disconnect (struct usb_interface *intf)
{ {
wait_queue_t __wait;
pdabusb_t s = usb_get_intfdata (intf); pdabusb_t s = usb_get_intfdata (intf);
dbg("dabusb_disconnect"); dbg("dabusb_disconnect");
init_waitqueue_entry(&__wait, current);
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (s) { if (s) {
usb_deregister_dev (intf, &dabusb_class); usb_deregister_dev (intf, &dabusb_class);
s->remove_pending = 1; s->remove_pending = 1;
wake_up (&s->wait); wake_up (&s->wait);
add_wait_queue(&s->remove_ok, &__wait);
set_current_state(TASK_UNINTERRUPTIBLE);
if (s->state == _started) if (s->state == _started)
sleep_on (&s->remove_ok); schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&s->remove_ok, &__wait);
s->usbdev = NULL; s->usbdev = NULL;
s->overruns = 0; s->overruns = 0;
} }
......
...@@ -6,6 +6,7 @@ comment "USB Miscellaneous drivers" ...@@ -6,6 +6,7 @@ comment "USB Miscellaneous drivers"
config USB_EMI62 config USB_EMI62
tristate "EMI 6|2m USB Audio interface support" tristate "EMI 6|2m USB Audio interface support"
depends on USB
---help--- ---help---
This driver loads firmware to Emagic EMI 6|2m low latency USB This driver loads firmware to Emagic EMI 6|2m low latency USB
Audio and Midi interface. Audio and Midi interface.
...@@ -20,6 +21,7 @@ config USB_EMI62 ...@@ -20,6 +21,7 @@ config USB_EMI62
config USB_EMI26 config USB_EMI26
tristate "EMI 2|6 USB Audio interface support" tristate "EMI 2|6 USB Audio interface support"
depends on USB
---help--- ---help---
This driver loads firmware to Emagic EMI 2|6 low latency USB This driver loads firmware to Emagic EMI 2|6 low latency USB
Audio interface. Audio interface.
......
...@@ -1927,7 +1927,6 @@ static int auerswald_probe (struct usb_interface *intf, ...@@ -1927,7 +1927,6 @@ static int auerswald_probe (struct usb_interface *intf,
{ {
struct usb_device *usbdev = interface_to_usbdev(intf); struct usb_device *usbdev = interface_to_usbdev(intf);
pauerswald_t cp = NULL; pauerswald_t cp = NULL;
DECLARE_WAIT_QUEUE_HEAD (wqh);
unsigned int u = 0; unsigned int u = 0;
char *pbuf; char *pbuf;
int ret; int ret;
...@@ -1975,7 +1974,8 @@ static int auerswald_probe (struct usb_interface *intf, ...@@ -1975,7 +1974,8 @@ static int auerswald_probe (struct usb_interface *intf,
dbg ("Version is %X", cp->version); dbg ("Version is %X", cp->version);
/* allow some time to settle the device */ /* allow some time to settle the device */
sleep_on_timeout (&wqh, HZ / 3 ); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/3);
/* Try to get a suitable textual description of the device */ /* Try to get a suitable textual description of the device */
/* Device name:*/ /* Device name:*/
......
...@@ -161,7 +161,7 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos) ...@@ -161,7 +161,7 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
int bytes_to_read = 0; int bytes_to_read = 0;
int bytes_read = 0; int bytes_read = 0;
int result = 0; int result = 0;
char buffer[BULK_RCV_MAX]; char *buffer;
unsigned int pipe; unsigned int pipe;
if (*f_pos) if (*f_pos)
...@@ -173,6 +173,10 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos) ...@@ -173,6 +173,10 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
if (!s->dev) if (!s->dev)
return -EIO; return -EIO;
buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count; bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
pipe = usb_rcvbulkpipe (s->dev, 1); pipe = usb_rcvbulkpipe (s->dev, 1);
...@@ -203,6 +207,7 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos) ...@@ -203,6 +207,7 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
} }
out: out:
kfree(buffer);
return ret ? ret : bytes_read; return ret ? ret : bytes_read;
} }
...@@ -214,7 +219,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * ...@@ -214,7 +219,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
int bytes_to_write = 0; int bytes_to_write = 0;
int bytes_written = 0; int bytes_written = 0;
int result = 0; int result = 0;
char buffer[BULK_SND_MAX]; char *buffer;
unsigned int pipe; unsigned int pipe;
if (*f_pos) if (*f_pos)
...@@ -226,6 +231,10 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * ...@@ -226,6 +231,10 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
if (!s->dev) if (!s->dev)
return -EIO; return -EIO;
buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count; bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
if (copy_from_user (buffer, buf, bytes_to_write)) { if (copy_from_user (buffer, buf, bytes_to_write)) {
ret = -EFAULT; ret = -EFAULT;
...@@ -258,6 +267,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * ...@@ -258,6 +267,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
} }
out: out:
kfree(buffer);
return ret ? ret : bytes_written; return ret ? ret : bytes_written;
} }
...@@ -387,7 +397,11 @@ tiglusb_probe (struct usb_interface *intf, ...@@ -387,7 +397,11 @@ tiglusb_probe (struct usb_interface *intf,
static void static void
tiglusb_disconnect (struct usb_interface *intf) tiglusb_disconnect (struct usb_interface *intf)
{ {
wait_queue_t __wait;
ptiglusb_t s = usb_get_intfdata (intf); ptiglusb_t s = usb_get_intfdata (intf);
init_waitqueue_entry(&__wait, current);
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (!s || !s->dev) { if (!s || !s->dev) {
...@@ -397,8 +411,12 @@ tiglusb_disconnect (struct usb_interface *intf) ...@@ -397,8 +411,12 @@ tiglusb_disconnect (struct usb_interface *intf)
s->remove_pending = 1; s->remove_pending = 1;
wake_up (&s->wait); wake_up (&s->wait);
add_wait_queue(&s->wait, &__wait);
set_current_state(TASK_UNINTERRUPTIBLE);
if (s->state == _started) if (s->state == _started)
sleep_on (&s->remove_ok); schedule();
current->state = TASK_RUNNING;
remove_wait_queue(&s->wait, &__wait);
down (&s->mutex); down (&s->mutex);
s->dev = NULL; s->dev = NULL;
s->opened = 0; s->opened = 0;
......
...@@ -651,7 +651,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -651,7 +651,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
return 0; return 0;
case TCSETS: // 0x5402 case TCSETS: // 0x5402
if (! &port->tty->termios) { if (!(port->tty->termios)) {
dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
return -ENOTTY; return -ENOTTY;
} }
......
...@@ -353,8 +353,8 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -353,8 +353,8 @@ static int whiteheat_attach (struct usb_serial *serial)
int pipe; int pipe;
int ret; int ret;
int alen; int alen;
__u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 }; __u8 *command;
__u8 result[sizeof(*hw_info) + 1]; __u8 *result;
int i; int i;
int j; int j;
struct urb *urb; struct urb *urb;
...@@ -365,13 +365,22 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -365,13 +365,22 @@ static int whiteheat_attach (struct usb_serial *serial)
command_port = serial->port[COMMAND_PORT]; command_port = serial->port[COMMAND_PORT];
pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress); pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
command = kmalloc(2, GFP_KERNEL);
if (!command)
goto no_command_buffer;
command[0] = WHITEHEAT_GET_HW_INFO;
command[1] = 0;
result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL);
if (!result)
goto no_result_buffer;
/* /*
* When the module is reloaded the firmware is still there and * When the module is reloaded the firmware is still there and
* the endpoints are still in the usb core unchanged. This is the * the endpoints are still in the usb core unchanged. This is the
* unlinking bug in disguise. Same for the call below. * unlinking bug in disguise. Same for the call below.
*/ */
usb_clear_halt(serial->dev, pipe); usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, COMMAND_TIMEOUT); ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT);
if (ret) { if (ret) {
err("%s: Couldn't send command [%d]", serial->type->name, ret); err("%s: Couldn't send command [%d]", serial->type->name, ret);
goto no_firmware; goto no_firmware;
...@@ -383,7 +392,7 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -383,7 +392,7 @@ static int whiteheat_attach (struct usb_serial *serial)
pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress); pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */ /* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe); usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, COMMAND_TIMEOUT); ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT);
if (ret) { if (ret) {
err("%s: Couldn't get results [%d]", serial->type->name, ret); err("%s: Couldn't get results [%d]", serial->type->name, ret);
goto no_firmware; goto no_firmware;
...@@ -485,6 +494,8 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -485,6 +494,8 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_set_serial_port_data(command_port, command_info); usb_set_serial_port_data(command_port, command_info);
command_port->write_urb->complete = command_port_write_callback; command_port->write_urb->complete = command_port_write_callback;
command_port->read_urb->complete = command_port_read_callback; command_port->read_urb->complete = command_port_read_callback;
kfree(result);
kfree(command);
return 0; return 0;
...@@ -526,6 +537,10 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -526,6 +537,10 @@ static int whiteheat_attach (struct usb_serial *serial)
no_private: no_private:
; ;
} }
kfree(result);
no_result_buffer:
kfree(command);
no_command_buffer:
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -309,44 +309,6 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off ...@@ -309,44 +309,6 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off
* Sysfs interface * Sysfs interface
***********************************************************************/ ***********************************************************************/
/* Output routine for the sysfs info file */
static ssize_t show_info(struct device *dev, char *buffer)
{
char *pos = buffer;
const int length = PAGE_SIZE;
struct scsi_device *sdev = to_scsi_device(dev);
struct us_data *us = (struct us_data*)sdev->host->hostdata[0];
/* print the controller name */
SPRINTF(" Host scsi%d: usb-storage\n", sdev->host->host_no);
/* print product, vendor, and serial number strings */
SPRINTF(" Vendor: %s\n", us->vendor);
SPRINTF(" Product: %s\n", us->product);
SPRINTF("Serial Number: %s\n", us->serial);
/* show the protocol and transport */
SPRINTF(" Protocol: %s\n", us->protocol_name);
SPRINTF(" Transport: %s\n", us->transport_name);
/* show the device flags */
if (pos < buffer + length) {
pos += sprintf(pos, " Quirks:");
DO_FLAG(SINGLE_LUN);
DO_FLAG(SCM_MULT_TARG);
DO_FLAG(FIX_INQUIRY);
DO_FLAG(FIX_CAPACITY);
*(pos++) = '\n';
}
return (pos - buffer);
}
static DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
/* Output routine for the sysfs max_sectors file */ /* Output routine for the sysfs max_sectors file */
static ssize_t show_max_sectors(struct device *dev, char *buf) static ssize_t show_max_sectors(struct device *dev, char *buf)
{ {
...@@ -373,7 +335,6 @@ static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors, ...@@ -373,7 +335,6 @@ static DEVICE_ATTR(max_sectors, S_IRUGO | S_IWUSR, show_max_sectors,
store_max_sectors); store_max_sectors);
static struct device_attribute *sysfs_device_attr_list[] = { static struct device_attribute *sysfs_device_attr_list[] = {
&dev_attr_info,
&dev_attr_max_sectors, &dev_attr_max_sectors,
NULL, NULL,
}; };
......
...@@ -115,6 +115,13 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, ...@@ -115,6 +115,13 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
"DVD-CAM DZ-MV100A Camcorder", "DVD-CAM DZ-MV100A Camcorder",
US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
/* Reported by Simon Levitt <simon@whattf.com>
* This entry needs Sub and Proto fields */
UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100,
"Epson",
"875DC Storage",
US_SC_SCSI, US_PR_CB, NULL, US_FL_FIX_INQUIRY),
/* Reported by Khalid Aziz <khalid@gonehiking.org> /* Reported by Khalid Aziz <khalid@gonehiking.org>
* This entry is needed because the device reports Sub=ff */ * This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110, UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110,
...@@ -482,11 +489,6 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, ...@@ -482,11 +489,6 @@ UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
"Freecom", "Freecom",
"USB-IDE", "USB-IDE",
US_SC_QIC, US_PR_FREECOM, freecom_init, 0), US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
UNUSUAL_DEV( 0x07ab, 0xfc84, 0x0000, 0x9999,
"Freecom",
"FX-5/FX-50",
US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
#endif #endif
UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133,
......
...@@ -856,7 +856,6 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, ...@@ -856,7 +856,6 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
/* wrappers around usb_control_msg() for the most common standard requests */ /* wrappers around usb_control_msg() for the most common standard requests */
extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
unsigned char descindex, void *buf, int size); unsigned char descindex, void *buf, int size);
extern int usb_get_device_descriptor(struct usb_device *dev);
extern int usb_get_status(struct usb_device *dev, extern int usb_get_status(struct usb_device *dev,
int type, int target, void *data); int type, int target, void *data);
extern int usb_get_string(struct usb_device *dev, extern int usb_get_string(struct usb_device *dev,
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb_ch9.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/info.h> #include <sound/info.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -2560,9 +2561,10 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac ...@@ -2560,9 +2561,10 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
err = usb_control_msg(dev, usb_sndctrlpipe(dev,0), err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ); 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ);
if (err < 0) snd_printdd("error sending boot message: %d\n", err); if (err < 0) snd_printdd("error sending boot message: %d\n", err);
err = usb_get_device_descriptor(dev); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
config = dev->actconfig; config = dev->actconfig;
if (err < 0) snd_printdd("error usb_get_device_descriptor: %d\n", err); if (err < 0) snd_printdd("error usb_get_descriptor: %d\n", err);
err = usb_reset_configuration(dev); err = usb_reset_configuration(dev);
if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err); if (err < 0) snd_printdd("error usb_reset_configuration: %d\n", err);
snd_printdd("extigy_boot: new boot length = %d\n", get_cfg_desc(config)->wTotalLength); snd_printdd("extigy_boot: new boot length = %d\n", get_cfg_desc(config)->wTotalLength);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment