Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-15 Thread Felipe Balbi
On Fri, Oct 12, 2012 at 07:24:33PM +0530, Vikas Sajjan wrote:
 Hi kishon,
 
 On 12 October 2012 16:27, kishon kis...@ti.com wrote:
  Hi,
 
 
  On Wednesday 10 October 2012 07:35 PM, Vikas C Sajjan wrote:
 
  From: Vikas Sajjan vikas.saj...@linaro.org
 
  Adding the suspend and resume funtionality to DWC3 core.
 
  Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
  Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
  CC: Doug Anderson diand...@chromium.org
  ---
drivers/usb/dwc3/core.c |  268
  +-
1 files changed, 169 insertions(+), 99 deletions(-)
 
  diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
  index b415c0c..58b51e1 100644
  --- a/drivers/usb/dwc3/core.c
  +++ b/drivers/usb/dwc3/core.c
 
  @@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported
  speed.);
 
static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
 
  -int dwc3_get_device_id(void)
  -{
  -   int id;
  -
  -again:
  -   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
  -   if (id  DWC3_DEVS_POSSIBLE) {
  -   int old;
  -
  -   old = test_and_set_bit(id, dwc3_devs);
  -   if (old)
  -   goto again;
  -   } else {
  -   pr_err(dwc3: no space for new device\n);
  -   id = -ENOMEM;
  -   }
  -
  -   return id;
  -}
  -EXPORT_SYMBOL_GPL(dwc3_get_device_id);
  -
  -void dwc3_put_device_id(int id)
  -{
  -   int ret;
  -
  -   if (id  0)
  -   return;
  -
  -   ret = test_bit(id, dwc3_devs);
  -   WARN(!ret, dwc3: ID %d not in use\n, id);
  -   smp_mb__before_clear_bit();
  -   clear_bit(id, dwc3_devs);
  -}
  -EXPORT_SYMBOL_GPL(dwc3_put_device_id);
  -
  -void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
  +static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
{
  -   u32 reg;
  +   struct dwc3_hwparams*parms = dwc-hwparams;
 
  -   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
  -   reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
  -   reg |= DWC3_GCTL_PRTCAPDIR(mode);
  -   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  +   parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
  +   parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
  +   parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
  +   parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
  +   parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
  +   parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
  +   parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
  +   parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
  +   parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
}
  -
