diff options
Diffstat (limited to 'drivers/usb/musb/musb_core.c')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 2c624a107..ee9ff7028 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1028,18 +1028,22 @@ void musb_start(struct musb *musb) { void __iomem *regs = musb->mregs; u8 devctl = musb_readb(regs, MUSB_DEVCTL); + u8 power; dev_dbg(musb->controller, "<== devctl %02x\n", devctl); musb_enable_interrupts(musb); musb_writeb(regs, MUSB_TESTMODE, 0); - /* put into basic highspeed mode and start session */ - musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE - | MUSB_POWER_HSENAB - /* ENSUSPEND wedges tusb */ - /* | MUSB_POWER_ENSUSPEND */ - ); + power = MUSB_POWER_ISOUPDATE; + /* + * treating UNKNOWN as unspecified maximum speed, in which case + * we will default to high-speed. + */ + if (musb->config->maximum_speed == USB_SPEED_HIGH || + musb->config->maximum_speed == USB_SPEED_UNKNOWN) + power |= MUSB_POWER_HSENAB; + musb_writeb(regs, MUSB_POWER, power); musb->is_active = 0; devctl = musb_readb(regs, MUSB_DEVCTL); @@ -1664,7 +1668,7 @@ EXPORT_SYMBOL_GPL(musb_interrupt); static bool use_dma = 1; /* "modprobe ... use_dma=0" etc */ -module_param(use_dma, bool, 0); +module_param(use_dma, bool, 0644); MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) @@ -1771,13 +1775,20 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) unsigned long flags; unsigned long val; int vbus; + u8 devctl; spin_lock_irqsave(&musb->lock, flags); val = musb->a_wait_bcon; - /* FIXME get_vbus_status() is normally #defined as false... - * and is effectively TUSB-specific. - */ vbus = musb_platform_get_vbus_status(musb); + if (vbus < 0) { + /* Use default MUSB method by means of DEVCTL register */ + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if ((devctl & MUSB_DEVCTL_VBUS) + == (3 << MUSB_DEVCTL_VBUS_SHIFT)) + vbus = 1; + else + vbus = 0; + } spin_unlock_irqrestore(&musb->lock, flags); return sprintf(buf, "Vbus %s, timeout %lu msec\n", @@ -2006,7 +2017,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* We need musb_read/write functions initialized for PM */ pm_runtime_use_autosuspend(musb->controller); pm_runtime_set_autosuspend_delay(musb->controller, 200); - pm_runtime_irq_safe(musb->controller); pm_runtime_enable(musb->controller); /* The musb_platform_init() call: @@ -2084,6 +2094,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) #ifndef CONFIG_MUSB_PIO_ONLY if (!musb->ops->dma_init || !musb->ops->dma_exit) { dev_err(dev, "DMA controller not set\n"); + status = -ENODEV; goto fail2; } musb_dma_controller_create = musb->ops->dma_init; @@ -2207,6 +2218,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_put(musb->controller); + /* + * For why this is currently needed, see commit 3e43a0725637 + * ("usb: musb: core: add pm_runtime_irq_safe()") + */ + pm_runtime_irq_safe(musb->controller); + return 0; fail5: |