Merge tag 'usb-5.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Jun 2020 20:12:10 +0000 (13:12 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 27 Jun 2020 20:12:10 +0000 (13:12 -0700)
Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 5.8-rc3 to resolve some reported
  issues.

  Nothing major here:

   - gadget driver fixes

   - cdns3 driver fixes

   - xhci fixes

   - renesas_usbhs driver fixes

   - some new device support with ids

   - documentation update

  All of these have been in linux-next with no reported issues"

* tag 'usb-5.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (27 commits)
  usb: renesas_usbhs: getting residue from callback_result
  Revert "usb: dwc3: exynos: Add support for Exynos5422 suspend clk"
  xhci: Poll for U0 after disabling USB2 LPM
  xhci: Return if xHCI doesn't support LPM
  usb: host: xhci-mtk: avoid runtime suspend when removing hcd
  xhci: Fix enumeration issue when setting max packet size for FS devices.
  xhci: Fix incorrect EP_STATE_MASK
  usb: cdns3: ep0: add spinlock for cdns3_check_new_setup
  usb: cdns3: trace: using correct dir value
  usb: cdns3: ep0: fix the test mode set incorrectly
  Revert "usb: dwc3: exynos: Add support for Exynos5422 suspend clk"
  usb: gadget: udc: Potential Oops in error handling code
  usb: phy: tegra: Fix unnecessary check in tegra_usb_phy_probe()
  usb: dwc3: pci: Fix reference count leak in dwc3_pci_resume_work
  usb: cdns3: ep0: add spinlock for cdns3_check_new_setup
  usb: cdns3: trace: using correct dir value
  usb: cdns3: ep0: fix the test mode set incorrectly
  usb: typec: tcpci_rt1711h: avoid screaming irq causing boot hangs
  USB: ohci-sm501: Add missed iounmap() in remove
  cdc-acm: Add DISABLE_ECHO quirk for Microchip/SMSC chip
  ...

22 files changed:
Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg
drivers/usb/cdns3/ep0.c
drivers/usb/cdns3/trace.h
drivers/usb/class/cdc-acm.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/gadget/udc/mv_udc_core.c
drivers/usb/host/ehci-exynos.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-sm501.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/usbtest.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/fifo.h
drivers/usb/typec/mux/intel_pmc_mux.c
drivers/usb/typec/tcpm/tcpci_rt1711h.c

index 151c595..f58cfb0 100644 (file)
@@ -1,6 +1,6 @@
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read.
                Set a_bus_req(A-device bus request) input to be 1 if
@@ -17,7 +17,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read
                The a_bus_drop(A-device bus drop) input is 1 when the
@@ -32,7 +32,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Can be set and read.
                The b_bus_req(B-device bus request) input is 1 during the time
@@ -47,7 +47,7 @@ Description:
 
 What:          /sys/bus/platform/devices/ci_hdrc.0/inputs/a_clr_err
 Date:          Feb 2014
-Contact:       Li Jun <b47624@freescale.com>
+Contact:       Li Jun <jun.li@nxp.com>
 Description:
                Only can be set.
                The a_clr_err(A-device Vbus error clear) input is used to clear
index 82645a2..61ec5bb 100644 (file)
@@ -327,7 +327,8 @@ static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev,
                if (!set || (tmode & 0xff) != 0)
                        return -EINVAL;
 
