Commit 691a5599 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: sisusbvga: add USB ID for 0711:0918 Magic Control Technology Corp.
  USB: automatically enable RHSC interrupts
  USB: Don't rebind before "complete" callback
  USB: Add new PM callback methods for USB
  USB: Defer Set-Interface for suspended devices
  USB: Add udev argument to interface suspend/resume functions
  USB: cdc-acm: don't unlock acm->mutex on error path
  MUSB: Fix index register corruption seen with g_ether and Windows host
  usb: musb: get rid of MUSB_LOGLEVEL and use parameter
  usb: musb: get rid of procfs entry
  USB: Fix pxa27x_udc usb speed handling.
  USB: cdc-acm: quirk for Conexant CX93010 USB modem
  USB: fix bug in usb_unlink_anchored_urbs()
  usb-serial: option support HSDPA modem A2502
  USB: ISP1760: fixed trivial math in comment
parents cce7496d eaea0435
......@@ -589,8 +589,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
tasklet_schedule(&acm->urb_task);
done:
err_out:
mutex_unlock(&acm->mutex);
err_out:
mutex_unlock(&open_mutex);
return rv;
......@@ -1362,6 +1362,9 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
{ USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
/* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
......
......@@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev)
*/
intf->pm_usage_cnt = !(driver->supports_autosuspend);
/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0) {
usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
intf->needs_altsetting0 = 0;
}
error = driver->probe(intf, id);
if (error) {
mark_quiesced(intf);
......@@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev)
driver->disconnect(intf);
/* reset other interface state */
usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
/* Reset other interface state.
* We cannot do a Set-Interface if the device is suspended or
* if it is prepared for a system sleep (since installing a new
* altsetting means creating new endpoint device entries).
* When either of these happens, defer the Set-Interface.
*/
if (!error && intf->dev.power.status == DPM_ON)
usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
else
intf->needs_altsetting0 = 1;
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
......@@ -798,7 +814,8 @@ void usb_forced_unbind_intf(struct usb_interface *intf)
* The caller must hold @intf's device's lock, but not its pm_mutex
* and not @intf->dev.sem.
*
* FIXME: The caller must block system sleep transitions.
* Note: Rebinds will be skipped if a system sleep transition is in
* progress and the PM "complete" callback hasn't occurred yet.
*/
void usb_rebind_intf(struct usb_interface *intf)
{
......@@ -814,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf)
}
/* Try to rebind the interface */
if (intf->dev.power.status == DPM_ON) {
intf->needs_binding = 0;
rc = device_attach(&intf->dev);
if (rc < 0)
dev_warn(&intf->dev, "rebind failed: %d\n", rc);
}
}
#ifdef CONFIG_PM
......@@ -829,7 +848,6 @@ void usb_rebind_intf(struct usb_interface *intf)
* or rebind interfaces that have been unbound, according to @action.
*
* The caller must hold @udev's device lock.
* FIXME: For rebinds, the caller must block system sleep transitions.
*/
static void do_unbind_rebind(struct usb_device *udev, int action)
{
......@@ -851,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
}
break;
case DO_REBIND:
if (intf->needs_binding) {
/* FIXME: The next line is needed because we are going to probe
* the interface, but as far as the PM core is concerned the
* interface is still suspended. The problem wouldn't exist
* if we could rebind the interface during the interface's own
* resume() call, but at the time the usb_device isn't locked!
*
* The real solution will be to carry this out during the device's
* complete() callback. Until that is implemented, we have to
* use this hack.
*/
// intf->dev.power.sleeping = 0;
if (intf->needs_binding)
usb_rebind_intf(intf);
}
break;
}
}
......@@ -926,14 +930,14 @@ static int usb_resume_device(struct usb_device *udev)
}
/* Caller has locked intf's usb_device's pm mutex */
static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
static int usb_suspend_interface(struct usb_device *udev,
struct usb_interface *intf, pm_message_t msg)
{
struct usb_driver *driver;
int status = 0;
/* with no hardware, USB interfaces only use FREEZE and ON states */
if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
!is_active(intf))
if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
goto done;
if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */
......@@ -944,7 +948,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
status = driver->suspend(intf, msg);
if (status == 0)
mark_quiesced(intf);
else if (!interface_to_usbdev(intf)->auto_pm)
else if (!udev->auto_pm)
dev_err(&intf->dev, "%s error %d\n",
"suspend", status);
} else {
......@@ -961,13 +965,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
}
/* Caller has locked intf's usb_device's pm_mutex */
static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
static int usb_resume_interface(struct usb_device *udev,
struct usb_interface *intf, int reset_resume)
{
struct usb_driver *driver;
int status = 0;
if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
is_active(intf))
if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
goto done;
/* Don't let autoresume interfere with unbinding */
......@@ -975,8 +979,17 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
goto done;
/* Can't resume it if it doesn't have a driver. */
if (intf->condition == USB_INTERFACE_UNBOUND)
if (intf->condition == USB_INTERFACE_UNBOUND) {
/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0 &&
intf->dev.power.status == DPM_ON) {
usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
intf->needs_altsetting0 = 0;
}
goto done;
}
/* Don't resume if the interface is marked for rebinding */
if (intf->needs_binding)
......@@ -1151,7 +1164,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
if (udev->actconfig) {
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
status = usb_suspend_interface(intf, msg);
status = usb_suspend_interface(udev, intf, msg);
if (status != 0)
break;
}
......@@ -1163,7 +1176,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
if (status != 0) {
while (--i >= 0) {
intf = udev->actconfig->interface[i];
usb_resume_interface(intf, 0);
usb_resume_interface(udev, intf, 0);
}
/* Try another autosuspend when the interfaces aren't busy */
......@@ -1276,7 +1289,7 @@ static int usb_resume_both(struct usb_device *udev)
if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
usb_resume_interface(intf, udev->reset_resume);
usb_resume_interface(udev, intf, udev->reset_resume);
}
}
......@@ -1605,12 +1618,10 @@ int usb_external_resume_device(struct usb_device *udev)
return status;
}
static int usb_suspend(struct device *dev, pm_message_t message)
int usb_suspend(struct device *dev, pm_message_t message)
{
struct usb_device *udev;
if (!is_usb_device(dev)) /* Ignore PM for interfaces */
return 0;
udev = to_usb_device(dev);
/* If udev is already suspended, we can skip this suspend and
......@@ -1629,12 +1640,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
return usb_external_suspend_device(udev, message);
}
static int usb_resume(struct device *dev)
int usb_resume(struct device *dev)
{
struct usb_device *udev;
if (!is_usb_device(dev)) /* Ignore PM for interfaces */
return 0;
udev = to_usb_device(dev);
/* If udev->skip_sys_resume is set then udev was already suspended
......@@ -1646,17 +1655,10 @@ static int usb_resume(struct device *dev)
return usb_external_resume_device(udev);
}
#else
#define usb_suspend NULL
#define usb_resume NULL
#endif /* CONFIG_PM */
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
.suspend = usb_suspend,
.resume = usb_resume,
};
......@@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd)
return retval;
}
void usb_enable_root_hub_irq (struct usb_bus *bus)
{
struct usb_hcd *hcd;
hcd = container_of (bus, struct usb_hcd, self);
if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
hcd->driver->hub_irq_enable (hcd);
}
/*-------------------------------------------------------------------------*/
......
......@@ -212,8 +212,6 @@ struct hc_driver {
int (*bus_suspend)(struct usb_hcd *);
int (*bus_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
void (*hub_irq_enable)(struct usb_hcd *);
/* Needed only if port-change IRQs are level-triggered */
/* force handover of high-speed port to full-speed companion */
void (*relinquish_port)(struct usb_hcd *, int);
......@@ -379,8 +377,6 @@ extern struct list_head usb_bus_list;
extern struct mutex usb_bus_list_lock;
extern wait_queue_head_t usb_kill_urb_queue;
extern void usb_enable_root_hub_irq(struct usb_bus *bus);
extern int usb_find_interface_driver(struct usb_device *dev,
struct usb_interface *interface);
......
......@@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *udev)
}
clear_bit(port1, hub->busy_bits);
if (!hub->hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hub->hdev->bus);
status = check_port_resume_type(udev,
hub, port1, status, portchange, portstatus);
......@@ -3081,11 +3079,6 @@ static void hub_events(void)
}
}
/* If this is a root hub, tell the HCD it's okay to
* re-enable port-change interrupts now. */
if (!hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hdev->bus);
loop_autopm:
/* Allow autosuspend if we're not going to run again */
if (list_empty(&hub->event_list))
......@@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
break;
}
clear_bit(port1, parent_hub->busy_bits);
if (!parent_hdev->parent && !parent_hub->busy_bits[0])
usb_enable_root_hub_irq(parent_hdev->bus);
if (ret < 0)
goto re_enumerate;
......
......@@ -601,15 +601,20 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
{
struct urb *victim;
unsigned long flags;
spin_lock_irq(&anchor->lock);
spin_lock_irqsave(&anchor->lock, flags);
while (!list_empty(&anchor->urb_list)) {
victim = list_entry(anchor->urb_list.prev, struct urb,
anchor_list);
usb_get_urb(victim);
spin_unlock_irqrestore(&anchor->lock, flags);
/* this will unanchor the URB */
usb_unlink_urb(victim);
usb_put_urb(victim);
spin_lock_irqsave(&anchor->lock, flags);
}
spin_unlock_irq(&anchor->lock);
spin_unlock_irqrestore(&anchor->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
......
......@@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
}
#endif /* CONFIG_HOTPLUG */
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
.uevent = usb_dev_uevent,
};
#ifdef CONFIG_PM
static int ksuspend_usb_init(void)
......@@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void)
destroy_workqueue(ksuspend_usb_wq);
}
/* USB device Power-Management thunks.
* There's no need to distinguish here between quiescing a USB device
* and powering it down; the generic_suspend() routine takes care of
* it by skipping the usb_port_suspend() call for a quiesce. And for
* USB interfaces there's no difference at all.
*/
static int usb_dev_prepare(struct device *dev)
{
return 0; /* Implement eventually? */
}
static void usb_dev_complete(struct device *dev)
{
/* Currently used only for rebinding interfaces */
usb_resume(dev); /* Implement eventually? */
}
static int usb_dev_suspend(struct device *dev)
{
return usb_suspend(dev, PMSG_SUSPEND);
}
static int usb_dev_resume(struct device *dev)
{
return usb_resume(dev);
}
static int usb_dev_freeze(struct device *dev)
{
return usb_suspend(dev, PMSG_FREEZE);
}
static int usb_dev_thaw(struct device *dev)
{
return usb_resume(dev);
}
static int usb_dev_poweroff(struct device *dev)
{
return usb_suspend(dev, PMSG_HIBERNATE);
}
static int usb_dev_restore(struct device *dev)
{
return usb_resume(dev);
}
static struct pm_ops usb_device_pm_ops = {
.prepare = usb_dev_prepare,
.complete = usb_dev_complete,
.suspend = usb_dev_suspend,
.resume = usb_dev_resume,
.freeze = usb_dev_freeze,
.thaw = usb_dev_thaw,
.poweroff = usb_dev_poweroff,
.restore = usb_dev_restore,
};
#else
#define ksuspend_usb_init() 0
#define ksuspend_usb_cleanup() do {} while (0)
#define usb_device_pm_ops (*(struct pm_ops *)0)
#endif /* CONFIG_PM */
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
.uevent = usb_dev_uevent,
.pm = &usb_device_pm_ops,
};
/* Returns 1 if @usb_bus is WUSB, 0 otherwise */
static unsigned usb_bus_is_wusb(struct usb_bus *bus)
......
......@@ -41,6 +41,9 @@ extern void usb_host_cleanup(void);
#ifdef CONFIG_PM
extern int usb_suspend(struct device *dev, pm_message_t msg);
extern int usb_resume(struct device *dev);
extern void usb_autosuspend_work(struct work_struct *work);
extern int usb_port_suspend(struct usb_device *dev);
extern int usb_port_resume(struct usb_device *dev);
......
......@@ -1622,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
struct pxa_udc *udc = the_controller;
int retval;
if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind
if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind
|| !driver->disconnect || !driver->setup)
return -EINVAL;
if (!udc)
......
......@@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
/*
* write bank1 address twice to ensure the 90ns delay (time
* between BANK0 write and the priv_read_copy() call is at
* least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
* least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns)
*/
isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs +
HC_MEMORY_REG);
......
......@@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
.get_frame_number = ohci_get_frame,
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -36,18 +36,6 @@
/*-------------------------------------------------------------------------*/
/* hcd->hub_irq_enable() */
static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
spin_lock_irq(&ohci->lock);
if (!ohci->autostop)
del_timer(&hcd->rh_timer); /* Prevent next poll */
ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
spin_unlock_irq(&ohci->lock);
}
#define OHCI_SCHED_ENABLES \
(OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
......@@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
int any_connected)
{
int poll_rh = 1;
int rhsc;
rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
/* keep on polling until we know a device is connected
* and RHSC is enabled */
/* If no status changes are pending, enable status-change
* interrupts.
*/
if (!rhsc && !changed) {
rhsc = OHCI_INTR_RHSC;
ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
}
/* Keep on polling until we know a device is connected
* and RHSC is enabled, or until we autostop.
*/
if (!ohci->autostop) {
if (any_connected ||
!device_may_wakeup(&ohci_to_hcd(ohci)
->self.root_hub->dev)) {
if (ohci_readl(ohci, &ohci->regs->intrenable) &
OHCI_INTR_RHSC)
if (rhsc)
poll_rh = 0;
} else {
ohci->autostop = 1;
......@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
ohci->autostop = 0;
ohci->next_statechange = jiffies +
STATECHANGE_DELAY;
} else if (time_after_eq(jiffies,
} else if (rhsc && time_after_eq(jiffies,
ohci->next_statechange)
&& !ohci->ed_rm_list
&& !(ohci->hc_control &
OHCI_SCHED_ENABLES)) {
ohci_rh_suspend(ohci, 1);
poll_rh = 0;
}
}
break;
......@@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
else
usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
} else {
if (!rhsc && (ohci->autostop ||
ohci_to_hcd(ohci)->self.root_hub->
do_remote_wakeup))
ohci_writel(ohci, OHCI_INTR_RHSC,
&ohci->regs->intrenable);
/* everything is idle, no need for polling */
poll_rh = 0;
}
......@@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
int any_connected)
{
int poll_rh = 1;
/* keep on polling until RHSC is enabled */
/* If RHSC is enabled, don't poll */
if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
poll_rh = 0;
return poll_rh;
return 0;
/* If no status changes are pending, enable status-change interrupts */
if (!changed) {
ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
return 0;
}
return 1;
}
#endif /* CONFIG_PM */
......
......@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = {
.get_frame_number = ohci_get_frame,
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
.start_port_reset = ohci_start_port_reset,
#if defined(CONFIG_PM)
.bus_suspend = ohci_bus_suspend,
......
......@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.hub_status_data = ohci_s3c2410_hub_status_data,
.hub_control = ohci_s3c2410_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = {
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
......
......@@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
return 0;
}
static void u132_hub_irq_enable(struct usb_hcd *hcd)
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 1) {
dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
, u132->going);
} else if (u132->going > 0)
dev_err(&u132->platform_dev->dev, "device is being removed\n");
}
#ifdef CONFIG_PM
static int u132_bus_suspend(struct usb_hcd *hcd)
......@@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = {
.bus_suspend = u132_bus_suspend,
.bus_resume = u132_bus_resume,
.start_port_reset = u132_start_port_reset,
.hub_irq_enable = u132_hub_irq_enable,
};
/*
......
......@@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = {
{ USB_DEVICE(0x0711, 0x0900) },
{ USB_DEVICE(0x0711, 0x0901) },
{ USB_DEVICE(0x0711, 0x0902) },
{ USB_DEVICE(0x0711, 0x0918) },
{ USB_DEVICE(0x182d, 0x021c) },
{ USB_DEVICE(0x182d, 0x0269) },
{ }
......
......@@ -165,12 +165,11 @@ config USB_TUSB_OMAP_DMA
help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
config USB_MUSB_LOGLEVEL
config USB_MUSB_DEBUG
depends on USB_MUSB_HDRC
int 'Logging Level (0 - none / 3 - annoying / ... )'
default 0
bool "Enable debugging messages"
default n
help
Set the logging level. 0 disables the debugging altogether,
although when USB_DEBUG is set the value is at least 1.
Starting at level 3, per-transfer (urb, usb_request, packet,
or dma transfer) tracing may kick in.
This enables musb debugging. To set the logging level use the debug
module parameter. Starting at level 3, per-transfer (urb, usb_request,
packet, or dma transfer) tracing may kick in.
......@@ -64,23 +64,6 @@ endif
# Debugging
MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL)
ifeq ("$(strip $(MUSB_DEBUG))","")
ifdef CONFIG_USB_DEBUG
MUSB_DEBUG:=1
else
MUSB_DEBUG:=0
endif
endif
ifneq ($(MUSB_DEBUG),0)
ifeq ($(CONFIG_USB_MUSB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
ifeq ($(CONFIG_PROC_FS),y)
musb_hdrc-objs += musb_procfs.o
endif
endif
EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG)
......@@ -114,23 +114,14 @@
#if MUSB_DEBUG > 0
unsigned debug = MUSB_DEBUG;
module_param(debug, uint, 0);
MODULE_PARM_DESC(debug, "initial debug message level");
#define MUSB_VERSION_SUFFIX "/dbg"
#endif
unsigned debug;
module_param(debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
#define MUSB_VERSION_BASE "6.0"
#ifndef MUSB_VERSION_SUFFIX
#define MUSB_VERSION_SUFFIX ""
#endif
#define MUSB_VERSION MUSB_VERSION_BASE MUSB_VERSION_SUFFIX
#define MUSB_VERSION "6.0"
#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
......@@ -2037,6 +2028,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->xceiv.state = OTG_STATE_A_IDLE;
status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
if (status)
goto fail;
DBG(1, "%s mode, status %d, devctl %02x %c\n",
"HOST", status,
......@@ -2051,6 +2044,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->xceiv.state = OTG_STATE_B_IDLE;
status = musb_gadget_setup(musb);
if (status)
goto fail;
DBG(1, "%s mode, status %d, dev%02x\n",
is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
......@@ -2059,16 +2054,14 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
}
if (status == 0)
musb_debug_create("driver/musb_hdrc", musb);
else {
return 0;
fail:
if (musb->clock)
clk_put(musb->clock);
device_init_wakeup(dev, 0);
musb_free(musb);
return status;
}
#ifdef CONFIG_SYSFS
status = device_create_file(dev, &dev_attr_mode);
......@@ -2131,7 +2124,6 @@ static int __devexit musb_remove(struct platform_device *pdev)
* - OTG mode: both roles are deactivated (or never-activated)
*/
musb_shutdown(pdev);
musb_debug_delete("driver/musb_hdrc", musb);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (musb->board_mode == MUSB_HOST)
usb_remove_hcd(musb_to_hcd(musb));
......
......@@ -485,23 +485,4 @@ extern int musb_platform_get_vbus_status(struct musb *musb);
extern int __init musb_platform_init(struct musb *musb);
extern int musb_platform_exit(struct musb *musb);
/*-------------------------- ProcFS definitions ---------------------*/
struct proc_dir_entry;
#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS)
extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
extern void musb_debug_delete(char *name, struct musb *data);
#else
static inline struct proc_dir_entry *
musb_debug_create(char *name, struct musb *data)
{
return NULL;
}
static inline void musb_debug_delete(char *name, struct musb *data)
{
}
#endif
#endif /* __MUSB_CORE_H__ */
......@@ -48,11 +48,7 @@
__func__, __LINE__ , ## args); \
} } while (0)
#if MUSB_DEBUG > 0
extern unsigned debug;
#else
#define debug 0
#endif
static inline int _dbg_level(unsigned l)
{
......
......@@ -476,6 +476,7 @@ static void ep0_rxstate(struct musb *musb)
return;
musb->ackpend = 0;
}
musb_ep_select(musb->mregs, 0);
musb_writew(regs, MUSB_CSR0, tmp);
}
......@@ -528,6 +529,7 @@ static void ep0_txstate(struct musb *musb)
}
/* send it out, triggering a "txpktrdy cleared" irq */
musb_ep_select(musb->mregs, 0);
musb_writew(regs, MUSB_CSR0, csr);
}
......
/*
* MUSB OTG driver debug support
*
* Copyright 2005 Mentor Graphics Corporation
* Copyright (C) 2005-2006 by Texas Instruments
* Copyright (C) 2006-2007 Nokia Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h> /* FIXME remove procfs writes */
#include <asm/arch/hardware.h>
#include "musb_core.h"
#include "davinci.h"
#ifdef CONFIG_USB_MUSB_HDRC_HCD
static int dump_qh(struct musb_qh *qh, char *buf, unsigned max)
{
int count;
int tmp;
struct usb_host_endpoint *hep = qh->hep;
struct urb *urb;
count = snprintf(buf, max, " qh %p dev%d ep%d%s max%d\n",
qh, qh->dev->devnum, qh->epnum,
({ char *s; switch (qh->type) {
case USB_ENDPOINT_XFER_BULK:
s = "-bulk"; break;
case USB_ENDPOINT_XFER_INT:
s = "-int"; break;
case USB_ENDPOINT_XFER_CONTROL:
s = ""; break;
default:
s = "iso"; break;
}; s; }),
qh->maxpacket);
if (count <= 0)
return 0;
buf += count;
max -= count;
list_for_each_entry(urb, &hep->urb_list, urb_list) {
tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n",
usb_pipein(urb->pipe) ? "in" : "out",
urb, urb->actual_length,
urb->transfer_buffer_length);
if (tmp <= 0)
break;
tmp = min(tmp, (int)max);
count += tmp;
buf += tmp;
max -= tmp;
}
return count;
}
static int
dump_queue(struct list_head *q, char *buf, unsigned max)
{
int count = 0;
struct musb_qh *qh;
list_for_each_entry(qh, q, ring) {
int tmp;
tmp = dump_qh(qh, buf, max);
if (tmp <= 0)
break;
tmp = min(tmp, (int)max);
count += tmp;
buf += tmp;
max -= tmp;
}
return count;
}
#endif /* HCD */
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max)
{
char *buf = buffer;
int code = 0;
void __iomem *regs = ep->hw_ep->regs;
char *mode = "1buf";
if (ep->is_in) {
if (ep->hw_ep->tx_double_buffered)
mode = "2buf";
} else {
if (ep->hw_ep->rx_double_buffered)
mode = "2buf";
}
do {
struct usb_request *req;
code = snprintf(buf, max,
"\n%s (hw%d): %s%s, csr %04x maxp %04x\n",
ep->name, ep->current_epnum,
mode, ep->dma ? " dma" : "",
musb_readw(regs,
(ep->is_in || !ep->current_epnum)
? MUSB_TXCSR
: MUSB_RXCSR),
musb_readw(regs, ep->is_in
? MUSB_TXMAXP
: MUSB_RXMAXP)
);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
if (is_cppi_enabled() && ep->current_epnum) {
unsigned cppi = ep->current_epnum - 1;
void __iomem *base = ep->musb->ctrl_base;
unsigned off1 = cppi << 2;
void __iomem *ram = base;
char tmp[16];
if (ep->is_in) {
ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi);
tmp[0] = 0;
} else {
ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi);
snprintf(tmp, sizeof tmp, "%d left, ",
musb_readl(base,
DAVINCI_RXCPPI_BUFCNT0_REG + off1));
}
code = snprintf(buf, max, "%cX DMA%d: %s"
"%08x %08x, %08x %08x; "
"%08x %08x %08x .. %08x\n",
ep->is_in ? 'T' : 'R',
ep->current_epnum - 1, tmp,
musb_readl(ram, 0 * 4),
musb_readl(ram, 1 * 4),
musb_readl(ram, 2 * 4),
musb_readl(ram, 3 * 4),
musb_readl(ram, 4 * 4),
musb_readl(ram, 5 * 4),
musb_readl(ram, 6 * 4),
musb_readl(ram, 7 * 4));
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
if (list_empty(&ep->req_list)) {
code = snprintf(buf, max, "\t(queue empty)\n");
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
break;
}
list_for_each_entry(req, &ep->req_list, list) {
code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n",
req,
req->zero ? "zero, " : "",
req->short_not_ok ? "!short, " : "",
req->actual, req->length);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
} while (0);
return buf - buffer;
}
#endif
static int
dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max)
{
int code = 0;
char *buf = aBuffer;
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
do {
musb_ep_select(musb->mregs, epnum);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (is_host_active(musb)) {
int dump_rx, dump_tx;
void __iomem *regs = hw_ep->regs;
/* TEMPORARY (!) until we have a real periodic
* schedule tree ...
*/
if (!epnum) {
/* control is shared, uses RX queue
* but (mostly) shadowed tx registers
*/
dump_tx = !list_empty(&musb->control);
dump_rx = 0;
} else if (hw_ep == musb->bulk_ep) {
dump_tx = !list_empty(&musb->out_bulk);
dump_rx = !list_empty(&musb->in_bulk);
} else if (musb->periodic[epnum]) {
struct usb_host_endpoint *hep;
hep = musb->periodic[epnum]->hep;
dump_rx = hep->desc.bEndpointAddress
& USB_ENDPOINT_DIR_MASK;
dump_tx = !dump_rx;
} else
break;
/* END TEMPORARY */
if (dump_rx) {
code = snprintf(buf, max,
"\nRX%d: %s rxcsr %04x interval %02x "
"max %04x type %02x; "
"dev %d hub %d port %d"
"\n",
epnum,
hw_ep->rx_double_buffered
? "2buf" : "1buf",
musb_readw(regs, MUSB_RXCSR),
musb_readb(regs, MUSB_RXINTERVAL),
musb_readw(regs, MUSB_RXMAXP),
musb_readb(regs, MUSB_RXTYPE),
/* FIXME: assumes multipoint */
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_RXFUNCADDR)),
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_RXHUBADDR)),
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_RXHUBPORT))
);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
if (is_cppi_enabled()
&& epnum
&& hw_ep->rx_channel) {
unsigned cppi = epnum - 1;
unsigned off1 = cppi << 2;
void __iomem *base;
void __iomem *ram;
char tmp[16];
base = musb->ctrl_base;
ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
cppi) + base;
snprintf(tmp, sizeof tmp, "%d left, ",
musb_readl(base,
DAVINCI_RXCPPI_BUFCNT0_REG
+ off1));
code = snprintf(buf, max,
" rx dma%d: %s"
"%08x %08x, %08x %08x; "
"%08x %08x %08x .. %08x\n",
cppi, tmp,
musb_readl(ram, 0 * 4),
musb_readl(ram, 1 * 4),
musb_readl(ram, 2 * 4),
musb_readl(ram, 3 * 4),
musb_readl(ram, 4 * 4),
musb_readl(ram, 5 * 4),
musb_readl(ram, 6 * 4),
musb_readl(ram, 7 * 4));
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
if (hw_ep == musb->bulk_ep
&& !list_empty(
&musb->in_bulk)) {
code = dump_queue(&musb->in_bulk,
buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
} else if (musb->periodic[epnum]) {
code = dump_qh(musb->periodic[epnum],
buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
}
if (dump_tx) {
code = snprintf(buf, max,
"\nTX%d: %s txcsr %04x interval %02x "
"max %04x type %02x; "
"dev %d hub %d port %d"
"\n",
epnum,
hw_ep->tx_double_buffered
? "2buf" : "1buf",
musb_readw(regs, MUSB_TXCSR),
musb_readb(regs, MUSB_TXINTERVAL),
musb_readw(regs, MUSB_TXMAXP),
musb_readb(regs, MUSB_TXTYPE),
/* FIXME: assumes multipoint */
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_TXFUNCADDR)),
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_TXHUBADDR)),
musb_readb(musb->mregs,
MUSB_BUSCTL_OFFSET(epnum,
MUSB_TXHUBPORT))
);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
if (is_cppi_enabled()
&& epnum
&& hw_ep->tx_channel) {
unsigned cppi = epnum - 1;
void __iomem *base;
void __iomem *ram;
base = musb->ctrl_base;
ram = DAVINCI_RXCPPI_STATERAM_OFFSET(
cppi) + base;
code = snprintf(buf, max,
" tx dma%d: "
"%08x %08x, %08x %08x; "
"%08x %08x %08x .. %08x\n",
cppi,
musb_readl(ram, 0 * 4),
musb_readl(ram, 1 * 4),
musb_readl(ram, 2 * 4),
musb_readl(ram, 3 * 4),
musb_readl(ram, 4 * 4),
musb_readl(ram, 5 * 4),
musb_readl(ram, 6 * 4),
musb_readl(ram, 7 * 4));
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
if (hw_ep == musb->control_ep
&& !list_empty(
&musb->control)) {
code = dump_queue(&musb->control,
buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
} else if (hw_ep == musb->bulk_ep
&& !list_empty(
&musb->out_bulk)) {
code = dump_queue(&musb->out_bulk,
buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
} else if (musb->periodic[epnum]) {
code = dump_qh(musb->periodic[epnum],
buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
}
}
#endif
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
if (is_peripheral_active(musb)) {
code = 0;
if (hw_ep->ep_in.desc || !epnum) {
code = dump_ep(&hw_ep->ep_in, buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
if (hw_ep->ep_out.desc) {
code = dump_ep(&hw_ep->ep_out, buf, max);
if (code <= 0)
break;
code = min(code, (int) max);
buf += code;
max -= code;
}
}
#endif
} while (0);
return buf - aBuffer;
}
/* Dump the current status and compile options.
* @param musb the device driver instance
* @param buffer where to dump the status; it must be big enough to hold the
* result otherwise "BAD THINGS HAPPENS(TM)".
*/
static int dump_header_stats(struct musb *musb, char *buffer)
{
int code, count = 0;
const void __iomem *mbase = musb->mregs;
*buffer = 0;
count = sprintf(buffer, "Status: %sHDRC, Mode=%s "
"(Power=%02x, DevCtl=%02x)\n",
(musb->is_multipoint ? "M" : ""), MUSB_MODE(musb),
musb_readb(mbase, MUSB_POWER),
musb_readb(mbase, MUSB_DEVCTL));
if (count <= 0)
return 0;
buffer += count;
code = sprintf(buffer, "OTG state: %s; %sactive\n",
otg_state_string(musb),
musb->is_active ? "" : "in");
if (code <= 0)
goto done;
buffer += code;
count += code;
code = sprintf(buffer,
"Options: "
#ifdef CONFIG_MUSB_PIO_ONLY
"pio"
#elif defined(CONFIG_USB_TI_CPPI_DMA)
"cppi-dma"
#elif defined(CONFIG_USB_INVENTRA_DMA)
"musb-dma"
#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
"tusb-omap-dma"
#else
"?dma?"
#endif
", "
#ifdef CONFIG_USB_MUSB_OTG
"otg (peripheral+host)"
#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
"peripheral"
#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
"host"
#endif
", debug=%d [eps=%d]\n",
debug,
musb->nr_endpoints);
if (code <= 0)
goto done;
count += code;
buffer += code;
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
code = sprintf(buffer, "Peripheral address: %02x\n",
musb_readb(musb->ctrl_base, MUSB_FADDR));
if (code <= 0)
goto done;
buffer += code;
count += code;
#endif
#ifdef CONFIG_USB_MUSB_HDRC_HCD
code = sprintf(buffer, "Root port status: %08x\n",
musb->port1_status);
if (code <= 0)
goto done;
buffer += code;
count += code;
#endif
#ifdef CONFIG_ARCH_DAVINCI
code = sprintf(buffer,
"DaVinci: ctrl=%02x stat=%1x phy=%03x\n"
"\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x"
"\n",
musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG),
musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG),
__raw_readl((void __force __iomem *)
IO_ADDRESS(USBPHY_CTL_PADDR)),
musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG),
musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG),
musb_readl(musb->ctrl_base,
DAVINCI_USB_INT_SOURCE_REG),
musb_readl(musb->ctrl_base,
DAVINCI_USB_INT_MASK_REG));
if (code <= 0)
goto done;
count += code;
buffer += code;
#endif /* DAVINCI */
#ifdef CONFIG_USB_TUSB6010
code = sprintf(buffer,
"TUSB6010: devconf %08x, phy enable %08x drive %08x"
"\n\totg %03x timer %08x"
"\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x"
"\n",
musb_readl(musb->ctrl_base, TUSB_DEV_CONF),
musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE),
musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL),
musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT),
musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER),
musb_readl(musb->ctrl_base, TUSB_PRCM_CONF),
musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT),
musb_readl(musb->ctrl_base, TUSB_INT_SRC),
musb_readl(musb->ctrl_base, TUSB_INT_MASK));
if (code <= 0)
goto done;
count += code;
buffer += code;
#endif /* DAVINCI */
if (is_cppi_enabled() && musb->dma_controller) {
code = sprintf(buffer,
"CPPI: txcr=%d txsrc=%01x txena=%01x; "
"rxcr=%d rxsrc=%01x rxena=%01x "
"\n",
musb_readl(musb->ctrl_base,
DAVINCI_TXCPPI_CTRL_REG),
musb_readl(musb->ctrl_base,
DAVINCI_TXCPPI_RAW_REG),
musb_readl(musb->ctrl_base,
DAVINCI_TXCPPI_INTENAB_REG),
musb_readl(musb->ctrl_base,
DAVINCI_RXCPPI_CTRL_REG),
musb_readl(musb->ctrl_base,
DAVINCI_RXCPPI_RAW_REG),
musb_readl(musb->ctrl_base,
DAVINCI_RXCPPI_INTENAB_REG));
if (code <= 0)
goto done;
count += code;
buffer += code;
}
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
if (is_peripheral_enabled(musb)) {
code = sprintf(buffer, "Gadget driver: %s\n",
musb->gadget_driver
? musb->gadget_driver->driver.name
: "(none)");
if (code <= 0)
goto done;
count += code;
buffer += code;
}
#endif
done:
return count;
}
/* Write to ProcFS
*
* C soft-connect
* c soft-disconnect
* I enable HS
* i disable HS
* s stop session
* F force session (OTG-unfriendly)
* E rElinquish bus (OTG)
* H request host mode
* h cancel host request
* T start sending TEST_PACKET
* D<num> set/query the debug level
*/
static int musb_proc_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
char cmd;
u8 reg;
struct musb *musb = (struct musb *)data;
void __iomem *mbase = musb->mregs;
/* MOD_INC_USE_COUNT; */
if (unlikely(copy_from_user(&cmd, buffer, 1)))
return -EFAULT;
switch (cmd) {
case 'C':
if (mbase) {
reg = musb_readb(mbase, MUSB_POWER)
| MUSB_POWER_SOFTCONN;
musb_writeb(mbase, MUSB_POWER, reg);
}
break;
case 'c':
if (mbase) {
reg = musb_readb(mbase, MUSB_POWER)
& ~MUSB_POWER_SOFTCONN;
musb_writeb(mbase, MUSB_POWER, reg);
}
break;
case 'I':
if (mbase) {
reg = musb_readb(mbase, MUSB_POWER)
| MUSB_POWER_HSENAB;
musb_writeb(mbase, MUSB_POWER, reg);
}
break;
case 'i':
if (mbase) {
reg = musb_readb(mbase, MUSB_POWER)
& ~MUSB_POWER_HSENAB;
musb_writeb(mbase, MUSB_POWER, reg);
}
break;
case 'F':
reg = musb_readb(mbase, MUSB_DEVCTL);
reg |= MUSB_DEVCTL_SESSION;
musb_writeb(mbase, MUSB_DEVCTL, reg);
break;
case 'H':
if (mbase) {
reg = musb_readb(mbase, MUSB_DEVCTL);
reg |= MUSB_DEVCTL_HR;
musb_writeb(mbase, MUSB_DEVCTL, reg);
/* MUSB_HST_MODE( ((struct musb*)data) ); */
/* WARNING("Host Mode\n"); */
}
break;
case 'h':
if (mbase) {
reg = musb_readb(mbase, MUSB_DEVCTL);
reg &= ~MUSB_DEVCTL_HR;
musb_writeb(mbase, MUSB_DEVCTL, reg);
}
break;
case 'T':
if (mbase) {
musb_load_testpacket(musb);
musb_writeb(mbase, MUSB_TESTMODE,
MUSB_TEST_PACKET);
}
break;
#if (MUSB_DEBUG > 0)
/* set/read debug level */
case 'D':{
if (count > 1) {
char digits[8], *p = digits;
int i = 0, level = 0, sign = 1;
int len = min(count - 1, (unsigned long)8);
if (copy_from_user(&digits, &buffer[1], len))
return -EFAULT;
/* optional sign */
if (*p == '-') {
len -= 1;
sign = -sign;
p++;
}
/* read it */
while (i++ < len && *p > '0' && *p < '9') {
level = level * 10 + (*p - '0');
p++;
}
level *= sign;
DBG(1, "debug level %d\n", level);
debug = level;
}
}
break;
case '?':
INFO("?: you are seeing it\n");
INFO("C/c: soft connect enable/disable\n");
INFO("I/i: hispeed enable/disable\n");
INFO("F: force session start\n");
INFO("H: host mode\n");
INFO("T: start sending TEST_PACKET\n");
INFO("D: set/read dbug level\n");
break;
#endif
default:
ERR("Command %c not implemented\n", cmd);
break;
}
musb_platform_try_idle(musb, 0);
return count;
}
static int musb_proc_read(char *page, char **start,
off_t off, int count, int *eof, void *data)
{
char *buffer = page;
int code = 0;
unsigned long flags;
struct musb *musb = data;
unsigned epnum;
count -= off;
count -= 1; /* for NUL at end */
if (count <= 0)
return -EINVAL;
spin_lock_irqsave(&musb->lock, flags);
code = dump_header_stats(musb, buffer);
if (code > 0) {
buffer += code;
count -= code;
}
/* generate the report for the end points */
/* REVISIT ... not unless something's connected! */
for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints;
epnum++) {
code = dump_end_info(musb, epnum, buffer, count);
if (code > 0) {
buffer += code;
count -= code;
}
}
musb_platform_try_idle(musb, 0);
spin_unlock_irqrestore(&musb->lock, flags);
*eof = 1;
return buffer - page;
}
void __devexit musb_debug_delete(char *name, struct musb *musb)
{
if (musb->proc_entry)
remove_proc_entry(name, NULL);
}
struct proc_dir_entry *__init
musb_debug_create(char *name, struct musb *data)
{
struct proc_dir_entry *pde;
/* FIXME convert everything to seq_file; then later, debugfs */
if (!name)
return NULL;
pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL);
data->proc_entry = pde;
if (pde) {
pde->data = data;
/* pde->owner = THIS_MODULE; */
pde->read_proc = musb_proc_read;
pde->write_proc = musb_proc_write;
pde->size = 0;
pr_debug("Registered /proc/%s\n", name);
} else {
pr_debug("Cannot create a valid proc file entry");
}
return pde;
}
......@@ -173,6 +173,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
#define KYOCERA_PRODUCT_KPC680 0x180a
#define ANYDATA_VENDOR_ID 0x16d5
#define ANYDATA_PRODUCT_ADU_620UW 0x6202
#define ANYDATA_PRODUCT_ADU_E100A 0x6501
#define ANYDATA_PRODUCT_ADU_500A 0x6502
......@@ -318,6 +319,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
......
......@@ -110,6 +110,8 @@ enum usb_interface_condition {
* @sysfs_files_created: sysfs attributes exist
* @needs_remote_wakeup: flag set when the driver requires remote-wakeup
* capability during autosuspend.
* @needs_altsetting0: flag set when a set-interface request for altsetting 0
* has been deferred.
* @needs_binding: flag set when the driver should be re-probed or unbound
* following a reset or suspend operation it doesn't support.
* @dev: driver model's view of this device
......@@ -162,6 +164,7 @@ struct usb_interface {
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
unsigned needs_altsetting0:1; /* switch to altsetting 0 is pending */
unsigned needs_binding:1; /* needs delayed unbind/rebind */
struct device dev; /* interface specific device info */
......
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