From: Minas Harutyunyan Date: Wed, 13 Mar 2024 09:19:42 +0000 (+0000) Subject: usb: dwc2: Add eUSB2 PHY disconnect flow support X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=7fd22e5bcaa5b1224fe3fb2196c26f1a14e843ff;p=linux.git usb: dwc2: Add eUSB2 PHY disconnect flow support To support eUSB2 PHY disconnect flow required in Soft disconnect state set GOTGCTL_EUSB2_DISC_SUPP bit, if applicable. On Session End Detected interrupt clear PCGCTL_GATEHCLK and PCGCTL_STOPPCLK bits if eusb2_disc parameter true. Signed-off-by: Minas Harutyunyan Link: https://lore.kernel.org/r/9d50b83df693cda8c391313e90048df8dd611c04.1708948356.git.Minas.Harutyunyan@synopsys.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 158ede7538548..bb6bb771375ae 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -84,6 +84,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) u32 gotgint; u32 gotgctl; u32 gintmsk; + u32 pcgctl; gotgint = dwc2_readl(hsotg, GOTGINT); gotgctl = dwc2_readl(hsotg, GOTGCTL); @@ -96,8 +97,22 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) dwc2_op_state_str(hsotg)); gotgctl = dwc2_readl(hsotg, GOTGCTL); - if (dwc2_is_device_mode(hsotg)) + if (dwc2_is_device_mode(hsotg)) { + if (hsotg->params.eusb2_disc) { + /* Clear the Gate hclk. */ + pcgctl = dwc2_readl(hsotg, PCGCTL); + pcgctl &= ~PCGCTL_GATEHCLK; + dwc2_writel(hsotg, pcgctl, PCGCTL); + udelay(5); + + /* Clear Phy Clock bit. */ + pcgctl = dwc2_readl(hsotg, PCGCTL); + pcgctl &= ~PCGCTL_STOPPCLK; + dwc2_writel(hsotg, pcgctl, PCGCTL); + udelay(5); + } dwc2_hsotg_disconnect(hsotg); + } if (hsotg->op_state == OTG_STATE_B_HOST) { hsotg->op_state = OTG_STATE_B_PERIPHERAL; @@ -117,7 +132,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) * disconnected */ /* Reset to a clean state */ - hsotg->lx_state = DWC2_L0; + hsotg->lx_state = DWC2_L3; } gotgctl = dwc2_readl(hsotg, GOTGCTL); @@ -286,7 +301,7 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) hsotg->lx_state); if (dwc2_is_device_mode(hsotg)) { - if (hsotg->lx_state == DWC2_L2) { + if (hsotg->lx_state != DWC2_L0) { if (hsotg->in_ppd) { ret = dwc2_exit_partial_power_down(hsotg, 0, true); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index b517a7216de22..680737d471c12 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3420,8 +3420,11 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, dwc2_hsotg_init_fifo(hsotg); - if (!is_usb_reset) + if (!is_usb_reset) { dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON); + if (hsotg->params.eusb2_disc) + dwc2_set_bit(hsotg, GOTGCTL, GOTGCTL_EUSB2_DISC_SUPP); + } dcfg |= DCFG_EPMISCNT(1);