-               switch (tmode >> 8) {
+               tmode >>= 8;
+               switch (tmode) {
                case TEST_J:
                case TEST_K:
                case TEST_SE0_NAK:
@@ -704,15 +705,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
        int ret = 0;
        u8 zlp = 0;
 
+       spin_lock_irqsave(&priv_dev->lock, flags);
        trace_cdns3_ep0_queue(priv_dev, request);
 
        /* cancel the request if controller receive new SETUP packet. */
-       if (cdns3_check_new_setup(priv_dev))
+       if (cdns3_check_new_setup(priv_dev)) {
+               spin_unlock_irqrestore(&priv_dev->lock, flags);
                return -ECONNRESET;
+       }
 
        /* send STATUS stage. Should be called only for SET_CONFIGURATION */
        if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) {
-               spin_lock_irqsave(&priv_dev->lock, flags);
                cdns3_select_ep(priv_dev, 0x00);
 
                erdy_sent = !priv_dev->hw_configured_flag;
@@ -737,7 +740,6 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
                return 0;
        }
 
-       spin_lock_irqsave(&priv_dev->lock, flags);
        if (!list_empty(&priv_ep->pending_req_list)) {
                dev_err(priv_dev->dev,
                        "can't handle multiple requests for ep0\n");
index 8d121e2..755c565 100644 (file)
@@ -156,7 +156,7 @@ DECLARE_EVENT_CLASS(cdns3_log_ep0_irq,
                __dynamic_array(char, str, CDNS3_MSG_MAX)
        ),
        TP_fast_assign(
-               __entry->ep_dir = priv_dev->ep0_data_dir;
+               __entry->ep_dir = priv_dev->selected_ep;
                __entry->ep_sts = ep_sts;
        ),
        TP_printk("%s", cdns3_decode_ep0_irq(__get_str(str),
index f67088b..d5187b5 100644 (file)
@@ -1689,6 +1689,8 @@ static int acm_pre_reset(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x0424, 0x274e), /* Microchip Technology, Inc. (formerly SMSC) */
+         .driver_info = DISABLE_ECHO, }, /* DISABLE ECHO in termios flag */
        { USB_DEVICE(0x076d, 0x0006), /* Denso Cradle CU-321 */
        .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
index 3e8efe7..e0b7767 100644 (file)
@@ -218,11 +218,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Logitech HD Webcam C270 */
        { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
 
-       /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
+       /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x046d, 0x085c), .driver_info = USB_QUIRK_DELAY_INIT },
 
        /* Logitech ConferenceCam CC3000e */
        { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
index 12b98b4..7faf5f8 100644 (file)
@@ -4920,12 +4920,6 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg)
                                          epnum, 0);
        }
 
-       ret = usb_add_gadget_udc(dev, &hsotg->gadget);
-       if (ret) {
-               dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep,
-                                          hsotg->ctrl_req);
-               return ret;
-       }
        dwc2_hsotg_dump(hsotg);
 
        return 0;
index e571c8a..c347d93 100644 (file)
@@ -575,6 +575,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
        if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+       IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+       /* Postponed adding a new gadget to the udc class driver list */
+       if (hsotg->gadget_enabled) {
+               retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget);
+               if (retval) {
+                       dwc2_hsotg_remove(hsotg);
+                       goto error_init;
+               }
+       }
+#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
        return 0;
 
 error_init:
index 48b68b6..90bb022 100644 (file)
@@ -162,12 +162,6 @@ static const struct dwc3_exynos_driverdata exynos5250_drvdata = {
        .suspend_clk_idx = -1,
 };
 
