Commit 4ab33f9d authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents deb8e8c4 40eed590
This diff is collapsed.
This diff is collapsed.
...@@ -14,10 +14,10 @@ Index ...@@ -14,10 +14,10 @@ Index
4. Module dependencies 4. Module dependencies
5. Module loading 5. Module loading
6. Module parameters 6. Module parameters
7. Device control through "sysfs" 7. Optional device control through "sysfs"
8. Supported devices 8. Supported devices
9. How to add support for new image sensors 9. How to add support for new image sensors
10. Note for V4L2 developers 10. Notes for V4L2 application developers
11. Contact information 11. Contact information
12. Credits 12. Credits
...@@ -148,8 +148,8 @@ Default: 2 ...@@ -148,8 +148,8 @@ Default: 2
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
7. Device control through "sysfs" 7. Optional device control through "sysfs"
================================= ==========================================
It is possible to read and write both the SN9C10[12] and the image sensor It is possible to read and write both the SN9C10[12] and the image sensor
registers by using the "sysfs" filesystem interface. registers by using the "sysfs" filesystem interface.
...@@ -206,7 +206,7 @@ Vendor ID Product ID ...@@ -206,7 +206,7 @@ Vendor ID Product ID
0xc45 0x6029 0xc45 0x6029
0xc45 0x602a 0xc45 0x602a
0xc45 0x602c 0xc45 0x602c
0xc45 0x8001 0xc45 0x6030
The list above does NOT imply that all those devices work with this driver: up The list above does NOT imply that all those devices work with this driver: up
until now only the ones that mount the following image sensors are supported. until now only the ones that mount the following image sensors are supported.
...@@ -242,19 +242,27 @@ At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA), ...@@ -242,19 +242,27 @@ At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
MI03 (VGA), OV7620 (VGA). MI03 (VGA), OV7620 (VGA).
10. Note for V4L2 developers 10. Notes for V4L2 application developers
============================ =========================================
This driver follows the V4L2 API specifications. In particular, it enforces two This driver follows the V4L2 API specifications. In particular, it enforces two
rules: rules:
1) Exactly one I/O method, either "mmap" or "read", is associated with each - exactly one I/O method, either "mmap" or "read", is associated with each
file descriptor. Once it is selected, the application must close and reopen the file descriptor. Once it is selected, the application must close and reopen the
device to switch to the other I/O method. device to switch to the other I/O method;
2) Previously mapped buffer memory must always be unmapped before calling any - previously mapped buffer memory must always be unmapped before calling any
of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case, of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
the same number of buffers as before will be allocated again to match the size number of buffers as before will be allocated again to match the size of the
of the new video frames, so you have to map them again before any I/O attempts. new video frames, so you have to map them again before any I/O attempts.
Consistently with the hardware limits, this driver also supports image
downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
However the V4L2 API specifications don't correctly define how the scaling
factor can be choosen arbitrarily by the "negotiation" of the "source" and
"target" rectangles. To work around this flaw, we have added the convention
that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
scaling factor is restored to 1.
11. Contact information 11. Contact information
......
...@@ -107,6 +107,8 @@ struct ub_dev; ...@@ -107,6 +107,8 @@ struct ub_dev;
* A second ought to be enough for a 32K transfer (UB_MAX_SECTORS) * A second ought to be enough for a 32K transfer (UB_MAX_SECTORS)
* even if a webcam hogs the bus (famous last words). * even if a webcam hogs the bus (famous last words).
* Some CDs need a second to spin up though. * Some CDs need a second to spin up though.
* ZIP drive rejects commands when it's not spinning,
* so it does not need long timeouts either.
*/ */
#define UB_URB_TIMEOUT (HZ*2) #define UB_URB_TIMEOUT (HZ*2)
#define UB_CTRL_TIMEOUT (HZ/2) /* 500ms ought to be enough to clear a stall */ #define UB_CTRL_TIMEOUT (HZ/2) /* 500ms ought to be enough to clear a stall */
...@@ -287,6 +289,7 @@ struct ub_dev { ...@@ -287,6 +289,7 @@ struct ub_dev {
struct ub_completion work_done; struct ub_completion work_done;
struct urb work_urb; struct urb work_urb;
struct timer_list work_timer;
int last_pipe; /* What might need clearing */ int last_pipe; /* What might need clearing */
struct bulk_cb_wrap work_bcb; struct bulk_cb_wrap work_bcb;
struct bulk_cs_wrap work_bcs; struct bulk_cs_wrap work_bcs;
...@@ -776,16 +779,20 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -776,16 +779,20 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->send_bulk_pipe; sc->last_pipe = sc->send_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT; sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
/* Fill what we shouldn't be filling, because usb-storage did so. */ /* Fill what we shouldn't be filling, because usb-storage did so. */
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */ /* XXX Clear stalls */
printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */ printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done); ub_complete(&sc->work_done);
return rc; return rc;
} }
...@@ -795,6 +802,19 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -795,6 +802,19 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return 0; return 0;
} }
/*
* Timeout handler.
*/
static void ub_urb_timeout(unsigned long arg)
{
struct ub_dev *sc = (struct ub_dev *) arg;
unsigned long flags;
spin_lock_irqsave(&sc->lock, flags);
usb_unlink_urb(&sc->work_urb);
spin_unlock_irqrestore(&sc->lock, flags);
}
/* /*
* Completion routine for the work URB. * Completion routine for the work URB.
* *
...@@ -943,14 +963,18 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -943,14 +963,18 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = pipe; sc->last_pipe = pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
cmd->data, cmd->len, ub_urb_complete, sc); cmd->data, cmd->len, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT; sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */ /* XXX Clear stalls */
printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done); ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc); ub_state_done(sc, cmd, rc);
return; return;
...@@ -1034,16 +1058,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1034,16 +1058,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
usb_fill_bulk_urb(&sc->work_urb, sc->dev, usb_fill_bulk_urb(&sc->work_urb, sc->dev,
sc->recv_bulk_pipe, &sc->work_bcs, sc->recv_bulk_pipe, &sc->work_bcs,
US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT; sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC); rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC);
if (rc != 0) { if (rc != 0) {
/* XXX Clear stalls */ /* XXX Clear stalls */
printk("%s: CSW #%d submit failed (%d)\n", printk("%s: CSW #%d submit failed (%d)\n",
sc->name, cmd->tag, rc); /* P3 */ sc->name, cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done); ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc); ub_state_done(sc, cmd, rc);
return; return;
...@@ -1153,14 +1181,18 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) ...@@ -1153,14 +1181,18 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->recv_bulk_pipe; sc->last_pipe = sc->recv_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
&sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT; sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */ /* XXX Clear stalls */
printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done); ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc); ub_state_done(sc, cmd, rc);
return; return;
...@@ -1233,14 +1265,17 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, ...@@ -1233,14 +1265,17 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
UB_INIT_COMPLETION(sc->work_done); UB_INIT_COMPLETION(sc->work_done);
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0, (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.timeout = UB_CTRL_TIMEOUT;
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
del_timer(&sc->work_timer);
ub_complete(&sc->work_done); ub_complete(&sc->work_done);
return rc; return rc;
} }
...@@ -1653,6 +1688,12 @@ static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt) ...@@ -1653,6 +1688,12 @@ static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
complete(cop); complete(cop);
} }
static void ub_probe_timeout(unsigned long arg)
{
struct completion *cop = (struct completion *) arg;
complete(cop);
}
/* /*
* Clear initial stalls. * Clear initial stalls.
*/ */
...@@ -1661,6 +1702,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) ...@@ -1661,6 +1702,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
int endp; int endp;
struct usb_ctrlrequest *cr; struct usb_ctrlrequest *cr;
struct completion compl; struct completion compl;
struct timer_list timer;
int rc; int rc;
init_completion(&compl); init_completion(&compl);
...@@ -1677,21 +1719,35 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) ...@@ -1677,21 +1719,35 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
cr->wLength = cpu_to_le16(0); cr->wLength = cpu_to_le16(0);
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0, (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
ub_probe_urb_complete, &compl); sc->work_urb.transfer_flags = 0;
sc->work_urb.timeout = UB_CTRL_TIMEOUT;
sc->work_urb.actual_length = 0; sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0; sc->work_urb.error_count = 0;
sc->work_urb.status = 0; sc->work_urb.status = 0;
init_timer(&timer);
timer.function = ub_probe_timeout;
timer.data = (unsigned long) &compl;
timer.expires = jiffies + UB_CTRL_TIMEOUT;
add_timer(&timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Unable to submit a probe clear (%d)\n", sc->name, rc); "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
del_timer_sync(&timer);
return rc; return rc;
} }
wait_for_completion(&compl); wait_for_completion(&compl);
del_timer_sync(&timer);
/*
* Most of the time, URB was done and dev set to NULL, and so
* the unlink bounces out with ENODEV. We do not call usb_kill_urb
* because we still think about a backport to 2.4.
*/
usb_unlink_urb(&sc->work_urb);
/* reset the endpoint toggle */ /* reset the endpoint toggle */
usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0); usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
...@@ -1767,6 +1823,10 @@ static int ub_probe(struct usb_interface *intf, ...@@ -1767,6 +1823,10 @@ static int ub_probe(struct usb_interface *intf,
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0); atomic_set(&sc->poison, 0);
init_timer(&sc->work_timer);
sc->work_timer.data = (unsigned long) sc;
sc->work_timer.function = ub_urb_timeout;
ub_init_completion(&sc->work_done); ub_init_completion(&sc->work_done);
sc->work_done.done = 1; /* A little yuk, but oh well... */ sc->work_done.done = 1; /* A little yuk, but oh well... */
......
...@@ -299,4 +299,16 @@ config SENSORS_RTC8564 ...@@ -299,4 +299,16 @@ config SENSORS_RTC8564
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-rtc8564. will be called i2c-rtc8564.
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
help
If you say yes here you get support for the Philips ISP1301
USB-On-The-Go transceiver working with the OMAP OTG controller.
The ISP1301 is used in products including H2 and H3 development
boards for Texas Instruments OMAP processors.
This driver can also be built as a module. If so, the module
will be called isp1301_omap.
endmenu endmenu
...@@ -29,7 +29,9 @@ obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o ...@@ -29,7 +29,9 @@ obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
endif endif
This diff is collapsed.
...@@ -268,7 +268,6 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) ...@@ -268,7 +268,6 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
speed_bulk_callback, self); speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER; urb->transfer_buffer_length = USB_IRDA_HEADER;
urb->transfer_flags = URB_ASYNC_UNLINK; urb->transfer_flags = URB_ASYNC_UNLINK;
urb->timeout = msecs_to_jiffies(100);
/* Irq disabled -> GFP_ATOMIC */ /* Irq disabled -> GFP_ATOMIC */
if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
...@@ -411,8 +410,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -411,8 +410,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* after each of our packets that is exact multiple of the frame size. * after each of our packets that is exact multiple of the frame size.
* This is how the dongle will detect the end of packet - Jean II */ * This is how the dongle will detect the end of packet - Jean II */
urb->transfer_flags |= URB_ZERO_PACKET; urb->transfer_flags |= URB_ZERO_PACKET;
/* Timeout need to be shorter than NET watchdog timer */
urb->timeout = msecs_to_jiffies(200);
/* Generate min turn time. FIXME: can we do better than this? */ /* Generate min turn time. FIXME: can we do better than this? */
/* Trying to a turnaround time at this level is trying to measure /* Trying to a turnaround time at this level is trying to measure
......
...@@ -367,7 +367,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c ...@@ -367,7 +367,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
acm->writeurb->dev = acm->dev; acm->writeurb->dev = acm->dev;
acm->ready_for_write = 0; acm->ready_for_write = 0;
stat = usb_submit_urb(acm->writeurb, GFP_NOIO); stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC);
if (stat < 0) { if (stat < 0) {
dbg("usb_submit_urb(write bulk) failed"); dbg("usb_submit_urb(write bulk) failed");
acm->ready_for_write = 1; acm->ready_for_write = 1;
......
...@@ -71,3 +71,29 @@ config USB_SUSPEND ...@@ -71,3 +71,29 @@ config USB_SUSPEND
may not yet work as expected. may not yet work as expected.
If you are unsure about this, say N here. If you are unsure about this, say N here.
config USB_OTG
bool
depends on USB && EXPERIMENTAL
select USB_SUSPEND
default n
config USB_OTG_WHITELIST
bool "Rely on OTG Targeted Peripherals List"
depends on USB_OTG
default y
help
If you say Y here, the "otg_whitelist.h" file will be used as a
product whitelist, so USB peripherals not listed there will be
rejected during enumeration. This behavior is required by the
USB OTG specification for all devices not on your product's
"Targeted Peripherals List".
Otherwise, peripherals not listed there will only generate a
warning and enumeration will continue. That's more like what
normal Linux-USB hosts do (other than the warning), and is
convenient for many stages of product development.
...@@ -790,6 +790,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev ...@@ -790,6 +790,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64; usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
if (retval != sizeof usb_dev->descriptor) { if (retval != sizeof usb_dev->descriptor) {
usb_dev->bus->root_hub = NULL;
up (&usb_bus_list_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n", dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
usb_dev->dev.bus_id, retval); usb_dev->dev.bus_id, retval);
return (retval < 0) ? retval : -EMSGSIZE; return (retval < 0) ? retval : -EMSGSIZE;
...@@ -1404,6 +1406,45 @@ static int hcd_hub_resume (struct usb_bus *bus) ...@@ -1404,6 +1406,45 @@ static int hcd_hub_resume (struct usb_bus *bus)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_OTG
/**
* usb_bus_start_enum - start immediate enumeration (for OTG)
* @bus: the bus (must use hcd framework)
* @port: 1-based number of port; usually bus->otg_port
* Context: in_interrupt()
*
* Starts enumeration, with an immediate reset followed later by
* khubd identifying and possibly configuring the device.
* This is needed by OTG controller drivers, where it helps meet
* HNP protocol timing requirements for starting a port reset.
*/
int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
{
struct usb_hcd *hcd;
int status = -EOPNOTSUPP;
/* NOTE: since HNP can't start by grabbing the bus's address0_sem,
* boards with root hubs hooked up to internal devices (instead of
* just the OTG port) may need more attention to resetting...
*/
hcd = container_of (bus, struct usb_hcd, self);
if (port_num && hcd->driver->start_port_reset)
status = hcd->driver->start_port_reset(hcd, port_num);
/* run khubd shortly after (first) root port reset finishes;
* it may issue others, until at least 50 msecs have passed.
*/
if (status == 0)
mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
return status;
}
EXPORT_SYMBOL (usb_bus_start_enum);
#endif
/*-------------------------------------------------------------------------*/
/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup. /* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup.
* we're guaranteed that the device is fully quiesced. also, that each * we're guaranteed that the device is fully quiesced. also, that each
* endpoint has been hcd_endpoint_disabled. * endpoint has been hcd_endpoint_disabled.
......
...@@ -212,6 +212,7 @@ struct hc_driver { ...@@ -212,6 +212,7 @@ struct hc_driver {
char *buf, u16 wLength); char *buf, u16 wLength);
int (*hub_suspend)(struct usb_hcd *); int (*hub_suspend)(struct usb_hcd *);
int (*hub_resume)(struct usb_hcd *); int (*hub_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
}; };
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
......
...@@ -1095,6 +1095,10 @@ static inline void show_string(struct usb_device *udev, char *id, int index) ...@@ -1095,6 +1095,10 @@ static inline void show_string(struct usb_device *udev, char *id, int index)
{} {}
#endif #endif
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
#endif
/** /**
* usb_new_device - perform initial device setup (usbcore-internal) * usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state) * @udev: newly addressed device (in ADDRESS state)
...@@ -1144,6 +1148,79 @@ int usb_new_device(struct usb_device *udev) ...@@ -1144,6 +1148,79 @@ int usb_new_device(struct usb_device *udev)
show_string(udev, "SerialNumber", show_string(udev, "SerialNumber",
udev->descriptor.iSerialNumber); udev->descriptor.iSerialNumber);
#ifdef CONFIG_USB_OTG
/*
* OTG-aware devices on OTG-capable root hubs may be able to use SRP,
* to wake us after we've powered off VBUS; and HNP, switching roles
* "host" to "peripheral". The OTG descriptor helps figure this out.
*/
if (!udev->bus->is_b_host
&& udev->config
&& udev->parent == udev->bus->root_hub) {
struct usb_otg_descriptor *desc = 0;
struct usb_bus *bus = udev->bus;
/* descriptor may appear anywhere in config */
if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
udev->config[0].desc.wTotalLength,
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
unsigned port;
struct usb_device *root = udev->parent;
for (port = 0; port < root->maxchild; port++) {
if (root->children[port] == udev)
break;
}
port++;
dev_info(&udev->dev,
"Dual-Role OTG device on %sHNP port\n",
(port == bus->otg_port)
? "" : "non-");
/* enable HNP before suspend, it's simpler */
if (port == bus->otg_port)
bus->b_hnp_enable = 1;
err = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, 0,
bus->b_hnp_enable
? USB_DEVICE_B_HNP_ENABLE
: USB_DEVICE_A_ALT_HNP_SUPPORT,
0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (err < 0) {
/* OTG MESSAGE: report errors here,
* customize to match your product.
*/
dev_info(&udev->dev,
"can't set HNP mode; %d\n",
err);
bus->b_hnp_enable = 0;
}
}
}
}
if (!is_targeted(udev)) {
/* Maybe it can talk to us, though we can't talk to it.
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
static int __usb_suspend_device (struct usb_device *,
int port, u32 state);
err = __usb_suspend_device(udev,
udev->bus->otg_port - 1,
PM_SUSPEND_MEM);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
err = -ENODEV;
goto fail;
}
#endif
/* put device-specific files into sysfs */ /* put device-specific files into sysfs */
err = device_add (&udev->dev); err = device_add (&udev->dev);
if (err) { if (err) {
...@@ -1934,6 +2011,10 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) ...@@ -1934,6 +2011,10 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
hdev->bus->b_hnp_enable = 0; hdev->bus->b_hnp_enable = 0;
} }
retval = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
if (retval < 0 && retval != -EPIPE)
dev_dbg(&udev->dev, "can't clear suspend; %d\n", retval);
/* Some low speed devices have problems with the quick delay, so */ /* Some low speed devices have problems with the quick delay, so */
/* be a bit pessimistic with those devices. RHbug #23670 */ /* be a bit pessimistic with those devices. RHbug #23670 */
if (oldspeed == USB_SPEED_LOW) if (oldspeed == USB_SPEED_LOW)
...@@ -2160,6 +2241,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port, ...@@ -2160,6 +2241,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
usb_disconnect(&hdev->children[port]); usb_disconnect(&hdev->children[port]);
clear_bit(port, hub->change_bits); clear_bit(port, hub->change_bits);
#ifdef CONFIG_USB_OTG
/* during HNP, don't repeat the debounce */
if (hdev->bus->is_b_host)
portchange &= ~USB_PORT_STAT_C_CONNECTION;
#endif
if (portchange & USB_PORT_STAT_C_CONNECTION) { if (portchange & USB_PORT_STAT_C_CONNECTION) {
status = hub_port_debounce(hdev, port); status = hub_port_debounce(hdev, port);
if (status < 0) { if (status < 0) {
......
...@@ -190,8 +190,8 @@ struct usb_hub { ...@@ -190,8 +190,8 @@ struct usb_hub {
struct usb_device *hdev; struct usb_device *hdev;
struct urb *urb; /* for interrupt polling pipe */ struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... 1 bit each for hub and children, rounded up */ /* buffer for urb ... with extra space in case of babble */
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; char (*buffer)[8];
dma_addr_t buffer_dma; /* DMA address for buffer */ dma_addr_t buffer_dma; /* DMA address for buffer */
union { union {
struct usb_hub_status hub; struct usb_hub_status hub;
......
...@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) ...@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
* unlink pending urbs so they won't rx/tx bad data. * unlink pending urbs so they won't rx/tx bad data.
*/ */
for (i = 0, found = 0; i < io->entries; i++) { for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i]) if (!io->urbs [i] || !io->urbs [i]->dev)
continue; continue;
if (found) { if (found) {
status = usb_unlink_urb (io->urbs [i]); status = usb_unlink_urb (io->urbs [i]);
...@@ -337,7 +337,7 @@ int usb_sg_init ( ...@@ -337,7 +337,7 @@ int usb_sg_init (
if (io->entries <= 0) if (io->entries <= 0)
return io->entries; return io->entries;
io->count = 0; io->count = io->entries;
io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
if (!io->urbs) if (!io->urbs)
goto nomem; goto nomem;
...@@ -347,7 +347,7 @@ int usb_sg_init ( ...@@ -347,7 +347,7 @@ int usb_sg_init (
if (usb_pipein (pipe)) if (usb_pipein (pipe))
urb_flags |= URB_SHORT_NOT_OK; urb_flags |= URB_SHORT_NOT_OK;
for (i = 0; i < io->entries; i++, io->count = i) { for (i = 0; i < io->entries; i++) {
unsigned len; unsigned len;
io->urbs [i] = usb_alloc_urb (0, mem_flags); io->urbs [i] = usb_alloc_urb (0, mem_flags);
...@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */ /* fail any uncompleted urbs */
default: default:
spin_lock_irq (&io->lock); io->urbs [i]->dev = NULL;
io->count -= entries - i;
if (io->status == -EINPROGRESS)
io->status = retval;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock);
io->urbs[i]->dev = NULL;
io->urbs [i]->status = retval; io->urbs [i]->status = retval;
dev_dbg (&io->dev->dev, "%s, submit --> %d\n", dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
usb_sg_cancel (io); usb_sg_cancel (io);
} }
spin_lock_irq (&io->lock); spin_lock_irq (&io->lock);
if (retval && io->status == -ECONNRESET) if (retval && (io->status == 0 || io->status == -ECONNRESET))
io->status = retval; io->status = retval;
} }
io->count -= entries - i;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock); spin_unlock_irq (&io->lock);
/* OK, yes, this could be packaged as non-blocking. /* OK, yes, this could be packaged as non-blocking.
......
/*
* drivers/usb/core/otg_whitelist.h
*
* Copyright (C) 2004 Texas Instruments
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* This OTG Whitelist is the OTG "Targeted Peripheral List". It should
* mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
*
* YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
*/
static struct usb_device_id whitelist_table [] = {
/* hubs are optional in OTG, but very handy ... */
{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
#ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
/* FIXME actually, printers are NOT supposed to use device classes;
* they're supposed to use interface classes...
*/
{ USB_DEVICE_INFO(7, 1, 1) },
{ USB_DEVICE_INFO(7, 1, 2) },
{ USB_DEVICE_INFO(7, 1, 3) },
#endif
#ifdef CONFIG_USB_CDCETHER
/* Linux-USB CDC Ethernet gadget */
{ USB_DEVICE(0x0525, 0xa4a1), },
/* Linux-USB CDC Ethernet + RNDIS gadget */
{ USB_DEVICE(0x0525, 0xa4a2), },
#endif
#if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
/* gadget zero, for testing */
{ USB_DEVICE(0x0525, 0xa4a0), },
#endif
{ } /* Terminating entry */
};
static int is_targeted(struct usb_device *dev)
{
struct usb_device_id *id = whitelist_table;
/* possible in developer configs only! */
if (!dev->bus->otg_port)
return 1;
/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
if (dev->descriptor.idVendor == 0x1a0a
&& dev->descriptor.idProduct == 0xbadd)
return 0;
/* NOTE: can't use usb_match_id() since interface caches
* aren't set up yet. this is cut/paste from that code.
*/
for (id = whitelist_table; id->match_flags; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != dev->descriptor.idVendor)
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != dev->descriptor.idProduct)
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > dev->descriptor.bcdDevice))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < dev->descriptor.bcdDevice))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
continue;
return 1;
}
/* add other match criteria here ... */
/* OTG MESSAGE: report errors here, customize to match your product */
dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
#ifdef CONFIG_USB_OTG_WHITELIST
return 0;
#else
return 1;
#endif
}
...@@ -135,6 +135,18 @@ config USB_SA1100 ...@@ -135,6 +135,18 @@ config USB_SA1100
depends on USB_GADGET_SA1100 depends on USB_GADGET_SA1100
default USB_GADGET default USB_GADGET
config USB_GADGET_LH7A40X
boolean "LH7A40X"
depends on ARCH_LH7A40X
help
This driver provides USB Device Controller driver for LH7A40x
config USB_LH7A40X
tristate
depends on USB_GADGET_LH7A40X
default USB_GADGET
config USB_GADGET_DUMMY_HCD config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)" boolean "Dummy HCD (DEVELOPMENT)"
depends on USB && EXPERIMENTAL depends on USB && EXPERIMENTAL
...@@ -163,6 +175,41 @@ config USB_DUMMY_HCD ...@@ -163,6 +175,41 @@ config USB_DUMMY_HCD
depends on USB_GADGET_DUMMY_HCD depends on USB_GADGET_DUMMY_HCD
default USB_GADGET default USB_GADGET
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
depends on ARCH_OMAP
select ISP1301_OMAP if MACH_OMAP_H2
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
endpoints (plus endpoint zero). This driver supports the
controller in the OMAP 1611, and should work with controllers
in other OMAP processors too, given minor tweaks.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "omap_udc" and force all
gadget drivers to also be dynamically linked.
config USB_OMAP
tristate
depends on USB_GADGET_OMAP
default USB_GADGET
config USB_OTG
boolean "OTG Support"
depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
help
The most notable feature of USB OTG is support for a
"Dual-Role" device, which can act as either a device
or a host. The initial role choice can be changed
later, when two dual-role devices talk to each other.
Select this only if your OMAP board has a Mini-AB connector.
config USB_OMAP_PROC
boolean "/proc/driver/udc file"
depends on USB_GADGET_OMAP
endchoice endchoice
config USB_GADGET_DUALSPEED config USB_GADGET_DUALSPEED
......
...@@ -5,6 +5,8 @@ obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o ...@@ -5,6 +5,8 @@ obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
# #
# USB gadget drivers # USB gadget drivers
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
/* /*
* Ethernet gadget driver -- with CDC and non-CDC options * Ethernet gadget driver -- with CDC and non-CDC options
* Builds on hardware support for a full duplex link.
* *
* CDC Ethernet is the standard USB solution for sending Ethernet frames * CDC Ethernet is the standard USB solution for sending Ethernet frames
* using USB. Real hardware tends to use the same framing protocol but look * using USB. Real hardware tends to use the same framing protocol but look
...@@ -242,6 +243,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); ...@@ -242,6 +243,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET #define DEV_CONFIG_SUBSET
#endif #endif
#ifdef CONFIG_USB_GADGET_LH7A40X
#define DEV_CONFIG_CDC
#endif
#ifdef CONFIG_USB_GADGET_SA1100 #ifdef CONFIG_USB_GADGET_SA1100
/* use non-CDC for backwards compatibility */ /* use non-CDC for backwards compatibility */
#define DEV_CONFIG_SUBSET #define DEV_CONFIG_SUBSET
...@@ -855,7 +860,7 @@ static char product_desc [40] = DRIVER_DESC; ...@@ -855,7 +860,7 @@ static char product_desc [40] = DRIVER_DESC;
static char ethaddr [2 * ETH_ALEN + 1]; static char ethaddr [2 * ETH_ALEN + 1];
#endif #endif
/* static strings, in iso 8859/1 */ /* static strings, in UTF-8 */
static struct usb_string strings [] = { static struct usb_string strings [] = {
{ STRING_MANUFACTURER, manufacturer, }, { STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, product_desc, }, { STRING_PRODUCT, product_desc, },
...@@ -897,9 +902,9 @@ config_buf (enum usb_device_speed speed, ...@@ -897,9 +902,9 @@ config_buf (enum usb_device_speed speed,
if (type == USB_DT_OTHER_SPEED_CONFIG) if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs; hs = !hs;
#define which_fn(t) (hs ? & hs_ ## t ## _function : & fs_ ## t ## _function) #define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function)
#else #else
#define which_fn(t) (& fs_ ## t ## _function) #define which_fn(t) (fs_ ## t ## _function)
#endif #endif
if (index >= device_desc.bNumConfigurations) if (index >= device_desc.bNumConfigurations)
...@@ -911,14 +916,12 @@ config_buf (enum usb_device_speed speed, ...@@ -911,14 +916,12 @@ config_buf (enum usb_device_speed speed,
*/ */
if (device_desc.bNumConfigurations == 2 && index == 0) { if (device_desc.bNumConfigurations == 2 && index == 0) {
config = &rndis_config; config = &rndis_config;
function = (const struct usb_descriptor_header **) function = which_fn (rndis);
which_fn (rndis);
} else } else
#endif #endif
{ {
config = &eth_config; config = &eth_config;
function = (const struct usb_descriptor_header **) function = which_fn (eth);
which_fn (eth);
} }
/* for now, don't advertise srp-only devices */ /* for now, don't advertise srp-only devices */
...@@ -2329,6 +2332,8 @@ eth_bind (struct usb_gadget *gadget) ...@@ -2329,6 +2332,8 @@ eth_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207); device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
} else if (gadget_is_omap (gadget)) { } else if (gadget_is_omap (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208); device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else { } else {
/* can't assume CDC works. don't want to default to /* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware, * anything less functional on CDC-capable hardware,
......
...@@ -3713,6 +3713,8 @@ static int __init check_parameters(struct fsg_dev *fsg) ...@@ -3713,6 +3713,8 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.release = __constant_cpu_to_le16(0x0307); mod_data.release = __constant_cpu_to_le16(0x0307);
else if (gadget_is_omap(fsg->gadget)) else if (gadget_is_omap(fsg->gadget))
mod_data.release = __constant_cpu_to_le16(0x0308); mod_data.release = __constant_cpu_to_le16(0x0308);
else if (gadget_is_lh7a40x(gadget))
mod_data.release = __constant_cpu_to_le16 (0x0309);
else { else {
WARN(fsg, "controller '%s' not recognized\n", WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name); fsg->gadget->name);
......
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
#define gadget_is_sa1100(g) 0 #define gadget_is_sa1100(g) 0
#endif #endif
#ifdef CONFIG_USB_GADGET_LH7A40X
#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
#else
#define gadget_is_lh7a40x(g) 0
#endif
#ifdef CONFIG_USB_GADGET_MQ11XX #ifdef CONFIG_USB_GADGET_MQ11XX
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name) #define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
#else #else
......
/* /*
* inode.c -- user mode filesystem api for usb gadget controllers * inode.c -- user mode filesystem api for usb gadget controllers
* *
* Copyright (C) 2003 David Brownell * Copyright (C) 2003-2004 David Brownell
* Copyright (C) 2003 Agilent Technologies * Copyright (C) 2003 Agilent Technologies
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
*/ */
#define DRIVER_DESC "USB Gadget filesystem" #define DRIVER_DESC "USB Gadget filesystem"
#define DRIVER_VERSION "18 Nov 2003" #define DRIVER_VERSION "24 Aug 2004"
static const char driver_desc [] = DRIVER_DESC; static const char driver_desc [] = DRIVER_DESC;
static const char shortname [] = "gadgetfs"; static const char shortname [] = "gadgetfs";
...@@ -229,37 +229,12 @@ static void put_ep (struct ep_data *data) ...@@ -229,37 +229,12 @@ static void put_ep (struct ep_data *data)
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
/* most "how to use the hardware" policy choices are in userspace: /* most "how to use the hardware" policy choices are in userspace:
* mapping endpoint roles the driver needs to the capabilities that * mapping endpoint roles (which the driver needs) to the capabilities
* the usb controller exposes. * which the usb controller has. most of those capabilities are exposed
* implicitly, starting with the driver name and then endpoint names.
*/ */
#ifdef CONFIG_USB_GADGET_DUMMY_HCD static const char *CHIP;
/* act (mostly) like a net2280 */
#define CONFIG_USB_GADGET_NET2280
#endif
#ifdef CONFIG_USB_GADGET_NET2280
#define CHIP "net2280"
#define HIGHSPEED
#endif
#ifdef CONFIG_USB_GADGET_PXA2XX
#define CHIP "pxa2xx_udc"
/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */
#warning works best with pxa255 or newer
#endif
#ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku_udc"
#endif
#ifdef CONFIG_USB_GADGET_OMAP
#define CHIP "omap_udc"
#endif
#ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100"
#endif
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -558,7 +533,7 @@ struct kiocb_priv { ...@@ -558,7 +533,7 @@ struct kiocb_priv {
static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
{ {
struct kiocb_priv *priv = (void *) &iocb->private; struct kiocb_priv *priv = iocb->private;
struct ep_data *epdata; struct ep_data *epdata;
int value; int value;
...@@ -579,7 +554,7 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e) ...@@ -579,7 +554,7 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
static ssize_t ep_aio_read_retry(struct kiocb *iocb) static ssize_t ep_aio_read_retry(struct kiocb *iocb)
{ {
struct kiocb_priv *priv = (void *) &iocb->private; struct kiocb_priv *priv = iocb->private;
ssize_t status = priv->actual; ssize_t status = priv->actual;
/* we "retry" to get the right mm context for this: */ /* we "retry" to get the right mm context for this: */
...@@ -589,6 +564,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ...@@ -589,6 +564,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
else else
status = priv->actual; status = priv->actual;
kfree(priv->buf); kfree(priv->buf);
kfree(priv);
aio_put_req(iocb); aio_put_req(iocb);
return status; return status;
} }
...@@ -596,7 +572,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) ...@@ -596,7 +572,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
{ {
struct kiocb *iocb = req->context; struct kiocb *iocb = req->context;
struct kiocb_priv *priv = (void *) &iocb->private; struct kiocb_priv *priv = iocb->private;
struct ep_data *epdata = priv->epdata; struct ep_data *epdata = priv->epdata;
/* lock against disconnect (and ideally, cancel) */ /* lock against disconnect (and ideally, cancel) */
...@@ -607,6 +583,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -607,6 +583,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|| unlikely(0 == req->actual) || unlikely(0 == req->actual)
|| unlikely(kiocbIsCancelled(iocb))) { || unlikely(kiocbIsCancelled(iocb))) {
kfree(req->buf); kfree(req->buf);
kfree(priv);
iocb->private = 0;
/* aio_complete() reports bytes-transferred _and_ faults */ /* aio_complete() reports bytes-transferred _and_ faults */
if (unlikely(kiocbIsCancelled(iocb))) if (unlikely(kiocbIsCancelled(iocb)))
aio_put_req(iocb); aio_put_req(iocb);
...@@ -631,17 +609,33 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -631,17 +609,33 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
} }
static ssize_t static ssize_t
ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) ep_aio_rwtail(
struct kiocb *iocb,
char *buf,
size_t len,
struct ep_data *epdata,
char __user *ubuf
)
{ {
struct kiocb_priv *priv = (void *) &iocb->private; struct kiocb_priv *priv = (void *) &iocb->private;
struct usb_request *req; struct usb_request *req;
ssize_t value; ssize_t value;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata); priv = kmalloc(sizeof *priv, GFP_KERNEL);
if (unlikely(value < 0)) { if (!priv) {
value = -ENOMEM;
fail:
kfree(buf); kfree(buf);
return value; return value;
} }
iocb->private = priv;
priv->ubuf = ubuf;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
if (unlikely(value < 0)) {
kfree(priv);
goto fail;
}
iocb->ki_cancel = ep_aio_cancel; iocb->ki_cancel = ep_aio_cancel;
get_ep(epdata); get_ep(epdata);
...@@ -671,9 +665,10 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) ...@@ -671,9 +665,10 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
up(&epdata->lock); up(&epdata->lock);
if (unlikely(value)) if (unlikely(value)) {
kfree(priv);
put_ep(epdata); put_ep(epdata);
else } else
value = -EIOCBQUEUED; value = -EIOCBQUEUED;
return value; return value;
} }
...@@ -681,7 +676,6 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata) ...@@ -681,7 +676,6 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
static ssize_t static ssize_t
ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o) ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
{ {
struct kiocb_priv *priv = (void *) &iocb->private;
struct ep_data *epdata = iocb->ki_filp->private_data; struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf; char *buf;
...@@ -691,8 +685,7 @@ ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o) ...@@ -691,8 +685,7 @@ ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
if (unlikely(!buf)) if (unlikely(!buf))
return -ENOMEM; return -ENOMEM;
iocb->ki_retry = ep_aio_read_retry; iocb->ki_retry = ep_aio_read_retry;
priv->ubuf = ubuf; return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
return ep_aio_rwtail(iocb, buf, len, epdata);
} }
static ssize_t static ssize_t
...@@ -710,7 +703,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) ...@@ -710,7 +703,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
kfree(buf); kfree(buf);
return -EFAULT; return -EFAULT;
} }
return ep_aio_rwtail(iocb, buf, len, epdata); return ep_aio_rwtail(iocb, buf, len, epdata, 0);
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -718,6 +711,8 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o) ...@@ -718,6 +711,8 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
/* used after endpoint configuration */ /* used after endpoint configuration */
static struct file_operations ep_io_operations = { static struct file_operations ep_io_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek,
.read = ep_read, .read = ep_read,
.write = ep_write, .write = ep_write,
.ioctl = ep_ioctl, .ioctl = ep_ioctl,
...@@ -874,6 +869,8 @@ ep_open (struct inode *inode, struct file *fd) ...@@ -874,6 +869,8 @@ ep_open (struct inode *inode, struct file *fd)
/* used before endpoint configuration */ /* used before endpoint configuration */
static struct file_operations ep_config_operations = { static struct file_operations ep_config_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek,
.open = ep_open, .open = ep_open,
.write = ep_config, .write = ep_config,
.release = ep_release, .release = ep_release,
...@@ -980,6 +977,18 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -980,6 +977,18 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
retval = usb_ep_queue (ep, req, GFP_ATOMIC); retval = usb_ep_queue (ep, req, GFP_ATOMIC);
dev->state = STATE_CONNECTED; dev->state = STATE_CONNECTED;
/* assume that was SET_CONFIGURATION */
if (dev->current_config) {
unsigned power;
#ifdef HIGHSPEED
if (dev->gadget->speed == USB_SPEED_HIGH)
power = dev->hs_config->bMaxPower;
else
#endif
power = dev->config->bMaxPower;
usb_gadget_vbus_draw(dev->gadget, 2 * power);
}
} else { /* collect OUT data */ } else { /* collect OUT data */
if ((fd->f_flags & O_NONBLOCK) != 0 if ((fd->f_flags & O_NONBLOCK) != 0
&& !dev->setup_out_ready) { && !dev->setup_out_ready) {
...@@ -1230,6 +1239,8 @@ static int dev_ioctl (struct inode *inode, struct file *fd, ...@@ -1230,6 +1239,8 @@ static int dev_ioctl (struct inode *inode, struct file *fd,
/* used after device configuration */ /* used after device configuration */
static struct file_operations ep0_io_operations = { static struct file_operations ep0_io_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek,
.read = ep0_read, .read = ep0_read,
.write = ep0_write, .write = ep0_write,
.fasync = ep0_fasync, .fasync = ep0_fasync,
...@@ -1406,19 +1417,25 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1406,19 +1417,25 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (0 == (u8) ctrl->wValue) { if (0 == (u8) ctrl->wValue) {
value = 0; value = 0;
dev->current_config = 0; dev->current_config = 0;
usb_gadget_vbus_draw(gadget, 8 /* mA */ );
// user mode expected to disable endpoints // user mode expected to disable endpoints
} else { } else {
u8 config; u8 config, power;
#ifdef HIGHSPEED #ifdef HIGHSPEED
if (gadget->speed == USB_SPEED_HIGH) if (gadget->speed == USB_SPEED_HIGH) {
config = dev->hs_config->bConfigurationValue; config = dev->hs_config->bConfigurationValue;
else power = dev->hs_config->bMaxPower;
} else
#endif #endif
{
config = dev->config->bConfigurationValue; config = dev->config->bConfigurationValue;
power = dev->config->bMaxPower;
}
if (config == (u8) ctrl->wValue) { if (config == (u8) ctrl->wValue) {
value = 0; value = 0;
dev->current_config = config; dev->current_config = config;
usb_gadget_vbus_draw(gadget, 2 * power);
} }
} }
...@@ -1636,8 +1653,8 @@ gadgetfs_bind (struct usb_gadget *gadget) ...@@ -1636,8 +1653,8 @@ gadgetfs_bind (struct usb_gadget *gadget)
if (!dev) if (!dev)
return -ESRCH; return -ESRCH;
if (0 != strcmp (CHIP, gadget->name)) { if (0 != strcmp (CHIP, gadget->name)) {
printk (KERN_ERR "%s expected " CHIP " controller not %s\n", printk (KERN_ERR "%s expected %s controller not %s\n",
shortname, gadget->name); shortname, CHIP, gadget->name);
return -ENODEV; return -ENODEV;
} }
...@@ -1727,6 +1744,26 @@ static struct usb_gadget_driver gadgetfs_driver = { ...@@ -1727,6 +1744,26 @@ static struct usb_gadget_driver gadgetfs_driver = {
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static void gadgetfs_nop(struct usb_gadget *arg) { }
static int gadgetfs_probe (struct usb_gadget *gadget)
{
CHIP = gadget->name;
return -EISNAM;
}
static struct usb_gadget_driver probe_driver = {
.speed = USB_SPEED_HIGH,
.bind = gadgetfs_probe,
.unbind = gadgetfs_nop,
.setup = (void *)gadgetfs_nop,
.disconnect = gadgetfs_nop,
.driver = {
.name = "nop",
},
};
/* DEVICE INITIALIZATION /* DEVICE INITIALIZATION
* *
* fd = open ("/dev/gadget/$CHIP", O_RDWR) * fd = open ("/dev/gadget/$CHIP", O_RDWR)
...@@ -1763,6 +1800,7 @@ static int is_valid_config (struct usb_config_descriptor *config) ...@@ -1763,6 +1800,7 @@ static int is_valid_config (struct usb_config_descriptor *config)
&& config->bConfigurationValue != 0 && config->bConfigurationValue != 0
&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0 && (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0; && (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
/* FIXME if gadget->is_otg, _must_ include an otg descriptor */
/* FIXME check lengths: walk to end */ /* FIXME check lengths: walk to end */
} }
...@@ -1881,6 +1919,8 @@ dev_open (struct inode *inode, struct file *fd) ...@@ -1881,6 +1919,8 @@ dev_open (struct inode *inode, struct file *fd)
static struct file_operations dev_init_operations = { static struct file_operations dev_init_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek,
.open = dev_open, .open = dev_open,
.write = dev_config, .write = dev_config,
.fasync = ep0_fasync, .fasync = ep0_fasync,
...@@ -1976,6 +2016,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) ...@@ -1976,6 +2016,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
if (the_device) if (the_device)
return -ESRCH; return -ESRCH;
/* fake probe to determine $CHIP */
(void) usb_gadget_register_driver (&probe_driver);
if (!CHIP)
return -ENODEV;
/* superblock */ /* superblock */
sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
......
This diff is collapsed.
/*
* linux/drivers/usb/gadget/lh7a40x_udc.h
* Sharp LH7A40x on-chip full speed USB device controllers
*
* Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
* Copyright (C) 2004 Bo Henriksen, Nordic ID
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __LH7A40X_H_
#define __LH7A40X_H_
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/hardware.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
/*
* Memory map
*/
#define USB_FA 0x80000200 // function address register
#define USB_PM 0x80000204 // power management register
#define USB_IN_INT 0x80000208 // IN interrupt register bank (EP0-EP3)
#define USB_OUT_INT 0x80000210 // OUT interrupt register bank (EP2)
#define USB_INT 0x80000218 // interrupt register bank
#define USB_IN_INT_EN 0x8000021C // IN interrupt enable register bank
#define USB_OUT_INT_EN 0x80000224 // OUT interrupt enable register bank
#define USB_INT_EN 0x8000022C // USB interrupt enable register bank
#define USB_FRM_NUM1 0x80000230 // Frame number1 register
#define USB_FRM_NUM2 0x80000234 // Frame number2 register
#define USB_INDEX 0x80000238 // index register
#define USB_IN_MAXP 0x80000240 // IN MAXP register
#define USB_IN_CSR1 0x80000244 // IN CSR1 register/EP0 CSR register
#define USB_EP0_CSR 0x80000244 // IN CSR1 register/EP0 CSR register
#define USB_IN_CSR2 0x80000248 // IN CSR2 register
#define USB_OUT_MAXP 0x8000024C // OUT MAXP register
#define USB_OUT_CSR1 0x80000250 // OUT CSR1 register
#define USB_OUT_CSR2 0x80000254 // OUT CSR2 register
#define USB_OUT_FIFO_WC1 0x80000258 // OUT FIFO write count1 register
#define USB_OUT_FIFO_WC2 0x8000025C // OUT FIFO write count2 register
#define USB_RESET 0x8000044C // USB reset register
#define USB_EP0_FIFO 0x80000280
#define USB_EP1_FIFO 0x80000284
#define USB_EP2_FIFO 0x80000288
#define USB_EP3_FIFO 0x8000028c
/*
* USB reset register
*/
#define USB_RESET_APB (1<<1) //resets USB APB control side WRITE
#define USB_RESET_IO (1<<0) //resets USB IO side WRITE
/*
* USB function address register
*/
#define USB_FA_ADDR_UPDATE (1<<7)
#define USB_FA_FUNCTION_ADDR (0x7F)
/*
* Power Management register
*/
#define PM_USB_DCP (1<<5)
#define PM_USB_ENABLE (1<<4)
#define PM_USB_RESET (1<<3)
#define PM_UC_RESUME (1<<2)
#define PM_SUSPEND_MODE (1<<1)
#define PM_ENABLE_SUSPEND (1<<0)
/*
* IN interrupt register
*/
#define USB_IN_INT_EP3 (1<<3)
#define USB_IN_INT_EP1 (1<<1)
#define USB_IN_INT_EP0 (1<<0)
/*
* OUT interrupt register
*/
#define USB_OUT_INT_EP2 (1<<2)
/*
* USB interrupt register
*/
#define USB_INT_RESET_INT (1<<2)
#define USB_INT_RESUME_INT (1<<1)
#define USB_INT_SUSPEND_INT (1<<0)
/*
* USB interrupt enable register
*/
#define USB_INT_EN_USB_RESET_INTER (1<<2)
#define USB_INT_EN_RESUME_INTER (1<<1)
#define USB_INT_EN_SUSPEND_INTER (1<<0)
/*
* INCSR1 register
*/
#define USB_IN_CSR1_CLR_DATA_TOGGLE (1<<6)
#define USB_IN_CSR1_SENT_STALL (1<<5)
#define USB_IN_CSR1_SEND_STALL (1<<4)
#define USB_IN_CSR1_FIFO_FLUSH (1<<3)
#define USB_IN_CSR1_FIFO_NOT_EMPTY (1<<1)
#define USB_IN_CSR1_IN_PKT_RDY (1<<0)
/*
* INCSR2 register
*/
#define USB_IN_CSR2_AUTO_SET (1<<7)
#define USB_IN_CSR2_USB_DMA_EN (1<<4)
/*
* OUT CSR1 register
*/
#define USB_OUT_CSR1_CLR_DATA_REG (1<<7)
#define USB_OUT_CSR1_SENT_STALL (1<<6)
#define USB_OUT_CSR1_SEND_STALL (1<<5)
#define USB_OUT_CSR1_FIFO_FLUSH (1<<4)
#define USB_OUT_CSR1_FIFO_FULL (1<<1)
#define USB_OUT_CSR1_OUT_PKT_RDY (1<<0)
/*
* OUT CSR2 register
*/
#define USB_OUT_CSR2_AUTO_CLR (1<<7)
#define USB_OUT_CSR2_USB_DMA_EN (1<<4)
/*
* EP0 CSR
*/
#define EP0_CLR_SETUP_END (1<<7) /* Clear "Setup Ends" Bit (w) */
#define EP0_CLR_OUT (1<<6) /* Clear "Out packet ready" Bit (w) */
#define EP0_SEND_STALL (1<<5) /* Send STALL Handshake (rw) */
#define EP0_SETUP_END (1<<4) /* Setup Ends (r) */
#define EP0_DATA_END (1<<3) /* Data end (rw) */
#define EP0_SENT_STALL (1<<2) /* Sent Stall Handshake (r) */
#define EP0_IN_PKT_RDY (1<<1) /* In packet ready (rw) */
#define EP0_OUT_PKT_RDY (1<<0) /* Out packet ready (r) */
/* general CSR */
#define OUT_PKT_RDY (1<<0)
#define IN_PKT_RDY (1<<0)
/*
* IN/OUT MAXP register
*/
#define USB_OUT_MAXP_MAXP (0xF)
#define USB_IN_MAXP_MAXP (0xF)
// Max packet size
//#define EP0_PACKETSIZE 0x10
#define EP0_PACKETSIZE 0x8
#define EP0_MAXPACKETSIZE 0x10
#define UDC_MAX_ENDPOINTS 4
#define WAIT_FOR_SETUP 0
#define DATA_STATE_XMIT 1
#define DATA_STATE_NEED_ZLP 2
#define WAIT_FOR_OUT_STATUS 3
#define DATA_STATE_RECV 4
/* ********************************************************************************************* */
/* IO
*/
typedef enum ep_type {
ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
} ep_type_t;
struct lh7a40x_ep {
struct usb_ep ep;
struct lh7a40x_udc *dev;
const struct usb_endpoint_descriptor *desc;
struct list_head queue;
unsigned long pio_irqs;
u8 stopped;
u8 bEndpointAddress;
u8 bmAttributes;
ep_type_t ep_type;
u32 fifo;
u32 csr1;
u32 csr2;
};
struct lh7a40x_request {
struct usb_request req;
struct list_head queue;
};
struct lh7a40x_udc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct device *dev;
spinlock_t lock;
int ep0state;
struct lh7a40x_ep ep[UDC_MAX_ENDPOINTS];
unsigned char usb_address;
unsigned req_pending:1, req_std:1, req_config:1;
};
extern struct lh7a40x_udc *the_controller;
#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN)
#define ep_index(EP) ((EP)->bEndpointAddress&0xF)
#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
#endif
...@@ -307,7 +307,6 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep) ...@@ -307,7 +307,6 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
| (1 << SET_NAK_OUT_PACKETS) | (1 << SET_NAK_OUT_PACKETS)
| (1 << CLEAR_EP_HIDE_STATUS_PHASE) | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
| (1 << CLEAR_INTERRUPT_MODE) | (1 << CLEAR_INTERRUPT_MODE)
| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
| (1 << CLEAR_ENDPOINT_TOGGLE) | (1 << CLEAR_ENDPOINT_TOGGLE)
| (1 << CLEAR_ENDPOINT_HALT) | (1 << CLEAR_ENDPOINT_HALT)
, &ep->regs->ep_rsp); , &ep->regs->ep_rsp);
...@@ -2511,15 +2510,23 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2511,15 +2510,23 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
static void handle_stat1_irqs (struct net2280 *dev, u32 stat) static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
{ {
struct net2280_ep *ep; struct net2280_ep *ep;
u32 tmp, num, scratch; u32 tmp, num, mask, scratch;
/* after disconnect there's nothing else to do! */ /* after disconnect there's nothing else to do! */
tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT); tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
* Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
* both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
* only indicates a change in the reset state).
*/
if (stat & tmp) { if (stat & tmp) {
writel (tmp, &dev->regs->irqstat1); writel (tmp, &dev->regs->irqstat1);
if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0 if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0 ((readl (&dev->usb->usbstat) & mask) == 0))
) && dev->gadget.speed != USB_SPEED_UNKNOWN) { || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0)
) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
DEBUG (dev, "disconnect %s\n", DEBUG (dev, "disconnect %s\n",
dev->driver->driver.name); dev->driver->driver.name);
stop_activity (dev, dev->driver); stop_activity (dev, dev->driver);
......
This diff is collapsed.
/*
* omap_udc.h -- for omap 3.2 udc, with OTG support
*
* 2004 (C) Texas Instruments, Inc.
* 2004 (C) David Brownell
*/
/*
* USB device/endpoint management registers
*/
#define UDC_REG(offset) __REG16(UDC_BASE + (offset))
#define UDC_REV_REG UDC_REG(0x0) /* Revision */
#define UDC_EP_NUM_REG UDC_REG(0x4) /* Which endpoint */
# define UDC_SETUP_SEL (1 << 6)
# define UDC_EP_SEL (1 << 5)
# define UDC_EP_DIR (1 << 4)
/* low 4 bits for endpoint number */
#define UDC_DATA_REG UDC_REG(0x08) /* Endpoint FIFO */
#define UDC_CTRL_REG UDC_REG(0x0C) /* Endpoint control */
# define UDC_CLR_HALT (1 << 7)
# define UDC_SET_HALT (1 << 6)
# define UDC_SET_FIFO_EN (1 << 2)
# define UDC_CLR_EP (1 << 1)
# define UDC_RESET_EP (1 << 0)
#define UDC_STAT_FLG_REG UDC_REG(0x10) /* Endpoint status */
# define UDC_NO_RXPACKET (1 << 15)
# define UDC_MISS_IN (1 << 14)
# define UDC_DATA_FLUSH (1 << 13)
# define UDC_ISO_ERR (1 << 12)
# define UDC_ISO_FIFO_EMPTY (1 << 9)
# define UDC_ISO_FIFO_FULL (1 << 8)
# define UDC_EP_HALTED (1 << 6)
# define UDC_STALL (1 << 5)
# define UDC_NAK (1 << 4)
# define UDC_ACK (1 << 3)
# define UDC_FIFO_EN (1 << 2)
# define UDC_NON_ISO_FIFO_EMPTY (1 << 1)
# define UDC_NON_ISO_FIFO_FULL (1 << 0)
#define UDC_RXFSTAT_REG UDC_REG(0x14) /* OUT bytecount */
#define UDC_SYSCON1_REG UDC_REG(0x18) /* System config 1 */
# define UDC_CFG_LOCK (1 << 8)
# define UDC_DATA_ENDIAN (1 << 7)
# define UDC_DMA_ENDIAN (1 << 6)
# define UDC_NAK_EN (1 << 4)
# define UDC_AUTODECODE_DIS (1 << 3)
# define UDC_SELF_PWR (1 << 2)
# define UDC_SOFF_DIS (1 << 1)
# define UDC_PULLUP_EN (1 << 0)
#define UDC_SYSCON2_REG UDC_REG(0x1C) /* System config 2 */
# define UDC_RMT_WKP (1 << 6)
# define UDC_STALL_CMD (1 << 5)
# define UDC_DEV_CFG (1 << 3)
# define UDC_CLR_CFG (1 << 2)
#define UDC_DEVSTAT_REG UDC_REG(0x20) /* Device status */
# define UDC_B_HNP_ENABLE (1 << 9)
# define UDC_A_HNP_SUPPORT (1 << 8)
# define UDC_A_ALT_HNP_SUPPORT (1 << 7)
# define UDC_R_WK_OK (1 << 6)
# define UDC_USB_RESET (1 << 5)
# define UDC_SUS (1 << 4)
# define UDC_CFG (1 << 3)
# define UDC_ADD (1 << 2)
# define UDC_DEF (1 << 1)
# define UDC_ATT (1 << 0)
#define UDC_SOF_REG UDC_REG(0x24) /* Start of frame */
# define UDC_FT_LOCK (1 << 12)
# define UDC_TS_OK (1 << 11)
# define UDC_TS 0x03ff
#define UDC_IRQ_EN_REG UDC_REG(0x28) /* Interrupt enable */
# define UDC_SOF_IE (1 << 7)
# define UDC_EPN_RX_IE (1 << 5)
# define UDC_EPN_TX_IE (1 << 4)
# define UDC_DS_CHG_IE (1 << 3)
# define UDC_EP0_IE (1 << 0)
#define UDC_DMA_IRQ_EN_REG UDC_REG(0x2C) /* DMA irq enable */
/* rx/tx dma channels numbered 1-3 not 0-2 */
# define UDC_TX_DONE_IE(n) (1 << (4 * (n) - 2))
# define UDC_RX_CNT_IE(n) (1 << (4 * (n) - 3))
# define UDC_RX_EOT_IE(n) (1 << (4 * (n) - 4))
#define UDC_IRQ_SRC_REG UDC_REG(0x30) /* Interrupt source */
# define UDC_TXN_DONE (1 << 10)
# define UDC_RXN_CNT (1 << 9)
# define UDC_RXN_EOT (1 << 8)
# define UDC_SOF (1 << 7)
# define UDC_EPN_RX (1 << 5)
# define UDC_EPN_TX (1 << 4)
# define UDC_DS_CHG (1 << 3)
# define UDC_SETUP (1 << 2)
# define UDC_EP0_RX (1 << 1)
# define UDC_EP0_TX (1 << 0)
# define UDC_IRQ_SRC_MASK 0x7bf
#define UDC_EPN_STAT_REG UDC_REG(0x34) /* EP irq status */
#define UDC_DMAN_STAT_REG UDC_REG(0x38) /* DMA irq status */
# define UDC_DMA_RX_SB (1 << 12)
# define UDC_DMA_RX_SRC(x) (((x)>>8) & 0xf)
# define UDC_DMA_TX_SRC(x) (((x)>>0) & 0xf)
/* DMA configuration registers: up to three channels in each direction. */
#define UDC_RXDMA_CFG_REG UDC_REG(0x40) /* 3 eps for RX DMA */
#define UDC_TXDMA_CFG_REG UDC_REG(0x44) /* 3 eps for TX DMA */
#define UDC_DATA_DMA_REG UDC_REG(0x48) /* rx/tx fifo addr */
/* rx/tx dma control, numbering channels 1-3 not 0-2 */
#define UDC_TXDMA_REG(chan) UDC_REG(0x50 - 4 + 4 * (chan))
# define UDC_TXN_EOT (1 << 15) /* bytes vs packets */
# define UDC_TXN_START (1 << 14) /* start transfer */
# define UDC_TXN_TSC 0x03ff /* units in xfer */
#define UDC_RXDMA_REG(chan) UDC_REG(0x60 - 4 + 4 * (chan))
# define UDC_RXN_STOP (1 << 15) /* enable EOT irq */
# define UDC_RXN_TC 0x00ff /* packets in xfer */
/*
* Endpoint configuration registers (used before CFG_LOCK is set)
* UDC_EP_TX_REG(0) is unused
*/
#define UDC_EP_RX_REG(endpoint) UDC_REG(0x80 + (endpoint)*4)
# define UDC_EPN_RX_VALID (1 << 15)
# define UDC_EPN_RX_DB (1 << 14)
/* buffer size in bits 13, 12 */
# define UDC_EPN_RX_ISO (1 << 11)
/* buffer pointer in low 11 bits */
#define UDC_EP_TX_REG(endpoint) UDC_REG(0xc0 + (endpoint)*4)
/* same bitfields as in RX_REG */
/*-------------------------------------------------------------------------*/
struct omap_req {
struct usb_request req;
struct list_head queue;
unsigned dma_bytes;
unsigned mapped:1;
};
struct omap_ep {
struct usb_ep ep;
struct list_head queue;
unsigned long irqs;
struct list_head iso;
const struct usb_endpoint_descriptor *desc;
char name[14];
u16 maxpacket;
u8 bEndpointAddress;
u8 bmAttributes;
unsigned double_buf:1;
unsigned stopped:1;
unsigned ackwait:1;
unsigned has_dma:1;
u8 dma_channel;
int lch;
struct omap_udc *udc;
};
struct omap_udc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
spinlock_t lock;
struct omap_ep ep[32];
u16 devstat;
struct otg_transceiver *transceiver;
struct list_head iso;
unsigned softconnect:1;
unsigned vbus_active:1;
unsigned ep0_pending:1;
unsigned ep0_in:1;
unsigned ep0_set_config:1;
unsigned ep0_reset_config:1;
unsigned ep0_setup:1;
unsigned hmc:6;
struct completion *done;
};
/*-------------------------------------------------------------------------*/
#ifdef DEBUG
#define DBG(stuff...) printk(KERN_DEBUG "udc: " stuff)
#else
#define DBG(stuff...) do{}while(0)
#endif
#ifdef VERBOSE
# define VDBG DBG
#else
# define VDBG(stuff...) do{}while(0)
#endif
#define ERR(stuff...) printk(KERN_ERR "udc: " stuff)
#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
/*-------------------------------------------------------------------------*/
// #define HMC_1510 ((MOD_CONF_CTRL_0_REG >> 1) & 0x3f)
#define HMC_1610 (OTG_SYSCON_2_REG & 0x3f)
#define HMC HMC_1610
...@@ -1299,6 +1299,9 @@ static int gs_bind(struct usb_gadget *gadget) ...@@ -1299,6 +1299,9 @@ static int gs_bind(struct usb_gadget *gadget)
} else if (gadget_is_omap(gadget)) { } else if (gadget_is_omap(gadget)) {
gs_device_desc.bcdDevice = gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0007); __constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
} else if (gadget_is_lh7a40x(gadget)) {
gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
} else { } else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n", printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name); gadget->name);
......
...@@ -399,7 +399,7 @@ static const struct usb_descriptor_header *hs_loopback_function [] = { ...@@ -399,7 +399,7 @@ static const struct usb_descriptor_header *hs_loopback_function [] = {
static char manufacturer [40]; static char manufacturer [40];
static char serial [40]; static char serial [40];
/* static strings, in iso 8859/1 */ /* static strings, in UTF-8 */
static struct usb_string strings [] = { static struct usb_string strings [] = {
{ STRING_MANUFACTURER, manufacturer, }, { STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, longname, }, { STRING_PRODUCT, longname, },
...@@ -960,7 +960,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -960,7 +960,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_STRING: case USB_DT_STRING:
/* wIndex == language code. /* wIndex == language code.
* this driver only handles one language, you can * this driver only handles one language, you can
* add others even if they don't use iso8859/1 * add string tables for other languages, using
* any UTF-8 characters
*/ */
value = usb_gadget_get_string (&stringtab, value = usb_gadget_get_string (&stringtab,
ctrl->wValue & 0xff, req->buf); ctrl->wValue & 0xff, req->buf);
...@@ -1185,6 +1186,8 @@ zero_bind (struct usb_gadget *gadget) ...@@ -1185,6 +1186,8 @@ zero_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207); device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
} else if (gadget_is_omap (gadget)) { } else if (gadget_is_omap (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208); device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else { } else {
/* gadget zero is so simple (for now, no altsettings) that /* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware. * it SHOULD NOT have problems with bulk-capable hardware.
...@@ -1236,6 +1239,12 @@ zero_bind (struct usb_gadget *gadget) ...@@ -1236,6 +1239,12 @@ zero_bind (struct usb_gadget *gadget)
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
} }
if (gadget->is_otg) {
otg_descriptor.bmAttributes |= USB_OTG_HNP,
source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
usb_gadget_set_selfpowered (gadget); usb_gadget_set_selfpowered (gadget);
init_timer (&dev->resume); init_timer (&dev->resume);
......
...@@ -52,6 +52,7 @@ config USB_EHCI_ROOT_HUB_TT ...@@ -52,6 +52,7 @@ config USB_EHCI_ROOT_HUB_TT
config USB_OHCI_HCD config USB_OHCI_HCD
tristate "OHCI HCD support" tristate "OHCI HCD support"
depends on USB depends on USB
select ISP1301_OMAP if MACH_OMAP_H2
---help--- ---help---
The Open Host Controller Interface (OHCI) is a standard for accessing The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's USB 1.1 host controller hardware. It does more in hardware than Intel's
......
...@@ -97,6 +97,7 @@ ...@@ -97,6 +97,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/interrupt.h> /* for in_interrupt () */ #include <linux/interrupt.h> /* for in_interrupt () */
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb_otg.h>
#include "../core/hcd.h" #include "../core/hcd.h"
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */ #include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */
...@@ -693,7 +694,7 @@ static void ohci_stop (struct usb_hcd *hcd) ...@@ -693,7 +694,7 @@ static void ohci_stop (struct usb_hcd *hcd)
/* must not be called from interrupt context */ /* must not be called from interrupt context */
#ifdef CONFIG_PM #if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
static void mark_children_gone (struct usb_device *dev) static void mark_children_gone (struct usb_device *dev)
{ {
......
...@@ -435,6 +435,89 @@ ohci_hub_descriptor ( ...@@ -435,6 +435,89 @@ ohci_hub_descriptor (
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_OTG
static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
u32 status;
if (!port)
return -EINVAL;
port--;
/* start port reset before HNP protocol times out */
status = ohci_readl(&ohci->regs->roothub.portstatus [port]);
if (!(status & RH_PS_CCS))
return -ENODEV;
/* khubd will finish the reset later */
writel(RH_PS_PRS, &ohci->regs->roothub.portstatus [port]);
return 0;
}
static void start_hnp(struct ohci_hcd *ohci);
#else
#define ohci_start_port_reset NULL
#endif
/*-------------------------------------------------------------------------*/
/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling,
* not necessarily continuous ... to guard against resume signaling.
* The short timeout is safe for non-root hubs, and is backward-compatible
* with earlier Linux hosts.
*/
#ifdef CONFIG_USB_SUSPEND
#define PORT_RESET_MSEC 50
#else
#define PORT_RESET_MSEC 10
#endif
/* this timer value might be vendor-specific ... */
#define PORT_RESET_HW_MSEC 10
/* wrap-aware logic stolen from <linux/jiffies.h> */
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* called from some task, normally khubd */
static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
u32 *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
u16 now = readl(&ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC;
/* build a "continuous enough" reset signal, with up to
* 3msec gap between pulses. scheduler HZ==100 must work;
* this might need to be deadline-scheduled.
*/
do {
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (portstat);
if (!(temp & RH_PS_PRS))
break;
udelay (500);
}
if (!(temp & RH_PS_CCS))
break;
if (temp & RH_PS_PRSC)
writel (RH_PS_PRSC, portstat);
/* start the next reset, sleep till it's probably done */
writel (RH_PS_PRS, portstat);
msleep(PORT_RESET_HW_MSEC);
now = readl(&ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
}
static int ohci_hub_control ( static int ohci_hub_control (
struct usb_hcd *hcd, struct usb_hcd *hcd,
u16 typeReq, u16 typeReq,
...@@ -533,6 +616,12 @@ static int ohci_hub_control ( ...@@ -533,6 +616,12 @@ static int ohci_hub_control (
wIndex--; wIndex--;
switch (wValue) { switch (wValue) {
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
#ifdef CONFIG_USB_OTG
if (ohci->hcd.self.otg_port == (wIndex + 1)
&& ohci->hcd.self.b_hnp_enable)
start_hnp(ohci);
else
#endif
writel (RH_PS_PSS, writel (RH_PS_PSS,
&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
break; break;
...@@ -541,10 +630,7 @@ static int ohci_hub_control ( ...@@ -541,10 +630,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
break; break;
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); root_port_reset (ohci, wIndex);
if (temp & RH_PS_CCS)
writel (RH_PS_PRS,
&ohci->regs->roothub.portstatus [wIndex]);
break; break;
default: default:
goto error; goto error;
......
This diff is collapsed.
This diff is collapsed.
...@@ -242,6 +242,7 @@ static const struct hc_driver ohci_pci_hc_driver = { ...@@ -242,6 +242,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
.hub_suspend = ohci_hub_suspend, .hub_suspend = ohci_hub_suspend,
.hub_resume = ohci_hub_resume, .hub_resume = ohci_hub_resume,
#endif #endif
.start_port_reset = ohci_start_port_reset,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -276,7 +277,7 @@ static int __init ohci_hcd_pci_init (void) ...@@ -276,7 +277,7 @@ static int __init ohci_hcd_pci_init (void)
if (usb_disabled()) if (usb_disabled())
return -ENODEV; return -ENODEV;
printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
sizeof (struct ed), sizeof (struct td)); sizeof (struct ed), sizeof (struct td));
return pci_module_init (&ohci_pci_driver); return pci_module_init (&ohci_pci_driver);
} }
......
...@@ -900,9 +900,6 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -900,9 +900,6 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* wrap-aware logic stolen from <linux/jiffies.h> */
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
static void static void
finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
......
...@@ -359,6 +359,13 @@ struct ohci_hcd { ...@@ -359,6 +359,13 @@ struct ohci_hcd {
struct ed *ed_controltail; /* last in ctrl list */ struct ed *ed_controltail; /* last in ctrl list */
struct ed *periodic [NUM_INTS]; /* shadow int_table */ struct ed *periodic [NUM_INTS]; /* shadow int_table */
/*
* OTG controllers and transceivers need software interaction;
* other external transceivers should be software-transparent
*/
struct otg_transceiver *transceiver;
unsigned power_budget;
/* /*
* memory management for queue data structures * memory management for queue data structures
*/ */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -704,7 +704,6 @@ static int stv680_start_stream (struct usb_stv *stv680) ...@@ -704,7 +704,6 @@ static int stv680_start_stream (struct usb_stv *stv680)
usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
stv680->sbuf[i].data, stv680->rawbufsize, stv680->sbuf[i].data, stv680->rawbufsize,
stv680_video_irq, stv680); stv680_video_irq, stv680);
urb->timeout = PENCAM_TIMEOUT * 2;
stv680->urb[i] = urb; stv680->urb[i] = urb;
err = usb_submit_urb (stv680->urb[i], GFP_KERNEL); err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
if (err) if (err)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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