Re: dwc2 gadget issues

2017-02-28 Thread Vardan Mikayelyan
On 2/28/2017 3:44 PM, Francesco Lavra wrote:
> Hi Vardan,
>
> On 02/28/2017 09:41 AM, Vardan Mikayelyan wrote:
>> On 2/27/2017 11:55 PM, Francesco Lavra wrote:
>>> Hi,
>>>
>>> On 02/23/2017 08:27 PM, Heiko Stuebner wrote:
>>>> Hi Francesco,
>>>>
>>>> Am Donnerstag, 23. Februar 2017, 19:11:37 CET schrieb Francesco Lavra:
>>>>> I'm having trouble getting the RK3288 OTG controller (the one at
>>>>> ff58) to work in peripheral mode. I'm using a Firefly Reload board,
>>>>> and I know the hardware is fine because I can successfully use the port
>>>>> in device mode with U-Boot's mass storage gadget driver.
>>>>> Under Linux, the OTG port works fine when used in host mode, but fails
>>>>> to work in device mode: nothing happens when the a USB host is plugged
>>>>> into the OTG port, not even a single interrupt is generated by the
>>>>> controller. I'm using the latest device tree definitions from
>>>>> git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git.
>>>>
>>>> you shouldn't use my tree as base for any real work :-) . Best to use the
>>>> regular mainline kernel or alternatively try linux-next to get all recent 
>>>> usb
>>>> changes schedules for the next release.
>>>
>>> Thanks for your inputs.
>>>
>>> I was actually using the mainline kernel (4.8.1), in which the dwc2
>>> driver wasn't working, that's why I went to your tree to pick up any
>>> fixes or new features that might have been done. I also went to the
>>> linux-usb tree for the same reason.
>>>
>>> Anyway, today I tried with the latest mainline release 4.10.0, and also
>>> with linux-next. Unfortunately, still no luck: I can load a gadget
>>> driver, which gets correctly bound to the OTG controller, but then
>>> nothing happens if a USB host is connected to the OTG port.
>>> I'm pasting below the dmesg contents (obtained with 4.10.0, with verbose
>>> debugging enabled for the dwc2 driver) when a gadget driver is loaded,
>>> in case you might spot something suspicious:
>>>
>>> [ 1147.035367] dwc2 ff58.usb: bound driver g_audio
>>> [ 1147.041203] dwc2 ff58.usb: dwc2_hsotg_pullup: is_on: 1 op_state: 3
>>> [ 1147.041250] dwc2 ff58.usb: dwc2_core_reset()
>>> [ 1147.041345] dwc2 ff58.usb: FIFOs reset, timeout at 100
>>> [ 1147.041405] dwc2 ff58.usb: EP0: DIEPCTL0=0x8000,
>>> DOEPCTL0=0x8000
>>> [ 1147.041447] dwc2 ff58.usb: gsintmsk now 0xd08c3cc4
>>> [ 1147.041554] dwc2 ff58.usb: DCTL=0x0002
>>> [ 1147.041631] dwc2 ff58.usb: dwc2_hsotg_enqueue_setup: queueing
>>> setup request
>>> [ 1147.041692] dwc2 ff58.usb: ep0: req ee241680: 8@ee241198, noi=0,
>>> zero=0, snok=0
>>> [ 1147.041757] dwc2 ff58.usb: dwc2_hsotg_start_req:
>>> DxEPCTL=0x80008000, ep 0, dir out
>>> [ 1147.041799] dwc2 ff58.usb: ureq->length:8 ureq->actual:0
>>> [ 1147.041896] dwc2 ff58.usb: dwc2_hsotg_start_req: 1@8/8,
>>> 0x00080008 => 0x0b10
>>> [ 1147.041975] dwc2 ff58.usb: dwc2_hsotg_start_req: 2e243000 pad =>
>>> 0x0b14
>>> [ 1147.042014] dwc2 ff58.usb: ep0 state:0
>>> [ 1147.042055] dwc2 ff58.usb: dwc2_hsotg_start_req: DxEPCTL=0x80008000
>>> [ 1147.042097] dwc2 ff58.usb: dwc2_hsotg_start_req: DXEPCTL=0x80008000
>>> [ 1147.042169] dwc2 ff58.usb: EP0: DIEPCTL0=0x8000,
>>> DOEPCTL0=0x80008000
>>>
>>> Thanks,
>>> Francesco
>>> --
>>
>> Hi Francesco,
>>
>> Could you please provide full log (with debugs enabled) from DWC2 driver
>> loading to issue point? Two logs are not giving us the full picture.
>
> The full log from the DWC2 driver is below:
>
> [1.498030] dwc2 ff58.usb: ff58.usb supply vusb_d not found,
> using dummy regulator
> [1.507431] dwc2 ff58.usb: ff58.usb supply vusb_a not found,
> using dummy regulator
> [1.880012] dwc2 ff58.usb: dwc2_check_param_tx_fifo_sizes:
> Invalid parameter g-tx-fifo-size, setting to default average
> [1.892596] dwc2 ff58.usb: EPs: 10, dedicated fifos, 972 entries
> in SPRAM
> [1.901018] dwc2 ff58.usb: DCFG=0x0810, DCTL=0x0002,
> DIEPMSK=
> [1.909432] dwc2 ff58.usb: GAHBCFG=0x, GHWCFG1=0x6664
> [1.916698] dwc2 ff58.usb: GRXFSIZ=0x0400, GNPTXFSIZ=0x00100400
> [1.924161] dwc2 ff58.usb: DPT

Re: dwc2 gadget issues

2017-02-28 Thread Vardan Mikayelyan
On 2/27/2017 11:55 PM, Francesco Lavra wrote:
> Hi,
>
> On 02/23/2017 08:27 PM, Heiko Stuebner wrote:
>> Hi Francesco,
>>
>> Am Donnerstag, 23. Februar 2017, 19:11:37 CET schrieb Francesco Lavra:
>>> I'm having trouble getting the RK3288 OTG controller (the one at
>>> ff58) to work in peripheral mode. I'm using a Firefly Reload board,
>>> and I know the hardware is fine because I can successfully use the port
>>> in device mode with U-Boot's mass storage gadget driver.
>>> Under Linux, the OTG port works fine when used in host mode, but fails
>>> to work in device mode: nothing happens when the a USB host is plugged
>>> into the OTG port, not even a single interrupt is generated by the
>>> controller. I'm using the latest device tree definitions from
>>> git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git.
>>
>> you shouldn't use my tree as base for any real work :-) . Best to use the
>> regular mainline kernel or alternatively try linux-next to get all recent usb
>> changes schedules for the next release.
>
> Thanks for your inputs.
>
> I was actually using the mainline kernel (4.8.1), in which the dwc2
> driver wasn't working, that's why I went to your tree to pick up any
> fixes or new features that might have been done. I also went to the
> linux-usb tree for the same reason.
>
> Anyway, today I tried with the latest mainline release 4.10.0, and also
> with linux-next. Unfortunately, still no luck: I can load a gadget
> driver, which gets correctly bound to the OTG controller, but then
> nothing happens if a USB host is connected to the OTG port.
> I'm pasting below the dmesg contents (obtained with 4.10.0, with verbose
> debugging enabled for the dwc2 driver) when a gadget driver is loaded,
> in case you might spot something suspicious:
>
> [ 1147.035367] dwc2 ff58.usb: bound driver g_audio
> [ 1147.041203] dwc2 ff58.usb: dwc2_hsotg_pullup: is_on: 1 op_state: 3
> [ 1147.041250] dwc2 ff58.usb: dwc2_core_reset()
> [ 1147.041345] dwc2 ff58.usb: FIFOs reset, timeout at 100
> [ 1147.041405] dwc2 ff58.usb: EP0: DIEPCTL0=0x8000,
> DOEPCTL0=0x8000
> [ 1147.041447] dwc2 ff58.usb: gsintmsk now 0xd08c3cc4
> [ 1147.041554] dwc2 ff58.usb: DCTL=0x0002
> [ 1147.041631] dwc2 ff58.usb: dwc2_hsotg_enqueue_setup: queueing
> setup request
> [ 1147.041692] dwc2 ff58.usb: ep0: req ee241680: 8@ee241198, noi=0,
> zero=0, snok=0
> [ 1147.041757] dwc2 ff58.usb: dwc2_hsotg_start_req:
> DxEPCTL=0x80008000, ep 0, dir out
> [ 1147.041799] dwc2 ff58.usb: ureq->length:8 ureq->actual:0
> [ 1147.041896] dwc2 ff58.usb: dwc2_hsotg_start_req: 1@8/8,
> 0x00080008 => 0x0b10
> [ 1147.041975] dwc2 ff58.usb: dwc2_hsotg_start_req: 2e243000 pad =>
> 0x0b14
> [ 1147.042014] dwc2 ff58.usb: ep0 state:0
> [ 1147.042055] dwc2 ff58.usb: dwc2_hsotg_start_req: DxEPCTL=0x80008000
> [ 1147.042097] dwc2 ff58.usb: dwc2_hsotg_start_req: DXEPCTL=0x80008000
> [ 1147.042169] dwc2 ff58.usb: EP0: DIEPCTL0=0x8000,
> DOEPCTL0=0x80008000
>
> Thanks,
> Francesco
> --

Hi Francesco,

Could you please provide full log (with debugs enabled) from DWC2 driver 
loading to issue point? Two logs are not giving us the full picture.

Thanks,
Vardan.

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: dwc2: Fix dwc2_hsotg_core_init_disconnected()

2017-02-25 Thread Vardan Mikayelyan
We should call dwc2_hsotg_enqueue_setup() after properly setting lx_state.
Because it may cause error-out from dwc2_hsotg_enqueue_setup() due to wrong
value in lx_state.

Issue can be reproduced by loading driver while connected A-Connector
(start in A-HOST mode) then disconnect A-Connector to switch to B-DEVICE.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 98a4a79..9322f80 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3402,12 +3402,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
   DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
 
-   dwc2_hsotg_enqueue_setup(hsotg);
-
-   dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-   dwc2_readl(hsotg->regs + DIEPCTL0),
-   dwc2_readl(hsotg->regs + DOEPCTL0));
-
/* clear global NAKs */
val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
if (!is_usb_reset)
@@ -3418,6 +3412,12 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
mdelay(3);
 
hsotg->lx_state = DWC2_L0;
+
+   dwc2_hsotg_enqueue_setup(hsotg);
+
+   dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+   dwc2_readl(hsotg->regs + DIEPCTL0),
+   dwc2_readl(hsotg->regs + DOEPCTL0));
 }
 
 static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/14] usb: dwc2: core: Add hibernated flag

2017-02-23 Thread Vardan Mikayelyan
True if core is hibernated.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h | 2 ++
 drivers/usb/dwc2/platform.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 60ad2e6..d84d0ce 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -779,6 +779,7 @@ struct dwc2_hregs_backup {
  * @hcd_enabledHost mode sub-driver initialization indicator.
  * @gadget_enabled Peripheral mode sub-driver initialization indicator.
  * @ll_hw_enabled  Status of low-level hardware resources.
+ * @hibernated:True if core is hibernated
  * @phy:The otg phy transceiver structure for phy control.
  * @uphy:   The otg phy transceiver structure for old USB phy
  *  control.
@@ -916,6 +917,7 @@ struct dwc2_hsotg {
unsigned int hcd_enabled:1;
unsigned int gadget_enabled:1;
unsigned int ll_hw_enabled:1;
+   unsigned int hibernated:1;
 
struct phy *phy;
struct usb_phy *uphy;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index db98463..c4e365a 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -462,6 +462,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
}
 
platform_set_drvdata(dev, hsotg);
+   hsotg->hibernated = 0;
 
dwc2_debugfs_init(hsotg);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/14] usb: dwc2: Add dwc2_enter_hibernation(), dwc2_exit_hibernation()

2017-02-23 Thread Vardan Mikayelyan
These are wrapper functions which are calling device or host
enter/exit hibernation functions.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 38 ++
 drivers/usb/dwc2/core.h |  3 +++
 2 files changed, 41 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index a37dfc2..2c90d8e 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -446,6 +446,44 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg 