-static const struct dwc3_exynos_driverdata exynos5420_drvdata = {
-       .clk_names = { "usbdrd30", "usbdrd30_susp_clk"},
-       .num_clks = 2,
-       .suspend_clk_idx = 1,
-};
-
 static const struct dwc3_exynos_driverdata exynos5433_drvdata = {
        .clk_names = { "aclk", "susp_clk", "pipe_pclk", "phyclk" },
        .num_clks = 4,
@@ -184,9 +178,6 @@ static const struct of_device_id exynos_dwc3_match[] = {
        {
                .compatible = "samsung,exynos5250-dwusb3",
                .data = &exynos5250_drvdata,
-       }, {
-               .compatible = "samsung,exynos5420-dwusb3",
-               .data = &exynos5420_drvdata,
        }, {
                .compatible = "samsung,exynos5433-dwusb3",
                .data = &exynos5433_drvdata,
index b673727..96c05b1 100644 (file)
@@ -206,8 +206,10 @@ static void dwc3_pci_resume_work(struct work_struct *work)
        int ret;
 
        ret = pm_runtime_get_sync(&dwc3->dev);
-       if (ret)
+       if (ret) {
+               pm_runtime_put_sync_autosuspend(&dwc3->dev);
                return;
+       }
 
        pm_runtime_mark_last_busy(&dwc3->dev);
        pm_runtime_put_sync_autosuspend(&dwc3->dev);
index cafde05..80a1b52 100644 (file)
@@ -2313,7 +2313,8 @@ static int mv_udc_probe(struct platform_device *pdev)
        return 0;
 
 err_create_workqueue:
-       destroy_workqueue(udc->qwork);
+       if (udc->qwork)
+               destroy_workqueue(udc->qwork);
 err_destroy_dma:
        dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
index a4e9abc..1a9b757 100644 (file)
@@ -203,9 +203,8 @@ static int exynos_ehci_probe(struct platform_device *pdev)
        hcd->rsrc_len = resource_size(res);
 
        irq = platform_get_irq(pdev, 0);
-       if (!irq) {
-               dev_err(&pdev->dev, "Failed to get IRQ\n");
-               err = -ENODEV;
+       if (irq < 0) {
+               err = irq;
                goto fail_io;
        }
 
index 3c3820a..af3c1b9 100644 (file)
@@ -216,6 +216,13 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                ehci_info(ehci, "applying MosChip frame-index workaround\n");
                ehci->frame_index_bug = 1;
                break;
+       case PCI_VENDOR_ID_HUAWEI:
+               /* Synopsys HC bug */
+               if (pdev->device == 0xa239) {
+                       ehci_info(ehci, "applying Synopsys HC workaround\n");
+                       ehci->has_synopsys_hc_bug = 1;
+               }
+               break;
        }
 
        /* optional debug port, normally in the first BAR */
index cff9652..b91d50d 100644 (file)
@@ -191,6 +191,7 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
        struct resource *mem;
 
        usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
index bfbdb3c..4311d4c 100644 (file)
@@ -587,6 +587,9 @@ static int xhci_mtk_remove(struct platform_device *dev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct usb_hcd  *shared_hcd = xhci->shared_hcd;
 
+       pm_runtime_put_noidle(&dev->dev);
+       pm_runtime_disable(&dev->dev);
+
        usb_remove_hcd(shared_hcd);
        xhci->shared_hcd = NULL;
        device_init_wakeup(&dev->dev, false);
@@ -597,8 +600,6 @@ static int xhci_mtk_remove(struct platform_device *dev)
        xhci_mtk_sch_exit(mtk);
        xhci_mtk_clks_disable(mtk);
        xhci_mtk_ldos_disable(mtk);
-       pm_runtime_put_sync(&dev->dev);
-       pm_runtime_disable(&dev->dev);
 
        return 0;
 }
index bee5dec..ed468ee 100644 (file)
@@ -1430,6 +1430,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
                                xhci->devs[slot_id]->out_ctx, ep_index);
 
                ep_ctx = xhci_get_ep_ctx(xhci, command->in_ctx, ep_index);
+               ep_ctx->ep_info &= cpu_to_le32(~EP_STATE_MASK);/* must clear */
                ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK);
                ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size));
 
@@ -4390,6 +4391,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
        int             hird, exit_latency;
        int             ret;
 
+       if (xhci->quirks & XHCI_HW_LPM_DISABLE)
+               return -EPERM;
+
        if (hcd->speed >= HCD_USB3 || !xhci->hw_lpm_support ||
                        !udev->lpm_capable)
                return -EPERM;
@@ -4412,7 +4416,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
        xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
                        enable ? "enable" : "disable", port_num + 1);
 
