usb: xhci-mtk: fix random remote wakeup
authorChunfeng Yun <chunfeng.yun@mediatek.com>
Tue, 2 Nov 2021 02:50:04 +0000 (10:50 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Nov 2021 13:56:55 +0000 (14:56 +0100)
Some platforms, e.g. 8183/8192, use low level latch way to keep
wakeup signal, it may latch a wrong signal if debounce more time,
and enable wakeup function earlier.
                   ____________________
ip_sleep      ____/                    \_____________
                           ___________________
wakeup_signal ____________/                   \______
                      _______________________________
wakeup_en     _______/
                      ^     ^
                      |(1)  |(2)
latch wakeup_signal mistakenly at (1), should latch it at (2);

Workaround: delay about 100us to enable wakeup, meanwhile decrease
debounce time.

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20211102025004.29156-2-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mtk.c

index 8b98de4..91738af 100644 (file)
@@ -245,11 +245,12 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
        /* wait for host ip to sleep */
        ret = readl_poll_timeout(&ippc->ip_pw_sts1, value,
                          (value & STS1_IP_SLEEP_STS), 100, 100000);
-       if (ret) {
+       if (ret)
                dev_err(mtk->dev, "ip sleep failed!!!\n");
-               return ret;
-       }
-       return 0;
+       else /* workaound for platforms using low level latch */
+               usleep_range(100, 200);
+
+       return ret;
 }
 
 static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
@@ -300,7 +301,7 @@ static void usb_wakeup_ip_sleep_set(struct xhci_hcd_mtk *mtk, bool enable)
        case SSUSB_UWK_V1_1:
                reg = mtk->uwk_reg_base + PERI_WK_CTRL0;
                msk = WC0_IS_EN | WC0_IS_C(0xf) | WC0_IS_P;
-               val = enable ? (WC0_IS_EN | WC0_IS_C(0x8)) : 0;
+               val = enable ? (WC0_IS_EN | WC0_IS_C(0x1)) : 0;
                break;
        case SSUSB_UWK_V1_2:
                reg = mtk->uwk_reg_base + PERI_WK_CTRL0;