/**
 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
 * @dwc: pointer to our context structure
  @@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
  dwc3_writel(dwc-regs, DWC3_GCTL, reg);
}
 
  +static int dwc3_core_reset(struct dwc3 *dwc)
  +{
  +   unsigned long   timeout;
  +   u32 reg;
  +
  +   /* issue device SoftReset too */
  +   timeout = jiffies + msecs_to_jiffies(500);
  +   dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
  +   do {
  +   reg = dwc3_readl(dwc-regs, DWC3_DCTL);
  +   if (!(reg  DWC3_DCTL_CSFTRST))
  +   break;
  +
  +   if (time_after(jiffies, timeout)) {
  +   dev_err(dwc-dev, Reset Timed Out\n);
  +   return -ETIMEDOUT;
  +   }
  +
  +   cpu_relax();
  +   } while (true);
  +
  +   dwc3_core_soft_reset(dwc);
  +
  +   dwc3_cache_hwparams(dwc);
  +
  +   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
  +   reg = ~DWC3_GCTL_SCALEDOWN_MASK;
  +   reg = ~DWC3_GCTL_DISSCRAMBLE;
  +
  +   switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
  +   case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
  +   reg = ~DWC3_GCTL_DSBLCLKGTNG;
  +   break;
  +   default:
  +   dev_dbg(dwc-dev, No power optimization available\n);
  +   }
  +
  +   /*
 
  +* WORKAROUND: DWC3 revisions 1.90a have a bug
  +* where the device can fail to connect at SuperSpeed
  +* and falls back to high-speed mode which causes
  +* the device to enter a Connect/Disconnect loop
  +*/
  +   if (dwc-revision  DWC3_REVISION_190A)
  +   reg |= DWC3_GCTL_U2RSTECN;
  +
  +   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  +
  +   return 0;
  +}
  +
  +int dwc3_get_device_id(void)
  +{
  +   int id;
  +
  +again:
  +   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
  +   if (id  DWC3_DEVS_POSSIBLE) {
  +   int old;
  +
  +   old = test_and_set_bit(id, dwc3_devs);
 

Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-12 Thread Vikas Sajjan
Hi Felipe,

On 11 October 2012 13:17, Felipe Balbi ba...@ti.com wrote:

 Hi,

 On Wed, Oct 10, 2012 at 07:35:47PM +0530, Vikas C Sajjan wrote:
  From: Vikas Sajjan vikas.saj...@linaro.org
 
  Adding the suspend and resume funtionality to DWC3 core.
 
  Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
  Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
  CC: Doug Anderson diand...@chromium.org
  ---
   drivers/usb/dwc3/core.c |  268
  +-
   1 files changed, 169 insertions(+), 99 deletions(-)
 
  diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
  index b415c0c..58b51e1 100644
  --- a/drivers/usb/dwc3/core.c
  +++ b/drivers/usb/dwc3/core.c
  @@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported
  speed.);
 
   static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
 
  -int dwc3_get_device_id(void)
  -{
  - int id;
  -
  -again:
  - id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
  - if (id  DWC3_DEVS_POSSIBLE) {
  - int old;
  -
  - old = test_and_set_bit(id, dwc3_devs);
  - if (old)
  - goto again;
  - } else {
  - pr_err(dwc3: no space for new device\n);
  - id = -ENOMEM;
  - }
  -
  - return id;
  -}
  -EXPORT_SYMBOL_GPL(dwc3_get_device_id);
  -
  -void dwc3_put_device_id(int id)
  -{
  - int ret;
  -
  - if (id  0)
  - return;
  -
  - ret = test_bit(id, dwc3_devs);
  - WARN(!ret, dwc3: ID %d not in use\n, id);
  - smp_mb__before_clear_bit();
  - clear_bit(id, dwc3_devs);
  -}
  -EXPORT_SYMBOL_GPL(dwc3_put_device_id);
  -
  -void dwc3_set_mode(struct dwc3 *dwc, u32 mode)

 why are you even moving all this code around ? Doesn't look necessary.

  +static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
   {
  - u32 reg;
  + struct dwc3_hwparams*parms = dwc-hwparams;
 
  - reg = dwc3_readl(dwc-regs, DWC3_GCTL);
  - reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
  - reg |= DWC3_GCTL_PRTCAPDIR(mode);
  - dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  + parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
  + parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
  + parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
  + parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
  + parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
  + parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
  + parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
  + parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
  + parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
   }
  -
   /**
* dwc3_core_soft_reset - Issues core soft reset and PHY reset
* @dwc: pointer to our context structure
  @@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
dwc3_writel(dwc-regs, DWC3_GCTL, reg);
   }
 
  +static int dwc3_core_reset(struct dwc3 *dwc)

 this looks unnecessary.

dwc3_core_reset() function is added to avoid the code duplication, and
can be reused both in probe and resume.
  +{
  + unsigned long   timeout;
  + u32 reg;
  +
  + /* issue device SoftReset too */
  + timeout = jiffies + msecs_to_jiffies(500);
  + dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
  + do {
  + reg = dwc3_readl(dwc-regs, DWC3_DCTL);
  + if (!(reg  DWC3_DCTL_CSFTRST))
  + break;
  +
  + if (time_after(jiffies, timeout)) {
  + dev_err(dwc-dev, Reset Timed Out\n);
  + return -ETIMEDOUT;
  + }
  +
  + cpu_relax();
  + } while (true);
  +
  + dwc3_core_soft_reset(dwc);
  +
  + dwc3_cache_hwparams(dwc);
  +
  + reg = dwc3_readl(dwc-regs, DWC3_GCTL);
  + reg = ~DWC3_GCTL_SCALEDOWN_MASK;
  + reg = ~DWC3_GCTL_DISSCRAMBLE;
  +
  + switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
  + case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
  + reg = ~DWC3_GCTL_DSBLCLKGTNG;
  + break;
  + default:
  + dev_dbg(dwc-dev, No power optimization available\n);
  + }
  +
  + /*
  +  * WORKAROUND: DWC3 revisions 1.90a have a bug
  +  * where the device can fail to connect at SuperSpeed
  +  * and falls back to high-speed mode which causes
  +  * the device to enter a Connect/Disconnect loop
  +  */
  + if (dwc-revision  DWC3_REVISION_190A)
  + reg |= DWC3_GCTL_U2RSTECN;
  +
  + dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  +
  + return 0;
  +}
  +
  +int dwc3_get_device_id(void)
  +{
  + int id;
  +
  +again:
  + id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
  + if (id  DWC3_DEVS_POSSIBLE) {
  + int old;
  +
  + old = test_and_set_bit(id, dwc3_devs);
  + if 

Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-12 Thread Felipe Balbi
Hi,

On Fri, Oct 12, 2012 at 02:29:39PM +0530, Vikas Sajjan wrote:
   @@ -339,49 +390,9 @@ static int __devinit dwc3_core_init(struct dwc3
   *dwc)
 }
 dwc-revision = reg;
  
   - /* issue device SoftReset too */
   - timeout = jiffies + msecs_to_jiffies(500);
   - dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
   - do {
   - reg = dwc3_readl(dwc-regs, DWC3_DCTL);
   - if (!(reg  DWC3_DCTL_CSFTRST))
   - break;
   -
   - if (time_after(jiffies, timeout)) {
   - dev_err(dwc-dev, Reset Timed Out\n);
   - ret = -ETIMEDOUT;
   - goto err0;
   - }
   -
   - cpu_relax();
   - } while (true);
   -
   - dwc3_core_soft_reset(dwc);
   -
   - dwc3_cache_hwparams(dwc);
   -
   - reg = dwc3_readl(dwc-regs, DWC3_GCTL);
   - reg = ~DWC3_GCTL_SCALEDOWN_MASK;
   - reg = ~DWC3_GCTL_DISSCRAMBLE;
   -
   - switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
   - case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
   - reg = ~DWC3_GCTL_DSBLCLKGTNG;
   - break;
   - default:
   - dev_dbg(dwc-dev, No power optimization available\n);
   - }
   -
   - /*
   -  * WORKAROUND: DWC3 revisions 1.90a have a bug
   -  * where the device can fail to connect at SuperSpeed
   -  * and falls back to high-speed mode which causes
   -  * the device to enter a Connect/Disconnect loop
   -  */
   - if (dwc-revision  DWC3_REVISION_190A)
   - reg |= DWC3_GCTL_U2RSTECN;
   -
   - dwc3_writel(dwc-regs, DWC3_GCTL, reg);
   + ret = dwc3_core_reset(dwc);
   + if (ret  0)
   + goto err0;
  
 ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
 
  I would rather move dwc3_alloc_event_buffers() outside of
  dwc3_core_init() and use that directly on -resume(). dwc3_core_init()
  shouldn't be doing any memory allocations, so we can re-use it, and it
  doesn't matter when we allocate the event buffers anyway.
 
 dwc3_alloc_event_buffers() was already inside the dwc3_core_init() in
 the existing code, the only change I made is, a common function called
  dwc3_core_reset() is added which will be used both in probe and
 resume.
 so basically resume only does dwc3_core_reset() and
 dwc3_event_buffers_setup() as dwc3_alloc_event_buffers() is done in
 probe.