-       if (enable && !(xhci->quirks & XHCI_HW_LPM_DISABLE)) {
+       if (enable) {
                /* Host supports BESL timeout instead of HIRD */
                if (udev->usb2_hw_lpm_besl_capable) {
                        /* if device doesn't have a preferred BESL value use a
@@ -4471,6 +4475,9 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
                        mutex_lock(hcd->bandwidth_mutex);
                        xhci_change_max_exit_latency(xhci, udev, 0);
                        mutex_unlock(hcd->bandwidth_mutex);
+                       readl_poll_timeout(ports[port_num]->addr, pm_val,
+                                          (pm_val & PORT_PLS_MASK) == XDEV_U0,
+                                          100, 10000);
                        return 0;
                }
        }
index 2c6c4f8..c295e8a 100644 (file)
@@ -716,7 +716,7 @@ struct xhci_ep_ctx {
  * 4 - TRB error
  * 5-7 - reserved
  */
-#define EP_STATE_MASK          (0xf)
+#define EP_STATE_MASK          (0x7)
 #define EP_STATE_DISABLED      0
 #define EP_STATE_RUNNING       1
 #define EP_STATE_HALTED                2
index 98ada1a..bae8889 100644 (file)
@@ -2873,6 +2873,7 @@ static void usbtest_disconnect(struct usb_interface *intf)
 
        usb_set_intfdata(intf, NULL);
        dev_dbg(&intf->dev, "disconnect\n");
+       kfree(dev->buf);
        kfree(dev);
 }
 
index cffe2ac..03a3337 100644 (file)
@@ -1199,11 +1199,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, tegra_phy);
 
-       err = usb_add_phy_dev(&tegra_phy->u_phy);
-       if (err)
-               return err;
-
-       return 0;
+       return usb_add_phy_dev(&tegra_phy->u_phy);
 }
 
 static int tegra_usb_phy_remove(struct platform_device *pdev)
index 01c6a48..ac9a81a 100644 (file)
@@ -803,7 +803,8 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
        return info->dma_map_ctrl(chan->device->dev, pkt, map);
 }
 
-static void usbhsf_dma_complete(void *arg);
+static void usbhsf_dma_complete(void *arg,
+                               const struct dmaengine_result *result);
 static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
@@ -813,6 +814,7 @@ static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
        struct dma_chan *chan;
        struct device *dev = usbhs_priv_to_dev(priv);
        enum dma_transfer_direction dir;
+       dma_cookie_t cookie;
 
        fifo = usbhs_pipe_to_fifo(pipe);
        if (!fifo)
@@ -827,11 +829,11 @@ static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt)
        if (!desc)
                return;
 
-       desc->callback          = usbhsf_dma_complete;
-       desc->callback_param    = pipe;
+       desc->callback_result   = usbhsf_dma_complete;
+       desc->callback_param    = pkt;
 
