usb: dwc2: gadget: Configure the core to enable LPM
authorSevak Arakelyan <sevaka@synopsys.com>
Wed, 24 Jan 2018 13:43:32 +0000 (17:43 +0400)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 13 Mar 2018 08:47:49 +0000 (10:47 +0200)
Configure core in device mode to support LPM according to
programming guide.
Device will start giving valid responses for LPM tokens.
After this patch device side LPM will start working.

Signed-off-by: Sevak Arakelyan <sevaka@synopsys.com>
Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc2/core.h
drivers/usb/dwc2/core_intr.c
drivers/usb/dwc2/gadget.c

index bd6672b8c2ffb3bf315dcafce315877dad6aabf7..96799a399393b7919ce6271a53bf57949b06e185 100644 (file)
@@ -1209,6 +1209,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);
 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);
+void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
 #else
 static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
 { return 0; }
@@ -1236,6 +1237,7 @@ static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
 { return 0; }
+static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
index 23599e798e24acb540a21e5eccfb1a901dc2c0c9..a8e43948f807d99ae40043f23d9a1fed70d9398f 100644 (file)
@@ -372,6 +372,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
                        dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
                        return;
                }
+               dwc2_gadget_init_lpm(hsotg);
        } else {
                /* TODO */
                dev_err(hsotg->dev, "Host side LPM is not supported.\n");
index ddfe6a94a12ab4e0c0ccf79804be79ea55ac634b..706fecf16b52c5bafb5cf58916009ed31a0b6ba1 100644 (file)
@@ -3372,6 +3372,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
                val |= DCTL_SFTDISCON;
        dwc2_set_bit(hsotg->regs + DCTL, val);
 
+       /* configure the core to support LPM */
+       dwc2_gadget_init_lpm(hsotg);
+
        /* must be at-least 3ms to allow bus to see disconnect */
        mdelay(3);
 
@@ -4862,3 +4865,26 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
 
        return 0;
 }
+
+/**
+ * dwc2_gadget_init_lpm - Configure the core to support LPM in device mode
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ */
+void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg)
+{
+       u32 val;
+
+       if (!hsotg->params.lpm)
+               return;
+
+       val = GLPMCFG_LPMCAP | GLPMCFG_APPL1RES;
+       val |= hsotg->params.hird_threshold_en ? GLPMCFG_HIRD_THRES_EN : 0;
+       val |= hsotg->params.lpm_clock_gating ? GLPMCFG_ENBLSLPM : 0;
+       val |= hsotg->params.hird_threshold << GLPMCFG_HIRD_THRES_SHIFT;
+       val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0;
+       dwc2_writel(val, hsotg->regs + GLPMCFG);
+       dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg->regs
+               + GLPMCFG));
+}