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>
Tue, 25 Jul 2023 16:24:17 +0000 (18:24 +0200)
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>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/udc.c

index f210b7489fd5b8ff825905da38c87674ce5a87a0..d262b9df7b3d3a4c79b578871b4f210b40f112f6 100644 (file)
@@ -281,8 +281,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;
 }
 
@@ -296,6 +307,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 54c09245ad055dc8a66c8e6a83d6686b37d2ab54..d58355427eeb139afb137852b0e92565c4392b3d 100644 (file)
@@ -1718,6 +1718,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);
 
@@ -2034,6 +2041,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);