>From 0c1a37ab187576715c667796f23cec1d83a7bee9 Mon Sep 17 00:00:00 2001
From: Hao Wu <[email protected]>
Date: Wed, 24 Nov 2010 13:14:40 +0800
Subject: [PATCH] usb: langwell_udc: add runtime pm support for otg.

This patch contains update on transceiver driver interfaces.
Mainly to support runtime pm for OTG.

Signed-off-by: Hao Wu <[email protected]>
---
 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 4ca4d3b..b39ed1c 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>
@@ -3594,18 +3595,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);
@@ -3613,24 +3670,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);
@@ -3638,7 +3715,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

Attachment: 0004-usb-langwell_udc-add-runtime-pm-support-for-otg.patch
Description: 0004-usb-langwell_udc-add-runtime-pm-support-for-otg.patch

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to