summaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorStanley Chang <stanley_chang@realtek.com>2023-12-13 11:10:09 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-01-27 17:36:14 -0800
commit53a2d95df83688d0e160e3d55a925d85dbfd4809 (patch)
treead381f42a491a8ce2b647cef245705e6bbf79cfa /drivers/usb/core/hub.c
parentb48415afe5fd7e6f5912d4c45720217b77d8e7ea (diff)
downloadlinux-stable-53a2d95df83688d0e160e3d55a925d85dbfd4809.tar.gz
linux-stable-53a2d95df83688d0e160e3d55a925d85dbfd4809.tar.bz2
linux-stable-53a2d95df83688d0e160e3d55a925d85dbfd4809.zip
usb: core: add phy notify connect and disconnect
In Realtek SoC, the parameter of usb phy is designed to can dynamic tuning base on port status. Therefore, add a notify callback of generic phy driver when usb device connect and disconnect change. The Realtek phy driver is designed to dynamically adjust disconnection level and calibrate phy parameters. When the device connected bit changes and when the disconnected bit changes, do connection change notification: Check if portstatus is USB_PORT_STAT_CONNECTION and portchange is USB_PORT_STAT_C_CONNECTION. 1. The device is connected, the driver lowers the disconnection level and calibrates the phy parameters. 2. The device disconnects, the driver increases the disconnect level and calibrates the phy parameters. Generic phy driver in usb core framework does not support device connect and disconnect notifications. Therefore, we add an api to notify phy the connection changes. Additionally, the generic phy only specifies primary_hcd in the original design. Added specific "usb2-phy" on primary_hcd and "usb3-phy" on shared_hcd. Signed-off-by: Stanley Chang <stanley_chang@realtek.com> Link: https://lore.kernel.org/r/20231213031203.4911-4-stanley_chang@realtek.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ffd7c99e24a3..6f99557fa4ba 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -37,6 +37,7 @@
#include <asm/byteorder.h>
#include "hub.h"
+#include "phy.h"
#include "otg_productlist.h"
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
@@ -634,6 +635,34 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
ret = 0;
}
mutex_unlock(&hub->status_mutex);
+
+ /*
+ * There is no need to lock status_mutex here, because status_mutex
+ * protects hub->status, and the phy driver only checks the port
+ * status without changing the status.
+ */
+ if (!ret) {
+ struct usb_device *hdev = hub->hdev;
+
+ /*
+ * Only roothub will be notified of connection changes,
+ * since the USB PHY only cares about changes at the next
+ * level.
+ */
+ if (is_root_hub(hdev)) {
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+ bool connect;
+ bool connect_change;
+
+ connect_change = *change & USB_PORT_STAT_C_CONNECTION;
+ connect = *status & USB_PORT_STAT_CONNECTION;
+ if (connect_change && connect)
+ usb_phy_roothub_notify_connect(hcd->phy_roothub, port1 - 1);
+ else if (connect_change)
+ usb_phy_roothub_notify_disconnect(hcd->phy_roothub, port1 - 1);
+ }
+ }
+
return ret;
}