-       pkt->cookie = dmaengine_submit(desc);
-       if (pkt->cookie < 0) {
+       cookie = dmaengine_submit(desc);
+       if (cookie < 0) {
                dev_err(dev, "Failed to submit dma descriptor\n");
                return;
        }
@@ -1152,12 +1154,10 @@ static size_t usbhs_dma_calc_received_size(struct usbhs_pkt *pkt,
                                           struct dma_chan *chan, int dtln)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
-       struct dma_tx_state state;
        size_t received_size;
        int maxp = usbhs_pipe_get_maxpacket(pipe);
 
-       dmaengine_tx_status(chan, pkt->cookie, &state);
-       received_size = pkt->length - state.residue;
+       received_size = pkt->length - pkt->dma_result->residue;
 
        if (dtln) {
                received_size -= USBHS_USB_DMAC_XFER_SIZE;
@@ -1363,13 +1363,16 @@ static int usbhsf_irq_ready(struct usbhs_priv *priv,
        return 0;
 }
 
-static void usbhsf_dma_complete(void *arg)
+static void usbhsf_dma_complete(void *arg,
+                               const struct dmaengine_result *result)
 {
-       struct usbhs_pipe *pipe = arg;
+       struct usbhs_pkt *pkt = arg;
+       struct usbhs_pipe *pipe = pkt->pipe;
        struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
        struct device *dev = usbhs_priv_to_dev(priv);
        int ret;
 
+       pkt->dma_result = result;
        ret = usbhsf_pkt_handler(pipe, USBHSF_PKT_DMA_DONE);
        if (ret < 0)
                dev_err(dev, "dma_complete run_error %d : %d\n",
index 7d3700b..039a2b9 100644 (file)
@@ -50,7 +50,7 @@ struct usbhs_pkt {
                     struct usbhs_pkt *pkt);
        struct work_struct work;
        dma_addr_t dma;
-       dma_cookie_t cookie;
+       const struct dmaengine_result *dma_result;
        void *buf;
        int length;
        int trans;
index 962bc69..70ddc9d 100644 (file)
@@ -148,7 +148,8 @@ pmc_usb_mux_dp_hpd(struct pmc_usb_port *port, struct typec_mux_state *state)
        msg[0] = PMC_USB_DP_HPD;
        msg[0] |= port->usb3_port << PMC_USB_MSG_USB3_PORT_SHIFT;
 
-       msg[1] = PMC_USB_DP_HPD_IRQ;
+       if (data->status & DP_STATUS_IRQ_HPD)
+               msg[1] = PMC_USB_DP_HPD_IRQ;
 
        if (data->status & DP_STATUS_HPD_STATE)
                msg[1] |= PMC_USB_DP_HPD_LVL;
@@ -161,6 +162,7 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
 {
        struct typec_displayport_data *data = state->data;
        struct altmode_req req = { };
+       int ret;
 
        if (data->status & DP_STATUS_IRQ_HPD)
                return pmc_usb_mux_dp_hpd(port, state);
@@ -181,7 +183,14 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state)
        if (data->status & DP_STATUS_HPD_STATE)
                req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH;
 
-       return pmc_usb_command(port, (void *)&req, sizeof(req));
+       ret = pmc_usb_command(port, (void *)&req, sizeof(req));
+       if (ret)
+               return ret;
+
+       if (data->status & DP_STATUS_HPD_STATE)
+               return pmc_usb_mux_dp_hpd(port, state);
+
+       return 0;
 }
 
 static int
index 0173890..b56a088 100644 (file)
@@ -179,26 +179,6 @@ out:
        return tcpci_irq(chip->tcpci);
 }
 
-static int rt1711h_init_alert(struct rt1711h_chip *chip,
-                             struct i2c_client *client)
-{
-       int ret;
-
-       /* Disable chip interrupts before requesting irq */
-       ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0);
-       if (ret < 0)
-               return ret;
-
-       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
-                                       rt1711h_irq,
-                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-                                       dev_name(chip->dev), chip);
-       if (ret < 0)
-               return ret;
-       enable_irq_wake(client->irq);
-       return 0;
-}
-
 static int rt1711h_sw_reset(struct rt1711h_chip *chip)
 {
        int ret;
@@ -260,7 +240,8 @@ static int rt1711h_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
 
-       ret = rt1711h_init_alert(chip, client);
+       /* Disable chip interrupts before requesting irq */
+       ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0);
        if (ret < 0)
                return ret;
 
@@ -271,6 +252,14 @@ static int rt1711h_probe(struct i2c_client *client,
        if (IS_ERR_OR_NULL(chip->tcpci))
                return PTR_ERR(chip->tcpci);
 
+       ret = devm_request_threaded_irq(chip->dev, client->irq, NULL,
+                                       rt1711h_irq,
+                                       IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+                                       dev_name(chip->dev), chip);
+       if (ret < 0)
+               return ret;
+       enable_irq_wake(client->irq);
+
        return 0;
 }