we already have too many functions call *reset*, adding another one will
just make code more difficult to follow and it will be error-prone.

This is what I suggested:

commit 9aba985696690c1e8c2cf4f34e35b3f5b296175d
Author: Felipe Balbi ba...@ti.com
Date:   Thu Oct 11 13:54:36 2012 +0300

usb: dwc3: core: move event buffer allocation out of dwc3_core_init()

This patch is in preparation for adding PM support
dwc3 driver. We want to re-use dwc3_core_init and
dwc3_core_exit() functions on resume() and suspend()
callbacks respectively.

Moving even buffer allocation away from dwc3_core_init()
will allow us to reuse the event buffer which was allocated
long ago on our probe() routine.

Signed-off-by: Felipe Balbi ba...@ti.com

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 8d543ea..b923183 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -381,24 +381,14 @@ static int __devinit dwc3_core_init(struct dwc3 *dwc)
 
dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 
-   ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
-   if (ret) {
-   dev_err(dwc-dev, failed to allocate event buffers\n);
-   ret = -ENOMEM;
-   goto err1;
-   }
-
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc-dev, failed to setup event buffers\n);
-   goto err1;
+   goto err0;
}
 
return 0;
 
-err1:
-   dwc3_free_event_buffers(dwc);
-
 err0:
return ret;
 }