*hsotg)
 }
 
 /*
+ * dwc2_enter_hibernation() - Common function to enter hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @is_host: True if core is in host mode.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host)
+{
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_HIBERNATION)
+   return -ENOTSUPP;
+
+   if (is_host)
+   return dwc2_host_enter_hibernation(hsotg);
+   else
+   return dwc2_gadget_enter_hibernation(hsotg);
+}
+
+/*
+ * dwc2_exit_hibernation() - Common function to exit from hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: Remote-wakeup, enabled in case of remote-wakeup.
+ * @reset: Enabled in case of restore with reset.
+ * @is_host: True if core is in host mode.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ int reset, int is_host)
+{
+   if (is_host)
+   return dwc2_host_exit_hibernation(hsotg, rem_wakeup, reset);
+   else
+   return dwc2_gadget_exit_hibernation(hsotg, rem_wakeup, reset);
+}
+
+/*
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
  */
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 9d17f4a..a3561e1 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1112,6 +1112,9 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
 int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg);
 int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore);
+int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host);
+int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ int reset, int is_host);
 
 void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/14] usb: dwc2: Add host/device hibernation functions

2017-02-23 Thread Vardan Mikayelyan
Add host/device hibernation functions which must be wrapped
by core's  dwc2_enter_hibernation()/dwc2_exit_hibernation()
functions.

Make dwc2_backup_global_registers dwc2_restore_global_register
non-static to use them in both host/gadget sides.

Added function names:
dwc2_gadget_enter_hibernation()
dwc2_gadget_exit_hibernation()
dwc2_host_enter_hibernation()
dwc2_host_exit_hibernation()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |   4 +-
 drivers/usb/dwc2/core.h   |  18 
 drivers/usb/dwc2/gadget.c | 196 ++
 drivers/usb/dwc2/hcd.c| 233 ++
 4 files changed, 449 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f478cdd..a37dfc2 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -63,7 +63,7 @@
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
+int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
 
@@ -94,7 +94,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
+int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 950915b..9d17f4a 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1131,6 +1131,8 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
 void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
 
 void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup);
+int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg);
+int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg);
 
 /* This function should be called on every hardware interrupt. */
 irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
@@ -1193,6 +1195,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*dwc2,
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
+int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
+int rem_wakeup, int reset);
 int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
@@ -1218,6 +1223,11 @@ static inline int dwc2_backup_device_registers(struct 
dwc2_hsotg *hsotg)
 static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
int remote_wakeup)
 { return 0; }
+static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
+  int rem_wakeup, int reset)
+{ return 0; }
 static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
@@ -1234,6 +1244,9 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct 
dwc2_hsotg *hsotg)
 void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
 int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
+int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);
+int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
+  int rem_wakeup, int reset);
 #else
 static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
 { return 0; }
@@ -1250,6 +1263,11 @@ static inline int dwc2_backup_host_registers(struct 
dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
+static inline int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
+int rem_wakeup, int reset)
+{ return 0; }
 
 #endif
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index fd274a8..e82e1db 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4870,3 +4870,199 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg, int remote_wakeup)
 
return 0;
 }
+
+/**
+ * dwc2_gadget_enter_hibernation() - Put controller in Hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ *
+ * Return non-zero if failed to enter to hibernation.
+ */
+int dwc2_gadget_enter_hibernation(struct dw

[PATCH v2 06/14] usb: dwc2: gadget: Add remote_wakeup_allowed flag

2017-02-23 Thread Vardan Mikayelyan
It will be set once corresponding set_feature command comes.

True if device is allowed to wake-up host by remote-wakeup
signalling.

This is preparation for remote wake-up support implementation,
it will not be implemented until gadget stack provide interface
for bringing remote wake-up signalling.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h   | 3 +++
 drivers/usb/dwc2/gadget.c | 6 ++
 2 files changed, 9 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index d84d0ce..ace383f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -897,6 +897,8 @@ struct dwc2_hregs_backup {
  * @ctrl_req:   Request for EP0 control packets.
  * @ep0_state:  EP0 control transfers state
  * @test_mode:  USB test mode requested by the host
+ * @remote_wakeup_allowed: True if device is allowed to wake-up host by
+ *  remote-wakeup signalling
  * @setup_desc_dma:EP0 setup stage desc chain DMA address
  * @setup_desc:EP0 setup stage desc chain pointer
  * @ctrl_in_desc_dma:  EP0 IN data phase desc chain DMA address
@@ -1061,6 +1063,7 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
+   unsigned int remote_wakeup_allowed:1;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
 #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3b082ed..fd274a8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1665,6 +1665,10 @@ static int dwc2_hsotg_process_req_feature(struct 
dwc2_hsotg *hsotg,
switch (recip) {
case USB_RECIP_DEVICE:
switch (wValue) {
+   case USB_DEVICE_REMOTE_WAKEUP:
+   hsotg->remote_wakeup_allowed = 1;
+   break;
+
case USB_DEVICE_TEST_MODE:
if ((wIndex & 0xff) != 0)
return -EINVAL;
@@ -4626,6 +4630,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = _hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
+   hsotg->remote_wakeup_allowed = 0;
+
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 08/14] usb: dwc2: Add helper functions for restore routine

2017-02-23 Thread Vardan Mikayelyan
Add common (host/device) helper functions, which will be called while
exiting from hibernation, from both sides.

dwc2_restore_essential_regs()
dwc2_hib_restore_common()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 136 
 drivers/usb/dwc2/core.h |   2 +
 2 files changed, 138 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 0e61511..f478cdd 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -239,6 +239,142 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg 
*hsotg)
 }
 
 /**
+ * dwc2_restore_essential_regs() - Restore essiential regs of core.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rmode: Restore mode, enabled in case of remote-wakeup.
+ */
+static void dwc2_restore_essential_regs(struct dwc2_hsotg *hsotg, int rmode)
+{
+   u32 pcgcctl;
+   struct dwc2_gregs_backup *gr;
+   struct dwc2_dregs_backup *dr;
+   struct dwc2_hregs_backup *hr;
+   int is_host = dwc2_is_host_mode(hsotg);
+
+   gr = >gr_backup;
+   dr = >dr_backup;
+   hr = >hr_backup;
+
+   dev_dbg(hsotg->dev, "%s: restoring essential regs\n", __func__);
+
+   /* Load restore values for [31:14] bits */
+   pcgcctl = (gr->pcgcctl & 0xc000) | 0x0002;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+
+   /* Umnask global Interrupt in GAHBCFG and restore it */
+   dwc2_writel(gr->gahbcfg | GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
+
+   /* Clear all pending interupts */
+   dwc2_writel(0x, hsotg->regs + GINTSTS);
+
+   /* Unmask restore done interrupt */
+   dwc2_writel(GINTSTS_RESTOREDONE, hsotg->regs + GINTMSK);
+
+   /* Restore GUSBCFG and HCFG/DCFG */
+   dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
+
+   if (is_host) {
+   dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
+   if (rmode)
+   pcgcctl |= 0x200;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+
+   pcgcctl = (gr->pcgcctl & 0xc000) | 0x0002;
+   pcgcctl |= PCGCTL_ESS_REG_RESTORED;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   } else {
+   dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
+   if (!rmode)
+   pcgcctl |= 0x208;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+
+   pcgcctl |= PCGCTL_ESS_REG_RESTORED;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   }
+}
+
+/**
+ * dwc2_hib_restore_common() - Common part of restore routine.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: Remote-wakeup, enabled in case of remote-wakeup.
+ */
+void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup)
+{
+   u32 gpwrdn;
+   u32 gintsts;
+   int timeout;
+   int is_host = dwc2_is_host_mode(hsotg);
+
+   /* Switch-on voltage to the core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNSWTCH;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Reset core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Enable restore from PMU */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn |= GPWRDN_RESTORE;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable Power Down Clamp */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNCLMP;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   if (!is_host && rem_wakeup)
+   udelay(70);
+
+   /* Deassert reset core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn |= GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable PMU interrupt */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PMUINTSEL;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+
+   /* Set Restore Essential Regs bit in PCGCCTL register */
+   dwc2_restore_essential_regs(hsotg, rem_wakeup);
+
+   /*
+* Wait For Restore_done Interrupt. This mechanism of polling the
+* interrupt is introduced to avoid any possible race conditions
+*/
+   timeout = 2000;
+   do {
+   gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+   if (!(gintsts & GINTSTS_RESTOREDONE)) {
+   udelay

[PATCH v2 07/14] usb: dwc2: Changes in registers backup/restore functions

2017-02-23 Thread Vardan Mikayelyan
Move hptxfsiz to host register's backup/restore functions, not
needed to have it in global register's backup/restore functions.

Add backup for glpmcfg, and read/write for gi2cctl and pcgcctl.
As requires programming guide.

Affected functions:
dwc2_backup_host_registers()
dwc2_restore_host_registers()
dwc2_backup_global_registers()
dwc2_restore_global_registers()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 8 ++--
 drivers/usb/dwc2/core.h | 6 --
 drivers/usb/dwc2/hcd.c  | 2 ++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 185d24c..0e61511 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -78,8 +78,10 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
-   gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
+   gr->glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+   gr->gi2cctl = dwc2_readl(hsotg->regs + GI2CCTL);
+   gr->pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
gr->valid = true;
return 0;
@@ -114,8 +116,10 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
-   dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
+   dwc2_writel(gr->glpmcfg, hsotg->regs + GLPMCFG);
+   dwc2_writel(gr->pcgcctl, hsotg->regs + PCGCTL);
+   dwc2_writel(gr->gi2cctl, hsotg->regs + GI2CCTL);
 
return 0;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index ace383f..31ebdfa 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -610,7 +610,7 @@ struct dwc2_hw_params {
  * @grxfsiz:   Backup of GRXFSIZ register
  * @gnptxfsiz: Backup of GNPTXFSIZ register
  * @gi2cctl:   Backup of GI2CCTL register
- * @hptxfsiz:  Backup of HPTXFSIZ register
+ * @glpmcfg:   Backup of GLPMCFG register
  * @gdfifocfg: Backup of GDFIFOCFG register
  * @gpwrdn:Backup of GPWRDN register
  */
@@ -622,7 +622,7 @@ struct dwc2_gregs_backup {
u32 grxfsiz;
u32 gnptxfsiz;
u32 gi2cctl;
-   u32 hptxfsiz;
+   u32 glpmcfg;
u32 pcgcctl;
u32 gdfifocfg;
u32 gpwrdn;
@@ -669,6 +669,7 @@ struct dwc2_dregs_backup {
  * @hcintmsk:  Backup of HCINTMSK register
  * @hptr0: Backup of HPTR0 register
  * @hfir:  Backup of HFIR register
+ * @hptxfsiz:  Backup of HPTXFSIZ register
  */
 struct dwc2_hregs_backup {
u32 hcfg;
@@ -676,6 +677,7 @@ struct dwc2_hregs_backup {
u32 hcintmsk[MAX_EPS_CHANNELS];
u32 hprt0;
u32 hfir;
+   u32 hptxfsiz;
bool valid;
 };
 
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 53d580f..e8adfeb 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5346,6 +5346,7 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
 
hr->hprt0 = dwc2_read_hprt0(hsotg);
hr->hfir = dwc2_readl(hsotg->regs + HFIR);
+   hr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
hr->valid = true;
 
return 0;
@@ -5382,6 +5383,7 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
 
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+   dwc2_writel(hr->hptxfsiz, hsotg->regs + HPTXFSIZ);
hsotg->frame_number = 0;
 
return 0;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 04/14] usb: dwc2: gadget: Fix dwc2_restore_device_registers

2017-02-23 Thread Vardan Mikayelyan
Add parameter remote_wakeup to dwc2_restore_device_registers()
to be able to restore device registers according to programming
guide for dwc-otg. It says that in case of rem_wakeup DCTL must not
be restored here.

Remove setting of DCTL_PWRONPRGDONE from this function, because it
will be done in function responsible for exiting from hibernation.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |  2 +-
 drivers/usb/dwc2/core.h   |  5 +++--
 drivers/usb/dwc2/gadget.c | 16 +++-
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 7addf69..185d24c 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -162,7 +162,7 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, 
bool restore)
return ret;
}
} else {
-   ret = dwc2_restore_device_registers(hsotg);
+   ret = dwc2_restore_device_registers(hsotg, 0);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore 
device registers\n",
__func__);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 4cb95b3..60ad2e6 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1183,7 +1183,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*dwc2,
 int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
 int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
@@ -1206,7 +1206,8 @@ static inline int dwc2_hsotg_set_test_mode(struct 
dwc2_hsotg *hsotg,
 #define dwc2_is_device_connected(hsotg) (0)
 static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
-static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
+   int remote_wakeup)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
 { return 0; }
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3e969a5..3b082ed 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4822,11 +4822,13 @@ int dwc2_backup_device_registers(struct dwc2_hsotg 
*hsotg)
  * if controller power were disabled.
  *
  * @hsotg: Programming view of the DWC_otg controller
+ * @remote_wakeup: Indicates whether resume is initiated by Device or Host.
+ *
+ * Return: 0 if successful, negative error code otherwise
  */
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 {
struct dwc2_dregs_backup *dr;
-   u32 dctl;
int i;
 
dev_dbg(hsotg->dev, "%s\n", __func__);
@@ -4840,8 +4842,9 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
}
dr->valid = false;
 
-   dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
-   dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+   if (!remote_wakeup)
+   dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+
dwc2_writel(dr->daintmsk, hsotg->regs + DAINTMSK);
dwc2_writel(dr->diepmsk, hsotg->regs + DIEPMSK);
dwc2_writel(dr->doepmsk, hsotg->regs + DOEPMSK);
@@ -4859,10 +4862,5 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
}
 
-   /* Set the Power-On Programming done bit */
-   dctl = dwc2_readl(hsotg->regs + DCTL);
-   dctl |= DCTL_PWRONPRGDONE;
-   dwc2_writel(dctl, hsotg->regs + DCTL);
-
return 0;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/14] usb: dwc2: Add hibernation field into dwc2_hw_params

2017-02-23 Thread Vardan Mikayelyan
Add parameter and it's initialization, needed for hibernation.

Reimplement dwc2_set_param_power_down() to support hibernation too.
Now 'power_down' parameter can be initialized with 0, 1 or 2.
0 - No
1 - Partial power down
2 - Hibernation

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |  2 +-
 drivers/usb/dwc2/core.h   | 12 ++--
 drivers/usb/dwc2/hcd.c|  4 ++--
 drivers/usb/dwc2/params.c | 34 ++
 4 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index e8708fd..fe976eb 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -135,7 +135,7 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, 
bool restore)
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.power_down)
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
return -ENOTSUPP;
 
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 61c5e56..526d870 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -422,7 +422,8 @@ enum dwc2_ep0_state {
  * power_down in both peripheral and host mode when
  * needed.
  * 0 - No (default)
- * 1 - Yes
+ * 1 - Partial power down
+ * 2 - Hibernation
  * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO
  * register.
  * 0 - Deactivate the transceiver (default)
@@ -480,7 +481,12 @@ struct dwc2_core_params {
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
-   bool power_down;
+
+   int power_down;
+#define DWC2_POWER_DOWN_PARAM_NONE 0
+#define DWC2_POWER_DOWN_PARAM_PARTIAL  1
+#define DWC2_POWER_DOWN_PARAM_HIBERNATION  2
+
bool activate_stm_fs_transceiver;
u16 max_packet_count;
u32 max_transfer_size;
@@ -554,6 +560,7 @@ struct dwc2_core_params {
  *   2 - FS pins shared with UTMI+ pins
  *   3 - FS pins shared with ULPI pins
  * @total_fifo_size:Total internal RAM for FIFOs (bytes)
+ * @hibernationIs hibernation enabled?
  * @utmi_phy_data_width UTMI+ PHY data width
  *   0 - 8 bits
  *   1 - 16 bits
@@ -584,6 +591,7 @@ struct dwc2_hw_params {
unsigned num_dev_perio_in_ep:4;
unsigned total_fifo_size:16;
unsigned power_optimized:1;
+   unsigned hibernation:1;
unsigned utmi_phy_data_width:2;
u32 snpsid;
u32 dev_ep_dirs;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 604356c..53d580f 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4396,7 +4396,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
goto unlock;
 
-   if (!hsotg->params.power_down)
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
goto skip_power_saving;
 
/*
@@ -4448,7 +4448,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
if (hsotg->lx_state != DWC2_L2)
goto unlock;
 
-   if (!hsotg->params.power_down) {
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
hsotg->lx_state = DWC2_L0;
goto unlock;
}
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 38336e5..baa76bf 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -446,6 +446,38 @@ static void dwc2_check_param_phy_utmi_width(struct 
dwc2_hsotg *hsotg)
dwc2_set_param_phy_utmi_width(hsotg);
 }
 
+static void dwc2_check_param_power_down(struct dwc2_hsotg *hsotg)
+{
+   int param = hsotg->params.power_down;
+
+   switch (param) {
+   case DWC2_POWER_DOWN_PARAM_NONE:
+   break;
+   case DWC2_POWER_DOWN_PARAM_PARTIAL:
+   if (hsotg->hw_params.power_optimized)
+   break;
+   dev_dbg(hsotg->dev,
+   "Partial power down isn't supported by HW\n");
+   param = DWC2_POWER_DOWN_PARAM_NONE;
+   break;
+   case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+   if (hsotg->hw_params.hibernation)
+   break;
+   dev_dbg(hsotg->dev,
+   "Hibernation isn't supported by HW\n");
+   param = DWC2_POWER_DOWN_PARAM_NONE;
+   break;
+   default:
+   dev_err(hsotg->dev,
+   "%s: Invalid parameter power_down=%d\n",
+ 

[PATCH v2 03/14] usb: dwc2: gadget: Moved dtxfsiz backup array place

2017-02-23 Thread Vardan Mikayelyan
Moved dtxfsiz from dwc2_gregs_backup to dwc2_dregs_backup,
because it is device register.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   | 8 ++--
 drivers/usb/dwc2/core.h   | 4 ++--
 drivers/usb/dwc2/gadget.c | 2 ++
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fe976eb..7addf69 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -66,7 +66,8 @@
 static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
-   int i;
+
+   dev_dbg(hsotg->dev, "%s\n", __func__);
 
/* Backup global regs */
gr = >gr_backup;
@@ -79,8 +80,6 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
-   for (i = 0; i < MAX_EPS_CHANNELS; i++)
-   gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
 
gr->valid = true;
return 0;
@@ -96,7 +95,6 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
 static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
-   int i;
 
dev_dbg(hsotg->dev, "%s\n", __func__);
 
@@ -118,8 +116,6 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
-   for (i = 0; i < MAX_EPS_CHANNELS; i++)
-   dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
 
return 0;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 526d870..4cb95b3 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -612,7 +612,6 @@ struct dwc2_hw_params {
  * @gi2cctl:   Backup of GI2CCTL register
  * @hptxfsiz:  Backup of HPTXFSIZ register
  * @gdfifocfg: Backup of GDFIFOCFG register
- * @dtxfsiz:   Backup of DTXFSIZ registers for each endpoint
  * @gpwrdn:Backup of GPWRDN register
  */
 struct dwc2_gregs_backup {
@@ -626,7 +625,6 @@ struct dwc2_gregs_backup {
u32 hptxfsiz;
u32 pcgcctl;
u32 gdfifocfg;
-   u32 dtxfsiz[MAX_EPS_CHANNELS];
u32 gpwrdn;
bool valid;
 };
@@ -645,6 +643,7 @@ struct dwc2_gregs_backup {
  * @doepctl:   Backup of DOEPCTL register
  * @doeptsiz:  Backup of DOEPTSIZ register
  * @doepdma:   Backup of DOEPDMA register
+ * @dtxfsiz:   Backup of DTXFSIZ registers for each endpoint
  */
 struct dwc2_dregs_backup {
u32 dcfg;
@@ -658,6 +657,7 @@ struct dwc2_dregs_backup {
u32 doepctl[MAX_EPS_CHANNELS];
u32 doeptsiz[MAX_EPS_CHANNELS];
u32 doepdma[MAX_EPS_CHANNELS];
+   u32 dtxfsiz[MAX_EPS_CHANNELS];
bool valid;
 };
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 4bd3cab..3e969a5 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4810,6 +4810,7 @@ int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
 
dr->doeptsiz[i] = dwc2_readl(hsotg->regs + DOEPTSIZ(i));
dr->doepdma[i] = dwc2_readl(hsotg->regs + DOEPDMA(i));
+   dr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
}
dr->valid = true;
return 0;
@@ -4850,6 +4851,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
dwc2_writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
dwc2_writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
+   dwc2_writel(dr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
 
/* Restore OUT EPs */
dwc2_writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/14] usb: dwc2: Add dwc2_handle_gpwrdn_intr() handler

2017-02-23 Thread Vardan Mikayelyan
The GPWRDN interrupts are those that occur in both Host and
Device mode while core is in hibernated state.

Export dwc2_core_init to be able to use it in GPWRDN_IDSTS
interrupt handler.

Here we have duplicated init functions in host and gadget sides
so I have left things as it was(used corresponing functions for
host and gadget), maybe in the future we'll resolve this problem
and will use dwc2_core_init for both sides.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h  |   3 ++
 drivers/usb/dwc2/core_intr.c | 110 +++
 drivers/usb/dwc2/hcd.c   |   2 +-
 3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a3561e1..263ad53 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1245,6 +1245,7 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct 
dwc2_hsotg *hsotg)
 void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);
 void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);
 void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
+int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);
 int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);
@@ -1260,6 +1261,8 @@ static inline void dwc2_hcd_connect(struct dwc2_hsotg 
*hsotg) {}
 static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) {}
 static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
 static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
+{ return 0; }
 static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 45c9b57..86cbbb9 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -520,6 +520,109 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
return 0;
 }
 
