summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig9
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/amd5536udc.c49
-rw-r--r--drivers/usb/gadget/arcotg_udc.c451
-rw-r--r--drivers/usb/gadget/arcotg_udc.h11
-rw-r--r--drivers/usb/gadget/composite.c39
-rw-r--r--drivers/usb/gadget/f_acm.c9
-rw-r--r--drivers/usb/gadget/file_storage.c9
8 files changed, 190 insertions, 389 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c29ebda61b2f..a19d73730470 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -791,15 +791,6 @@ config USB_G_PRINTER
For more information, see Documentation/usb/gadget_printer.txt
which includes sample code for accessing the device file.
-config USB_ANDROID
- tristate "Android Gadget"
- depends on SWITCH
- help
- The Android gadget provides mass storage and adb transport.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_android".
-
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 545c0e256e28..477114e43372 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -41,7 +41,6 @@ gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o
-g_android-objs := android.o f_adb.o f_mass_storage.o
obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_AUDIO) += g_audio.o
@@ -52,5 +51,4 @@ obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
-obj-$(CONFIG_USB_ANDROID) += g_android.o
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index 77352ccc245e..fb0976643a2f 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -1213,7 +1213,12 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
tmp &= AMD_UNMASK_BIT(ep->num);
writel(tmp, &dev->regs->ep_irqmsk);
}
- }
+ } else if (ep->in) {
+ /* enable ep irq */
+ tmp = readl(&dev->regs->ep_irqmsk);
+ tmp &= AMD_UNMASK_BIT(ep->num);
+ writel(tmp, &dev->regs->ep_irqmsk);
+ }
} else if (ep->dma) {
@@ -2005,18 +2010,17 @@ __acquires(dev->lock)
{
int tmp;
- /* empty queues and init hardware */
- udc_basic_init(dev);
- for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
- empty_req_queue(&dev->ep[tmp]);
- }
-
if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
- /* init */
+
+ /* empty queues and init hardware */
+ udc_basic_init(dev);
+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++)
+ empty_req_queue(&dev->ep[tmp]);
+
udc_setup_endpoints(dev);
}
@@ -2478,6 +2482,13 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix)
}
}
+ } else if (!use_dma && ep->in) {
+ /* disable interrupt */
+ tmp = readl(
+ &dev->regs->ep_irqmsk);
+ tmp |= AMD_BIT(ep->num);
+ writel(tmp,
+ &dev->regs->ep_irqmsk);
}
}
/* clear status bits */
@@ -3285,6 +3296,17 @@ static int udc_pci_probe(
goto finished;
}
+ spin_lock_init(&dev->lock);
+ /* udc csr registers base */
+ dev->csr = dev->virt_addr + UDC_CSR_ADDR;
+ /* dev registers base */
+ dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
+ /* ep registers base */
+ dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
+ /* fifo's base */
+ dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
+ dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
+
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
kfree(dev);
@@ -3337,7 +3359,6 @@ static int udc_probe(struct udc *dev)
udc_pollstall_timer.data = 0;
/* device struct setup */
- spin_lock_init(&dev->lock);
dev->gadget.ops = &udc_ops;
dev_set_name(&dev->gadget.dev, "gadget");
@@ -3346,16 +3367,6 @@ static int udc_probe(struct udc *dev)
dev->gadget.name = name;
dev->gadget.is_dualspeed = 1;
- /* udc csr registers base */
- dev->csr = dev->virt_addr + UDC_CSR_ADDR;
- /* dev registers base */
- dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR;
- /* ep registers base */
- dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR;
- /* fifo's base */
- dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR);
- dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
-
/* init registers, interrupts, ... */
startup_registers(dev);
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 8e94549f891e..abba4d2ae8d4 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -106,6 +106,19 @@ extern struct resource *otg_get_resources(void);
extern void fsl_platform_set_test_mode(struct fsl_usb2_platform_data *pdata, enum usb_test_mode mode);
+static inline void
+dr_wake_up_enable(struct fsl_udc *udc, bool enable)
+{
+ struct fsl_usb2_platform_data *pdata;
+ pdata = udc->pdata;
+
+ if (enable && (!device_may_wakeup(udc_controller->gadget.dev.parent)))
+ return;
+
+ if (pdata->wake_up_enable)
+ pdata->wake_up_enable(pdata, enable);
+}
+
#ifdef CONFIG_WORKAROUND_ARCUSB_REG_RW
static void safe_writel(u32 val32, void *addr)
{
@@ -270,12 +283,9 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
static void nuke(struct fsl_ep *ep, int status)
{
ep->stopped = 1;
- /*
- * At udc stop mode, the clock is already off
- * So flush fifo, should be done at clock on mode.
- */
- if (!ep->udc->stopped)
- fsl_ep_fifo_flush(&ep->ep);
+
+ /* Flush fifo */
+ fsl_ep_fifo_flush(&ep->ep);
/* Whether this eq has request linked */
while (!list_empty(&ep->queue)) {
@@ -290,83 +300,31 @@ static void nuke(struct fsl_ep *ep, int status)
/*------------------------------------------------------------------
Internal Hardware related function
------------------------------------------------------------------*/
-static inline void
-dr_wake_up_enable(struct fsl_udc *udc, bool enable)
-{
- struct fsl_usb2_platform_data *pdata;
- pdata = udc->pdata;
- if (pdata && pdata->wake_up_enable)
- pdata->wake_up_enable(pdata, enable);
-}
-static bool clk_stoped = false;
-static inline void dr_clk_gate(bool on)
+static void dr_phy_low_power_mode(struct fsl_udc *udc, bool enable)
{
- struct fsl_usb2_platform_data *pdata = udc_controller->pdata;
+ u32 temp;
- if (!pdata || !pdata->usb_clock_for_pm)
+ if (!device_may_wakeup(udc_controller->gadget.dev.parent))
return;
- if (on && clk_stoped) {
- pdata->usb_clock_for_pm(true);
- clk_stoped = false;
- }
- if (!on && !clk_stoped) {
- pdata->usb_clock_for_pm(false);
- clk_stoped = true;
- }
- if (on)
- reset_phy();
-}
-static void dr_phy_low_power_mode(struct fsl_udc *udc, bool enable)
-{
- struct fsl_usb2_platform_data *pdata = udc->pdata;
- u32 portsc;
+ if (enable) {
+ temp = fsl_readl(&dr_regs->portsc1);
+ temp |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(temp, &dr_regs->portsc1);
- if (pdata && pdata->phy_lowpower_suspend) {
- pdata->phy_lowpower_suspend(enable);
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
} else {
- if (enable){
- portsc = fsl_readl(&dr_regs->portsc1);
- portsc |= PORTSCX_PHY_LOW_POWER_SPD;
- fsl_writel(portsc, &dr_regs->portsc1);
- } else {
- portsc = fsl_readl(&dr_regs->portsc1);
- portsc &= ~PORTSCX_PHY_LOW_POWER_SPD;
- fsl_writel(portsc, &dr_regs->portsc1);
- }
- }
-}
-
-
-/* workaroud for some boards, maybe there is a large capacitor between the ground and the Vbus
- * that will cause the vbus dropping very slowly when device is detached,
- * may cost 2-3 seconds to below 0.8V */
-static void udc_wait_b_session_low(void)
-{
- u32 temp;
- u32 wait = 5000; /* max wait time is 5000 ms */
- /* if we are in host mode, don't need to care the B session */
- if ((fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) == 0)
- return;
- /* if the udc is dettached , there will be a suspend irq */
- if (udc_controller->usb_state != USB_STATE_SUSPENDED)
- return;
- temp = fsl_readl(&dr_regs->otgsc);
- temp &= ~(OTGSC_B_SESSION_VALID_IRQ_EN );
- fsl_writel(temp, &dr_regs->otgsc);
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
- do {
- if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_B_SESSION_VALID))
- break;
- mdelay(1);
- wait -= 1;
- } while(wait);
- if (!wait)
- printk("ERROR!!!!!: the vbus can not be lower then 0.8V for 5 seconds, Pls Check your HW design\n");
- temp = fsl_readl(&dr_regs->otgsc);
- temp |= (OTGSC_B_SESSION_VALID_IRQ_EN );
- fsl_writel(temp, &dr_regs->otgsc);
+ /* Due to mx35/mx25's phy's bug */
+ reset_phy();
+ temp = fsl_readl(&dr_regs->portsc1);
+ temp &= ~PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(temp, &dr_regs->portsc1);
+ }
}
static int dr_controller_setup(struct fsl_udc *udc)
@@ -490,20 +448,23 @@ static void dr_controller_run(struct fsl_udc *udc)
fsl_writel(temp, &dr_regs->usbintr);
- /* enable BSV irq */
- temp = fsl_readl(&dr_regs->otgsc);
- temp |= OTGSC_B_SESSION_VALID_IRQ_EN;
- fsl_writel(temp, &dr_regs->otgsc);
+ if (device_may_wakeup(udc_controller->gadget.dev.parent)) {
+ /* enable BSV irq */
+ temp = fsl_readl(&dr_regs->otgsc);
+ temp |= OTGSC_B_SESSION_VALID_IRQ_EN;
+ fsl_writel(temp, &dr_regs->otgsc);
+ }
/* If vbus not on and used low power mode */
- if (!(temp & OTGSC_B_SESSION_VALID)) {
- /* Set stopped before low power mode */
- udc->stopped = 1;
+ if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_B_SESSION_VALID)
+ && device_may_wakeup(udc_controller->gadget.dev.parent)) {
/* enable wake up */
dr_wake_up_enable(udc, true);
- /* enter lower power mode */
+ /* Set stopped before low power mode */
+ udc->stopped = 1;
+ /* close PHY clock */
dr_phy_low_power_mode(udc, true);
- printk(KERN_INFO "%s: udc enter low power mode \n", __func__);
+ printk(KERN_INFO "udc enter low power mode \n");
} else {
#ifdef CONFIG_ARCH_MX37
/*
@@ -515,11 +476,11 @@ static void dr_controller_run(struct fsl_udc *udc)
#endif
/* Clear stopped bit */
udc->stopped = 0;
-
- /* The usb line has already been connected to pc */
+ /* Set controller to Run */
temp = fsl_readl(&dr_regs->usbcmd);
temp |= USB_CMD_RUN_STOP;
fsl_writel(temp, &dr_regs->usbcmd);
+ printk(KERN_INFO "udc run \n");
}
return;
@@ -2015,36 +1976,15 @@ static void suspend_irq(struct fsl_udc *udc)
udc->driver->suspend(&udc->gadget);
}
-/* Process Wake up interrupt
- * Be careful that some boards will use ID pin to control the VBUS on/off
- * in these case, after the device enter the lowpower mode(clk off,
- * phy lowpower mode, wakeup enable), then an udisk is attaced to the otg port,
- * there will be an Vbus wakeup event and then an ID change wakeup, But the Vbus
- * event is not expected, so there is an workaround that will detect the ID, if ID=0
- * we just need the ID event so we can not disable the wakeup
- *
- * false: host wakeup event
- * true: device wakeup event
-*/
-static bool wake_up_irq(struct fsl_udc *udc)
-{
- /* Because the IC design needs to remove the glitch on ID so the otgsc bit 8 will
- * be delayed max 2 ms to show the real ID pin value
- */
- mdelay(3);
-
- /* if the ID=0, let arc host process the wakeup */
- if (fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) {
- dr_wake_up_enable(udc_controller, false);
- dr_phy_low_power_mode(udc, false);
- printk("device wake up event\n");
- return true;
- }else {/* wakeup is vbus wake event, but not for device so we need to clear b session */
- int irq_src = fsl_readl(&dr_regs->otgsc) & (~OTGSC_ID_CHANGE_IRQ_STS);
- fsl_writel(irq_src, &dr_regs->otgsc);
- printk("The host wakeup event, should be handled by host\n");
- return false;
- }
+/* Process Wake up interrupt */
+static void wake_up_irq(struct fsl_udc *udc)
+{
+ pr_debug("%s\n", __func__);
+
+ /* disable wake up irq */
+ dr_wake_up_enable(udc_controller, false);
+
+ udc->stopped = 0;
}
static void bus_resume(struct fsl_udc *udc)
@@ -2113,48 +2053,43 @@ static void reset_irq(struct fsl_udc *udc)
bool try_wake_up_udc(struct fsl_udc *udc)
{
u32 irq_src;
- bool b_device;
/* when udc is stopped, only handle wake up irq */
if (udc->stopped) {
+ if (!device_may_wakeup(&(udc->pdata->pdev->dev)))
+ return false;
+
+ dr_phy_low_power_mode(udc_controller, false);
+
/* check to see if wake up irq */
irq_src = fsl_readl(&dr_regs->usbctrl);
if (irq_src & USB_CTRL_OTG_WUIR) {
- if (wake_up_irq(udc) == false){
- return false; /* host wakeup event */
- }
+ wake_up_irq(udc);
+ } else {
+ dr_phy_low_power_mode(udc_controller, true);
}
}
+ if (!device_may_wakeup(udc_controller->gadget.dev.parent))
+ return true;
+
/* check if Vbus change irq */
irq_src = fsl_readl(&dr_regs->otgsc);
if (irq_src & OTGSC_B_SESSION_VALID_IRQ_STS) {
u32 tmp;
- /* Because the IC design needs to remove the glitch on ID so the otgsc bit 8 will
- * be delayed max 2 ms to show the real ID pin value, as it needs to use ID to judge
- * host or device
- */
- mdelay(3);
- b_device = (irq_src & OTGSC_STS_USB_ID)? true:false;
fsl_writel(irq_src, &dr_regs->otgsc);
- if (!b_device)
- return false;
tmp = fsl_readl(&dr_regs->usbcmd);
/* check BSV bit to see if fall or rise */
if (irq_src & OTGSC_B_SESSION_VALID) {
- if (udc->suspended) /*let the system pm resume the udc */
- return true;
udc->stopped = 0;
fsl_writel(tmp | USB_CMD_RUN_STOP, &dr_regs->usbcmd);
- printk(KERN_INFO "%s: udc out low power mode\n", __func__);
+ printk(KERN_INFO "udc out low power mode\n");
} else {
- printk(KERN_INFO "%s: udc enter low power mode \n", __func__);
- if (udc->driver)
- udc->driver->disconnect(&udc->gadget);
+ printk(KERN_INFO "udc enter low power mode \n");
fsl_writel(tmp & ~USB_CMD_RUN_STOP, &dr_regs->usbcmd);
- udc->stopped = 1;
/* enable wake up */
dr_wake_up_enable(udc, true);
+ udc->stopped = 1;
/* close USB PHY clock */
dr_phy_low_power_mode(udc, true);
return false;
@@ -2163,6 +2098,7 @@ bool try_wake_up_udc(struct fsl_udc *udc)
return true;
}
+
/*
* USB device controller interrupt handler
*/
@@ -2173,29 +2109,15 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
irqreturn_t status = IRQ_NONE;
unsigned long flags;
- spin_lock_irqsave(&udc->lock, flags);
- if (udc->stopped)
- dr_clk_gate(true);
-
- if (try_wake_up_udc(udc) == false) {
- goto irq_end;
- }
-#ifdef CONFIG_USB_OTG
- /* if no gadget register in this driver, we need do noting */
- if (udc->transceiver->gadget == NULL)
- goto irq_end;
-
- /* only handle device interrupt event */
- if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
- goto irq_end;
- }
-#endif
+ if (try_wake_up_udc(udc) == false)
+ return IRQ_NONE;
+ spin_lock_irqsave(&udc->lock, flags);
irq_src = fsl_readl(&dr_regs->usbsts) & fsl_readl(&dr_regs->usbintr);
/* Clear notification bits */
fsl_writel(irq_src, &dr_regs->usbsts);
- VDBG("0x%x\n", irq_src);
+ /* VDBG("irq_src [0x%8x]", irq_src); */
/* Need to resume? */
if (udc->usb_state == USB_STATE_SUSPENDED)
@@ -2240,24 +2162,12 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
/* Sleep Enable (Suspend) */
if (irq_src & USB_STS_SUSPEND) {
- VDBG("suspend int");
suspend_irq(udc);
status = IRQ_HANDLED;
}
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
- printk(KERN_ERR "Error IRQ %x ", irq_src);
- if (irq_src & USB_STS_SYS_ERR) {
- printk(KERN_ERR "This error can't be recoveried, \
- please reboot your board\n");
- printk(KERN_ERR "If this error happens frequently, \
- please check your dma buffer\n");
- }
- }
-
-irq_end:
- if (udc->stopped){
- dr_clk_gate(false);
+ VDBG("Error IRQ %x ", irq_src);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -2272,6 +2182,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
int retval = -ENODEV;
unsigned long flags = 0;
+ u32 portsc;
if (!udc_controller)
return -ENODEV;
@@ -2289,18 +2200,17 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&udc_controller->lock, flags);
driver->driver.bus = 0;
- udc_controller->pdata->port_enables = 1;
/* hook up the driver */
udc_controller->driver = driver;
udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
- dr_clk_gate(true);
- /* It doesn't need to switch usb from low power mode to normal mode
- * at otg mode
- */
- if (!udc_controller->transceiver){
- dr_phy_low_power_mode(udc_controller, false);
- }
+
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
+
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc &= ~PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
/* bind udc driver to gadget driver */
retval = driver->bind(&udc_controller->gadget);
@@ -2313,30 +2223,30 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (udc_controller->transceiver) {
/* Suspend the controller until OTG enable it */
- udc_controller->suspended = 1;/* let the otg resume it */
+ udc_controller->stopped = 1;
printk(KERN_INFO "Suspend udc for OTG auto detect\n");
dr_wake_up_enable(udc_controller, true);
+ dr_phy_low_power_mode(udc_controller, true);
/* export udc suspend/resume call to OTG */
udc_controller->gadget.dev.driver->suspend = (dev_sus)fsl_udc_suspend;
udc_controller->gadget.dev.driver->resume = (dev_res)fsl_udc_resume;
/* connect to bus through transceiver */
- retval = otg_set_peripheral(udc_controller->transceiver,
- &udc_controller->gadget);
- if (retval < 0) {
- ERR("can't bind to transceiver\n");
- driver->unbind(&udc_controller->gadget);
- udc_controller->gadget.dev.driver = 0;
- udc_controller->driver = 0;
- return retval;
+ if (udc_controller->transceiver) {
+ retval = otg_set_peripheral(udc_controller->transceiver,
+ &udc_controller->gadget);
+ if (retval < 0) {
+ ERR("can't bind to transceiver\n");
+ driver->unbind(&udc_controller->gadget);
+ udc_controller->gadget.dev.driver = 0;
+ udc_controller->driver = 0;
+ return retval;
+ }
}
- //dr_clk_gate(false);
} else {
/* Enable DR IRQ reg and Set usbcmd reg Run bit */
dr_controller_run(udc_controller);
- if (udc_controller->stopped)
- dr_clk_gate(false);
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
}
@@ -2344,10 +2254,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.name, driver->driver.name);
out:
- if (retval){
+ if (retval)
printk(KERN_DEBUG "retval %d \n", retval);
- udc_controller->pdata->port_enables = 0;
- }
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -2357,6 +2265,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
struct fsl_ep *loop_ep;
unsigned long flags;
+ u32 portsc;
if (!udc_controller)
return -ENODEV;
@@ -2364,16 +2273,15 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!driver || driver != udc_controller->driver || !driver->unbind)
return -EINVAL;
- if(udc_controller->stopped)
- dr_clk_gate(true);
-
if (udc_controller->transceiver)
(void)otg_set_peripheral(udc_controller->transceiver, 0);
+ /* open phy clock for following operation */
+ dr_phy_low_power_mode(udc_controller, false);
+
/* stop DR, disable intr */
dr_controller_stop(udc_controller);
- udc_controller->pdata->port_enables = 0;
/* in fact, no needed */
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
@@ -2395,11 +2303,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.dev.driver = 0;
udc_controller->driver = 0;
- if (udc_controller->gadget.is_otg) {
- dr_wake_up_enable(udc_controller, true);
- }
+ dr_wake_up_enable(udc_controller, false);
- dr_phy_low_power_mode(udc_controller, true);
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
+
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
printk(KERN_INFO "unregistered gadget driver '%s'\r\n",
driver->driver.name);
@@ -2814,7 +2725,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err1a;
}
- udc_controller->gadget.is_otg = 1;
#endif
if ((pdev->dev.parent) &&
@@ -2915,6 +2825,12 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
if (ret < 0)
goto err3;
+ if (udc_controller->transceiver) {
+ udc_controller->gadget.is_otg = 1;
+ /* now didn't support lpm in OTG mode*/
+ device_set_wakeup_capable(&pdev->dev, 0);
+ }
+
/* setup QH and epctrl for ep0 */
ep0_setup(udc_controller);
@@ -2957,29 +2873,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
#ifdef POSTPONE_FREE_LAST_DTD
last_free_td = NULL;
#endif
-
#ifndef CONFIG_USB_OTG
/* disable all INTR */
fsl_writel(0, &dr_regs->usbintr);
+
dr_wake_up_enable(udc_controller, false);
-#else
- dr_wake_up_enable(udc_controller, true);
-#endif
+ udc_controller->stopped = 1;
-/*
- * As mx25/mx35 does not implement clk_gate, should not let phy to low
- * power mode due to IC bug
- */
#if !(defined CONFIG_ARCH_MX35 || defined CONFIG_ARCH_MX25)
{
- dr_phy_low_power_mode(udc_controller, true);
+ u32 portsc;
+ portsc = fsl_readl(&dr_regs->portsc1);
+ portsc |= PORTSCX_PHY_LOW_POWER_SPD;
+ fsl_writel(portsc, &dr_regs->portsc1);
}
#endif
- udc_controller->stopped = 1;
-
- /* let the gadget register function open the clk */
- dr_clk_gate(false);
-
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
+#endif
create_proc_file();
return 0;
@@ -3006,6 +2917,9 @@ err1a:
*/
static int __exit fsl_udc_remove(struct platform_device *pdev)
{
+#ifndef CONFIG_USB_OTG
+ struct resource *res;
+#endif
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
DECLARE_COMPLETION(done);
@@ -3014,8 +2928,7 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
return -ENODEV;
udc_controller->done = &done;
/* open USB PHY clock */
- if (udc_controller->stopped)
- dr_clk_gate(true);
+ dr_phy_low_power_mode(udc_controller, false);
/* DR has been stopped in usb_gadget_unregister_driver() */
remove_proc_file();
@@ -3038,11 +2951,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
iounmap((u8 __iomem *)dr_regs);
#ifndef CONFIG_USB_OTG
-{
- struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
-}
#endif
device_unregister(&udc_controller->gadget.dev);
@@ -3056,8 +2966,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (pdata->platform_uninit)
pdata->platform_uninit(pdata);
- if (udc_controller->stopped)
- dr_clk_gate(false);
return 0;
}
@@ -3065,19 +2973,10 @@ static int udc_suspend(struct fsl_udc *udc)
{
u32 mode, usbcmd;
- /*
- * When it is the PM suspend routine and the device has no
- * abilities to wakeup system, it should not set wakeup enable.
- * Otherwise, the system will wakeup even the user only wants to
- * charge using usb
- */
- if (udc_controller->gadget.dev.parent->power.status
- == DPM_SUSPENDING) {
- if (!device_may_wakeup(udc_controller->gadget.dev.parent))
- dr_wake_up_enable(udc, false);
- else
- dr_wake_up_enable(udc, true);
- }
+ /* open clock for register access */
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(true);
+
mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK;
usbcmd = fsl_readl(&dr_regs->usbcmd);
@@ -3088,8 +2987,9 @@ static int udc_suspend(struct fsl_udc *udc)
* PM suspend. Remember this fact, so that we will leave the
* controller stopped at PM resume time.
*/
- if (udc->suspended) {
+ if (udc->stopped) {
pr_debug("gadget already stopped, leaving early\n");
+ udc->already_stopped = 1;
goto out;
}
@@ -3098,30 +2998,22 @@ static int udc_suspend(struct fsl_udc *udc)
goto out;
}
- /* For some buggy hardware designs, see comment of this function for detail */
- udc_wait_b_session_low();
-
udc->stopped = 1;
-
- /* stop the controller */
- usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
- fsl_writel(usbcmd, &dr_regs->usbcmd);
-
/* if the suspend is not for switch to host in otg mode */
if ((!(udc->gadget.is_otg)) ||
(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
- if (device_may_wakeup(udc_controller->gadget.dev.parent)) {
- dr_wake_up_enable(udc, true);
- }
+ dr_wake_up_enable(udc, true);
+ dr_phy_low_power_mode(udc, true);
}
- dr_phy_low_power_mode(udc, true);
+ /* stop the controller */
+ usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
+ fsl_writel(usbcmd, &dr_regs->usbcmd);
+
printk(KERN_INFO "USB Gadget suspended\n");
out:
- udc->suspended++;
- if (udc->suspended > 2)
- printk("ERROR: suspended times > 2\n");
-
+ if (udc_controller->pdata->usb_clock_for_pm)
+ udc_controller->pdata->usb_clock_for_pm(false);
return 0;
}
@@ -3131,24 +3023,13 @@ out:
-----------------------------------------------------------------*/
static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
{
- int ret;
-#ifdef CONFIG_USB_OTG
- if (udc_controller->transceiver->gadget == NULL)
- return 0;
-#endif
- if (udc_controller->stopped)
- dr_clk_gate(true);
if (((!(udc_controller->gadget.is_otg)) ||
(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) &&
(udc_controller->usb_state > USB_STATE_POWERED) &&
- (udc_controller->usb_state < USB_STATE_SUSPENDED)) {
- return -EBUSY;/* keep the clk on */
- }
- else
- ret = udc_suspend(udc_controller);
- dr_clk_gate(false);
+ (udc_controller->usb_state < USB_STATE_SUSPENDED))
+ return -EBUSY;
- return ret;
+ return udc_suspend(udc_controller);
}
/*-----------------------------------------------------------------
@@ -3157,54 +3038,30 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
*-----------------------------------------------------------------*/
static int fsl_udc_resume(struct platform_device *pdev)
{
- pr_debug("%s(): stopped %d suspended %d\n", __func__,
- udc_controller->stopped, udc_controller->suspended);
- printk("udc resume\n");
-#ifdef CONFIG_USB_OTG
- if (udc_controller->transceiver->gadget == NULL)
- return 0;
-#endif
- if (udc_controller->stopped)
- dr_clk_gate(true);
+ pr_debug("%s(): stopped %d already_stopped %d\n", __func__,
+ udc_controller->stopped, udc_controller->already_stopped);
+
/*
* If the controller was stopped at suspend time, then
* don't resume it now.
*/
- /*
- * If it is PM resume routine, the udc is at low power mode,
- * and the udc has no abilities to wakeup system, it should
- * set the abilities to wakeup itself. Otherwise, the usb
- * subsystem will not leave from low power mode.
- */
- if (!device_may_wakeup(udc_controller->gadget.dev.parent) &&
- udc_controller->gadget.dev.parent->power.status
- == DPM_RESUMING){
- dr_wake_up_enable(udc_controller, true);
- }
-
- if (--udc_controller->suspended) {
- printk("gadget was already stopped, leaving early\n");
- goto out;
+ if (udc_controller->already_stopped) {
+ udc_controller->already_stopped = 0;
+ pr_debug("gadget was already stopped, leaving early\n");
+ return 0;
}
+
/* Enable DR irq reg and set controller Run */
if (udc_controller->stopped) {
- /* if in host mode, we need to do nothing */
- if ((fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) == 0) {
- goto out;
- }
dr_wake_up_enable(udc_controller, false);
dr_phy_low_power_mode(udc_controller, false);
- mdelay(10);
+ mdelay(1);
+
dr_controller_setup(udc_controller);
dr_controller_run(udc_controller);
}
udc_controller->usb_state = USB_STATE_ATTACHED;
udc_controller->ep0_dir = 0;
-out:
- /* if udc is resume by otg id change and no device
- * connecting to the otg, otg will enter low power mode*/
- if (udc_controller->stopped)
- dr_clk_gate(false);
printk(KERN_INFO "USB Gadget resumed\n");
return 0;
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index 8d344acb8fef..4574954bf4f4 100644
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -266,7 +266,6 @@ struct usb_sys_interface {
#define PORTSCX_SPEED_BIT_POS (26)
/* OTGSC Register Bit Masks */
-#define OTGSC_ID_CHANGE_IRQ_STS (1 << 16)
#define OTGSC_B_SESSION_VALID_IRQ_EN (1 << 27)
#define OTGSC_B_SESSION_VALID_IRQ_STS (1 << 19)
#define OTGSC_B_SESSION_VALID (1 << 11)
@@ -594,15 +593,9 @@ struct fsl_udc {
struct otg_transceiver *transceiver;
unsigned softconnect:1;
unsigned vbus_active:1;
- unsigned remote_wakeup:1;
- /* we must distinguish the stopped and suspended state,
- * stopped means the udc enter lowpower mode, suspended
- * means the udc is suspended by system pm or by otg
- * switching to host mode.if the udc in suspended state
- * it also in the stopped state, while if the udc in
- * stopped state,it may not be in the suspended state*/
unsigned stopped:1;
- int suspended;
+ unsigned remote_wakeup:1;
+ unsigned already_stopped:1;
struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
struct fsl_req *status_req; /* ep0 status request */
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 2e79b8c389a4..59e85234fa0a 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -236,7 +236,6 @@ static int config_buf(struct usb_configuration *config,
int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
struct usb_function *f;
int status;
- int interfaceCount = 0;
/* write the config descriptor */
c = buf;
@@ -267,16 +266,8 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors;
else
descriptors = f->descriptors;
- if (f->hidden || !descriptors || descriptors[0] == NULL) {
- for (; f != config->interface[interfaceCount];) {
- interfaceCount++;
- c->bNumInterfaces--;
- }
+ if (!descriptors)
continue;
- }
- for (; f != config->interface[interfaceCount];)
- interfaceCount++;
-
status = usb_descriptor_fillbuf(next, len,
(const struct usb_descriptor_header **) descriptors);
if (status < 0)
@@ -765,11 +756,11 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
- if (cdev->config) {
+ if (cdev->config)
*(u8 *)req->buf = cdev->config->bConfigurationValue;
- value = min(w_length, (u16) 1);
- } else
+ else
*(u8 *)req->buf = 0;
+ value = min(w_length, (u16) 1);
break;
/* function drivers must handle get/set altsetting; if there's
@@ -819,9 +810,6 @@ unknown:
*/
if ((ctrl->bRequestType & USB_RECIP_MASK)
== USB_RECIP_INTERFACE) {
- if (cdev->config == NULL)
- return value;
-
f = cdev->config->interface[intf];
if (f && f->setup)
value = f->setup(f, ctrl);
@@ -836,25 +824,6 @@ unknown:
value = c->setup(c, ctrl);
}
- /* If the vendor request is not processed (value < 0),
- * call all device registered configure setup callbacks
- * to process it.
- * This is used to handle the following cases:
- * - vendor request is for the device and arrives before
- * setconfiguration.
- * - Some devices are required to handle vendor request before
- * setconfiguration such as MTP, USBNET.
- */
-
- if (value < 0) {
- struct usb_configuration *cfg;
-
- list_for_each_entry(cfg, &cdev->configs, list) {
- if (cfg && cfg->setup)
- value = cfg->setup(cfg, ctrl);
- }
- }
-
goto done;
}
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 7dd1a8bbe382..7953948bfe4a 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -761,12 +761,3 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
kfree(acm);
return status;
}
-
-int __init acm_function_add(struct usb_composite_dev *cdev,
- struct usb_configuration *c)
-{
- int ret = acm_bind_config(c, 0);
- if (ret == 0)
- gserial_setup(c->cdev->gadget, 1);
- return ret;
-}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8b0a13202573..66105ce49672 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -728,7 +728,6 @@ struct fsg_dev {
#include "fsl_updater.h"
#endif
-static int do_set_interface(struct fsg_dev *fsg, int altsetting);
typedef void (*fsg_routine_t)(struct fsg_dev *);
static int exception_in_progress(struct fsg_dev *fsg)
@@ -1109,14 +1108,6 @@ static void fsg_disconnect(struct usb_gadget *gadget)
struct fsg_dev *fsg = get_gadget_data(gadget);
DBG(fsg, "disconnect or port reset\n");
- /*
- * The disconnect exception will call do_set_config, and therefore will
- * visit controller registers. However it is a delayed event, and will be
- * handled at another process, so the controller maybe have already close the
- * usb clock.*/
- if (fsg->new_config)
- do_set_interface(fsg, -1);/* disable the interface */
-
raise_exception(fsg, FSG_STATE_DISCONNECT);
}