@@ -406,7 +396,6 @@ err0:
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
dwc3_event_buffers_cleanup(dwc);
-   dwc3_free_event_buffers(dwc);
 }
 
 #define DWC3_ALIGN_MASK(16 - 1)
@@ -509,10 +498,17 @@ static int __devinit dwc3_probe(struct platform_device 
*pdev)
pm_runtime_get_sync(dev);
pm_runtime_forbid(dev);
 
+   ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
+   if (ret) {
+   dev_err(dwc-dev, failed to allocate event buffers\n);
+   ret = -ENOMEM;
+   goto err0;
+   }
+
ret = dwc3_core_init(dwc);
if (ret) {
dev_err(dev, failed to initialize core\n);
-   return ret;
+   goto err0;
}
 
mode = DWC3_MODE(dwc-hwparams.hwparams0);
@@ -584,6 +580,9 @@ err2:
 err1:
dwc3_core_exit(dwc);
 
+err0:
+   dwc3_free_event_buffers(dwc);
+
return 

Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-12 Thread kishon

Hi,

On Wednesday 10 October 2012 07:35 PM, Vikas C Sajjan wrote:

From: Vikas Sajjan vikas.saj...@linaro.org

Adding the suspend and resume funtionality to DWC3 core.

Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
CC: Doug Anderson diand...@chromium.org
---
  drivers/usb/dwc3/core.c |  268 +-
  1 files changed, 169 insertions(+), 99 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index b415c0c..58b51e1 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported speed.);

  static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);

-int dwc3_get_device_id(void)
-{
-   int id;
-
-again:
-   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
-   if (id  DWC3_DEVS_POSSIBLE) {
-   int old;
-
-   old = test_and_set_bit(id, dwc3_devs);
-   if (old)
-   goto again;
-   } else {
-   pr_err(dwc3: no space for new device\n);
-   id = -ENOMEM;
-   }
-
-   return id;
-}
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
-
-void dwc3_put_device_id(int id)
-{
-   int ret;
-
-   if (id  0)
-   return;
-
-   ret = test_bit(id, dwc3_devs);
-   WARN(!ret, dwc3: ID %d not in use\n, id);
-   smp_mb__before_clear_bit();
-   clear_bit(id, dwc3_devs);
-}
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
-
-void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
+static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
  {
-   u32 reg;
+   struct dwc3_hwparams*parms = dwc-hwparams;

-   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
-   reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
-   reg |= DWC3_GCTL_PRTCAPDIR(mode);
-   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
+   parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
+   parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
+   parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
+   parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
+   parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
+   parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
+   parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
+   parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
+   parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
  }
