From nobody Sat Oct 4 00:26:51 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C7512DECBF for ; Thu, 21 Aug 2025 16:32:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; cv=none; b=ntUnVuZa+SqcAhVDDvo3JEDGNWeubAkSkgCc3F/k3bitK88os3nj5Quayp91qNDACowdejmBndEB7RUvAyJqz1RmH10KIMnGgmYxeZVY03cJb5VDJt9Z+27X/X1q3em89rFk1RemX1bsipcMRkou9LEt26h7EOekbbfCHYV6Wj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; c=relaxed/simple; bh=uU9S3iV8gtVLVtHTvJYv7B3gY8qV1azXSOhP9qI2zYA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VLxRtMmqr4sbk1jBlK3Ec5lkBLJNnKG4asl/RSo/0LFZBA6yYkLgpZYgThhV6TnFl8GoqZZ8gkVcjqPGwWDoOrSxBfNi/14hqxO/7Prtz7dXkajyeG/nR6YBXPU7NES7ZrGY0cgymysHBczfGo/pWgCiSqtBlEgOBftBHb5e8cA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from dude02.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::28]) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1up8Cj-0004O7-Jg; Thu, 21 Aug 2025 18:31:57 +0200 From: Marco Felsch Date: Thu, 21 Aug 2025 18:31:55 +0200 Subject: [PATCH v3 1/4] usb: port: track the disabled state Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250821-v6-16-topic-usb-onboard-dev-v3-1-6d2b38a5d818@pengutronix.de> References: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> In-Reply-To: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Fabio Estevam , Matthias Kaehlcke , Liam Girdwood , Mark Brown Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Marco Felsch X-Mailer: b4 0.14.2 X-SA-Exim-Connect-IP: 2a0a:edc0:0:1101:1d::28 X-SA-Exim-Mail-From: m.felsch@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org The disable state isn't tracked at the moment, instead the state is directly passed to the hub driver. Change this behavior to only trigger the hub if a state change happened. Exit early in case of no state changes but don't return an error. Signed-off-by: Marco Felsch --- drivers/usb/core/hub.h | 2 ++ drivers/usb/core/port.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 9ebc5ef54a325d63e01b0deb59a1853d2b13c8d5..297adf2c6078809ca582104f228= e5222c464f999 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -97,6 +97,7 @@ struct usb_hub { * @usb3_lpm_u2_permit: whether USB3 U2 LPM is permitted. * @early_stop: whether port initialization will be stopped earlier. * @ignore_event: whether events of the port are ignored. + * @disabled: whether the port is disabled */ struct usb_port { struct usb_device *child; @@ -118,6 +119,7 @@ struct usb_port { unsigned int is_superspeed:1; unsigned int usb3_lpm_u1_permit:1; unsigned int usb3_lpm_u2_permit:1; + unsigned int disabled:1; }; =20 #define to_usb_port(_dev) \ diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index f54198171b6a3fb49c5f74f4a8a303b422d099eb..cae08a9a71e65c42fb9a8f53690= 60bd82b8daebb 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -117,6 +117,10 @@ static ssize_t disable_store(struct device *dev, struc= t device_attribute *attr, if (rc) return rc; =20 + /* Early quit if no change was detected */ + if (port_dev->disabled =3D=3D disabled) + return count; + hub_get(hub); rc =3D usb_autopm_get_interface(intf); if (rc < 0) @@ -148,6 +152,8 @@ static ssize_t disable_store(struct device *dev, struct= device_attribute *attr, usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); } =20 + port_dev->disabled =3D disabled; + if (!rc) rc =3D count; =20 --=20 2.39.5 From nobody Sat Oct 4 00:26:51 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05D07277CBD for ; Thu, 21 Aug 2025 16:32:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; cv=none; b=oHG6kfMsMqSC6HdezKtN1Oc/QGkQIlPniWD+X2cxJvwBTVLkeeL0nI3nYOWbX4/CqcoKNUlQeBFJFg27P73N+M2XMTxaWJQQNMij0cGM8xF0jNNo5li5Bb+o3NSze7/+609euetxAawoIecrHhaLw9V0iCWJo0R9ZKD5trJxF8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; c=relaxed/simple; bh=hIJ3Cs9EYY6S0Fjb3v3srWt//vNNreb4Za1FM7tQoLg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MVFRmpn0Y/SieRbv4ioaPOWkybb+y/4KHTb5YF//pIYwHw4aMBwXgHhcLvef8RvyDnzMKmbUpkJX88pW0iqnU5+VqSQkC17Juw/T1cFlV23SG8JX02yaYzoj+XM6MzwAr16QKKCL1utqpYnBcRV9+gBWHih8kA2vK7T4T1xlTOw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from dude02.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::28]) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1up8Cj-0004O7-Lk; Thu, 21 Aug 2025 18:31:57 +0200 From: Marco Felsch Date: Thu, 21 Aug 2025 18:31:56 +0200 Subject: [PATCH v3 2/4] usb: hub: add infrastructure to pass onboard_dev port features Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250821-v6-16-topic-usb-onboard-dev-v3-2-6d2b38a5d818@pengutronix.de> References: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> In-Reply-To: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Fabio Estevam , Matthias Kaehlcke , Liam Girdwood , Mark Brown Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Marco Felsch X-Mailer: b4 0.14.2 X-SA-Exim-Connect-IP: 2a0a:edc0:0:1101:1d::28 X-SA-Exim-Mail-From: m.felsch@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org On board devices may require special handling for en-/disable port features due to PCB design decisions e.g. enable/disable the VBUS power on the port via a host controlled regulator or GPIO. This commit adds the necessary infrastructure to prepare the common code base for such use-cases. Signed-off-by: Marco Felsch --- drivers/usb/core/hub.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++= ++-- drivers/usb/core/hub.h | 2 ++ include/linux/usb.h | 3 +++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 256fe8c86828d51c33442345acdb7f3fe80a98ce..50ae500e2ad3711996609fc8480= 6803449a5bf16 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -457,9 +457,19 @@ static int clear_hub_feature(struct usb_device *hdev, = int feature) */ int usb_clear_port_feature(struct usb_device *hdev, int port1, int feature) { - return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + struct usb_hub *hub =3D usb_hub_to_struct_hub(hdev); + int ret; + + ret =3D usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, NULL, 0, 1000); + if (ret) + return ret; + + if (hub->onboard_hub_clear_port_feature) + ret =3D hub->onboard_hub_clear_port_feature(hdev, feature, port1); + + return ret; } =20 /* @@ -467,9 +477,19 @@ int usb_clear_port_feature(struct usb_device *hdev, in= t port1, int feature) */ static int set_port_feature(struct usb_device *hdev, int port1, int featur= e) { - return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + struct usb_hub *hub =3D usb_hub_to_struct_hub(hdev); + int ret; + + ret =3D usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1, NULL, 0, 1000); + if (ret) + return ret; + + if (hub->onboard_hub_set_port_feature) + ret =3D hub->onboard_hub_set_port_feature(hdev, feature, port1); + + return ret; } =20 static char *to_led_name(int selector) @@ -6544,6 +6564,37 @@ void usb_hub_adjust_deviceremovable(struct usb_devic= e *hdev, } } =20 +/** + * usb_hub_register_port_feature_hooks - Register port set/get feature hoo= ks + * @hdev: USB device belonging to the usb hub + * @set_port_feature: set_feature hook which gets called by the hub core + * @clear_port_feature: clear_feature hook which gets called by the hub co= re + * + * Register set/get_port_feature hooks for a onboard_dev hub. + */ +void usb_hub_register_port_feature_hooks(struct usb_device *hdev, + int (*set_port_feature)(struct usb_device *, int, int), + int (*clear_port_feature)(struct usb_device *, int, int)) +{ + struct usb_hub *hub =3D usb_hub_to_struct_hub(hdev); + + if (WARN_ON_ONCE(is_root_hub(hdev) || !hub)) + return; + + if (set_port_feature) + hub->onboard_hub_set_port_feature =3D set_port_feature; + if (clear_port_feature) + hub->onboard_hub_clear_port_feature =3D clear_port_feature; + + /* + * Keep it simple for now. Just check the power state and re-sync it + * after adding the hooks since the onboard-dev may do some additional + * logic e.g. controlling regulators. + */ + hub_power_on(hub, false); +} +EXPORT_SYMBOL_GPL(usb_hub_register_port_feature_hooks); + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 297adf2c6078809ca582104f228e5222c464f999..31800b5922ba896dc7cac5f9e3e= d1a77e7c5a801 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -76,6 +76,8 @@ struct usb_hub { struct timer_list irq_urb_retry; struct usb_port **ports; struct list_head onboard_devs; + int (*onboard_hub_set_port_feature)(struct usb_device *udev, int feature,= int port1); + int (*onboard_hub_clear_port_feature)(struct usb_device *udev, int featur= e, int port1); }; =20 /** diff --git a/include/linux/usb.h b/include/linux/usb.h index 92c752f5446ff37ef09b9296f7711e1a622680ea..1415a826953ac5488619073e2f6= 59188f7988d6e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -928,6 +928,9 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigne= d port1, struct usb_dev_state *owner); int usb_hub_release_port(struct usb_device *hdev, unsigned port1, struct usb_dev_state *owner); +void usb_hub_register_port_feature_hooks(struct usb_device *hdev, + int (*set_port_feature)(struct usb_device *, int, int), + int (*clear_port_feature)(struct usb_device *, int, int)); =20 /** * usb_make_path - returns stable device path in the usb tree --=20 2.39.5 From nobody Sat Oct 4 00:26:51 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C1802DECC2 for ; Thu, 21 Aug 2025 16:32:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; cv=none; b=OsQnTf//xlx9r/+eQF1r3mi1WiMwIdlWPQO6NaH6rScknmsNgOvmwvmaXqxIUBk2ylzdcDTyU0FtGBd7YLc5Ekhaag0bgfdCoZ6ledLHTMW1r183GuqjjOWjQpBUGAwQwkpKVs9/G9OqMvCQOlOWDkTLcz4TnlPSBOONL+suy5Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793928; c=relaxed/simple; bh=4cPDIenIDZFT0xPmTB+xHrnqirfM/zBjaZe2zVKjOYI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J6HP2QSo5F0hePC/mtx1mCyHwFkE2Szamq/1x+TKRxiib01TEWCQUFMlwbBoNseBdwgpN/dOmC37xo1M28Cz52FXg8ZmT1+lp6zJSgHA0tWbcN76/pIy8QNDlcvY+ijEriGD3mCTbXfVeaX3rFDO1Zlkh04IiB4pTaunXIvYWTY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from dude02.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::28]) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1up8Cj-0004O7-OD; Thu, 21 Aug 2025 18:31:57 +0200 From: Marco Felsch Date: Thu, 21 Aug 2025 18:31:57 +0200 Subject: [PATCH v3 3/4] dt-bindings: usb: microchip,usb2514: add support for port vbus-supply Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250821-v6-16-topic-usb-onboard-dev-v3-3-6d2b38a5d818@pengutronix.de> References: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> In-Reply-To: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Fabio Estevam , Matthias Kaehlcke , Liam Girdwood , Mark Brown Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Marco Felsch X-Mailer: b4 0.14.2 X-SA-Exim-Connect-IP: 2a0a:edc0:0:1101:1d::28 X-SA-Exim-Mail-From: m.felsch@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Some PCB designs don't connect the USB hub port power control GPIO and instead make use of a host controllable regulator. Add support for this use-case by introducing portX-vbus-supply property. Signed-off-by: Marco Felsch --- Documentation/devicetree/bindings/usb/microchip,usb2514.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml b= /Documentation/devicetree/bindings/usb/microchip,usb2514.yaml index 4e3901efed3fcd4fbbd8cb777f9df4fcadf2ca00..ac1e5f1a5ea2e66c61ce9215438= 5952b15e78e55 100644 --- a/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml +++ b/Documentation/devicetree/bindings/usb/microchip,usb2514.yaml @@ -49,6 +49,12 @@ patternProperties: $ref: /schemas/usb/usb-device.yaml additionalProperties: true =20 + "^port[1-7]-vbus-supply$": + type: object + description: + Regulator controlling the USB VBUS on portX. Only required if the ho= st + controls the portX VBUS. + allOf: - $ref: usb-device.yaml# - if: --=20 2.39.5 From nobody Sat Oct 4 00:26:51 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BEA932D46CB for ; Thu, 21 Aug 2025 16:32:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793929; cv=none; b=GfY2FxWGQek/vPidI5vOR4xOOdtx2LkHY0lWytMrnErwyRSleiT1LusWEWnAi9eU0yvesDqYjyicScMFzdLTRH5ko9LDKJBXhxbaQEjr/w9kJwFRQ/Ryn6bOY37DdJVyd6wdtG9m/yD4lkHvKB6kM/hdpjt1pDRnzHC3z5hAA04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755793929; c=relaxed/simple; bh=ra9ISEyMXDs2zybscuSanrfQzAoOc8Qx/WwdPW0DGuw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U933mmwmU8s9Q0i24olH3mivCsFX3ShOzV6Ej2Fd9h6k8YHzf4rIt7SnR+ng8Dgbe2NHfdNjspBO9p5WUp294rf7Pplkr3zAJq4meZVWfDe6y2Jjhc0OGGISwYjXhCxy33mkHy5RePg8iqBYGVsBMpDf/5RTz0b/+utA9iKcGVQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from dude02.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::28]) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1up8Cj-0004O7-Q8; Thu, 21 Aug 2025 18:31:57 +0200 From: Marco Felsch Date: Thu, 21 Aug 2025 18:31:58 +0200 Subject: [PATCH v3 4/4] usb: misc: onboard_dev: add ext-vbus-supply handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250821-v6-16-topic-usb-onboard-dev-v3-4-6d2b38a5d818@pengutronix.de> References: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> In-Reply-To: <20250821-v6-16-topic-usb-onboard-dev-v3-0-6d2b38a5d818@pengutronix.de> To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Fabio Estevam , Matthias Kaehlcke , Liam Girdwood , Mark Brown Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, kernel@pengutronix.de, Marco Felsch X-Mailer: b4 0.14.2 X-SA-Exim-Connect-IP: 2a0a:edc0:0:1101:1d::28 X-SA-Exim-Mail-From: m.felsch@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Add support to power the port VBUS via host controlled regulators since some embedded hub PCB designs don't connect the dedicated USB hub port power GPIOs accordingly. To support the above use-case this commits adds support to parse the OF information and setup the regulators accordingly within the platform driver part. Furthermore the usb driver registers the set/clear features hooks via the new usb_hub_register_port_feature_hooks() if the onboard_dev is a hub. Afterwards all generic hub handling is passed to the onboard_dev driver too which allows us to control the regulators. At the moment this feature is limited to the following hubs: - usb424,2412 - usb424,2414 - usb424,2417 Signed-off-by: Marco Felsch --- drivers/usb/misc/onboard_usb_dev.c | 95 ++++++++++++++++++++++++++++++++++= ++++ drivers/usb/misc/onboard_usb_dev.h | 3 ++ 2 files changed, 98 insertions(+) diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_= usb_dev.c index 5b481876af1b2c10ce625fcf0fb8bfbe8905aa8c..bcb227c8dca2cecb3e49abfd41d= cbe4e586d7d07 100644 --- a/drivers/usb/misc/onboard_usb_dev.c +++ b/drivers/usb/misc/onboard_usb_dev.c @@ -49,6 +49,8 @@ static DECLARE_WORK(attach_usb_driver_work, onboard_dev_a= ttach_usb_driver); =20 /************************** Platform driver **************************/ =20 +#define MAX_DOWNSTREAM_PORTS 7 + struct usbdev_node { struct usb_device *udev; struct list_head list; @@ -65,6 +67,7 @@ struct onboard_dev { struct list_head udev_list; struct mutex lock; struct clk *clk; + struct regulator *ext_vbus_supplies[MAX_DOWNSTREAM_PORTS]; }; =20 static int onboard_dev_get_regulators(struct onboard_dev *onboard_dev) @@ -226,6 +229,53 @@ static int onboard_dev_add_usbdev(struct onboard_dev *= onboard_dev, return err; } =20 +static int onboard_dev_port_power(struct onboard_dev *onboard_dev, int por= t1, + bool enable) +{ + struct regulator *vbus_supply; + unsigned int port =3D port1 - 1; + + if (WARN_ON(port >=3D MAX_DOWNSTREAM_PORTS)) + return -EINVAL; + + vbus_supply =3D onboard_dev->ext_vbus_supplies[port]; + + /* External supplies are optional */ + if (!vbus_supply) + return 0; + + if (enable) + return regulator_enable(vbus_supply); + + return regulator_disable(vbus_supply); +} + +static int onboard_dev_add_ext_vbus_supplies(struct onboard_dev *onboard_d= ev) +{ + struct device *dev =3D onboard_dev->dev; + unsigned int i; + + if (!onboard_dev->pdata->support_ext_vbus_supplies) + return 0; + + for (i =3D 0; i < MAX_DOWNSTREAM_PORTS; i++) { + char supply_name[] =3D "portX-vbus"; + struct regulator *reg; + + sprintf(supply_name, "port%u-vbus", i + 1); + reg =3D devm_regulator_get_optional(dev, supply_name); + if (!IS_ERR(reg)) { + onboard_dev->ext_vbus_supplies[i] =3D reg; + } else { + if (PTR_ERR(reg) !=3D -ENODEV) + return dev_err_probe(dev, PTR_ERR(reg), + "failed to get %s-supply\n", supply_name); + } + } + + return 0; +} + static void onboard_dev_remove_usbdev(struct onboard_dev *onboard_dev, const struct usb_device *udev) { @@ -460,6 +510,10 @@ static int onboard_dev_probe(struct platform_device *p= dev) return dev_err_probe(dev, PTR_ERR(onboard_dev->reset_gpio), "failed to get reset GPIO\n"); =20 + err =3D onboard_dev_add_ext_vbus_supplies(onboard_dev); + if (err) + return err; + mutex_init(&onboard_dev->lock); INIT_LIST_HEAD(&onboard_dev->udev_list); =20 @@ -573,6 +627,44 @@ static struct platform_driver onboard_dev_driver =3D { #define VENDOR_ID_VIA 0x2109 #define VENDOR_ID_XMOS 0x20B1 =20 +static int onboard_dev_port_feature(struct usb_device *udev, bool set, + int feature, int port1) +{ + struct device *dev =3D &udev->dev; + struct onboard_dev *onboard_dev =3D dev_get_drvdata(dev); + + /* + * Check usb_hub_register_port_feature_hooks() if you want to extent + * the list of handled features. At the moment only power is synced + * after adding the hook. + */ + switch (feature) { + case USB_PORT_FEAT_POWER: + return onboard_dev_port_power(onboard_dev, port1, set); + default: + return 0; + } +} + +static int +onboard_dev_set_port_feature(struct usb_device *udev, int feature, int por= t1) +{ + return onboard_dev_port_feature(udev, true, feature, port1); +} + +static int +onboard_dev_clear_port_feature(struct usb_device *udev, int feature, int p= ort1) +{ + return onboard_dev_port_feature(udev, false, feature, port1); +} + +static void +onboard_dev_register_hub_hooks(struct usb_device *udev) +{ + usb_hub_register_port_feature_hooks(udev, onboard_dev_set_port_feature, + onboard_dev_clear_port_feature); +} + /* * Returns the onboard_dev platform device that is associated with the USB * device passed as parameter. @@ -632,6 +724,9 @@ static int onboard_dev_usbdev_probe(struct usb_device *= udev) =20 dev_set_drvdata(dev, onboard_dev); =20 + if (onboard_dev->pdata->is_hub) + onboard_dev_register_hub_hooks(udev); + err =3D onboard_dev_add_usbdev(onboard_dev, udev); if (err) return err; diff --git a/drivers/usb/misc/onboard_usb_dev.h b/drivers/usb/misc/onboard_= usb_dev.h index e017b8e22f936be66da73789abb4f620e6af4d6a..75aa2ab9297e272a98de15270d3= 595d7df03fb9c 100644 --- a/drivers/usb/misc/onboard_usb_dev.h +++ b/drivers/usb/misc/onboard_usb_dev.h @@ -14,6 +14,7 @@ struct onboard_dev_pdata { unsigned int num_supplies; /* number of supplies */ const char * const supply_names[MAX_SUPPLIES]; bool is_hub; + bool support_ext_vbus_supplies; }; =20 static const struct onboard_dev_pdata microchip_usb424_data =3D { @@ -21,6 +22,7 @@ static const struct onboard_dev_pdata microchip_usb424_da= ta =3D { .num_supplies =3D 1, .supply_names =3D { "vdd" }, .is_hub =3D true, + .support_ext_vbus_supplies =3D true, }; =20 static const struct onboard_dev_pdata microchip_usb2514_data =3D { @@ -28,6 +30,7 @@ static const struct onboard_dev_pdata microchip_usb2514_d= ata =3D { .num_supplies =3D 2, .supply_names =3D { "vdd", "vdda" }, .is_hub =3D true, + .support_ext_vbus_supplies =3D true, }; =20 static const struct onboard_dev_pdata microchip_usb5744_data =3D { --=20 2.39.5