+/**
+ * GPWRDN interrupt handler.
+ *
+ * The GPWRDN interrupts are those that occur in both Host and
+ * Device mode while core is in hibernated state.
+ */
+static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
+{
+   u32 gpwrdn;
+   int linestate;
+
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
+   dev_dbg(hsotg->dev,
+   "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
+   gpwrdn);
+
+   if ((gpwrdn & GPWRDN_DISCONN_DET) &&
+   (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
+   u32 gpwrdn_tmp;
+
+   dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
+   /* clear interrupt */
+   dwc2_writel(GPWRDN_DISCONN_DET, hsotg->regs + GPWRDN);
+
+   /* Switch-on voltage to the core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Reset core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable Power Down Clamp */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Deassert reset core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable PMU interrupt */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+
+   /* De-assert Wakeup Logic */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PMUACTV;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+
+   hsotg->hibernated = 0;
+
+   if (gpwrdn & GPWRDN_IDSTS) {
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+   dwc2_core_init(hsotg, false);
+   dwc2_enable_global_interrupts(hsotg);
+   dwc2_hsotg_core_init_disc

[PATCH v2 11/14] usb: dwc2: Allow entering hibernation from USB_SUSPEND interrupt

2017-02-23 Thread Vardan Mikayelyan
Do changes to allow entering hibernated state from USB_SUSPEND
interrupt. All code is added under if conditions and mustn't impact
existing functionality.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 52 +++-
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 0fb8cf6..45c9b57 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -427,32 +427,44 @@ static void dwc2_handle_usb_suspend_intr(struct 
dwc2_hsotg *hsotg)
 * state is active
 */
dsts = dwc2_readl(hsotg->regs + DSTS);
-   dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
+   dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
dev_dbg(hsotg->dev,
-   "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
+   "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d 
HWCFG4.Hibernation=%d\n",
!!(dsts & DSTS_SUSPSTS),
-   hsotg->hw_params.power_optimized);
-   if ((dsts & DSTS_SUSPSTS) && hsotg->hw_params.power_optimized) {
-   /* Ignore suspend request before enumeration */
-   if (!dwc2_is_device_connected(hsotg)) {
-   dev_dbg(hsotg->dev,
-   "ignore suspend request before 
enumeration\n");
-   return;
+   hsotg->hw_params.power_optimized,
+   hsotg->hw_params.hibernation);
+
+   /* Ignore suspend request before enumeration */
+   if (!dwc2_is_device_connected(hsotg)) {
+   dev_dbg(hsotg->dev,
+   "ignore suspend request before enumeration\n");
+   return;
+   }
+   if (dsts & DSTS_SUSPSTS) {
+   if (hsotg->hw_params.power_optimized) {
+   ret = dwc2_enter_partial_power_down(hsotg);
+   if (ret) {
+   if (ret != -ENOTSUPP)
+   dev_err(hsotg->dev,
+   "%s: enter 
partial_power_down failed\n",
+   __func__);
+   goto skip_power_saving;
+   }
+
+   udelay(100);
+
+   /* Ask phy to be suspended */
+   if (!IS_ERR_OR_NULL(hsotg->uphy))
+   usb_phy_set_suspend(hsotg->uphy, true);
}
 
-   ret = dwc2_enter_partial_power_down(hsotg);
-   if (ret) {
-   if (ret != -ENOTSUPP)
+   if (hsotg->hw_params.hibernation) {
+   ret = dwc2_enter_hibernation(hsotg, 0);
+   if (ret && ret != -ENOTSUPP)
dev_err(hsotg->dev,
-   "enter power_down failed\n");
-   goto skip_power_saving;
+   "%s: enter hibernation 
failed\n",
+   __func__);
}
-
-   udelay(100);
-
-   /* Ask phy to be suspended */
-   if (!IS_ERR_OR_NULL(hsotg->uphy))
-   usb_phy_set_suspend(hsotg->uphy, true);
 skip_power_saving:
/*
 * Change to L2 (suspend) state before releasing
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 14/14] usb: dwc2: Enable power down

2017-02-23 Thread Vardan Mikayelyan
From: John Youn <johny...@synopsys.com>

Enable the power down option based on the core capability.

Signed-off-by: John Youn <johny...@synopsys.com>
Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
 drivers/usb/dwc2/params.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index baa76bf..9480b8f 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -238,6 +238,20 @@ static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg 
*hsotg)
p->g_tx_fifo_size[i] = depth_average;
 }
 
+static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg)
+{
+   int val;
+
+   if (hsotg->hw_params.hibernation)
+   val = 2;
+   else if (hsotg->hw_params.power_optimized)
+   val = 1;
+   else
+   val = 0;
+
+   hsotg->params.power_down = val;
+}
+
 /**
  * dwc2_set_default_params() - Set all core parameters to their
  * auto-detected default values.
@@ -252,6 +266,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg 
*hsotg)
dwc2_set_param_phy_type(hsotg);
dwc2_set_param_speed(hsotg);
dwc2_set_param_phy_utmi_width(hsotg);
+   dwc2_set_param_power_down(hsotg);
p->phy_ulpi_ddr = false;
p->phy_ulpi_ext_vbus = false;
 
@@ -263,7 +278,6 @@ static void dwc2_set_default_params(struct dwc2_hsotg 
*hsotg)
p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a);
p->uframe_sched = true;
p->external_id_pin_ctl = false;
-   p->power_down = false;
p->max_packet_count = hw->max_packet_count;
p->max_transfer_size = hw->max_transfer_size;
p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 13/14] usb: dwc2: Change hub-control to allow hibernation

2017-02-23 Thread Vardan Mikayelyan
Affected cases:
ClearPortFeature's
 USB_PORT_FEAT_SUSPEND

SetPortFeature's
 USB_PORT_FEAT_SUSPEND
 USB_PORT_FEAT_RESET

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 0b889a0..636dffc 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3471,8 +3471,12 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
 
-   if (hsotg->bus_suspended)
-   dwc2_port_resume(hsotg);
+   if (hsotg->bus_suspended) {
+   if (hsotg->hibernated)
+   dwc2_exit_hibernation(hsotg, 0, 0, 1);
+   else
+   dwc2_port_resume(hsotg);
+   }
break;
 
case USB_PORT_FEAT_POWER:
@@ -3680,7 +3684,10 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
"SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
if (windex != hsotg->otg_port)
goto error;
-   dwc2_port_suspend(hsotg, windex);
+   if (hsotg->params.power_down == 2)
+   dwc2_enter_hibernation(hsotg, 1);
+   else
+   dwc2_port_suspend(hsotg, windex);
break;
 
case USB_PORT_FEAT_POWER:
@@ -3692,6 +3699,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, 
u16 typereq,
break;
 
case USB_PORT_FEAT_RESET:
+   if (hsotg->params.power_down == 2 &&
+   hsotg->hibernated)
+   dwc2_exit_hibernation(hsotg, 0, 1, 1);
hprt0 = dwc2_read_hprt0(hsotg);
dev_dbg(hsotg->dev,
"SetPortFeature - USB_PORT_FEAT_RESET\n");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 00/14] usb: dwc2: Add hibernation feature support.

2017-02-23 Thread Vardan Mikayelyan
The functions with name hibernation are misnamed originally. They were only
responsible for partial power down and not for hibernation.

This patch set adds the real hibernation support for dwc2 driver and renames
existing functions to power_down.xisting functions to power_down.

Changes in v2:
 -remove "usb: dwc2: Replace msleep with mdelay in dwc2_clear_force_mode()"
  from this series because it is unnescessary after force mode optimizations.

John Youn (1):
  usb: dwc2: Enable power down

Vardan Mikayelyan (13):
  usb: dwc2: Rename hibernation to partial_power_down
  usb: dwc2: Add hibernation field into dwc2_hw_params
  usb: dwc2: gadget: Moved dtxfsiz backup array place
  usb: dwc2: gadget: Fix dwc2_restore_device_registers
  usb: dwc2: core: Add hibernated flag
  usb: dwc2: gadget: Add remote_wakeup_allowed flag
  usb: dwc2: Changes in registers backup/restore functions
  usb: dwc2: Add helper functions for restore routine
  usb: dwc2: Add host/device hibernation functions
  usb: dwc2: Add dwc2_enter_hibernation(), dwc2_exit_hibernation()
  usb: dwc2: Allow entering hibernation from USB_SUSPEND interrupt
  usb: dwc2: Add dwc2_handle_gpwrdn_intr() handler
  usb: dwc2: Change hub-control to allow hibernation

 drivers/usb/dwc2/core.c  | 210 +---
 drivers/usb/dwc2/core.h  |  68 +--
 drivers/usb/dwc2/core_intr.c | 172 ++
 drivers/usb/dwc2/debugfs.c   |   2 +-
 drivers/usb/dwc2/gadget.c| 226 +--
 drivers/usb/dwc2/hcd.c   | 279 ---
 drivers/usb/dwc2/params.c|  50 +++-
 drivers/usb/dwc2/platform.c  |   1 +
 8 files changed, 921 insertions(+), 87 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 01/14] usb: dwc2: Rename hibernation to partial_power_down

2017-02-23 Thread Vardan Mikayelyan
No-op change, only rename.

This code was misnamed originally. It was only responsible for partial
power down and not for hibernation.

Rename core_params->hibernation to core_params->power_down,
dwc2_set_param_hibernation() to dwc2_set_param_power_down().

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c  | 14 +++---
 drivers/usb/dwc2/core.h  | 12 ++--
 drivers/usb/dwc2/core_intr.c | 14 +++---
 drivers/usb/dwc2/debugfs.c   |  2 +-
 drivers/usb/dwc2/gadget.c|  6 +++---
 drivers/usb/dwc2/hcd.c   | 26 +-
 drivers/usb/dwc2/params.c|  2 +-
 7 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 42ac47f..e8708fd 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -125,17 +125,17 @@ static int dwc2_restore_global_registers(struct 
dwc2_hsotg *hsotg)
 }
 
 /**
- * dwc2_exit_hibernation() - Exit controller from Partial Power Down.
+ * dwc2_exit_partial_power_down() - Exit controller from Partial Power Down.
  *
  * @hsotg: Programming view of the DWC_otg controller
  * @restore: Controller registers need to be restored
  */
-int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
+int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 {
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.hibernation)
+   if (!hsotg->params.power_down)
return -ENOTSUPP;
 
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -179,16 +179,16 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool 
restore)
 }
 
 /**
- * dwc2_enter_hibernation() - Put controller in Partial Power Down.
+ * dwc2_enter_partial_power_down() - Put controller in Partial Power Down.
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
+int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 {
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.hibernation)
+   if (!hsotg->params.power_down)
return -ENOTSUPP;
 
/* Backup all registers */
@@ -217,7 +217,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
 
/*
 * Clear any pending interrupts since dwc2 will not be able to
-* clear them after entering hibernation.
+* clear them after entering partial_power_down.
 */
dwc2_writel(0x, hsotg->regs + GINTSTS);
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 67ca757..61c5e56 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -417,9 +417,9 @@ enum dwc2_ep0_state {
  *  case.
  *  0 - No (default)
  *  1 - Yes
- * @hibernation:   Specifies whether the controller support hibernation.
- * If hibernation is enabled, the controller will enter
- * hibernation in both peripheral and host mode when
+ * @power_down: Specifies whether the controller support power_down.
+ * If power_down is enabled, the controller will enter
+ * power_down in both peripheral and host mode when
  * needed.
  * 0 - No (default)
  * 1 - Yes
@@ -480,7 +480,7 @@ struct dwc2_core_params {
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
-   bool hibernation;
+   bool power_down;
bool activate_stm_fs_transceiver;
u16 max_packet_count;
u32 max_transfer_size;
@@ -1095,8 +1095,8 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
  * and the DWC_otg controller
  */
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
-int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
-int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
+int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg);
+int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore);
 
 void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index b8bcb00..0fb8cf6 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -320,10 +320,10 @@ static void dwc2_handle_session_req_intr(struct 
dwc2_hsotg *hsotg)
 
if (dwc2_is_device_mode(hsotg)) {
if (hsotg->lx_state == DWC2_L2) {
-   ret = dwc2_exit_hibernation(hsotg, true);
+   ret = dwc2_exit_partial_power_down(hsotg, true);
if (ret && (ret != -ENOTSUPP))
dev_err(hsotg->dev,
-   

Re: [PATCH 15/15] usb: dwc2: Replace msleep with mdelay in dwc2_clear_force_mode()

2017-02-22 Thread Vardan Mikayelyan
On 2/22/2017 10:59 PM, John Youn wrote:
> On 2/21/2017 5:16 AM, David Laight wrote:
>> From: Vardan Mikayelyan
>>> Sent: 20 February 2017 15:15
>>> dwc2_clear_force_mode() can be called in hibernation exit flow which
>>> can occur in interrupt context.
>>>
>>> Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
>>> ---
>>>  drivers/usb/dwc2/core.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
>>> index 2c90d8e..c7c76e8 100644
>>> --- a/drivers/usb/dwc2/core.c
>>> +++ b/drivers/usb/dwc2/core.c
>>> @@ -634,7 +634,7 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
>>> dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
>>>
>>> if (dwc2_iddig_filter_enabled(hsotg))
>>> -   msleep(100);
>>> +   mdelay(100);
>>
>> Spinning for 100ms isn't good at all.
>>
>
> Agreed.
>
> Vardan, I thought you had a change that avoided this issue entirely?
>
> Thanks,
> John
>
John, David thank you for review.

Yeah actually that was fixed by "usb: dwc2: Force mode optimizations" 
which is now in the "next". So we can exclude last patch from this series.

Thanks,
Vardan.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/15] usb: dwc2: gadget: Fix dwc2_restore_device_registers

2017-02-20 Thread Vardan Mikayelyan
Add parameter remote_wakeup to dwc2_restore_device_registers()
to be able to restore device registers according to programming
guide for dwc-otg. It says that in case of rem_wakeup DCTL must not
be restored here.

Remove setting of DCTL_PWRONPRGDONE from this function, because it
will be done in function responsible for exiting from hibernation.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |  2 +-
 drivers/usb/dwc2/core.h   |  5 +++--
 drivers/usb/dwc2/gadget.c | 16 +++-
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 7addf69..185d24c 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -162,7 +162,7 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, 
bool restore)
return ret;
}
} else {
-   ret = dwc2_restore_device_registers(hsotg);
+   ret = dwc2_restore_device_registers(hsotg, 0);
if (ret) {
dev_err(hsotg->dev, "%s: failed to restore 
device registers\n",
__func__);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 4cb95b3..60ad2e6 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1183,7 +1183,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*dwc2,
 int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
 int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
@@ -1206,7 +1206,8 @@ static inline int dwc2_hsotg_set_test_mode(struct 
dwc2_hsotg *hsotg,
 #define dwc2_is_device_connected(hsotg) (0)
 static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
-static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
+   int remote_wakeup)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
 { return 0; }
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3e969a5..3b082ed 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4822,11 +4822,13 @@ int dwc2_backup_device_registers(struct dwc2_hsotg 
*hsotg)
  * if controller power were disabled.
  *
  * @hsotg: Programming view of the DWC_otg controller
+ * @remote_wakeup: Indicates whether resume is initiated by Device or Host.
+ *
+ * Return: 0 if successful, negative error code otherwise
  */
-int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 {
struct dwc2_dregs_backup *dr;
-   u32 dctl;
int i;
 
dev_dbg(hsotg->dev, "%s\n", __func__);
@@ -4840,8 +4842,9 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
}
dr->valid = false;
 
-   dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
-   dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+   if (!remote_wakeup)
+   dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+
dwc2_writel(dr->daintmsk, hsotg->regs + DAINTMSK);
dwc2_writel(dr->diepmsk, hsotg->regs + DIEPMSK);
dwc2_writel(dr->doepmsk, hsotg->regs + DOEPMSK);
@@ -4859,10 +4862,5 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
}
 
-   /* Set the Power-On Programming done bit */
-   dctl = dwc2_readl(hsotg->regs + DCTL);
-   dctl |= DCTL_PWRONPRGDONE;
-   dwc2_writel(dctl, hsotg->regs + DCTL);
-
return 0;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/15] usb: dwc2: Replace msleep with mdelay in dwc2_clear_force_mode()

2017-02-20 Thread Vardan Mikayelyan
dwc2_clear_force_mode() can be called in hibernation exit flow which
can occur in interrupt context.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 2c90d8e..c7c76e8 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -634,7 +634,7 @@ void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
 
if (dwc2_iddig_filter_enabled(hsotg))
-   msleep(100);
+   mdelay(100);
 }
 
 /*
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/15] usb: dwc2: Change hub-control to allow hibernation

2017-02-20 Thread Vardan Mikayelyan
Affected cases:
ClearPortFeature's
 USB_PORT_FEAT_SUSPEND

SetPortFeature's
 USB_PORT_FEAT_SUSPEND
 USB_PORT_FEAT_RESET

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 0b889a0..636dffc 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3471,8 +3471,12 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
 
-   if (hsotg->bus_suspended)
-   dwc2_port_resume(hsotg);
+   if (hsotg->bus_suspended) {
+   if (hsotg->hibernated)
+   dwc2_exit_hibernation(hsotg, 0, 0, 1);
+   else
+   dwc2_port_resume(hsotg);
+   }
break;
 
case USB_PORT_FEAT_POWER:
@@ -3680,7 +3684,10 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
"SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
if (windex != hsotg->otg_port)
goto error;
-   dwc2_port_suspend(hsotg, windex);
+   if (hsotg->params.power_down == 2)
+   dwc2_enter_hibernation(hsotg, 1);
+   else
+   dwc2_port_suspend(hsotg, windex);
break;
 
case USB_PORT_FEAT_POWER:
@@ -3692,6 +3699,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, 
u16 typereq,
break;
 
case USB_PORT_FEAT_RESET:
+   if (hsotg->params.power_down == 2 &&
+   hsotg->hibernated)
+   dwc2_exit_hibernation(hsotg, 0, 1, 1);
hprt0 = dwc2_read_hprt0(hsotg);
dev_dbg(hsotg->dev,
"SetPortFeature - USB_PORT_FEAT_RESET\n");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/15] usb: dwc2: Add dwc2_handle_gpwrdn_intr() handler

2017-02-20 Thread Vardan Mikayelyan
The GPWRDN interrupts are those that occur in both Host and
Device mode while core is in hibernated state.

Export dwc2_core_init to be able to use it in GPWRDN_IDSTS
interrupt handler.

Here we have duplicated init functions in host and gadget sides
so I have left things as it was(used corresponing functions for
host and gadget), maybe in the future we'll resolve this problem
and will use dwc2_core_init for both sides.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h  |   3 ++
 drivers/usb/dwc2/core_intr.c | 110 +++
 drivers/usb/dwc2/hcd.c   |   2 +-
 3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a3561e1..263ad53 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1245,6 +1245,7 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct 
dwc2_hsotg *hsotg)
 void dwc2_hcd_connect(struct dwc2_hsotg *hsotg);
 void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force);
 void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
+int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);
 int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);
@@ -1260,6 +1261,8 @@ static inline void dwc2_hcd_connect(struct dwc2_hsotg 
*hsotg) {}
 static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) {}
 static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
 static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
+{ return 0; }
 static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 45c9b57..86cbbb9 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -520,6 +520,109 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
return 0;
 }
 
+/**
+ * GPWRDN interrupt handler.
+ *
+ * The GPWRDN interrupts are those that occur in both Host and
+ * Device mode while core is in hibernated state.
+ */
+static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
+{
+   u32 gpwrdn;
+   int linestate;
+
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   linestate = (gpwrdn & GPWRDN_LINESTATE_MASK) >> GPWRDN_LINESTATE_SHIFT;
+   dev_dbg(hsotg->dev,
+   "%s: dwc2_handle_gpwrdwn_intr called gpwrdn= %08x\n", __func__,
+   gpwrdn);
+
+   if ((gpwrdn & GPWRDN_DISCONN_DET) &&
+   (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
+   u32 gpwrdn_tmp;
+
+   dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
+   /* clear interrupt */
+   dwc2_writel(GPWRDN_DISCONN_DET, hsotg->regs + GPWRDN);
+
+   /* Switch-on voltage to the core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Reset core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable Power Down Clamp */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Deassert reset core */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable PMU interrupt */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+
+   /* De-assert Wakeup Logic */
+   gpwrdn_tmp = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn_tmp &= ~GPWRDN_PMUACTV;
+   dwc2_writel(gpwrdn_tmp, hsotg->regs + GPWRDN);
+
+   hsotg->hibernated = 0;
+
+   if (gpwrdn & GPWRDN_IDSTS) {
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+   dwc2_core_init(hsotg, false);
+   dwc2_enable_global_interrupts(hsotg);
+   dwc2_hsotg_core_init_disc

[PATCH 14/15] usb: dwc2: Enable power down

2017-02-20 Thread Vardan Mikayelyan
From: John Youn <johny...@synopsys.com>

Enable the power down option based on the core capability.

Signed-off-by: John Youn <johny...@synopsys.com>
Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
 drivers/usb/dwc2/params.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index baa76bf..9480b8f 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -238,6 +238,20 @@ static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg 
*hsotg)
p->g_tx_fifo_size[i] = depth_average;
 }
 
+static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg)
+{
+   int val;
+
+   if (hsotg->hw_params.hibernation)
+   val = 2;
+   else if (hsotg->hw_params.power_optimized)
+   val = 1;
+   else
+   val = 0;
+
+   hsotg->params.power_down = val;
+}
+
 /**
  * dwc2_set_default_params() - Set all core parameters to their
  * auto-detected default values.
@@ -252,6 +266,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg 
*hsotg)
dwc2_set_param_phy_type(hsotg);
dwc2_set_param_speed(hsotg);
dwc2_set_param_phy_utmi_width(hsotg);
+   dwc2_set_param_power_down(hsotg);
p->phy_ulpi_ddr = false;
p->phy_ulpi_ext_vbus = false;
 
@@ -263,7 +278,6 @@ static void dwc2_set_default_params(struct dwc2_hsotg 
*hsotg)
p->reload_ctl = (hw->snpsid >= DWC2_CORE_REV_2_92a);
p->uframe_sched = true;
p->external_id_pin_ctl = false;
-   p->power_down = false;
p->max_packet_count = hw->max_packet_count;
p->max_transfer_size = hw->max_transfer_size;
p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/15] usb: dwc2: Rename hibernation to partial_power_down

2017-02-20 Thread Vardan Mikayelyan
No-op change, only rename.

This code was misnamed originally. It was only responsible for partial
power down and not for hibernation.

Rename core_params->hibernation to core_params->power_down,
dwc2_set_param_hibernation() to dwc2_set_param_power_down().

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c  | 14 +++---
 drivers/usb/dwc2/core.h  | 12 ++--
 drivers/usb/dwc2/core_intr.c | 14 +++---
 drivers/usb/dwc2/debugfs.c   |  2 +-
 drivers/usb/dwc2/gadget.c|  6 +++---
 drivers/usb/dwc2/hcd.c   | 26 +-
 drivers/usb/dwc2/params.c|  2 +-
 7 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 42ac47f..e8708fd 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -125,17 +125,17 @@ static int dwc2_restore_global_registers(struct 
dwc2_hsotg *hsotg)
 }
 
 /**
- * dwc2_exit_hibernation() - Exit controller from Partial Power Down.
+ * dwc2_exit_partial_power_down() - Exit controller from Partial Power Down.
  *
  * @hsotg: Programming view of the DWC_otg controller
  * @restore: Controller registers need to be restored
  */
-int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
+int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 {
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.hibernation)
+   if (!hsotg->params.power_down)
return -ENOTSUPP;
 
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -179,16 +179,16 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool 
restore)
 }
 
 /**
- * dwc2_enter_hibernation() - Put controller in Partial Power Down.
+ * dwc2_enter_partial_power_down() - Put controller in Partial Power Down.
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
+int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 {
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.hibernation)
+   if (!hsotg->params.power_down)
return -ENOTSUPP;
 
/* Backup all registers */
@@ -217,7 +217,7 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
 
/*
 * Clear any pending interrupts since dwc2 will not be able to
-* clear them after entering hibernation.
+* clear them after entering partial_power_down.
 */
dwc2_writel(0x, hsotg->regs + GINTSTS);
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 67ca757..61c5e56 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -417,9 +417,9 @@ enum dwc2_ep0_state {
  *  case.
  *  0 - No (default)
  *  1 - Yes
- * @hibernation:   Specifies whether the controller support hibernation.
- * If hibernation is enabled, the controller will enter
- * hibernation in both peripheral and host mode when
+ * @power_down: Specifies whether the controller support power_down.
+ * If power_down is enabled, the controller will enter
+ * power_down in both peripheral and host mode when
  * needed.
  * 0 - No (default)
  * 1 - Yes
@@ -480,7 +480,7 @@ struct dwc2_core_params {
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
-   bool hibernation;
+   bool power_down;
bool activate_stm_fs_transceiver;
u16 max_packet_count;
u32 max_transfer_size;
@@ -1095,8 +1095,8 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
  * and the DWC_otg controller
  */
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
-int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
-int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
+int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg);
+int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore);
 
 void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index b8bcb00..0fb8cf6 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -320,10 +320,10 @@ static void dwc2_handle_session_req_intr(struct 
dwc2_hsotg *hsotg)
 
if (dwc2_is_device_mode(hsotg)) {
if (hsotg->lx_state == DWC2_L2) {
-   ret = dwc2_exit_hibernation(hsotg, true);
+   ret = dwc2_exit_partial_power_down(hsotg, true);
if (ret && (ret != -ENOTSUPP))
dev_err(hsotg->dev,
-   

[PATCH 02/15] usb: dwc2: Add hibernation field into dwc2_hw_params

2017-02-20 Thread Vardan Mikayelyan
Add parameter and it's initialization, needed for hibernation.

Reimplement dwc2_set_param_power_down() to support hibernation too.
Now 'power_down' parameter can be initialized with 0, 1 or 2.
0 - No
1 - Partial power down
2 - Hibernation

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |  2 +-
 drivers/usb/dwc2/core.h   | 12 ++--
 drivers/usb/dwc2/hcd.c|  4 ++--
 drivers/usb/dwc2/params.c | 34 ++
 4 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index e8708fd..fe976eb 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -135,7 +135,7 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, 
bool restore)
u32 pcgcctl;
int ret = 0;
 
-   if (!hsotg->params.power_down)
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
return -ENOTSUPP;
 
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 61c5e56..526d870 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -422,7 +422,8 @@ enum dwc2_ep0_state {
  * power_down in both peripheral and host mode when
  * needed.
  * 0 - No (default)
- * 1 - Yes
+ * 1 - Partial power down
+ * 2 - Hibernation
  * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO
  * register.
  * 0 - Deactivate the transceiver (default)
@@ -480,7 +481,12 @@ struct dwc2_core_params {
bool reload_ctl;
bool uframe_sched;
bool external_id_pin_ctl;
-   bool power_down;
+
+   int power_down;
+#define DWC2_POWER_DOWN_PARAM_NONE 0
+#define DWC2_POWER_DOWN_PARAM_PARTIAL  1
+#define DWC2_POWER_DOWN_PARAM_HIBERNATION  2
+
bool activate_stm_fs_transceiver;
u16 max_packet_count;
u32 max_transfer_size;
@@ -554,6 +560,7 @@ struct dwc2_core_params {
  *   2 - FS pins shared with UTMI+ pins
  *   3 - FS pins shared with ULPI pins
  * @total_fifo_size:Total internal RAM for FIFOs (bytes)
+ * @hibernationIs hibernation enabled?
  * @utmi_phy_data_width UTMI+ PHY data width
  *   0 - 8 bits
  *   1 - 16 bits
@@ -584,6 +591,7 @@ struct dwc2_hw_params {
unsigned num_dev_perio_in_ep:4;
unsigned total_fifo_size:16;
unsigned power_optimized:1;
+   unsigned hibernation:1;
unsigned utmi_phy_data_width:2;
u32 snpsid;
u32 dev_ep_dirs;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 604356c..53d580f 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4396,7 +4396,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
goto unlock;
 
-   if (!hsotg->params.power_down)
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
goto skip_power_saving;
 
/*
@@ -4448,7 +4448,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
if (hsotg->lx_state != DWC2_L2)
goto unlock;
 
-   if (!hsotg->params.power_down) {
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
hsotg->lx_state = DWC2_L0;
goto unlock;
}
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 38336e5..baa76bf 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -446,6 +446,38 @@ static void dwc2_check_param_phy_utmi_width(struct 
dwc2_hsotg *hsotg)
dwc2_set_param_phy_utmi_width(hsotg);
 }
 
+static void dwc2_check_param_power_down(struct dwc2_hsotg *hsotg)
+{
+   int param = hsotg->params.power_down;
+
+   switch (param) {
+   case DWC2_POWER_DOWN_PARAM_NONE:
+   break;
+   case DWC2_POWER_DOWN_PARAM_PARTIAL:
+   if (hsotg->hw_params.power_optimized)
+   break;
+   dev_dbg(hsotg->dev,
+   "Partial power down isn't supported by HW\n");
+   param = DWC2_POWER_DOWN_PARAM_NONE;
+   break;
+   case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+   if (hsotg->hw_params.hibernation)
+   break;
+   dev_dbg(hsotg->dev,
+   "Hibernation isn't supported by HW\n");
+   param = DWC2_POWER_DOWN_PARAM_NONE;
+   break;
+   default:
+   dev_err(hsotg->dev,
+   "%s: Invalid parameter power_down=%d\n",
+ 

[PATCH 10/15] usb: dwc2: Add dwc2_enter_hibernation(), dwc2_exit_hibernation()

2017-02-20 Thread Vardan Mikayelyan
These are wrapper functions which are calling device or host
enter/exit hibernation functions.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 38 ++
 drivers/usb/dwc2/core.h |  3 +++
 2 files changed, 41 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index a37dfc2..2c90d8e 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -446,6 +446,44 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg 
*hsotg)
 }
 
 /*
+ * dwc2_enter_hibernation() - Common function to enter hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @is_host: True if core is in host mode.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host)
+{
+   if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_HIBERNATION)
+   return -ENOTSUPP;
+
+   if (is_host)
+   return dwc2_host_enter_hibernation(hsotg);
+   else
+   return dwc2_gadget_enter_hibernation(hsotg);
+}
+
+/*
+ * dwc2_exit_hibernation() - Common function to exit from hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: Remote-wakeup, enabled in case of remote-wakeup.
+ * @reset: Enabled in case of restore with reset.
+ * @is_host: True if core is in host mode.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ int reset, int is_host)
+{
+   if (is_host)
+   return dwc2_host_exit_hibernation(hsotg, rem_wakeup, reset);
+   else
+   return dwc2_gadget_exit_hibernation(hsotg, rem_wakeup, reset);
+}
+
+/*
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
  */
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 9d17f4a..a3561e1 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1112,6 +1112,9 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
 int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
 int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg);
 int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore);
+int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg, int is_host);
+int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ int reset, int is_host);
 
 void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host);
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/15] usb: dwc2: Allow entering hibernation from USB_SUSPEND interrupt

2017-02-20 Thread Vardan Mikayelyan
Do changes to allow entering hibernated state from USB_SUSPEND
interrupt. All code is added under if conditions and mustn't impact
existing functionality.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 52 +++-
 1 file changed, 32 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 0fb8cf6..45c9b57 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -427,32 +427,44 @@ static void dwc2_handle_usb_suspend_intr(struct 
dwc2_hsotg *hsotg)
 * state is active
 */
dsts = dwc2_readl(hsotg->regs + DSTS);
-   dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
+   dev_dbg(hsotg->dev, "%s: DSTS=0x%0x\n", __func__, dsts);
dev_dbg(hsotg->dev,
-   "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
+   "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d 
HWCFG4.Hibernation=%d\n",
!!(dsts & DSTS_SUSPSTS),
-   hsotg->hw_params.power_optimized);
-   if ((dsts & DSTS_SUSPSTS) && hsotg->hw_params.power_optimized) {
-   /* Ignore suspend request before enumeration */
-   if (!dwc2_is_device_connected(hsotg)) {
-   dev_dbg(hsotg->dev,
-   "ignore suspend request before 
enumeration\n");
-   return;
+   hsotg->hw_params.power_optimized,
+   hsotg->hw_params.hibernation);
+
+   /* Ignore suspend request before enumeration */
+   if (!dwc2_is_device_connected(hsotg)) {
+   dev_dbg(hsotg->dev,
+   "ignore suspend request before enumeration\n");
+   return;
+   }
+   if (dsts & DSTS_SUSPSTS) {
+   if (hsotg->hw_params.power_optimized) {
+   ret = dwc2_enter_partial_power_down(hsotg);
+   if (ret) {
+   if (ret != -ENOTSUPP)
+   dev_err(hsotg->dev,
+   "%s: enter 
partial_power_down failed\n",
+   __func__);
+   goto skip_power_saving;
+   }
+
+   udelay(100);
+
+   /* Ask phy to be suspended */
+   if (!IS_ERR_OR_NULL(hsotg->uphy))
+   usb_phy_set_suspend(hsotg->uphy, true);
}
 
-   ret = dwc2_enter_partial_power_down(hsotg);
-   if (ret) {
-   if (ret != -ENOTSUPP)
+   if (hsotg->hw_params.hibernation) {
+   ret = dwc2_enter_hibernation(hsotg, 0);
+   if (ret && ret != -ENOTSUPP)
dev_err(hsotg->dev,
-   "enter power_down failed\n");
-   goto skip_power_saving;
+   "%s: enter hibernation 
failed\n",
+   __func__);
}
-
-   udelay(100);
-
-   /* Ask phy to be suspended */
-   if (!IS_ERR_OR_NULL(hsotg->uphy))
-   usb_phy_set_suspend(hsotg->uphy, true);
 skip_power_saving:
/*
 * Change to L2 (suspend) state before releasing
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/15] usb: dwc2: Add hibernation support.

2017-02-20 Thread Vardan Mikayelyan
The functions with name hibernation are misnamed originally. They were only
responsible for partial power down and not for hibernation.

This patch set adds the real hibernation support for dwc2 driver and renames
existing functions to power_down.xisting functions to power_down.


John Youn (1):
  usb: dwc2: Enable power down

Vardan Mikayelyan (14):
  usb: dwc2: Rename hibernation to partial_power_down
  usb: dwc2: Add hibernation field into dwc2_hw_params
  usb: dwc2: gadget: Moved dtxfsiz backup array place
  usb: dwc2: gadget: Fix dwc2_restore_device_registers
  usb: dwc2: core: Add hibernated flag
  usb: dwc2: gadget: Add remote_wakeup_allowed flag
  usb: dwc2: Changes in registers backup/restore functions
  usb: dwc2: Add helper functions for restore routine
  usb: dwc2: Add host/device hibernation functions
  usb: dwc2: Add dwc2_enter_hibernation(), dwc2_exit_hibernation()
  usb: dwc2: Allow entering hibernation from USB_SUSPEND interrupt
  usb: dwc2: Add dwc2_handle_gpwrdn_intr() handler
  usb: dwc2: Change hub-control to allow hibernation
  usb: dwc2: Replace msleep with mdelay in dwc2_clear_force_mode()

 drivers/usb/dwc2/core.c  | 212 +---
 drivers/usb/dwc2/core.h  |  68 +--
 drivers/usb/dwc2/core_intr.c | 172 ++
 drivers/usb/dwc2/debugfs.c   |   2 +-
 drivers/usb/dwc2/gadget.c| 226 +--
 drivers/usb/dwc2/hcd.c   | 279 ---
 drivers/usb/dwc2/params.c|  50 +++-
 drivers/usb/dwc2/platform.c  |   1 +
 8 files changed, 922 insertions(+), 88 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/15] usb: dwc2: gadget: Add remote_wakeup_allowed flag

2017-02-20 Thread Vardan Mikayelyan
It will be set once corresponding set_feature command comes.

True if device is allowed to wake-up host by remote-wakeup
signalling.

This is preparation for remote wake-up support implementation,
it will not be implemented until gadget stack provide interface
for bringing remote wake-up signalling.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h   | 3 +++
 drivers/usb/dwc2/gadget.c | 6 ++
 2 files changed, 9 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index d84d0ce..ace383f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -897,6 +897,8 @@ struct dwc2_hregs_backup {
  * @ctrl_req:   Request for EP0 control packets.
  * @ep0_state:  EP0 control transfers state
  * @test_mode:  USB test mode requested by the host
+ * @remote_wakeup_allowed: True if device is allowed to wake-up host by
+ *  remote-wakeup signalling
  * @setup_desc_dma:EP0 setup stage desc chain DMA address
  * @setup_desc:EP0 setup stage desc chain pointer
  * @ctrl_in_desc_dma:  EP0 IN data phase desc chain DMA address
@@ -1061,6 +1063,7 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
+   unsigned int remote_wakeup_allowed:1;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
 #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3b082ed..fd274a8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1665,6 +1665,10 @@ static int dwc2_hsotg_process_req_feature(struct 
dwc2_hsotg *hsotg,
switch (recip) {
case USB_RECIP_DEVICE:
switch (wValue) {
+   case USB_DEVICE_REMOTE_WAKEUP:
+   hsotg->remote_wakeup_allowed = 1;
+   break;
+
case USB_DEVICE_TEST_MODE:
if ((wIndex & 0xff) != 0)
return -EINVAL;
@@ -4626,6 +4630,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = _hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
+   hsotg->remote_wakeup_allowed = 0;
+
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/15] usb: dwc2: Changes in registers backup/restore functions

2017-02-20 Thread Vardan Mikayelyan
Move hptxfsiz to host register's backup/restore functions, not
needed to have it in global register's backup/restore functions.

Add backup for glpmcfg, and read/write for gi2cctl and pcgcctl.
As requires programming guide.

Affected functions:
dwc2_backup_host_registers()
dwc2_restore_host_registers()
dwc2_backup_global_registers()
dwc2_restore_global_registers()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 8 ++--
 drivers/usb/dwc2/core.h | 6 --
 drivers/usb/dwc2/hcd.c  | 2 ++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 185d24c..0e61511 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -78,8 +78,10 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
-   gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
+   gr->glpmcfg = dwc2_readl(hsotg->regs + GLPMCFG);
+   gr->gi2cctl = dwc2_readl(hsotg->regs + GI2CCTL);
+   gr->pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
gr->valid = true;
return 0;
@@ -114,8 +116,10 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
-   dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
+   dwc2_writel(gr->glpmcfg, hsotg->regs + GLPMCFG);
+   dwc2_writel(gr->pcgcctl, hsotg->regs + PCGCTL);
+   dwc2_writel(gr->gi2cctl, hsotg->regs + GI2CCTL);
 
return 0;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index ace383f..31ebdfa 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -610,7 +610,7 @@ struct dwc2_hw_params {
  * @grxfsiz:   Backup of GRXFSIZ register
  * @gnptxfsiz: Backup of GNPTXFSIZ register
  * @gi2cctl:   Backup of GI2CCTL register
- * @hptxfsiz:  Backup of HPTXFSIZ register
+ * @glpmcfg:   Backup of GLPMCFG register
  * @gdfifocfg: Backup of GDFIFOCFG register
  * @gpwrdn:Backup of GPWRDN register
  */
@@ -622,7 +622,7 @@ struct dwc2_gregs_backup {
u32 grxfsiz;
u32 gnptxfsiz;
u32 gi2cctl;
-   u32 hptxfsiz;
+   u32 glpmcfg;
u32 pcgcctl;
u32 gdfifocfg;
u32 gpwrdn;
@@ -669,6 +669,7 @@ struct dwc2_dregs_backup {
  * @hcintmsk:  Backup of HCINTMSK register
  * @hptr0: Backup of HPTR0 register
  * @hfir:  Backup of HFIR register
+ * @hptxfsiz:  Backup of HPTXFSIZ register
  */
 struct dwc2_hregs_backup {
u32 hcfg;
@@ -676,6 +677,7 @@ struct dwc2_hregs_backup {
u32 hcintmsk[MAX_EPS_CHANNELS];
u32 hprt0;
u32 hfir;
+   u32 hptxfsiz;
bool valid;
 };
 
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 53d580f..e8adfeb 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5346,6 +5346,7 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
 
hr->hprt0 = dwc2_read_hprt0(hsotg);
hr->hfir = dwc2_readl(hsotg->regs + HFIR);
+   hr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
hr->valid = true;
 
return 0;
@@ -5382,6 +5383,7 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
 
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+   dwc2_writel(hr->hptxfsiz, hsotg->regs + HPTXFSIZ);
hsotg->frame_number = 0;
 
return 0;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/15] usb: dwc2: Add helper functions for restore routine

2017-02-20 Thread Vardan Mikayelyan
Add common (host/device) helper functions, which will be called while
exiting from hibernation, from both sides.

dwc2_restore_essential_regs()
dwc2_hib_restore_common()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c | 136 
 drivers/usb/dwc2/core.h |   2 +
 2 files changed, 138 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 0e61511..f478cdd 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -239,6 +239,142 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg 
*hsotg)
 }
 
 /**
+ * dwc2_restore_essential_regs() - Restore essiential regs of core.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rmode: Restore mode, enabled in case of remote-wakeup.
+ */
+static void dwc2_restore_essential_regs(struct dwc2_hsotg *hsotg, int rmode)
+{
+   u32 pcgcctl;
+   struct dwc2_gregs_backup *gr;
+   struct dwc2_dregs_backup *dr;
+   struct dwc2_hregs_backup *hr;
+   int is_host = dwc2_is_host_mode(hsotg);
+
+   gr = >gr_backup;
+   dr = >dr_backup;
+   hr = >hr_backup;
+
+   dev_dbg(hsotg->dev, "%s: restoring essential regs\n", __func__);
+
+   /* Load restore values for [31:14] bits */
+   pcgcctl = (gr->pcgcctl & 0xc000) | 0x0002;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+
+   /* Umnask global Interrupt in GAHBCFG and restore it */
+   dwc2_writel(gr->gahbcfg | GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
+
+   /* Clear all pending interupts */
+   dwc2_writel(0x, hsotg->regs + GINTSTS);
+
+   /* Unmask restore done interrupt */
+   dwc2_writel(GINTSTS_RESTOREDONE, hsotg->regs + GINTMSK);
+
+   /* Restore GUSBCFG and HCFG/DCFG */
+   dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
+
+   if (is_host) {
+   dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
+   if (rmode)
+   pcgcctl |= 0x200;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+
+   pcgcctl = (gr->pcgcctl & 0xc000) | 0x0002;
+   pcgcctl |= PCGCTL_ESS_REG_RESTORED;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   } else {
+   dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
+   if (!rmode)
+   pcgcctl |= 0x208;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+
+   pcgcctl |= PCGCTL_ESS_REG_RESTORED;
+   dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   }
+}
+
+/**
+ * dwc2_hib_restore_common() - Common part of restore routine.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: Remote-wakeup, enabled in case of remote-wakeup.
+ */
+void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup)
+{
+   u32 gpwrdn;
+   u32 gintsts;
+   int timeout;
+   int is_host = dwc2_is_host_mode(hsotg);
+
+   /* Switch-on voltage to the core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNSWTCH;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Reset core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Enable restore from PMU */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn |= GPWRDN_RESTORE;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable Power Down Clamp */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PWRDNCLMP;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   if (!is_host && rem_wakeup)
+   udelay(70);
+
+   /* Deassert reset core */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn |= GPWRDN_PWRDNRSTN;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+   udelay(10);
+
+   /* Disable PMU interrupt */
+   gpwrdn = dwc2_readl(hsotg->regs + GPWRDN);
+   gpwrdn &= ~GPWRDN_PMUINTSEL;
+   dwc2_writel(gpwrdn, hsotg->regs + GPWRDN);
+
+   /* Set Restore Essential Regs bit in PCGCCTL register */
+   dwc2_restore_essential_regs(hsotg, rem_wakeup);
+
+   /*
+* Wait For Restore_done Interrupt. This mechanism of polling the
+* interrupt is introduced to avoid any possible race conditions
+*/
+   timeout = 2000;
+   do {
+   gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+   if (!(gintsts & GINTSTS_RESTOREDONE)) {
+   udelay

[PATCH 05/15] usb: dwc2: core: Add hibernated flag

2017-02-20 Thread Vardan Mikayelyan
True if core is hibernated.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h | 2 ++
 drivers/usb/dwc2/platform.c | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 60ad2e6..d84d0ce 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -779,6 +779,7 @@ struct dwc2_hregs_backup {
  * @hcd_enabledHost mode sub-driver initialization indicator.
  * @gadget_enabled Peripheral mode sub-driver initialization indicator.
  * @ll_hw_enabled  Status of low-level hardware resources.
+ * @hibernated:True if core is hibernated
  * @phy:The otg phy transceiver structure for phy control.
  * @uphy:   The otg phy transceiver structure for old USB phy
  *  control.
@@ -916,6 +917,7 @@ struct dwc2_hsotg {
unsigned int hcd_enabled:1;
unsigned int gadget_enabled:1;
unsigned int ll_hw_enabled:1;
+   unsigned int hibernated:1;
 
struct phy *phy;
struct usb_phy *uphy;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index db98463..c4e365a 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -462,6 +462,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
}
 
platform_set_drvdata(dev, hsotg);
+   hsotg->hibernated = 0;
 
dwc2_debugfs_init(hsotg);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/15] usb: dwc2: Add host/device hibernation functions

2017-02-20 Thread Vardan Mikayelyan
Add host/device hibernation functions which must be wrapped
by core's  dwc2_enter_hibernation()/dwc2_exit_hibernation()
functions.

Make dwc2_backup_global_registers dwc2_restore_global_register
non-static to use them in both host/gadget sides.

Added function names:
dwc2_gadget_enter_hibernation()
dwc2_gadget_exit_hibernation()
dwc2_host_enter_hibernation()
dwc2_host_exit_hibernation()

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   |   4 +-
 drivers/usb/dwc2/core.h   |  18 
 drivers/usb/dwc2/gadget.c | 196 ++
 drivers/usb/dwc2/hcd.c| 233 ++
 4 files changed, 449 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f478cdd..a37dfc2 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -63,7 +63,7 @@
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
+int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
 
@@ -94,7 +94,7 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
  *
  * @hsotg: Programming view of the DWC_otg controller
  */
-static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
+int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 950915b..9d17f4a 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1131,6 +1131,8 @@ static inline bool dwc2_is_hs_iot(struct dwc2_hsotg 
*hsotg)
 void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
 
 void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup);
+int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg);
+int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg);
 
 /* This function should be called on every hardware interrupt. */
 irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
@@ -1193,6 +1195,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*dwc2,
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup);
+int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg);
+int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
+int rem_wakeup, int reset);
 int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
 int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
@@ -1218,6 +1223,11 @@ static inline int dwc2_backup_device_registers(struct 
dwc2_hsotg *hsotg)
 static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg,
int remote_wakeup)
 { return 0; }
+static inline int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
+  int rem_wakeup, int reset)
+{ return 0; }
 static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