-
  /**
   * dwc3_core_soft_reset - Issues core soft reset and PHY reset
   * @dwc: pointer to our context structure
@@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  }

+static int dwc3_core_reset(struct dwc3 *dwc)
+{
+   unsigned long   timeout;
+   u32 reg;
+
+   /* issue device SoftReset too */
+   timeout = jiffies + msecs_to_jiffies(500);
+   dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
+   do {
+   reg = dwc3_readl(dwc-regs, DWC3_DCTL);
+   if (!(reg  DWC3_DCTL_CSFTRST))
+   break;
+
+   if (time_after(jiffies, timeout)) {
+   dev_err(dwc-dev, Reset Timed Out\n);
+   return -ETIMEDOUT;
+   }
+
+   cpu_relax();
+   } while (true);
+
+   dwc3_core_soft_reset(dwc);
+
+   dwc3_cache_hwparams(dwc);
+
+   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
+   reg = ~DWC3_GCTL_SCALEDOWN_MASK;
+   reg = ~DWC3_GCTL_DISSCRAMBLE;
+
+   switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
+   case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
+   reg = ~DWC3_GCTL_DSBLCLKGTNG;
+   break;
+   default:
+   dev_dbg(dwc-dev, No power optimization available\n);
+   }
+
+   /*
+* WORKAROUND: DWC3 revisions 1.90a have a bug
+* where the device can fail to connect at SuperSpeed
+* and falls back to high-speed mode which causes
+* the device to enter a Connect/Disconnect loop
+*/
+   if (dwc-revision  DWC3_REVISION_190A)
+   reg |= DWC3_GCTL_U2RSTECN;
+
+   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
+
+   return 0;
+}
+
+int dwc3_get_device_id(void)
+{
+   int id;
+
+again:
+   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
+   if (id  DWC3_DEVS_POSSIBLE) {
+   int old;
+
+   old = test_and_set_bit(id, dwc3_devs);
+   if (old)
+   goto again;
+   } else {
+   pr_err(dwc3: no space for new device\n);
+   id = -ENOMEM;
+   }
+
+   return id;
+}
+EXPORT_SYMBOL_GPL(dwc3_get_device_id);
+
+void dwc3_put_device_id(int id)
+{
+   int ret;
+
+   if (id  0)
+   return;
+
+   ret = test_bit(id, dwc3_devs);
+   WARN(!ret, dwc3: 

Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-12 Thread Vikas Sajjan
Hi kishon,

On 12 October 2012 16:27, kishon kis...@ti.com wrote:
 Hi,


 On Wednesday 10 October 2012 07:35 PM, Vikas C Sajjan wrote:

 From: Vikas Sajjan vikas.saj...@linaro.org

 Adding the suspend and resume funtionality to DWC3 core.

 Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
 Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
 CC: Doug Anderson diand...@chromium.org
 ---
   drivers/usb/dwc3/core.c |  268
 +-
   1 files changed, 169 insertions(+), 99 deletions(-)

 diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
 index b415c0c..58b51e1 100644
 --- a/drivers/usb/dwc3/core.c
 +++ b/drivers/usb/dwc3/core.c

 @@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported
 speed.);

   static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);

 -int dwc3_get_device_id(void)
 -{
 -   int id;
 -
 -again:
 -   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
 -   if (id  DWC3_DEVS_POSSIBLE) {
 -   int old;
 -
 -   old = test_and_set_bit(id, dwc3_devs);
 -   if (old)
 -   goto again;
 -   } else {
 -   pr_err(dwc3: no space for new device\n);
 -   id = -ENOMEM;
 -   }
 -
 -   return id;
 -}
 -EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 -
 -void dwc3_put_device_id(int id)
 -{
 -   int ret;
 -
 -   if (id  0)
 -   return;
 -
 -   ret = test_bit(id, dwc3_devs);
 -   WARN(!ret, dwc3: ID %d not in use\n, id);
 -   smp_mb__before_clear_bit();
 -   clear_bit(id, dwc3_devs);
 -}
 -EXPORT_SYMBOL_GPL(dwc3_put_device_id);
 -
 -void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 +static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
   {
 -   u32 reg;
 +   struct dwc3_hwparams*parms = dwc-hwparams;

 -   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
 -   reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 -   reg |= DWC3_GCTL_PRTCAPDIR(mode);
 -   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 +   parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
 +   parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
 +   parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
 +   parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
 +   parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
 +   parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
 +   parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
 +   parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
 +   parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
   }
 -
   /**
* dwc3_core_soft_reset - Issues core soft reset and PHY reset
* @dwc: pointer to our context structure
 @@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
 dwc3_writel(dwc-regs, DWC3_GCTL, reg);
   }

 +static int dwc3_core_reset(struct dwc3 *dwc)
 +{
 +   unsigned long   timeout;
 +   u32 reg;
 +
 +   /* issue device SoftReset too */
 +   timeout = jiffies + msecs_to_jiffies(500);
 +   dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
 +   do {
 +   reg = dwc3_readl(dwc-regs, DWC3_DCTL);
 +   if (!(reg  DWC3_DCTL_CSFTRST))
 +   break;
 +
 +   if (time_after(jiffies, timeout)) {
 +   dev_err(dwc-dev, Reset Timed Out\n);
 +   return -ETIMEDOUT;
 +   }
 +
 +   cpu_relax();
 +   } while (true);
 +
 +   dwc3_core_soft_reset(dwc);
 +
 +   dwc3_cache_hwparams(dwc);
 +
 +   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
 +   reg = ~DWC3_GCTL_SCALEDOWN_MASK;
 +   reg = ~DWC3_GCTL_DISSCRAMBLE;
 +
 +   switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
 +   case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
 +   reg = ~DWC3_GCTL_DSBLCLKGTNG;
 +   break;
 +   default:
 +   dev_dbg(dwc-dev, No power optimization available\n);
 +   }
 +
 +   /*

 +* WORKAROUND: DWC3 revisions 1.90a have a bug
 +* where the device can fail to connect at SuperSpeed
 +* and falls back to high-speed mode which causes
 +* the device to enter a Connect/Disconnect loop
 +*/
 +   if (dwc-revision  DWC3_REVISION_190A)
 +   reg |= DWC3_GCTL_U2RSTECN;
 +
 +   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 +
 +   return 0;
 +}
 +
 +int dwc3_get_device_id(void)
 +{
 +   int id;
 +
 +again:
 +   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
 +   if (id  DWC3_DEVS_POSSIBLE) {
 +   int old;
 +
 +   old = test_and_set_bit(id, dwc3_devs);
 +   if (old)
 +   goto again;
 +   } else {
 +   pr_err(dwc3: no space for new device\n);
 +   id = -ENOMEM;
 +   }
 +
 +   return id;
 +}
 

