summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2/gadget.c
diff options
context:
space:
mode:
authorArtur Petrosyan <Arthur.Petrosyan@synopsys.com>2021-04-13 11:36:07 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-13 12:25:11 +0200
commit012466fc8ccc013f9a3320428043e096dc581b36 (patch)
tree6a4d7659dea8ac64db7b51801a9cc45abb5c5f10 /drivers/usb/dwc2/gadget.c
parent5367f82a212305c35b35303a8a21ca348f653ca3 (diff)
usb: dwc2: Add device clock gating support functions
Added device clock gating support functions according programming guide. Moved "bus_suspended" flag to "dwc2_hsotg" struct because we need to set that flag while entering to clock gating in case when the driver is built in peripheral mode. Added function names: dwc2_gadget_enter_clock_gating() dwc2_gadget_exit_clock_gating() Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com> Link: https://lore.kernel.org/r/20210413073607.F41E8A0094@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r--drivers/usb/dwc2/gadget.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index e08baee4987b..2f50f3e62caa 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5483,3 +5483,74 @@ int dwc2_gadget_exit_partial_power_down(struct dwc2_hsotg *hsotg,
dev_dbg(hsotg->dev, "Exiting device partial Power Down completed.\n");
return ret;
}
+
+/**
+ * dwc2_gadget_enter_clock_gating() - Put controller in clock gating.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ *
+ * Return: non-zero if failed to enter device partial power down.
+ *
+ * This function is for entering device mode clock gating.
+ */
+void dwc2_gadget_enter_clock_gating(struct dwc2_hsotg *hsotg)
+{
+ u32 pcgctl;
+
+ dev_dbg(hsotg->dev, "Entering device clock gating.\n");
+
+ /* Set the Phy Clock bit as suspend is received. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl |= PCGCTL_STOPPCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+
+ /* Set the Gate hclk as suspend is received. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl |= PCGCTL_GATEHCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+
+ hsotg->lx_state = DWC2_L2;
+ hsotg->bus_suspended = true;
+}
+
+/*
+ * dwc2_gadget_exit_clock_gating() - Exit controller from device clock gating.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @rem_wakeup: indicates whether remote wake up is enabled.
+ *
+ * This function is for exiting from device mode clock gating.
+ */
+void dwc2_gadget_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup)
+{
+ u32 pcgctl;
+ u32 dctl;
+
+ dev_dbg(hsotg->dev, "Exiting device clock gating.\n");
+
+ /* Clear the Gate hclk. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl &= ~PCGCTL_GATEHCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+
+ /* Phy Clock bit. */
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl &= ~PCGCTL_STOPPCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ udelay(5);
+
+ if (rem_wakeup) {
+ /* Set Remote Wakeup Signaling */
+ dctl = dwc2_readl(hsotg, DCTL);
+ dctl |= DCTL_RMTWKUPSIG;
+ dwc2_writel(hsotg, dctl, DCTL);
+ }
+
+ /* Change to L0 state */
+ call_gadget(hsotg, resume);
+ hsotg->lx_state = DWC2_L0;
+ hsotg->bus_suspended = false;
+}