@@ -1234,6 +1244,9 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct 
dwc2_hsotg *hsotg)
 void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
 int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
+int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);
+int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
+  int rem_wakeup, int reset);
 #else
 static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
 { return 0; }
@@ -1250,6 +1263,11 @@ static inline int dwc2_backup_host_registers(struct 
dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
+static inline int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
+int rem_wakeup, int reset)
+{ return 0; }
 
 #endif
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index fd274a8..e82e1db 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4870,3 +4870,199 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg, int remote_wakeup)
 
return 0;
 }
+
+/**
+ * dwc2_gadget_enter_hibernation() - Put controller in Hibernation.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ *
+ * Return non-zero if failed to enter to hibernation.
+ */
+int dwc2_gadget_enter_hibernation(struct dw

[PATCH 03/15] usb: dwc2: gadget: Moved dtxfsiz backup array place

2017-02-20 Thread Vardan Mikayelyan
Moved dtxfsiz from dwc2_gregs_backup to dwc2_dregs_backup,
because it is device register.

Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.c   | 8 ++--
 drivers/usb/dwc2/core.h   | 4 ++--
 drivers/usb/dwc2/gadget.c | 2 ++
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fe976eb..7addf69 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -66,7 +66,8 @@
 static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
-   int i;
+
+   dev_dbg(hsotg->dev, "%s\n", __func__);
 
/* Backup global regs */
gr = >gr_backup;
@@ -79,8 +80,6 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
-   for (i = 0; i < MAX_EPS_CHANNELS; i++)
-   gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
 
gr->valid = true;
return 0;
@@ -96,7 +95,6 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg 
*hsotg)
 static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
 {
struct dwc2_gregs_backup *gr;
-   int i;
 
dev_dbg(hsotg->dev, "%s\n", __func__);
 
@@ -118,8 +116,6 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
-   for (i = 0; i < MAX_EPS_CHANNELS; i++)
-   dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
 
return 0;
 }
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 526d870..4cb95b3 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -612,7 +612,6 @@ struct dwc2_hw_params {
  * @gi2cctl:   Backup of GI2CCTL register
  * @hptxfsiz:  Backup of HPTXFSIZ register
  * @gdfifocfg: Backup of GDFIFOCFG register
- * @dtxfsiz:   Backup of DTXFSIZ registers for each endpoint
  * @gpwrdn:Backup of GPWRDN register
  */
 struct dwc2_gregs_backup {
@@ -626,7 +625,6 @@ struct dwc2_gregs_backup {
u32 hptxfsiz;
u32 pcgcctl;
u32 gdfifocfg;
-   u32 dtxfsiz[MAX_EPS_CHANNELS];
u32 gpwrdn;
bool valid;
 };
@@ -645,6 +643,7 @@ struct dwc2_gregs_backup {
  * @doepctl:   Backup of DOEPCTL register
  * @doeptsiz:  Backup of DOEPTSIZ register
  * @doepdma:   Backup of DOEPDMA register
+ * @dtxfsiz:   Backup of DTXFSIZ registers for each endpoint
  */
 struct dwc2_dregs_backup {
u32 dcfg;
@@ -658,6 +657,7 @@ struct dwc2_dregs_backup {
u32 doepctl[MAX_EPS_CHANNELS];
u32 doeptsiz[MAX_EPS_CHANNELS];
u32 doepdma[MAX_EPS_CHANNELS];
+   u32 dtxfsiz[MAX_EPS_CHANNELS];
bool valid;
 };
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 4bd3cab..3e969a5 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4810,6 +4810,7 @@ int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
 
dr->doeptsiz[i] = dwc2_readl(hsotg->regs + DOEPTSIZ(i));
dr->doepdma[i] = dwc2_readl(hsotg->regs + DOEPDMA(i));
+   dr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
}
dr->valid = true;
return 0;
@@ -4850,6 +4851,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg 
*hsotg)
dwc2_writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
dwc2_writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
dwc2_writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
+   dwc2_writel(dr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
 
/* Restore OUT EPs */
dwc2_writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] usb: dwc2: pci: Fix error handling in dwc2_pci_probe

2017-02-17 Thread Vardan Mikayelyan
Move usb_phy_generic_register() function call to the top, to simplify
error handling.

Replace kzalloc() with devm_kzalloc().

After platform_device_add(), if we error out, we must do
platform_device_unregister(), which also does the put. So lets move
devm_kzalloc() to simplify error handling and avoid
calling of platform_device_unregister().

Reviewed-by: Wei Yongjun <weiyongj...@huawei.com>
Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
Changes in v2:
 - Remove kfree(glue) as suggested Janusz Dziedzic.

 drivers/usb/dwc2/pci.c | 27 +--
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index fdeb8c7..70b0b9c 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -82,7 +82,6 @@ static void dwc2_pci_remove(struct pci_dev *pci)
 
platform_device_unregister(glue->dwc2);
usb_phy_generic_unregister(glue->phy);
-   kfree(glue);
pci_set_drvdata(pci, NULL);
 }
 
@@ -104,10 +103,17 @@ static int dwc2_pci_probe(struct pci_dev *pci,
 
pci_set_master(pci);
 
+   phy = usb_phy_generic_register();
+   if (IS_ERR(phy)) {
+   dev_err(dev, "error registering generic PHY (%ld)\n",
+   PTR_ERR(phy));
+   return PTR_ERR(phy);
+   }
+
dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
if (!dwc2) {
dev_err(dev, "couldn't allocate dwc2 device\n");
-   return -ENOMEM;
+   goto err;
}
 
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -124,32 +130,25 @@ static int dwc2_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
if (ret) {
dev_err(dev, "couldn't add resources to dwc2 device\n");
-   return ret;
+   goto err;
}
 
dwc2->dev.parent = dev;
 
-   phy = usb_phy_generic_register();
-   if (IS_ERR(phy)) {
-   dev_err(dev, "error registering generic PHY (%ld)\n",
-   PTR_ERR(phy));
-   return PTR_ERR(phy);
-   }
-
ret = dwc2_pci_quirks(pci, dwc2);
if (ret)
goto err;
 
+   glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
+   if (!glue)
+   goto err;
+
ret = platform_device_add(dwc2);
if (ret) {
dev_err(dev, "failed to register dwc2 device\n");
goto err;
}
 
-   glue = kzalloc(sizeof(*glue), GFP_KERNEL);
-   if (!glue)
-   return -ENOMEM;
-
glue->phy = phy;
glue->dwc2 = dwc2;
pci_set_drvdata(pci, glue);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] usb: dwc2: pci: Fix error handling in dwc2_pci_probe

2017-02-17 Thread Vardan Mikayelyan
Move usb_phy_generic_register() function call to the top, to simplify
error handling.

Replace kzalloc() with devm_kzalloc().

After platform_device_add(), if we error out, we must do
platform_device_unregister(), which also does the put. So lets move
devm_kzalloc() to simplify error handling and avoid
calling of platform_device_unregister().

Reviewed-by: Wei Yongjun <weiyongj...@huawei.com>
Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>
---
 drivers/usb/dwc2/pci.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index fdeb8c7..7696131 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -104,10 +104,17 @@ static int dwc2_pci_probe(struct pci_dev *pci,
 
pci_set_master(pci);
 
+   phy = usb_phy_generic_register();
+   if (IS_ERR(phy)) {
+   dev_err(dev, "error registering generic PHY (%ld)\n",
+   PTR_ERR(phy));
+   return PTR_ERR(phy);
+   }
+
dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
if (!dwc2) {
dev_err(dev, "couldn't allocate dwc2 device\n");
-   return -ENOMEM;
+   goto err;
}
 
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -124,32 +131,25 @@ static int dwc2_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
if (ret) {
dev_err(dev, "couldn't add resources to dwc2 device\n");
-   return ret;
+   goto err;
}
 
dwc2->dev.parent = dev;
 
-   phy = usb_phy_generic_register();
-   if (IS_ERR(phy)) {
-   dev_err(dev, "error registering generic PHY (%ld)\n",
-   PTR_ERR(phy));
-   return PTR_ERR(phy);
-   }
-
ret = dwc2_pci_quirks(pci, dwc2);
if (ret)
goto err;
 
+   glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
+   if (!glue)
+   goto err;
+
ret = platform_device_add(dwc2);
if (ret) {
dev_err(dev, "failed to register dwc2 device\n");
goto err;
}
 
-   glue = kzalloc(sizeof(*glue), GFP_KERNEL);
-   if (!glue)
-   return -ENOMEM;
-
glue->phy = phy;
glue->dwc2 = dwc2;
pci_set_drvdata(pci, glue);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH -next] usb: dwc2: Fix the error handling of dwc2_pci_probe()

2017-02-13 Thread Vardan Mikayelyan
On 2/7/2017 7:54 PM, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongj...@huawei.com>
>
> Fix the error handling of dwc2_pci_probe() to avoid resources leak.
>
> Signed-off-by: Wei Yongjun <weiyongj...@huawei.com>
> ---
>  drivers/usb/dwc2/pci.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
> index fdeb8c7..58fc1bf 100644
> --- a/drivers/usb/dwc2/pci.c
> +++ b/drivers/usb/dwc2/pci.c
> @@ -124,7 +124,7 @@ static int dwc2_pci_probe(struct pci_dev *pci,
>   ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
>   if (ret) {
>   dev_err(dev, "couldn't add resources to dwc2 device\n");
> - return ret;
> + goto err_device_put;
>   }
>
>   dwc2->dev.parent = dev;
> @@ -133,30 +133,37 @@ static int dwc2_pci_probe(struct pci_dev *pci,
>   if (IS_ERR(phy)) {
>   dev_err(dev, "error registering generic PHY (%ld)\n",
>   PTR_ERR(phy));
> - return PTR_ERR(phy);
> + ret = PTR_ERR(phy);
> + goto err_device_put;
>   }
>
>   ret = dwc2_pci_quirks(pci, dwc2);
>   if (ret)
> - goto err;
> + goto err_unregister;
>
>   ret = platform_device_add(dwc2);
>   if (ret) {
>   dev_err(dev, "failed to register dwc2 device\n");
> - goto err;
> + goto err_unregister;
>   }
>
>   glue = kzalloc(sizeof(*glue), GFP_KERNEL);
> - if (!glue)
> - return -ENOMEM;
> + if (!glue) {
> + ret = -ENOMEM;
> + goto err_device_del;
> + }
>
>   glue->phy = phy;
>   glue->dwc2 = dwc2;
>   pci_set_drvdata(pci, glue);
>
>   return 0;
> -err:
> +
> +err_device_del:
> + platform_device_del(dwc2);
> +err_unregister:
>   usb_phy_generic_unregister(phy);
> +err_device_put:
>   platform_device_put(dwc2);
>   return ret;
>  }
>
> --

Hi Wei Yongjun,

We have patch doing the same in our internal branch, please review it 
below. We will send it out after internal review/testing process.

usb: dwc2: pci: Fix error handling in dwc2_pci_probe

Move usb_phy_generic_register() function call to the top, to simplify
error handling.

Replace kzalloc() with devm_kzalloc().

After platform_device_add(), if we error out, we must do
platform_device_unregister(), which also does the put. So lets move
devm_kzalloc() to simplify error handling and avoid
calling of platform_device_unregister().

Change-Id: Ic183ee233f5dc622e9e6126c1bfd4890baee1f76
Signed-off-by: Vardan Mikayelyan <mvar...@synopsys.com>

diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index fdeb8c7..7696131 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -104,10 +104,17 @@ static int dwc2_pci_probe(struct pci_dev *pci,

 pci_set_master(pci);

+   phy = usb_phy_generic_register();
+   if (IS_ERR(phy)) {
+   dev_err(dev, "error registering generic PHY (%ld)\n",
+   PTR_ERR(phy));
+   return PTR_ERR(phy);
+   }
+
 dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
 if (!dwc2) {
 dev_err(dev, "couldn't allocate dwc2 device\n");
-   return -ENOMEM;
+   goto err;
 }

 memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -124,32 +131,25 @@ static int dwc2_pci_probe(struct pci_dev *pci,
 ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
 if (ret) {
 dev_err(dev, "couldn't add resources to dwc2 device\n");
-   return ret;
+   goto err;
 }

 dwc2->dev.parent = dev;

-   phy = usb_phy_generic_register();
-   if (IS_ERR(phy)) {
-   dev_err(dev, "error registering generic PHY (%ld)\n",
-   PTR_ERR(phy));
-   return PTR_ERR(phy);
-   }
-
 ret = dwc2_pci_quirks(pci, dwc2);
 if (ret)
 goto err;

+   glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
+   if (!glue)
+   goto err;
+
 ret = platform_device_add(dwc2);
 if (ret) {
 dev_err(dev, "failed to register dwc2 device\n");
 goto err;
 }

-   glue = kzalloc(sizeof(*glue), GFP_KERNEL);
-   if (!glue)
-   return -ENOMEM;
-
 glue->phy = phy;


Thanks,
Vardan.



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [REGRESSION] dwc2: 5f54c54b0ba8 Add DDMA chain pointers to dwc2_hsotg_ep structure

2016-12-14 Thread Vardan Mikayelyan
On 12/14/2016 6:25 AM, John Stultz wrote:
> On Tue, Dec 13, 2016 at 3:51 PM, John Youn  wrote:
>> On 12/13/2016 3:23 PM, John Stultz wrote:
>>> I've found trying to boot Linus' HEAD today on HiKey, I'm hitting the
>>> following WARNINGS/panics, which I bisected down to being introduced
>>> with 5f54c54b0ba8 ("Add DDMA chain pointers to dwc2_hsotg_ep
>>> structure").
>>>
>>> It seems the issue is calling dma_alloc_coherent() in
>>> dwc2_hsotg_ep_enable() isn't safe, as we may get there from irq
>>> context with irqs off.
>>>
>>> Any thoughts on a fix?
>>>
>>
>> Hi John,
>>
>> Check this:
>> http://marc.info/?l=linux-usb=148058361526211=2
>
> So digging further here, it seems that patch addresses the allocation
> side, but I'm also seeing warnings on the free side, as irqs are
> disabled in dwc2_hsotg_vbus_session() before calling
> dwc2_hsotg_disconnect().
>
> (Note that this is triggered using the extcon patch I have, but the
> problematic logic seems to be pre-existing).
>
> thanks
> -john

Hi John Stultz,

Related to free side, we have fix which will be submitted after internal 
review and testing. You'll see it here soon.

Thanks,
Vardan.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong

2016-12-13 Thread Vardan Mikayelyan
On 12/13/2016 11:12 AM, John Stultz wrote:
> When removing a USB-A to USB-otg adapter cable, we get a change
> status irq, and then in dwc2_conn_id_status_change, we
> erroniously see the GOTGCTL_CONID_B flag set. This causes us to
> get  stuck in the "while (!dwc2_is_device_mode(hsotg))" loop,
> spitting out "Waiting for Peripheral Mode, Mode=Host" warnings
> until it fails out many seconds later.
>
> This patch works around the issue by re-reading the GOTGCTL
> state to check if the GOTGCTL_CONID_B is still set and if not
> restarting the change status logic.
>
> I suspect this isn't the best solution, but it seems to work
> well for me.
>
> Feedback would be greatly appreciated!
>
> Cc: Wei Xu <xuw...@hisilicon.com>
> Cc: Guodong Xu <guodong...@linaro.org>
> Cc: Amit Pundir <amit.pun...@linaro.org>
> Cc: Rob Herring <robh...@kernel.org>
> Cc: John Youn <johny...@synopsys.com>
> Cc: Douglas Anderson <diand...@chromium.org>
> Cc: Chen Yu <cheny...@huawei.com>
> Cc: Kishon Vijay Abraham I <kis...@ti.com>
> Cc: Felipe Balbi <felipe.ba...@linux.intel.com>
> Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
> Cc: linux-usb@vger.kernel.org
> Acked-by: John Youn <johny...@synopsys.com>
> Signed-off-by: John Stultz <john.stu...@linaro.org>
> ---
>  drivers/usb/dwc2/hcd.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index df5a065..a3f34dd 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3199,7 +3199,7 @@ static void dwc2_conn_id_status_change(struct 
> work_struct *work)
>   dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
>   dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
>   !!(gotgctl & GOTGCTL_CONID_B));
> -
> +again:
>   /* B-Device connector (Device Mode) */
>   if (gotgctl & GOTGCTL_CONID_B) {
>   /* Wait for switch to device mode */
> @@ -3210,6 +3210,9 @@ static void dwc2_conn_id_status_change(struct 
> work_struct *work)
>dwc2_is_host_mode(hsotg) ? "Host" :
>"Peripheral");
>   usleep_range(2, 4);
> + gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
> + if (!(gotgctl & GOTGCTL_CONID_B))
> + goto again;
>   if (++count > 250)
>   break;
>   }
>
Hi John Stultz,

When it goes to ":again", it will go to else anyways. I'll suggest 
alternative way to do this. Please see below.

Also you can add "Reviewed-by: Vardan Mikayelyan <mvar...@synopsys.com>"

Thanks,
Vardan.

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b7311a6..128311b 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3242,6 +3242,9 @@ static void dwc2_conn_id_status_change(struct 
work_struct *work)
  dwc2_is_host_mode(hsotg) ? "Host" :
  "Peripheral");
 usleep_range(2, 4);
+   gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+   if (!(gotgctl & GOTGCTL_CONID_B))
+   goto host;
 if (++count > 250)
 break;
 }
@@ -3256,6 +3259,7 @@ static void dwc2_conn_id_status_change(struct 
work_struct *work)
 spin_unlock_irqrestore(>lock, flags);
 dwc2_hsotg_core_connect(hsotg);
 } else {
+host:
 /* A-Device connector (Host Mode) */
 dev_dbg(hsotg->dev, "connId A\n");
 while (!dwc2_is_host_mode(hsotg)) {

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html