Re: [PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-11 Thread Felipe Balbi
Hi,

On Wed, Oct 10, 2012 at 07:35:47PM +0530, Vikas C Sajjan wrote:
 From: Vikas Sajjan vikas.saj...@linaro.org
 
 Adding the suspend and resume funtionality to DWC3 core.
 
 Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
 Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
 CC: Doug Anderson diand...@chromium.org
 ---
  drivers/usb/dwc3/core.c |  268 +-
  1 files changed, 169 insertions(+), 99 deletions(-)
 
 diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
 index b415c0c..58b51e1 100644
 --- a/drivers/usb/dwc3/core.c
 +++ b/drivers/usb/dwc3/core.c
 @@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported 
 speed.);
  
  static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
  
 -int dwc3_get_device_id(void)
 -{
 - int id;
 -
 -again:
 - id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
 - if (id  DWC3_DEVS_POSSIBLE) {
 - int old;
 -
 - old = test_and_set_bit(id, dwc3_devs);
 - if (old)
 - goto again;
 - } else {
 - pr_err(dwc3: no space for new device\n);
 - id = -ENOMEM;
 - }
 -
 - return id;
 -}
 -EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 -
 -void dwc3_put_device_id(int id)
 -{
 - int ret;
 -
 - if (id  0)
 - return;
 -
 - ret = test_bit(id, dwc3_devs);
 - WARN(!ret, dwc3: ID %d not in use\n, id);
 - smp_mb__before_clear_bit();
 - clear_bit(id, dwc3_devs);
 -}
 -EXPORT_SYMBOL_GPL(dwc3_put_device_id);
 -
 -void dwc3_set_mode(struct dwc3 *dwc, u32 mode)

