]> 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>
Fri, 15 Aug 2025 10:04:52 +0000 (12:04 +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 2ff83911219f85218cefb7d400a5f53765bbd390..de23e10470d387b5e61427f3c55144ea94ca30a4 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 3795c70a31555c07597bfc9b9d22569ed77a2b9b..e7a02d9e1c079b1b077b32eda408ff0f98dbf86d 100644 (file)
@@ -1724,6 +1724,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);
 
@@ -2040,6 +2047,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);