This patch contains update on transceiver driver interfaces. Mainly to support runtime pm for OTG. Signed-off-by: Hao Wu <hao.wu@xxxxxxxxx> --- drivers/usb/gadget/langwell_udc.c | 116 +++++++++++++++++++++++++++++++------ 1 files changed, 98 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index df2b82b..2c56faf 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -45,6 +45,7 @@ #include <linux/usb/gadget.h> #include <linux/usb/otg.h> #include <linux/pm.h> +#include <linux/pm_runtime.h> #include <linux/io.h> #include <linux/irq.h> #include <asm/system.h> @@ -3505,18 +3506,74 @@ static struct pci_driver langwell_pci_driver = { static int intel_mid_start_peripheral(struct intel_mid_otg_xceiv *iotg) { struct langwell_udc *dev = the_controller; - struct pci_dev *pdev; + size_t size; unsigned long flags; - int retval; - if (iotg == NULL) - return -EINVAL; + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); - pdev = to_pci_dev(iotg->otg.dev); + pm_runtime_get(&dev->pdev->dev); - retval = langwell_udc_resume(pdev); - if (retval) - dev_dbg(&pdev->dev, "Failed to start peripheral driver\n"); + /* exit PHY low power suspend */ + langwell_phy_low_power(dev, 0); + + /* enable SRAM caching if detected */ + if (dev->has_sram && !dev->got_sram) + sram_init(dev); + + /* allocate device dQH memory */ + size = dev->ep_max * sizeof(struct langwell_dqh); + dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size); + if (size < DQH_ALIGNMENT) + size = DQH_ALIGNMENT; + else if ((size % DQH_ALIGNMENT) != 0) { + size += DQH_ALIGNMENT + 1; + size &= ~(DQH_ALIGNMENT - 1); + } + dev->ep_dqh = dma_alloc_coherent(&dev->pdev->dev, size, + &dev->ep_dqh_dma, GFP_KERNEL); + if (!dev->ep_dqh) { + dev_err(&dev->pdev->dev, "allocate dQH memory failed\n"); + return -ENOMEM; + } + dev->ep_dqh_size = size; + dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size); + + /* create dTD dma_pool resource */ + dev->dtd_pool = dma_pool_create("langwell_dtd", + &dev->pdev->dev, + sizeof(struct langwell_dtd), + DTD_ALIGNMENT, + DMA_BOUNDARY); + + if (!dev->dtd_pool) + return -ENOMEM; + + /* enable IRQ handler */ + if (request_irq(dev->pdev->irq, langwell_irq, IRQF_SHARED, + driver_name, dev) != 0) { + dev_err(&dev->pdev->dev, "request interrupt %d failed\n", + dev->pdev->irq); + return -EBUSY; + } + dev->got_irq = 1; + + /* reset and start controller to run state */ + if (dev->stopped) { + /* reset device controller */ + langwell_udc_reset(dev); + + /* reset ep0 dQH and endptctrl */ + ep0_reset(dev); + + /* start device if gadget is loaded */ + if (dev->driver) + langwell_udc_start(dev); + } + + /* reset USB status */ + dev->usb_state = USB_STATE_ATTACHED; + dev->ep0_state = WAIT_FOR_SETUP; + dev->ep0_dir = USB_DIR_OUT; if (dev) { spin_lock_irqsave(&dev->lock, flags); @@ -3524,24 +3581,44 @@ static int intel_mid_start_peripheral(struct intel_mid_otg_xceiv *iotg) spin_unlock_irqrestore(&dev->lock, flags); } - return retval; + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; } static int intel_mid_stop_peripheral(struct intel_mid_otg_xceiv *iotg) { struct langwell_udc *dev = the_controller; - struct pci_dev *pdev; unsigned long flags; - int retval; - if (iotg == NULL) - return -EINVAL; + dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__); - pdev = to_pci_dev(iotg->otg.dev); + /* disable interrupt and set controller to stop state */ + langwell_udc_stop(dev); - retval = langwell_udc_suspend(pdev, PMSG_FREEZE); - if (retval) - dev_dbg(&pdev->dev, "Failed to stop peripheral driver\n"); + /* diable IRQ handler */ + if (dev->got_irq) + free_irq(dev->pdev->irq, dev); + dev->got_irq = 0; + + spin_lock_irqsave(&dev->lock, flags); + /* stop all usb activities */ + stop_activity(dev, dev->driver); + spin_unlock_irqrestore(&dev->lock, flags); + + /* free dTD dma_pool and dQH */ + if (dev->dtd_pool) + dma_pool_destroy(dev->dtd_pool); + + if (dev->ep_dqh) + dma_free_coherent(&dev->pdev->dev, dev->ep_dqh_size, + dev->ep_dqh, dev->ep_dqh_dma); + + /* release SRAM caching */ + if (dev->has_sram && dev->got_sram) + sram_deinit(dev); + + /* enter PHY low power suspend */ + langwell_phy_low_power(dev, 1); if (dev) { spin_lock_irqsave(&dev->lock, flags); @@ -3549,7 +3626,10 @@ static int intel_mid_stop_peripheral(struct intel_mid_otg_xceiv *iotg) spin_unlock_irqrestore(&dev->lock, flags); } - return retval; + pm_runtime_put(&dev->pdev->dev); + + dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__); + return 0; } static int intel_mid_register_peripheral(struct pci_driver *peripheral_driver) -- 1.6.0.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html