why are you even moving all this code around ? Doesn't look necessary.

 +static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
  {
 - u32 reg;
 + struct dwc3_hwparams*parms = dwc-hwparams;
  
 - reg = dwc3_readl(dwc-regs, DWC3_GCTL);
 - reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 - reg |= DWC3_GCTL_PRTCAPDIR(mode);
 - dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 + parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
 + parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
 + parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
 + parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
 + parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
 + parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
 + parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
 + parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
 + parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
  }
 -
  /**
   * dwc3_core_soft_reset - Issues core soft reset and PHY reset
   * @dwc: pointer to our context structure
 @@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
  }
  
 +static int dwc3_core_reset(struct dwc3 *dwc)

this looks unnecessary.

 +{
 + unsigned long   timeout;
 + u32 reg;
 +
 + /* issue device SoftReset too */
 + timeout = jiffies + msecs_to_jiffies(500);
 + dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
 + do {
 + reg = dwc3_readl(dwc-regs, DWC3_DCTL);
 + if (!(reg  DWC3_DCTL_CSFTRST))
 + break;
 +
 + if (time_after(jiffies, timeout)) {
 + dev_err(dwc-dev, Reset Timed Out\n);
 + return -ETIMEDOUT;
 + }
 +
 + cpu_relax();
 + } while (true);
 +
 + dwc3_core_soft_reset(dwc);
 +
 + dwc3_cache_hwparams(dwc);
 +
 + reg = dwc3_readl(dwc-regs, DWC3_GCTL);
 + reg = ~DWC3_GCTL_SCALEDOWN_MASK;
 + reg = ~DWC3_GCTL_DISSCRAMBLE;
 +
 + switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
 + case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
 + reg = ~DWC3_GCTL_DSBLCLKGTNG;
 + break;
 + default:
 + dev_dbg(dwc-dev, No power optimization available\n);
 + }
 +
 + /*
 +  * WORKAROUND: DWC3 revisions 1.90a have a bug
 +  * where the device can fail to connect at SuperSpeed
 +  * and falls back to high-speed mode which causes
 +  * the device to enter a Connect/Disconnect loop
 +  */
 + if (dwc-revision  DWC3_REVISION_190A)
 + reg |= DWC3_GCTL_U2RSTECN;
 +
 + dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 +
 + return 0;
 +}
 +
 +int dwc3_get_device_id(void)
 +{
 + int id;
 +
 +again:
 + id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
 + if (id  DWC3_DEVS_POSSIBLE) {
 + int old;
 +
 + old = test_and_set_bit(id, dwc3_devs);
 + if (old)
 + goto again;
 + } else {
 + pr_err(dwc3: no space for new device\n);
 + id = -ENOMEM;
 + }
 +
 + return id;
 +}
 +EXPORT_SYMBOL_GPL(dwc3_get_device_id);
 +
 +void dwc3_put_device_id(int id)
 +{
 + int ret;
 +
 + if (id  0)
 + 

[PATCH 1/3] usb: dwc3: Add the suspend/resume functionality

2012-10-10 Thread Vikas C Sajjan
From: Vikas Sajjan vikas.saj...@linaro.org

Adding the suspend and resume funtionality to DWC3 core.

Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com
Signed-off-by: Vikas C Sajjan vikas.saj...@linaro.org
CC: Doug Anderson diand...@chromium.org
---
 drivers/usb/dwc3/core.c |  268 +-
 1 files changed, 169 insertions(+), 99 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index b415c0c..58b51e1 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -70,51 +70,20 @@ MODULE_PARM_DESC(maximum_speed, Maximum supported speed.);
 
 static DECLARE_BITMAP(dwc3_devs, DWC3_DEVS_POSSIBLE);
 
-int dwc3_get_device_id(void)
-{
-   int id;
-
-again:
-   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
-   if (id  DWC3_DEVS_POSSIBLE) {
-   int old;
-
-   old = test_and_set_bit(id, dwc3_devs);
-   if (old)
-   goto again;
-   } else {
-   pr_err(dwc3: no space for new device\n);
-   id = -ENOMEM;
-   }
-
-   return id;
-}
-EXPORT_SYMBOL_GPL(dwc3_get_device_id);
-
-void dwc3_put_device_id(int id)
-{
-   int ret;
-
-   if (id  0)
-   return;
-
-   ret = test_bit(id, dwc3_devs);
-   WARN(!ret, dwc3: ID %d not in use\n, id);
-   smp_mb__before_clear_bit();
-   clear_bit(id, dwc3_devs);
-}
-EXPORT_SYMBOL_GPL(dwc3_put_device_id);
-
-void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
+static void __devinit dwc3_cache_hwparams(struct dwc3 *dwc)
 {
-   u32 reg;
+   struct dwc3_hwparams*parms = dwc-hwparams;
 
-   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
-   reg = ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
-   reg |= DWC3_GCTL_PRTCAPDIR(mode);
-   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
+   parms-hwparams0 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS0);
+   parms-hwparams1 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS1);
+   parms-hwparams2 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS2);
+   parms-hwparams3 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS3);
+   parms-hwparams4 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS4);
+   parms-hwparams5 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS5);
+   parms-hwparams6 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS6);
+   parms-hwparams7 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS7);
+   parms-hwparams8 = dwc3_readl(dwc-regs, DWC3_GHWPARAMS8);
 }
