From f4e8e5648dea68906a2d0430657088d98790184a Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Fri, 5 May 2023 12:00:44 +0200 Subject: usb: chipidea: remove broken suspend/resume downstream code The suspend/resume code is broken for i.MX 8 CPUs. When waking up from suspend it might happen that devices are not recognized anymore. To reproduce do: root@apalis-imx8-07107223:~# lsusb -t /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ci_hdrc/1p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M |__ Port 1: Dev 4, If 0, Class=Wireless, Driver=btusb, 480M |__ Port 1: Dev 4, If 1, Class=Wireless, Driver=btusb, 480M |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M root@apalis-imx8-12345678:~# rtcwake -s 1 -m mem -d rtc1 root@apalis-imx8-07107223:~# lsusb -t /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ci_hdrc/1p, 480M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M We remove this broken code to replace it with the upstream code for suspend and resume. Upstream-Status: Inappropriate [other] This is an issue of the downstream driver. We replace the broken suspend/resume with the upstream solution. Signed-off-by: Stefan Eichenberger --- drivers/usb/chipidea/host.c | 85 --------------------------------------------- 1 file changed, 85 deletions(-) diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 212adb132fdf..f70c77db45dc 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -498,89 +498,6 @@ static void ci_hdrc_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) ci_hdrc_free_dma_aligned_buffer(urb); } -static void ci_hdrc_host_save_for_power_lost(struct ci_hdrc *ci) -{ - struct ehci_hcd *ehci; - - if (!ci->hcd) - return; - - ehci = hcd_to_ehci(ci->hcd); - /* save EHCI registers */ - ci->pm_usbmode = ehci_readl(ehci, &ehci->regs->usbmode); - ci->pm_command = ehci_readl(ehci, &ehci->regs->command); - ci->pm_command &= ~CMD_RUN; - ci->pm_status = ehci_readl(ehci, &ehci->regs->status); - ci->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); - ci->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); - ci->pm_segment = ehci_readl(ehci, &ehci->regs->segment); - ci->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); - ci->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); - ci->pm_configured_flag = - ehci_readl(ehci, &ehci->regs->configured_flag); - ci->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); -} - -static void ci_hdrc_host_restore_from_power_lost(struct ci_hdrc *ci) -{ - struct ehci_hcd *ehci; - unsigned long flags; - u32 tmp; - int step_ms; - /* - * If the vbus is off during system suspend, most of devices will pull - * DP up within 200ms when they see vbus, set 1000ms for safety. - */ - int timeout_ms = 1000; - - if (!ci->hcd) - return; - - hw_controller_reset(ci); - - ehci = hcd_to_ehci(ci->hcd); - spin_lock_irqsave(&ehci->lock, flags); - /* Restore EHCI registers */ - ehci_writel(ehci, ci->pm_usbmode, &ehci->regs->usbmode); - ehci_writel(ehci, ci->pm_portsc, &ehci->regs->port_status[0]); - ehci_writel(ehci, ci->pm_command, &ehci->regs->command); - ehci_writel(ehci, ci->pm_intr_enable, &ehci->regs->intr_enable); - ehci_writel(ehci, ci->pm_frame_index, &ehci->regs->frame_index); - ehci_writel(ehci, ci->pm_segment, &ehci->regs->segment); - ehci_writel(ehci, ci->pm_frame_list, &ehci->regs->frame_list); - ehci_writel(ehci, ci->pm_async_next, &ehci->regs->async_next); - ehci_writel(ehci, ci->pm_configured_flag, - &ehci->regs->configured_flag); - /* Restore the PHY's connect notifier setting */ - if (ci->pm_portsc & PORTSC_HSP) - usb_phy_notify_connect(ci->usb_phy, USB_SPEED_HIGH); - - tmp = ehci_readl(ehci, &ehci->regs->command); - tmp |= CMD_RUN; - ehci_writel(ehci, tmp, &ehci->regs->command); - spin_unlock_irqrestore(&ehci->lock, flags); - - if (!(ci->pm_portsc & PORTSC_CCS)) - return; - - for (step_ms = 0; step_ms < timeout_ms; step_ms += 25) { - if (ehci_readl(ehci, &ehci->regs->port_status[0]) & PORTSC_CCS) - break; - msleep(25); - } -} - -static void ci_hdrc_host_suspend(struct ci_hdrc *ci) -{ - ci_hdrc_host_save_for_power_lost(ci); -} - -static void ci_hdrc_host_resume(struct ci_hdrc *ci, bool power_lost) -{ - if (power_lost) - ci_hdrc_host_restore_from_power_lost(ci); -} - static int ci_ehci_bus_resume(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -624,8 +541,6 @@ int ci_hdrc_host_init(struct ci_hdrc *ci) rdrv->start = host_start; rdrv->stop = host_stop; - rdrv->suspend = ci_hdrc_host_suspend; - rdrv->resume = ci_hdrc_host_resume; rdrv->irq = host_irq; rdrv->name = "host"; ci->roles[CI_ROLE_HOST] = rdrv; -- cgit v1.2.3