]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: chipidea: add USB PHY event
authorXu Yang <xu.yang_2@nxp.com>
Tue, 27 Jun 2023 11:03:51 +0000 (19:03 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:22:31 +0000 (16:22 +0200)
[ Upstream commit b7a62611fab72e585c729a7fcf666aa9c4144214 ]

Add USB PHY event for below situation:
- usb role changed
- vbus connect
- vbus disconnect
- gadget driver is enumerated

USB PHY driver can get the last event after above situation occurs
and deal with different situations.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Peter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/20230627110353.1879477-1-xu.yang_2@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/udc.c

index 7b00b93dad9b8d5347a05e1857d7ca230b9838b2..f12e177bfc551a072b909f503b7558e2db4d1116 100644 (file)
@@ -278,8 +278,19 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role)
                return -ENXIO;
 
        ret = ci->roles[role]->start(ci);
-       if (!ret)
-               ci->role = role;
+       if (ret)
+               return ret;
+
+       ci->role = role;
+
+       if (ci->usb_phy) {
+               if (role == CI_ROLE_HOST)
+                       usb_phy_set_event(ci->usb_phy, USB_EVENT_ID);
+               else
+                       /* in device mode but vbus is invalid*/
+                       usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
+       }
+
        return ret;
 }
 
@@ -293,6 +304,9 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
        ci->role = CI_ROLE_END;
 
        ci->roles[role]->stop(ci);
+
+       if (ci->usb_phy)
+               usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
 }
 
 static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci)
index 1c7af91bf03af488d3cbbbf80087d3e324b74866..122d2d82c67c7df222617d4d371c2c73e2f386b8 100644 (file)
@@ -1697,6 +1697,13 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
                ret = ci->platdata->notify_event(ci,
                                CI_HDRC_CONTROLLER_VBUS_EVENT);
 
+       if (ci->usb_phy) {
+               if (is_active)
+                       usb_phy_set_event(ci->usb_phy, USB_EVENT_VBUS);
+               else
+                       usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE);
+       }
+
        if (ci->driver)
                ci_hdrc_gadget_connect(_gadget, is_active);
 
@@ -2012,6 +2019,9 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
                if (USBi_PCI & intr) {
                        ci->gadget.speed = hw_port_is_high_speed(ci) ?
                                USB_SPEED_HIGH : USB_SPEED_FULL;
+                       if (ci->usb_phy)
+                               usb_phy_set_event(ci->usb_phy,
+                                       USB_EVENT_ENUMERATED);
                        if (ci->suspended) {
                                if (ci->driver->resume) {
                                        spin_unlock(&ci->lock);