-
 /**
  * dwc3_core_soft_reset - Issues core soft reset and PHY reset
  * @dwc: pointer to our context structure
@@ -160,6 +129,102 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
dwc3_writel(dwc-regs, DWC3_GCTL, reg);
 }
 
+static int dwc3_core_reset(struct dwc3 *dwc)
+{
+   unsigned long   timeout;
+   u32 reg;
+
+   /* issue device SoftReset too */
+   timeout = jiffies + msecs_to_jiffies(500);
+   dwc3_writel(dwc-regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
+   do {
+   reg = dwc3_readl(dwc-regs, DWC3_DCTL);
+   if (!(reg  DWC3_DCTL_CSFTRST))
+   break;
+
+   if (time_after(jiffies, timeout)) {
+   dev_err(dwc-dev, Reset Timed Out\n);
+   return -ETIMEDOUT;
+   }
+
+   cpu_relax();
+   } while (true);
+
+   dwc3_core_soft_reset(dwc);
+
+   dwc3_cache_hwparams(dwc);
+
+   reg = dwc3_readl(dwc-regs, DWC3_GCTL);
+   reg = ~DWC3_GCTL_SCALEDOWN_MASK;
+   reg = ~DWC3_GCTL_DISSCRAMBLE;
+
+   switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc-hwparams.hwparams1)) {
+   case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
+   reg = ~DWC3_GCTL_DSBLCLKGTNG;
+   break;
+   default:
+   dev_dbg(dwc-dev, No power optimization available\n);
+   }
+
+   /*
+* WORKAROUND: DWC3 revisions 1.90a have a bug
+* where the device can fail to connect at SuperSpeed
+* and falls back to high-speed mode which causes
+* the device to enter a Connect/Disconnect loop
+*/
+   if (dwc-revision  DWC3_REVISION_190A)
+   reg |= DWC3_GCTL_U2RSTECN;
+
+   dwc3_writel(dwc-regs, DWC3_GCTL, reg);
+
+   return 0;
+}
+
+int dwc3_get_device_id(void)
+{
+   int id;
+
+again:
+   id = find_first_zero_bit(dwc3_devs, DWC3_DEVS_POSSIBLE);
+   if (id  DWC3_DEVS_POSSIBLE) {
+   int old;
+
+   old = test_and_set_bit(id, dwc3_devs);
+   if (old)
+   goto again;
+   } else {
+   pr_err(dwc3: no space for new device\n);
+   id = -ENOMEM;
+   }
+
+   return id;
+}
+EXPORT_SYMBOL_GPL(dwc3_get_device_id);
+
+void dwc3_put_device_id(int id)
+{
+   int ret;
+
+   if (id  0)
+   return;
+
+   ret = test_bit(id, dwc3_devs);
+   WARN(!ret, dwc3: ID %d not in use\n, id);
+   smp_mb__before_clear_bit();
+