usb: mtu3: fix random remote wakeup
authorChunfeng Yun <chunfeng.yun@mediatek.com>
Thu, 26 Aug 2021 08:36:37 +0000 (16:36 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Aug 2021 11:41:52 +0000 (13:41 +0200)
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 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.

Fixes: b1a344589eea ("usb: mtu3: support ip-sleep wakeup for MT8183")
Cc: stable@vger.kernel.org
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20210826083637.33237-2-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/mtu3/mtu3_host.c
drivers/usb/mtu3/mtu3_plat.c

index 7d528f3..f390336 100644 (file)
@@ -62,7 +62,7 @@ static void ssusb_wakeup_ip_sleep_set(struct ssusb_mtk *ssusb, bool enable)
        case SSUSB_UWK_V1_1:
                reg = ssusb->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 = ssusb->uwk_reg_base + PERI_WK_CTRL0;
index 5b3f7f7..f135310 100644 (file)
@@ -63,6 +63,9 @@ static int wait_for_ip_sleep(struct ssusb_mtk *ssusb)
        if (ret) {
                dev_err(ssusb->dev, "ip sleep failed!!!\n");
                ret = -EBUSY;
+       } else {
+               /* workaround: avoid wrong wakeup signal latch for some soc */
+               usleep_range(100, 200);
        }
 
        return ret;