* [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks
@ 2026-06-10 8:40 Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
` (15 more replies)
0 siblings, 16 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
Hi everyone,
This is v2 of my attempt at integrating the power sequencing API into
the USB core to support the USB connection on M.2 E-key slots. M.2
E-key was enabled in v7.1-rc1 with just PCIe and UART supported [1].
Major changes since v1:
- No longer adding the "index" parameter the power sequencing API
- Switched from OF graph to fwnode graph APIs
- Tie "port@" node to usb_port device, and use this device as consumer
to acquire power sequencing descriptor
- Power sequencing descriptor now only tied to USB 2.0 port to avoid
double reference
- Power sequencing state tracking added
- Link to v1
https://lore.kernel.org/all/20260515090149.3169406-1-wenst@chromium.org/
The series is based on next-20260608.
Patch 1 and 2 add new fwnode graph helpers. These are used by the patch
5 and 7, respectively.
Patch 3 changes the power sequencing framework's Kconfig symbol from
tristate to bool. This is needed as the USB core is bool. And since a
later patch introduces power sequencing API usage to the USB core, the
power sequencing framework cannot be built as a module anymore. This
patch needs to go in with "usb: hub: Power on connected M.2 E-key
connectors", or we will get allmodconfig build failures.
Patch 4 reworks the USB hub driver to return the actual error code from
hub_configure() in hub_probe(). This is needed in the next patch to
correctly return -EPROBE_DEFER returned by pwrseq_get() in patch 7.
Patch 5 makes the USB port device associated with a "port@" fwnode if
available. This depends on patch 1.
Patch 6 changes usb_port_is_power_on() so that |struct usb_port*| is
passed in instead of |struct usb_hub*|. This patch does not change any
functionality.
Patch 7 lets the USB hub driver look for power sequencers for each port.
Currently this only works for M.2 E-key connections, but it could be
extended to cover other cases. It should also make port reset via turning
off the port VBUS work, even when VBUS is not directly controlled by the
hub. This depends on patch 2 (for the new helper) and patch 3 (to avoid
allmodconfig link failures).
Patch 8 reverts an incorrectly modeled OF graph connection for the
MediaTek XHCI controller.
Patch 9 then adds a proper representation.
Patch 10 adds matching pwrseq consumer by "port@" node to the M.2 slot
driver. This is only used for the USB target, but there is no attempt
to differentiate the connection type. The driver simply tries matching
the "port@" node first, then falling back to the port parent or device's
node.
Patch 11 reworks the power sequencing targets for the E-key connector in
the pcie-m2 driver to add targets for USB and SDIO. The former is used
later on in this series.
Patches 12 through 16 enable the M.2 E-key slots (used for WiFi/BT) and
USB type-A connectors found on MediaTek-based Chromebooks. These are
provided in this series for reference. The USB type-A connector changes,
while not directly related, have overlapping context, and was easier to
include. They were also used to test some extra local changes I tried
to convert the USB A connector from an onboard USB device to a power
sequencing provider.
This series unfortunately spans multiple trees. The way I see it:
- Patch 1 and 2 go through the driver core, and an immutable tag is
provided to be merged together with the USB patches.
- Patch 3 gets an ack from Bartosz, and goes through the USB tree.
- Patch 4 through 9 (all the USB related ones) go through the USB
tree, along with the dependencies above.
- Patch 10 and 11 go through the power sequencing tree.
- Patch 12 through 16 (device tree only) go through the soc tree via
the mediatek tree.
Some of us discussed v1 at Embedded Recipes, and I believe Bartosz, Mani
and I agree on this approach. The debate is likely going to be on
whether this should be integrated into the USB core or not. I believe it
should, so that the power sequencing timing is tied to the USB port
being brought up. I do have a fallback option of just enabling the USB
power sequencing target inside the M.2 slot driver if a valid OF graph
connection is seen. But this is less desired for the reason given above.
Please have a look and share your thoughts.
Thanks
ChenYu
[1] https://lore.kernel.org/all/20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com/
Chen-Yu Tsai (16):
device property: Add fwnode_graph_get_port_by_id()
device property: Add fwnode_graph_get_next_port_endpoint()
power: sequencing: Change CONFIG_POWER_SEQUENCING to bool
usb: hub: Return actual error from hub_configure() in hub_probe()
usb: hub: Associate port@ fwnode with USB port device
usb: hub: Pass |struct usb_port*| to usb_port_is_power_on()
usb: hub: Power on connected M.2 E-key connectors
Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed
EP"
dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections
power: sequencing: pcie-m2: support matching on remote "port" node
power: sequencing: pcie-m2: Add usb and sdio targets for E-key
connector
arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector
arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot
arm64: dts: mediatek: mt8195-cherry: Add M.2 E-key slot
arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector
arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot
.../bindings/usb/mediatek,mtk-xhci.yaml | 17 +-
.../boot/dts/mediatek/mt8188-geralt.dtsi | 93 ++++++++++-
.../boot/dts/mediatek/mt8192-asurada.dtsi | 139 +++++++++++++++--
.../boot/dts/mediatek/mt8195-cherry.dtsi | 147 +++++++++++++++++-
drivers/base/property.c | 55 +++++++
drivers/power/sequencing/Kconfig | 2 +-
drivers/power/sequencing/pwrseq-pcie-m2.c | 50 ++++--
drivers/usb/core/hub.c | 55 +++++--
drivers/usb/core/hub.h | 6 +-
drivers/usb/core/port.c | 72 ++++++++-
include/linux/property.h | 3 +
11 files changed, 583 insertions(+), 56 deletions(-)
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id()
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint() Chen-Yu Tsai
` (14 subsequent siblings)
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
In some cases the driver needs a reference to the port firmware node.
Once such case is the upcoming USB power sequencing integration. The
USB hub port is tied to the corresponding port firmware node if it
exists.
Provide a helper for this.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/base/property.c | 22 ++++++++++++++++++++++
include/linux/property.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 9387bb83eb54..a2afd854a604 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1346,6 +1346,28 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
}
EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
+/**
+ * fwnode_graph_get_port_by_id - get the port matching a given id
+ * @fwnode: parent fwnode_handle containing the graph
+ * @id: id of the port
+ *
+ * Return: A 'port' firmware node pointer with refcount incremented.
+ *
+ * The caller is responsible for calling fwnode_handle_put() on the returned
+ * fwnode pointer.
+ */
+struct fwnode_handle *fwnode_graph_get_port_by_id(struct fwnode_handle *fwnode, u32 id)
+{
+ struct fwnode_handle *ep;
+
+ ep = fwnode_graph_get_endpoint_by_id(fwnode, id, 0, FWNODE_GRAPH_ENDPOINT_NEXT);
+ if (!ep)
+ return NULL;
+
+ return fwnode_get_next_parent(ep);
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_get_port_by_id);
+
const void *device_get_match_data(const struct device *dev)
{
return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev);
diff --git a/include/linux/property.h b/include/linux/property.h
index e30ef23a9af3..11f3b54c7de0 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -499,6 +499,7 @@ int fwnode_get_phy_mode(const struct fwnode_handle *fwnode);
void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index);
+struct fwnode_handle *fwnode_graph_get_port_by_id(struct fwnode_handle *fwnode, u32 id);
struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
struct fwnode_handle *
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint()
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:57 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
` (13 subsequent siblings)
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
Due to design constraints of the power sequencing API, the consumer
must first be sure that the other side is actually a provider, or it
will continually get -EPROBE_DEFER when requesting the power
sequencing descriptor.
In the upcoming USB power sequencing integration, the USB hub driver
first needs to check whether a graph connection exists, and whether
the other side of the connection is a supported connector type. The
USB port is tied to a "port" firmware node, and this new helper will
be used to get the endpoint under the known "port" firmware node.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/base/property.c | 33 +++++++++++++++++++++++++++++++++
include/linux/property.h | 2 ++
2 files changed, 35 insertions(+)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index a2afd854a604..cf14f9b0a3e0 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1099,6 +1099,39 @@ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
}
EXPORT_SYMBOL(fwnode_irq_get_byname);
+/**
+ * fwnode_graph_get_next_port_endpoint - Get next endpoint firmware node in port
+ * @port: Pointer to the target port firmware node
+ * @prev: Previous endpoint node or %NULL to get the first
+ *
+ * The caller is responsible for calling fwnode_handle_put() on the returned
+ * fwnode pointer. Note that this function also puts a reference to @prev
+ * unconditionally.
+ *
+ * Return: an endpoint firmware node pointer or %NULL if no more endpoints
+ * are available.
+ */
+struct fwnode_handle *fwnode_graph_get_next_port_endpoint(const struct fwnode_handle *port,
+ struct fwnode_handle *prev)
+{
+ struct fwnode_handle *ep;
+
+ while (1) {
+ prev = fwnode_get_next_child_node(port, prev);
+ if (!prev)
+ break;
+
+ if (WARN(!fwnode_name_eq(prev, "endpoint"),
+ "non endpoint node is used (%pfw)", prev))
+ continue;
+
+ break;
+ }
+
+ return prev;
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_get_next_port_endpoint);
+
/**
* fwnode_graph_get_next_endpoint - Get next endpoint firmware node
* @fwnode: Pointer to the parent firmware node
diff --git a/include/linux/property.h b/include/linux/property.h
index 11f3b54c7de0..2e744c6f251d 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -500,6 +500,8 @@ int fwnode_get_phy_mode(const struct fwnode_handle *fwnode);
void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index);
struct fwnode_handle *fwnode_graph_get_port_by_id(struct fwnode_handle *fwnode, u32 id);
+struct fwnode_handle *fwnode_graph_get_next_port_endpoint(
+ const struct fwnode_handle *port, struct fwnode_handle *prev);
struct fwnode_handle *fwnode_graph_get_next_endpoint(
const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
struct fwnode_handle *
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint() Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 9:00 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 04/16] usb: hub: Return actual error from hub_configure() in hub_probe() Chen-Yu Tsai
` (12 subsequent siblings)
15 siblings, 2 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
USB support, including the core and hub driver, is bool, no modules. To
be able to use the power sequencing API in the USB core, the former must
also be bool to avoid the latter being built as a module.
Change CONFIG_POWER_SEQUENCING to bool.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
index 1c5f5820f5b7..27448fba9dc5 100644
--- a/drivers/power/sequencing/Kconfig
+++ b/drivers/power/sequencing/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig POWER_SEQUENCING
- tristate "Power Sequencing support"
+ bool "Power Sequencing support"
help
Say Y here to enable the Power Sequencing subsystem.
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 04/16] usb: hub: Return actual error from hub_configure() in hub_probe()
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (2 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device Chen-Yu Tsai
` (11 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The addition of power sequencing descriptor handling in the USB hub code
requires dealing with deferred probing from pwrseq_get(). The power
sequencing provider may not yet be available when the USB hub probes.
Return the actual error code from hub_configure() when it fails, so that
the driver core can notice the deferred probe request.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v1:
- Moved "int ret" declaration in hub_configure() over here from the next
patch
---
drivers/usb/core/hub.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 13264e86bc6d..985551d013b2 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1874,6 +1874,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_host_interface *desc;
struct usb_device *hdev;
struct usb_hub *hub;
+ int ret;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
@@ -2005,14 +2006,15 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_set_interface(hdev, 0, 0);
}
- if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) {
+ ret = hub_configure(hub, &desc->endpoint[0].desc);
+ if (ret >= 0) {
onboard_dev_create_pdevs(hdev, &hub->onboard_devs);
return 0;
}
hub_disconnect(intf);
- return -ENODEV;
+ return ret;
}
static int
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (3 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 04/16] usb: hub: Return actual error from hub_configure() in hub_probe() Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:56 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 06/16] usb: hub: Pass |struct usb_port*| to usb_port_is_power_on() Chen-Yu Tsai
` (10 subsequent siblings)
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
When a USB hub port is connected to a connector in a firmware node
graph, the port itself has a node in the graph.
Associate the port's firmware node with the USB port's device,
usb_port::dev. This is used in later changes for the M.2 slot power
sequencing provider to match against the requesting port.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/usb/core/port.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index b1364f0c384c..1846eb1206a4 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -780,6 +780,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
port_dev->dev.driver = &usb_port_driver;
dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev),
port1);
+ device_set_node(&port_dev->dev,
+ fwnode_graph_get_port_by_id(dev_fwnode(&hdev->dev), port1));
mutex_init(&port_dev->status_lock);
retval = device_register(&port_dev->dev);
if (retval) {
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 06/16] usb: hub: Pass |struct usb_port*| to usb_port_is_power_on()
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (4 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors Chen-Yu Tsai
` (9 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
usb_port_is_power_on() currently takes |struct usb_hub*|, but only needs
it to tell if the hub/port is SuperSpeed or not.
In a subsequent change, usb_port_is_power_on() needs access to a pwrseq
state tracking field in |struct usb_port|. Either structure can be used
to identify whether a port/hub is SuperSpeed or not, as the field in
|struct usb_port| is inherited from the hub:
port->is_superspeed = hub_is_superspeed(hub)
Replace usb_port_is_power_on()'s |struct usb_hub*| parameter with
|struct usb_port*| so a subsequent change can use it.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/usb/core/hub.c | 11 ++++++-----
drivers/usb/core/hub.h | 2 +-
drivers/usb/core/port.c | 2 +-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 985551d013b2..362a10f7eddb 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3240,11 +3240,11 @@ static bool hub_port_stop_enumerate(struct usb_hub *hub, int port1, int retries)
}
/* Check if a port is power on */
-int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus)
+int usb_port_is_power_on(struct usb_port *port, unsigned int portstatus)
{
int ret = 0;
- if (hub_is_superspeed(hub->hdev)) {
+ if (port->is_superspeed) {
if (portstatus & USB_SS_PORT_STAT_POWER)
ret = 1;
} else {
@@ -3306,7 +3306,7 @@ static int check_port_resume_type(struct usb_device *udev,
}
/* Is the device still present? */
else if (status || port_is_suspended(hub, portstatus) ||
- !usb_port_is_power_on(hub, portstatus)) {
+ !usb_port_is_power_on(port_dev, portstatus)) {
if (status >= 0)
status = -ENODEV;
} else if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
@@ -3748,12 +3748,13 @@ static int wait_for_connected(struct usb_device *udev,
struct usb_hub *hub, int port1,
u16 *portchange, u16 *portstatus)
{
+ struct usb_port *port_dev = hub->ports[port1 - 1];
int status = 0, delay_ms = 0;
while (delay_ms < 2000) {
if (status || *portstatus & USB_PORT_STAT_CONNECTION)
break;
- if (!usb_port_is_power_on(hub, *portstatus)) {
+ if (!usb_port_is_power_on(port_dev, *portstatus)) {
status = -ENODEV;
break;
}
@@ -5449,7 +5450,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
* but only if the port isn't owned by someone else.
*/
if (hub_is_port_power_switchable(hub)
- && !usb_port_is_power_on(hub, portstatus)
+ && !usb_port_is_power_on(port_dev, portstatus)
&& !port_dev->port_owner)
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 9ebc5ef54a32..b65d9192379d 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -138,7 +138,7 @@ extern int usb_clear_port_feature(struct usb_device *hdev,
int port1, int feature);
extern int usb_hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change);
-extern int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus);
+extern int usb_port_is_power_on(struct usb_port *port, unsigned int portstatus);
static inline bool hub_is_port_power_switchable(struct usb_hub *hub)
{
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 1846eb1206a4..d9d3e2bb8f25 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -97,7 +97,7 @@ static ssize_t disable_show(struct device *dev,
}
usb_hub_port_status(hub, port1, &portstatus, &unused);
- disabled = !usb_port_is_power_on(hub, portstatus);
+ disabled = !usb_port_is_power_on(port_dev, portstatus);
out_hdev_lock:
usb_unlock_device(hdev);
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (5 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 06/16] usb: hub: Pass |struct usb_port*| to usb_port_is_power_on() Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 08/16] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP" Chen-Yu Tsai
` (8 subsequent siblings)
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The new M.2 E-key connector can have a USB connection. For the USB device
on this connector to work, its power must be enabled and the W_DISABLE2#
signal deasserted. The connector driver handles this and provides a
toggle over the power sequencing API.
This feature currently only supports a directly connected (no mux in
between) M.2 E-key connector. Existing USB connector types are not
covered. The USB A connector was recently added to the onboard devices
driver. USB B connectors have historically been managed by the USB
gadget or dual-role device controller drivers. USB C connectors are
handled by TCPM drivers.
The power sequencing API does not know whether a power sequence provider
is not needed or not available yet, so we only request it for connectors
that we know need it, which at this time is just the E-key connector.
On the USB side, the port firmware node (if present) is tied to the
usb_port device. This device is used to acquire the power sequencing
descriptor. This allows the provider to tell the different ports on one
hub apart.
This feature is not implemented in the onboard USB devices driver. The
power sequencing API expects the consumer device to make the request,
but there is no device node to instantiate a platform device to tie
the driver to. The connector is not a child node of the USB host or
hub, and the graph connection is from a USB port to the connector.
And the connector itself already has a driver.
Power sequencing is not directly enabled in the connector driver as
that would completely decouple the timing of it from the USB subsystem.
It would not be possible for the USB subsystem to toggle the power
for a power cycle or to disable the port.
This change depends on another change to make the power sequencing
framework bool instead of tristate. The USB core and hub driver are
bool, so if the power sequencing framework is built as a module, the
kernel will fail to link.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v1:
- Switch to fwnode instead of OF
- Tie port@ fwnode to usb_port device
- Move remote node compatible checking to separate helper
- Use usb_port device to request power sequencing descriptor
- Drop "index" parameter from pwrseq_get()
- Do not get pwrseq descriptor for SuperSpeed port; share one for one
physical port
- Add pwrseq state tracking
---
drivers/usb/core/hub.c | 38 ++++++++++++++++++++---
drivers/usb/core/hub.h | 4 +++
drivers/usb/core/port.c | 68 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 104 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 362a10f7eddb..9a9eb7e3e1fd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -32,6 +32,7 @@
#include <linux/mutex.h>
#include <linux/random.h>
#include <linux/pm_qos.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/kobject.h>
#include <linux/bitfield.h>
@@ -886,20 +887,41 @@ static void hub_tt_work(struct work_struct *work)
int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
int port1, bool set)
{
- int ret;
+ struct usb_port *pwrseq_port = hub->ports[port1 - 1];
+ int ret = 0;
+
+ /* non-SuperSpeed USB port holds pwrseq descriptor reference. */
+ if (hub->ports[port1 - 1]->is_superspeed && hub->ports[port1 - 1]->peer)
+ pwrseq_port = hub->ports[port1 - 1]->peer;
+
+ if (set && !pwrseq_port->pwrseq_on)
+ ret = pwrseq_power_on(pwrseq_port->pwrseq);
+ else if (!set && pwrseq_port->pwrseq_on)
+ ret = pwrseq_power_off(pwrseq_port->pwrseq);
+ if (ret)
+ return ret;
if (set)
ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
else
ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
- if (ret)
+ if (ret) {
+ if (set && !pwrseq_port->pwrseq_on)
+ pwrseq_power_off(pwrseq_port->pwrseq);
+ else if (!set && pwrseq_port->pwrseq_on)
+ pwrseq_power_on(pwrseq_port->pwrseq);
return ret;
+ }
- if (set)
+ if (set) {
set_bit(port1, hub->power_bits);
- else
+ pwrseq_port->pwrseq_on = 1;
+ } else {
clear_bit(port1, hub->power_bits);
+ pwrseq_port->pwrseq_on = 0;
+ }
+
return 0;
}
@@ -3252,7 +3274,13 @@ int usb_port_is_power_on(struct usb_port *port, unsigned int portstatus)
ret = 1;
}
- return ret;
+ if (port->is_superspeed && port->peer)
+ port = port->peer;
+
+ if (!port->pwrseq)
+ return ret;
+
+ return ret && port->pwrseq_on;
}
static void usb_lock_port(struct usb_port *port_dev)
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index b65d9192379d..a2ac91726c61 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -85,6 +85,7 @@ struct usb_hub {
* @port_owner: port's owner
* @peer: related usb2 and usb3 ports (share the same connector)
* @connector: USB Type-C connector
+ * @pwrseq: power sequencing descriptor for the port
* @req: default pm qos request for hubs without port power control
* @connect_type: port's connect type
* @state: device state of the usb device attached to the port
@@ -97,6 +98,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.
+ * @pwrseq_on: whether power sequencing is turned on.
*/
struct usb_port {
struct usb_device *child;
@@ -104,6 +106,7 @@ struct usb_port {
struct usb_dev_state *port_owner;
struct usb_port *peer;
struct typec_connector *connector;
+ struct pwrseq_desc *pwrseq;
struct dev_pm_qos_request *req;
enum usb_port_connect_type connect_type;
enum usb_device_state state;
@@ -118,6 +121,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 pwrseq_on:1;
};
#define to_usb_port(_dev) \
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index d9d3e2bb8f25..a5e7fbf4aa6e 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -7,11 +7,14 @@
* Author: Lan Tianyu <tianyu.lan@intel.com>
*/
+#include <linux/cleanup.h>
#include <linux/kstrtox.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <linux/sysfs.h>
#include <linux/pm_qos.h>
+#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/component.h>
#include <linux/usb/of.h>
@@ -28,6 +31,9 @@ static bool usb_port_allow_power_off(struct usb_device *hdev,
if (hub_is_port_power_switchable(hub))
return true;
+ if (port_dev->pwrseq)
+ return true;
+
if (!IS_ENABLED(CONFIG_ACPI))
return false;
@@ -748,6 +754,43 @@ static const struct component_ops connector_ops = {
.unbind = connector_unbind,
};
+static bool port_pwrseq_is_supported(struct usb_port *port_dev)
+{
+ struct device *dev = &port_dev->dev;
+ struct fwnode_handle *port = dev->fwnode;
+ struct fwnode_handle *ep __free(fwnode_handle) =
+ fwnode_graph_get_next_port_endpoint(port, NULL);
+ if (!ep)
+ return false;
+
+ struct fwnode_handle *remote __free(fwnode_handle) =
+ fwnode_graph_get_remote_port_parent(ep);
+ if (!remote)
+ return false;
+
+ if (!fwnode_device_is_compatible(remote, "pcie-m2-e-connector")) {
+ dev_dbg(dev, "remote endpoint %pfw is not a supported connector", remote);
+ return false;
+ }
+
+ return true;
+}
+
+static struct pwrseq_desc *usb_hub_port_pwrseq_get(struct usb_port *port_dev)
+{
+ if (!IS_ENABLED(CONFIG_POWER_SEQUENCING))
+ return NULL;
+
+ /* A physical port should only have one pwrseq reference. */
+ if (port_dev->is_superspeed)
+ return NULL;
+
+ if (!port_pwrseq_is_supported(port_dev))
+ return NULL;
+
+ return pwrseq_get(&port_dev->dev, "usb");
+}
+
int usb_hub_create_port_device(struct usb_hub *hub, int port1)
{
struct usb_port *port_dev;
@@ -803,10 +846,25 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
goto err_put_kn;
}
+ port_dev->pwrseq = usb_hub_port_pwrseq_get(port_dev);
+ if (IS_ERR(port_dev->pwrseq)) {
+ retval = PTR_ERR(port_dev->pwrseq);
+ dev_err_probe(&port_dev->dev, retval,
+ "failed to get power sequencing descriptor\n");
+ goto err_put_kn;
+ }
+
+ retval = pwrseq_power_on(port_dev->pwrseq);
+ if (retval) {
+ dev_err_probe(&port_dev->dev, retval, "failed to enable power\n");
+ goto err_put_pwrseq;
+ }
+ port_dev->pwrseq_on = 1;
+
retval = component_add(&port_dev->dev, &connector_ops);
if (retval) {
dev_warn(&port_dev->dev, "failed to add component\n");
- goto err_put_kn;
+ goto err_pwrseq_off;
}
find_and_link_peer(hub, port1);
@@ -844,6 +902,11 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
}
return 0;
+err_pwrseq_off:
+ if (port_dev->pwrseq_on)
+ pwrseq_power_off(port_dev->pwrseq);
+err_put_pwrseq:
+ pwrseq_put(port_dev->pwrseq);
err_put_kn:
sysfs_put(port_dev->state_kn);
err_unregister:
@@ -860,6 +923,9 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
peer = port_dev->peer;
if (peer)
unlink_peers(port_dev, peer);
+ if (port_dev->pwrseq_on)
+ pwrseq_power_off(port_dev->pwrseq);
+ pwrseq_put(port_dev->pwrseq);
component_del(&port_dev->dev, &connector_ops);
sysfs_put(port_dev->state_kn);
device_unregister(&port_dev->dev);
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 08/16] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP"
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (6 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 09/16] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections Chen-Yu Tsai
` (7 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
This reverts commit 454a1e3cd36c113341d7b71e8e691c6e47ab4a8a.
mtk-xhci handles both USB 2.0 High Speed (HS) and USB 3.x SuperSpeed
(SS) host connections. And there are USB 2.0 only mtk-xhci blocks.
The SSUSB controller handles the device or gadget mode. Saying that
SSUSB handles the HS portion is wrong.
Fixes: 454a1e3cd36c ("dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP")
Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml | 4 ----
1 file changed, 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index 231e6f35a986..75ecce3bdc7a 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -107,10 +107,6 @@ properties:
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- port:
- $ref: /schemas/graph.yaml#/properties/port
- description: Super Speed (SS) Output endpoint to a Type-C connector
-
vusb33-supply:
description: Regulator of USB AVDD3.3v
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 09/16] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (7 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 08/16] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP" Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 10/16] power: sequencing: pcie-m2: support matching on remote "port" node Chen-Yu Tsai
` (6 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
MediaTek's XHCI implementation supports both USB 2.0 High Speed (HS)
and USB 3.x Super Speed (SS). The block can also be synthesized with
either HS-only capability or HS+SS capability.
For example, on the MT8195, the first two instances support both HS and
SS, while the latter two instances support only HS.
Allow a ports sub-node for describing USB connections. Port 1 is Super
Speed if the controller is SS-capable, otherwise it is High Speed. Port
2 is High Speed if SS-capable. This port mapping scheme directly matches
what the hardware returns in its capability registers.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../devicetree/bindings/usb/mediatek,mtk-xhci.yaml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index 75ecce3bdc7a..d6c75bd20b78 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -184,6 +184,19 @@ properties:
"#size-cells":
const: 0
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Super Speed (SS) data bus if SS-capable;
+ otherwise High Speed (HS) data bus.
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: High Speed (HS) data bus if controller is SS-capable.
+
patternProperties:
"@[0-9a-f]{1}$":
type: object
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 10/16] power: sequencing: pcie-m2: support matching on remote "port" node
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (8 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 09/16] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 11/16] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector Chen-Yu Tsai
` (5 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
A USB hub can have multiple ports, and this driver needs to
differentiate which port is being matched to. The USB hub driver now
associates the "port" node with the usb_port device, so here we can
use the remote "port" node to check for a match. Then fall back to
the remote device node for the other connection types.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/pwrseq-pcie-m2.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index e82821655fc4..49293376956b 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -176,8 +176,17 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
* parent matches the OF node of 'dev'.
*/
for_each_endpoint_of_node(ctx->of_node, endpoint) {
+ /* USB port devices are tied to the port nodes. */
+ struct device_node *remote_port __free(device_node) =
+ of_graph_get_remote_port(endpoint);
+
+ if (remote_port && remote_port == dev_of_node(dev))
+ return PWRSEQ_MATCH_OK;
+
+ /* Try the remote port parent for other types. */
struct device_node *remote __free(device_node) =
of_graph_get_remote_port_parent(endpoint);
+
if (remote && (remote == dev_of_node(dev)))
return PWRSEQ_MATCH_OK;
}
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 11/16] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (9 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 10/16] power: sequencing: pcie-m2: support matching on remote "port" node Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 12/16] arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector Chen-Yu Tsai
` (4 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The M.2 E-key connector allows either PCIe or SDIO for WiFi and USB or
UART for BT. Currently the driver only supports PCIe and UART.
Add power sequencing targets for SDIO and USB. To avoid adding a
complicated dependency tree, rename the existing power sequencing units
"pcie" and "uart" to "wifi" and "bt". The existing target names are left
untouched. The new "sdio" and "usb" targets just point to the renamed
"wifi" and "bt" units.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/pwrseq-pcie-m2.c | 41 +++++++++++++++--------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index 49293376956b..a21a3dbe8a5d 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -70,46 +70,46 @@ static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = {
NULL
};
-static int pwrseq_pci_m2_e_uart_enable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_bt_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0);
}
-static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_bt_disable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
}
-static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
- .name = "uart-enable",
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_bt_unit_data = {
+ .name = "bt-enable",
.deps = pwrseq_pcie_m2_unit_deps,
- .enable = pwrseq_pci_m2_e_uart_enable,
- .disable = pwrseq_pci_m2_e_uart_disable,
+ .enable = pwrseq_pci_m2_e_bt_enable,
+ .disable = pwrseq_pci_m2_e_bt_disable,
};
-static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_wifi_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0);
}
-static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_wifi_disable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
}
-static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
- .name = "pcie-enable",
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_wifi_unit_data = {
+ .name = "wifi-enable",
.deps = pwrseq_pcie_m2_unit_deps,
- .enable = pwrseq_pci_m2_e_pcie_enable,
- .disable = pwrseq_pci_m2_e_pcie_disable,
+ .enable = pwrseq_pci_m2_e_wifi_enable,
+ .disable = pwrseq_pci_m2_e_wifi_disable,
};
static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
@@ -131,13 +131,24 @@ static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq)
static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
.name = "uart",
- .unit = &pwrseq_pcie_m2_e_uart_unit_data,
+ .unit = &pwrseq_pcie_m2_e_bt_unit_data,
.post_enable = pwrseq_pcie_m2_e_pwup_delay,
};
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_usb_target_data = {
+ .name = "usb",
+ .unit = &pwrseq_pcie_m2_e_bt_unit_data,
+};
+
static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
.name = "pcie",
- .unit = &pwrseq_pcie_m2_e_pcie_unit_data,
+ .unit = &pwrseq_pcie_m2_e_wifi_unit_data,
+ .post_enable = pwrseq_pcie_m2_e_pwup_delay,
+};
+
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_sdio_target_data = {
+ .name = "sdio",
+ .unit = &pwrseq_pcie_m2_e_wifi_unit_data,
.post_enable = pwrseq_pcie_m2_e_pwup_delay,
};
@@ -148,7 +159,9 @@ static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = {
&pwrseq_pcie_m2_e_pcie_target_data,
+ &pwrseq_pcie_m2_e_sdio_target_data,
&pwrseq_pcie_m2_e_uart_target_data,
+ &pwrseq_pcie_m2_e_usb_target_data,
NULL
};
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 12/16] arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (10 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 11/16] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 13/16] arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot Chen-Yu Tsai
` (3 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The MT8192 Asurada design features a USB type-A connector for external
devices.
Add a proper representation for it with a node for the connector and
OF graph connection to the USB hub behind it.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../boot/dts/mediatek/mt8192-asurada.dtsi | 74 ++++++++++++++++++-
1 file changed, 71 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index b7387075cb87..fb4d92750770 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -292,6 +292,32 @@ sound: sound {
pinctrl-24 = <&aud_gpio_tdm_off_pins>;
pinctrl-25 = <&aud_gpio_tdm_on_pins>;
};
+
+ usb-a-connector {
+ compatible = "usb-a-connector";
+ vbus-supply = <&pp5000_a>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_a_u2_ep: endpoint {
+ remote-endpoint = <&usb2_hub_p3_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_a_u3_ep: endpoint {
+ remote-endpoint = <&usb3_hub_p3_ep>;
+ };
+ };
+ };
+ };
};
&afe {
@@ -1702,11 +1728,53 @@ &uart0 {
};
&xhci {
- status = "okay";
-
wakeup-source;
vusb33-supply = <&pp3300_g>;
- vbus-supply = <&pp5000_a>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ usb3_hub: usb-hub@1 {
+ compatible = "usb5e3,620";
+ reg = <1>;
+ reset-gpios = <&pio 44 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pp5000_a>;
+ peer-hub = <&usb2_hub>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@3 {
+ reg = <3>;
+
+ usb3_hub_p3_ep: endpoint {
+ remote-endpoint = <&usb_a_u3_ep>;
+ };
+ };
+ };
+ };
+
+ usb2_hub: usb-hub@2 {
+ compatible = "usb5e3,610";
+ reg = <2>;
+ reset-gpios = <&pio 44 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pp5000_a>;
+ peer-hub = <&usb3_hub>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@3 {
+ reg = <3>;
+
+ usb2_hub_p3_ep: endpoint {
+ remote-endpoint = <&usb_a_u2_ep>;
+ };
+ };
+ };
+ };
};
#include <arm/cros-ec-keyboard.dtsi>
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 13/16] arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (11 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 12/16] arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: " Chen-Yu Tsai
` (2 subsequent siblings)
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The MT8192 Asurada design features an M.2 E-key slot for WiFi/BT combo
cards. Only PCIe and USB are wired from the SoC to the slot, along with
some auxiliary signals.
Add the proper representation for it, replacing the PCIe wifi node and
vpcie3v3-supply property under the PCIe controller. Also clean up the
pcie controller node.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../boot/dts/mediatek/mt8192-asurada.dtsi | 65 +++++++++++++++++--
1 file changed, 58 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
index fb4d92750770..901240384a4a 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
@@ -318,6 +318,41 @@ usb_a_u3_ep: endpoint {
};
};
};
+
+ wifi-bt-connector {
+ compatible = "pcie-m2-e-connector";
+ pinctrl-names = "default";
+ pinctrl-0 = <&m2_e_key_kill_pins>;
+ vpcie3v3-supply = <&pp3300_wlan>;
+ w-disable1-gpios = <&pio 61 GPIO_ACTIVE_LOW>;
+ w-disable2-gpios = <&pio 59 GPIO_ACTIVE_LOW>;
+ /* PCIe auxiliary signals wired to controller. */
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* PCIe for WiFi */
+ port@0 {
+ reg = <0>;
+
+ wifi_ep: endpoint {
+ remote-endpoint = <&pcie_ep>;
+ };
+ };
+
+ /* USB for Bluetooth */
+ port@2 {
+ reg = <2>;
+
+ bt_ep: endpoint {
+ remote-endpoint = <&usb2_hub_p4_ep>;
+ };
+ };
+
+ /* SDIO, UART and I2S not implemented */
+ };
+ };
};
&afe {
@@ -671,19 +706,19 @@ &pcie {
pinctrl-0 = <&pcie_pins>;
memory-region = <&wifi_restricted_dma_region>;
- pcie0: pcie@0,0 {
+ pcie@0 {
+ compatible = "pciclass,0604";
+ reg = <0 0 0 0 0>;
device_type = "pci";
- reg = <0x0000 0 0 0 0>;
num-lanes = <1>;
- bus-range = <0x1 0x1>;
-
#address-cells = <3>;
#size-cells = <2>;
ranges;
- wifi: wifi@0,0 {
- reg = <0x10000 0 0 0 0x100000>,
- <0x10000 0 0x100000 0 0x100000>;
+ port {
+ pcie_ep: endpoint {
+ remote-endpoint = <&wifi_ep>;
+ };
};
};
};
@@ -1206,6 +1241,14 @@ pins-bus {
};
};
+ m2_e_key_kill_pins: m2-e-key-kill-pins {
+ pins-kill {
+ pinmux = <PINMUX_GPIO61__FUNC_GPIO61>,
+ <PINMUX_GPIO59__FUNC_GPIO59>;
+ output-high;
+ };
+ };
+
mmc0_default_pins: mmc0-default-pins {
pins-cmd-dat {
pinmux = <PINMUX_GPIO184__FUNC_MSDC0_DAT0>,
@@ -1773,6 +1816,14 @@ usb2_hub_p3_ep: endpoint {
remote-endpoint = <&usb_a_u2_ep>;
};
};
+
+ port@4 {
+ reg = <4>;
+
+ usb2_hub_p4_ep: endpoint {
+ remote-endpoint = <&bt_ep>;
+ };
+ };
};
};
};
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: Add M.2 E-key slot
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (12 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 13/16] arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 15/16] arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot Chen-Yu Tsai
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The Mt8195 Cherry design features an M.2 E-key slot for WiFi/BT combo
cards. Only PCIe and USB are wired from the SoC to the slot, along with
some auxiliary signals.
Add the proper representation for it, replacing the PCIe wifi node and
vpcie3v3-supply property under the PCIe controller, and the vbus-supply
property under the xhci3 node.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../boot/dts/mediatek/mt8195-cherry.dtsi | 74 +++++++++++++++++--
1 file changed, 69 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index ef7afc436aef..c95a54de3567 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -266,6 +266,47 @@ tboard_thermistor2: thermal-sensor-t2 {
120000 51
125000 44>;
};
+
+ wifi-bt-connector {
+ compatible = "pcie-m2-e-connector";
+ pinctrl-names = "default";
+ pinctrl-0 = <&m2_e_key_kill_pins>;
+ vpcie3v3-supply = <&pp3300_wlan>;
+ w-disable1-gpios = <&pio 61 GPIO_ACTIVE_LOW>;
+ w-disable2-gpios = <&pio 59 GPIO_ACTIVE_LOW>;
+ /* PCIe auxiliary signals wired to controller. */
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* PCIe for WiFi */
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wifi_ep: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&pcie1_ep>;
+ };
+ };
+
+ /* USB for Bluetooth */
+ port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ bt_ep: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usb3_ep>;
+ };
+ };
+
+ /* SDIO, UART and I2S not implemented */
+ };
+ };
};
&adsp {
@@ -791,14 +832,14 @@ pcie@0 {
reg = <0 0 0 0 0>;
device_type = "pci";
num-lanes = <1>;
- vpcie3v3-supply = <&pp3300_wlan>;
#address-cells = <3>;
#size-cells = <2>;
ranges;
- wifi@0 {
- reg = <0 0 0 0 0>;
- wakeup-source;
+ port {
+ pcie1_ep: endpoint {
+ remote-endpoint = <&wifi_ep>;
+ };
};
};
};
@@ -1085,6 +1126,14 @@ pins-bus {
};
};
+ m2_e_key_kill_pins: m2-e-key-kill-pins {
+ pins-kill {
+ pinmux = <PINMUX_GPIO61__FUNC_GPIO61>,
+ <PINMUX_GPIO59__FUNC_GPIO59>;
+ output-high;
+ };
+ };
+
mmc0_pins_default: mmc0-default-pins {
pins-cmd-dat {
pinmux = <PINMUX_GPIO126__FUNC_MSDC0_DAT0>,
@@ -1637,9 +1686,24 @@ &xhci2 {
&xhci3 {
/* MT7921's USB Bluetooth has issues with USB2 LPM */
usb2-lpm-disable;
- vbus-supply = <&pp3300_wlan>;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb3_ep: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&bt_ep>;
+ };
+ };
+ };
};
#include <arm/cros-ec-keyboard.dtsi>
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 15/16] arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (13 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: " Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot Chen-Yu Tsai
15 siblings, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The MT8195 Cherry design features a USB type-A connector for external
devices.
Add a proper representation for it with a node for the connector and
OF graph connection to the USB hub behind it.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../boot/dts/mediatek/mt8195-cherry.dtsi | 73 ++++++++++++++++++-
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index c95a54de3567..8a21a8b996df 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -153,7 +153,6 @@ usb_vbus: regulator-5v0-usb-vbus {
compatible = "regulator-fixed";
regulator-name = "usb-vbus";
enable-active-high;
- regulator-always-on;
vin-supply = <&pp5000_s5>;
};
@@ -267,6 +266,32 @@ tboard_thermistor2: thermal-sensor-t2 {
125000 44>;
};
+ usb-a-connector {
+ compatible = "usb-a-connector";
+ vbus-supply = <&usb_vbus>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ usb_a_u2_ep: endpoint {
+ remote-endpoint = <&usb2_hub_p3_ep>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ usb_a_u3_ep: endpoint {
+ remote-endpoint = <&usb3_hub_p3_ep>;
+ };
+ };
+ };
+ };
+
wifi-bt-connector {
compatible = "pcie-m2-e-connector";
pinctrl-names = "default";
@@ -1672,13 +1697,55 @@ vdosys1_ep_ext: endpoint@1 {
&xhci0 {
rx-fifo-depth = <3072>;
- vbus-supply = <&usb_vbus>;
+ #address-cells = <1>;
+ #size-cells = <0>;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
status = "okay";
+
+ usb3_hub: usb-hub@1 {
+ compatible = "usb5e3,620";
+ reg = <1>;
+ reset-gpios = <&pio 84 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pp5000_s5>;
+ peer-hub = <&usb2_hub>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@3 {
+ reg = <3>;
+
+ usb3_hub_p3_ep: endpoint {
+ remote-endpoint = <&usb_a_u3_ep>;
+ };
+ };
+ };
+ };
+
+ usb2_hub: usb-hub@2 {
+ compatible = "usb5e3,610";
+ reg = <2>;
+ reset-gpios = <&pio 84 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&pp5000_s5>;
+ peer-hub = <&usb3_hub>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@3 {
+ reg = <3>;
+
+ usb2_hub_p3_ep: endpoint {
+ remote-endpoint = <&usb_a_u2_ep>;
+ };
+ };
+ };
+ };
};
&xhci2 {
- vbus-supply = <&usb_vbus>;
vusb33-supply = <&mt6359_vusb_ldo_reg>;
status = "okay";
};
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
` (14 preceding siblings ...)
2026-06-10 8:40 ` [PATCH v2 15/16] arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector Chen-Yu Tsai
@ 2026-06-10 8:40 ` Chen-Yu Tsai
2026-06-10 9:02 ` sashiko-bot
15 siblings, 1 reply; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 8:40 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, Chen-Yu Tsai, linux-acpi, driver-core, linux-pm,
linux-usb, devicetree, linux-mediatek, linux-arm-kernel,
linux-kernel, Manivannan Sadhasivam
The MT8188 Geralt design features a chip-on-board WiFi/BT solution. This
is a M.2 E-key WiFi/BT board layout directly inserted into the mainboard
design. The connections to the rest of the board are almost the same as
if it were a separate M.2 card. The only addition is the PMU_EN pin on
the chip; on M.2 cards this would be tied to the primary power source.
Model the chip-on-board WiFi/BT solution as a M.2 E-key slot with PCIe,
USB and auxiliary signals. The PMU_EN pin, which enables the internal
power controls and regulators, is modeled as a regulator fed by the
pp3300_wlan regulator. Since power sequencing is now correctly modeled
using the M.2 E-key slot, drop the "regulator-always-on" property one
pp3300_wlan regulator. Also drop the comment in xhci2 saying "MT7921's
power is controlled by PCIe".
Also drop the voltage range on the pp3300_wlan regulator. This
"regulator" is just a load switch and does not provide any regulation.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../boot/dts/mediatek/mt8188-geralt.dtsi | 93 ++++++++++++++++++-
1 file changed, 89 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi b/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
index f382f90c48f5..c4cc2cff1b5b 100644
--- a/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
@@ -86,13 +86,11 @@ pp3300_z1: regulator-pp3300-z1 {
pp3300_wlan: regulator-pp3300-wlan {
compatible = "regulator-fixed";
regulator-name = "pp3300_wlan";
- regulator-always-on;
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
enable-active-high;
gpio = <&pio 12 GPIO_ACTIVE_HIGH>;
pinctrl-0 = <&wlan_en>;
pinctrl-names = "default";
+ /* load switch */
vin-supply = <&pp3300_z1>;
};
@@ -159,6 +157,17 @@ ppvar_mipi_disp_avee: regulator-ppvar-mipi-disp-avee {
vin-supply = <&pp5000_z1>;
};
+ /* PMU_EN pin controls internal regulators and power sequence */
+ wlan_pmu: regulator-wlan-pmu {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-pmu";
+ enable-active-high;
+ gpio = <&pio 145 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&wlan_pmu_en>;
+ pinctrl-names = "default";
+ vin-supply = <&pp3300_wlan>;
+ };
+
reserved_memory: reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -193,6 +202,39 @@ adsp_dma_mem: memory@61000000 {
no-map;
};
};
+
+ wifi-bt-connector {
+ compatible = "pcie-m2-e-connector";
+ pinctrl-names = "default";
+ pinctrl-0 = <&m2_e_key_kill_pins>;
+ vpcie1v8-supply = <&mt6359_vcn18_ldo_reg>;
+ vpcie3v3-supply = <&wlan_pmu>;
+ w-disable1-gpios = <&pio 13 GPIO_ACTIVE_LOW>;
+ w-disable2-gpios = <&pio 14 GPIO_ACTIVE_LOW>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* PCIe for WiFi */
+ port@0 {
+ reg = <0>;
+
+ wifi_ep: endpoint {
+ remote-endpoint = <&pcie_ep>;
+ };
+ };
+
+ /* USB for Bluetooth */
+ port@2 {
+ reg = <2>;
+
+ bt_ep: endpoint {
+ remote-endpoint = <&usb2_ep>;
+ };
+ };
+ };
+ };
};
&adsp {
@@ -657,6 +699,22 @@ &pcie {
pinctrl-names = "default";
pinctrl-0 = <&pcie_pins>;
status = "okay";
+
+ pcie@0 {
+ compatible = "pciclass,0604";
+ reg = <0 0 0 0 0>;
+ device_type = "pci";
+ num-lanes = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ port {
+ pcie_ep: endpoint {
+ remote-endpoint = <&wifi_ep>;
+ };
+ };
+ };
};
&pciephy {
@@ -1000,6 +1058,14 @@ pins-bus {
};
};
+ m2_e_key_kill_pins: m2-e-key-kill-pins {
+ pins-kill {
+ pinmux = <PINMUX_GPIO13__FUNC_B_GPIO13>,
+ <PINMUX_GPIO14__FUNC_B_GPIO14>;
+ output-high;
+ };
+ };
+
mipi_disp_avdd_en: mipi-disp-avdd-en-pins {
pins-en-ppvar-mipi-disp {
pinmux = <PINMUX_GPIO3__FUNC_B_GPIO3>;
@@ -1164,6 +1230,13 @@ pins-bus {
};
};
+ wlan_pmu_en: wlan-pmu-en-pins {
+ pins-wlan-pmu-en {
+ pinmux = <PINMUX_GPIO145__FUNC_B_GPIO145>;
+ output-low;
+ };
+ };
+
wlan_en: wlan-en-pins {
pins-en-pp3300-wlan {
pinmux = <PINMUX_GPIO12__FUNC_B_GPIO12>;
@@ -1343,10 +1416,22 @@ vdosys1_ep_ext: endpoint@1 {
};
&xhci2 {
- /* no power supply since MT7921's power is controlled by PCIe */
/* MT7921's USB BT has issues with USB2 LPM */
usb2-lpm-disable;
status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+
+ usb2_ep: endpoint {
+ remote-endpoint = <&bt_ep>;
+ };
+ };
+ };
};
#include <arm/cros-ec-keyboard.dtsi>
--
2.54.0.1099.g489fc7bff1-goog
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id()
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
@ 2026-06-10 8:55 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 8:55 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] fwnode_graph_get_port_by_id() incorrectly fails to find valid ports if they lack active endpoints, have unconnected endpoints, or are connected to disabled devices.
--
commit 4e84277140473261d2e5a644f3a43bf00c37b050
Author: Chen-Yu Tsai <wenst@chromium.org>
device property: Add fwnode_graph_get_port_by_id()
This commit introduces the fwnode_graph_get_port_by_id() helper to retrieve
a port firmware node matching a given id. It is intended for cases where
drivers need a reference to the port firmware node, such as USB power
sequencing integration.
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
[ ... ]
> @@ -1346,6 +1346,28 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> }
> EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
>
> +/**
> + * fwnode_graph_get_port_by_id - get the port matching a given id
> + * @fwnode: parent fwnode_handle containing the graph
> + * @id: id of the port
> + *
> + * Return: A 'port' firmware node pointer with refcount incremented.
> + *
> + * The caller is responsible for calling fwnode_handle_put() on the returned
> + * fwnode pointer.
> + */
> +struct fwnode_handle *fwnode_graph_get_port_by_id(struct fwnode_handle *fwnode, u32 id)
> +{
> + struct fwnode_handle *ep;
> +
> + ep = fwnode_graph_get_endpoint_by_id(fwnode, id, 0, FWNODE_GRAPH_ENDPOINT_NEXT);
[Severity: High]
Will this fail to find valid ports if they lack active endpoints or have
disabled remote targets?
By calling fwnode_graph_get_endpoint_by_id() without passing the
FWNODE_GRAPH_DEVICE_DISABLED flag, it appears this enforces an implicit
availability check. This skips any endpoints that are unconnected or whose
remote target is disabled.
Additionally, since port discovery is routed exclusively through endpoint
iteration, will this completely miss valid port nodes that contain no
endpoint child nodes?
> + if (!ep)
> + return NULL;
> +
> + return fwnode_get_next_parent(ep);
> +}
> +EXPORT_SYMBOL_GPL(fwnode_graph_get_port_by_id);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=1
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
@ 2026-06-10 8:55 ` sashiko-bot
2026-06-10 9:00 ` Chen-Yu Tsai
1 sibling, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 8:55 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The commit message incorrectly justifies changing CONFIG_POWER_SEQUENCING to bool by falsely claiming that USB support is a boolean option, which unnecessarily prevents building the power sequencing subsystem as a module.
--
commit 80f4a7ca3dbefd1dc2ae2274d131e8b5461c5c66
Author: Chen-Yu Tsai <wenst@chromium.org>
power: sequencing: Change CONFIG_POWER_SEQUENCING to bool
This commit changes the POWER_SEQUENCING Kconfig option from tristate
to bool, citing that USB support cannot be built as a module.
> USB support, including the core and hub driver, is bool, no modules. To
> be able to use the power sequencing API in the USB core, the former must
> also be bool to avoid the latter being built as a module.
[Severity: Medium]
Is this description of USB support accurate? Looking at drivers/usb/Kconfig,
CONFIG_USB is actually defined as a tristate:
config USB
tristate "Support for Host-side USB"
Since the USB core can indeed be built as a loadable module, does
POWER_SEQUENCING strictly need to be restricted to bool here? Could standard
Kconfig patterns like depends on POWER_SEQUENCING || POWER_SEQUENCING=n be
used instead if linkage dependencies need to be resolved?
> diff --git a/drivers/power/sequencing/Kconfig b/drivers/power/sequencing/Kconfig
> index 1c5f5820f5b76..27448fba9dc5d 100644
> --- a/drivers/power/sequencing/Kconfig
> +++ b/drivers/power/sequencing/Kconfig
> @@ -1,7 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-only
>
> menuconfig POWER_SEQUENCING
> - tristate "Power Sequencing support"
> + bool "Power Sequencing support"
[Severity: Medium]
Given that CONFIG_USB is a tristate, does this change unnecessarily prevent
the power sequencing subsystem from being built as a module?
> help
> Say Y here to enable the Power Sequencing subsystem.
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=3
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device
2026-06-10 8:40 ` [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device Chen-Yu Tsai
@ 2026-06-10 8:56 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 8:56 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Leaked firmware node reference obtained from fwnode_graph_get_port_by_id().
--
commit d665d488ed337df469077f70e021bbabc2b8ac61
Author: Chen-Yu Tsai <wenst@chromium.org>
usb: hub: Associate port@ fwnode with USB port device
When a USB hub port is connected to a connector in a firmware node
graph, the port itself has a node in the graph. This commit associates
the port's firmware node with the USB port's device. This is used in
later changes for the M.2 slot power sequencing provider to match
against the requesting port.
> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index b1364f0c384ce..1846eb1206a4d 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -780,6 +780,8 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
> port_dev->dev.driver = &usb_port_driver;
> dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev),
> port1);
> + device_set_node(&port_dev->dev,
> + fwnode_graph_get_port_by_id(dev_fwnode(&hdev->dev), port1));
[Severity: Medium]
Does this code leak the fwnode reference? fwnode_graph_get_port_by_id()
returns a firmware node with its reference count incremented, and the caller
is expected to drop it using fwnode_handle_put() when it is no longer
needed.
device_set_node() merely assigns the fwnode to the device without taking
ownership of the reference count. If device_register() fails:
drivers/usb/core/port.c:usb_hub_create_port_device() {
...
retval = device_register(&port_dev->dev);
if (retval) {
put_device(&port_dev->dev);
return retval;
}
...
}
put_device() eventually calls usb_port_device_release(), which frees the
device memory but does not release the fwnode:
drivers/usb/core/port.c:usb_port_device_release() {
struct usb_port *port_dev = to_usb_port(dev);
kfree(port_dev->req);
kfree(port_dev);
}
The reference also appears to be permanently leaked upon normal device
removal via usb_hub_remove_port_device(), since usb_port_device_release()
lacks a corresponding fwnode_handle_put(dev_fwnode(dev)) call.
> mutex_init(&port_dev->status_lock);
> retval = device_register(&port_dev->dev);
> if (retval) {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=5
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint()
2026-06-10 8:40 ` [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint() Chen-Yu Tsai
@ 2026-06-10 8:57 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 8:57 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Low] The local variable `ep` is declared but never used in `fwnode_graph_get_next_port_endpoint()`.
Pre-existing issues:
- [High] Preexisting Use-After-Free, Double-Free, Memory Leak, and Infinite Loop in `fwnode_get_next_child_node()` when crossing from primary to secondary fwnodes.
--
commit ef024cc56635ec6ba836569acc9c332f8f2249dc
Author: Chen-Yu Tsai <wenst@chromium.org>
device property: Add fwnode_graph_get_next_port_endpoint()
This commit introduces fwnode_graph_get_next_port_endpoint(), a new helper
function that allows consumers to find endpoint nodes under a given port
firmware node. It iterates over the child nodes of the port, checking if
their name matches "endpoint", and returns the matching node.
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 8cbf33f3a9428..badb49ac3d8a4 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
[ ... ]
> @@ -1099,6 +1099,39 @@ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
> }
> EXPORT_SYMBOL(fwnode_irq_get_byname);
>
> +/**
> + * fwnode_graph_get_next_port_endpoint - Get next endpoint firmware node in port
> + * @port: Pointer to the target port firmware node
> + * @prev: Previous endpoint node or %NULL to get the first
> + *
> + * The caller is responsible for calling fwnode_handle_put() on the returned
> + * fwnode pointer. Note that this function also puts a reference to @prev
> + * unconditionally.
> + *
> + * Return: an endpoint firmware node pointer or %NULL if no more endpoints
> + * are available.
> + */
> +struct fwnode_handle *fwnode_graph_get_next_port_endpoint(const struct fwnode_handle *port,
> + struct fwnode_handle *prev)
> +{
> + struct fwnode_handle *ep;
[Severity: Low]
Are there plans to use this local variable later? It appears to be declared
here but never used, which could cause a compiler warning.
> +
> + while (1) {
> + prev = fwnode_get_next_child_node(port, prev);
[Severity: High]
This is a pre-existing issue, but does calling fwnode_get_next_child_node()
here expose a use-after-free and double-free when crossing from primary to
secondary fwnodes?
If a fwnode has both primary (OF) and secondary (swnode) children:
1. When reaching the end of the primary OF children,
of_fwnode_get_next_child_node() drops the reference to the last OF child
and returns NULL.
2. fwnode_get_next_child_node() then delegates to the secondary ops
(software_node_get_next_child), passing the exact same child pointer.
Since the OF node was already put, the secondary ops access freed memory
when checking if the child is a software node, causing a use-after-free.
3. software_node_get_next_child() then unconditionally calls
fwnode_handle_put(child), triggering a double-free.
4. It then returns the first secondary software node. On the next iteration,
the caller passes this swnode back.
The primary OF ops evaluate to_of_node(swnode) as NULL, which causes
of_get_next_available_child() to restart iteration and return the first
OF child again. It also fails to put the swnode, causing a memory leak.
Could this create an infinite loop alternating between the first OF child
and the first software node, repeatedly triggering the use-after-free and
double-free on every cycle?
> + if (!prev)
> + break;
> +
> + if (WARN(!fwnode_name_eq(prev, "endpoint"),
> + "non endpoint node is used (%pfw)", prev))
> + continue;
> +
> + break;
> + }
> +
> + return prev;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_graph_get_next_port_endpoint);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=2
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
@ 2026-06-10 9:00 ` Chen-Yu Tsai
1 sibling, 0 replies; 25+ messages in thread
From: Chen-Yu Tsai @ 2026-06-10 9:00 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Andy Shevchenko,
Daniel Scally, Heikki Krogerus, Sakari Ailus, Rafael J. Wysocki,
Danilo Krummrich, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: Alan Stern, linux-acpi, driver-core, linux-pm, linux-usb,
devicetree, linux-mediatek, linux-arm-kernel, linux-kernel,
Manivannan Sadhasivam
On Wed, Jun 10, 2026 at 5:41 PM Chen-Yu Tsai <wenst@chromium.org> wrote:
>
> USB support, including the core and hub driver, is bool, no modules. To
> be able to use the power sequencing API in the USB core, the former must
> also be bool to avoid the latter being built as a module.
>
> Change CONFIG_POWER_SEQUENCING to bool.
As Sashiko pointed out, CONFIG_USB is tristate. I was looking at the
wrong symbol. Please ignore this patch.
ChenYu
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot
2026-06-10 8:40 ` [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot Chen-Yu Tsai
@ 2026-06-10 9:02 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 9:02 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The pinctrl configuration for the W_DISABLE kill pins drives them physically HIGH before the VIO/VCC regulators are enabled, causing chip back-powering and an initial signal glitch.
--
commit c9c4e7dd87a963320b0c2bf646e1e008f5ee5638
Author: Chen-Yu Tsai <wenst@chromium.org>
arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot
This commit models the chip-on-board WiFi/BT solution on MT8188 Geralt as
an M.2 E-key slot. It adds the PMU_EN pin controls and drops the always-on
property from the pp3300_wlan regulator to properly reflect power sequencing.
> diff --git a/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi b/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
> index 4cb23595d17b4..d7b5eb95ba0fe 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8188-geralt.dtsi
[ ... ]
> @@ -193,6 +202,39 @@ adsp_dma_mem: memory@61000000 {
> no-map;
> };
> };
> +
> + wifi-bt-connector {
> + compatible = "pcie-m2-e-connector";
> + pinctrl-names = "default";
> + pinctrl-0 = <&m2_e_key_kill_pins>;
> + vpcie1v8-supply = <&mt6359_vcn18_ldo_reg>;
> + vpcie3v3-supply = <&wlan_pmu>;
> + w-disable1-gpios = <&pio 13 GPIO_ACTIVE_LOW>;
> + w-disable2-gpios = <&pio 14 GPIO_ACTIVE_LOW>;
[ ... ]
> @@ -999,6 +1057,14 @@ pins-bus {
> };
> };
>
> + m2_e_key_kill_pins: m2-e-key-kill-pins {
> + pins-kill {
> + pinmux = <PINMUX_GPIO13__FUNC_B_GPIO13>,
> + <PINMUX_GPIO14__FUNC_B_GPIO14>;
> + output-high;
[Severity: High]
Since pp3300_wlan is no longer always-on, does this output-high configuration
cause the unpowered Wi-Fi/BT chip to be back-powered?
The device core automatically applies the default pinctrl state during
instantiation, before the power sequence driver probes and turns on the
regulators. Driving a physical HIGH voltage into the w-disable pins of an
unpowered IC can forward-bias internal ESD diodes and leak current.
Additionally, when the driver eventually probes, it will request the
w-disable pins. Since the wifi-bt-connector node defines them as
GPIO_ACTIVE_LOW, requesting a logical HIGH translates to a physical LOW.
Will this result in an unintended HIGH-to-LOW physical glitch on the
unpowered chip's w-disable lines before the regulators are finally enabled?
> + };
> + };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=16
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: Add M.2 E-key slot
2026-06-10 8:40 ` [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: " Chen-Yu Tsai
@ 2026-06-10 9:03 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 9:03 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Deletion of the `wifi@0` child node removes the `wakeup-source` property, breaking default Wake-on-WLAN (WOWLAN) capability.
--
commit f79abe85df05e70cd87af21f7a5b924157250109
Author: Chen-Yu Tsai <wenst@chromium.org>
arm64: dts: mediatek: mt8195-cherry: Add M.2 E-key slot
The commit adds an M.2 E-key slot representation for the Mt8195 Cherry
design. It wires up PCIe, USB, and auxiliary signals, replacing the older
PCIe wifi node and power supply properties.
> diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
> index ef7afc436aefc..c95a54de35672 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
[ ... ]
> @@ -791,14 +832,14 @@ pcie@0 {
> reg = <0 0 0 0 0>;
> device_type = "pci";
> num-lanes = <1>;
> - vpcie3v3-supply = <&pp3300_wlan>;
> #address-cells = <3>;
> #size-cells = <2>;
> ranges;
>
> - wifi@0 {
> - reg = <0 0 0 0 0>;
> - wakeup-source;
[Severity: Medium]
Does this removal break default Wake-on-WLAN (WOWLAN) capability?
The mt7921 Wi-Fi driver specifically checks for the wakeup-source property
on its Device Tree node during probe to call device_init_wakeup() and
enable Wake-on-WLAN by default.
By replacing the wifi@0 node with an OF graph port endpoint, the PCI core
will no longer match the PCI device to an OF node, making dev->of_node NULL.
This means the driver will not detect the property and could silently leave
default WOWLAN disabled.
> + port {
> + pcie1_ep: endpoint {
> + remote-endpoint = <&wifi_ep>;
> + };
> };
> };
> };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=14
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors
2026-06-10 8:40 ` [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors Chen-Yu Tsai
@ 2026-06-10 9:03 ` sashiko-bot
0 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 9:03 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] Unconditional calls to power sequencing APIs will fail all USB port initializations when `CONFIG_POWER_SEQUENCING` is disabled.
- [High] Concurrent modification of the `pwrseq_on` bitfield on a shared `usb_port` device causes data races and corruption of other bitfields.
- [High] Premature physical power-off of the shared M.2 E-key power sequencer when one peer logical port suspends, unexpectedly disconnecting the active peer.
- [Medium] Leaked fwnode reference during USB port creation via `fwnode_graph_get_port_by_id()`.
--
commit 984160fb49fab6dc951a766897ded9fb49d0992b
Author: Chen-Yu Tsai <wenst@chromium.org>
usb: hub: Power on connected M.2 E-key connectors
This patch adds support for powering on directly connected M.2 E-key
connectors via the power sequencing API. It ties the power sequencing
descriptor to the usb port device to allow providers to distinguish
ports on a hub. The power state is toggled using the power sequencing
API during port power changes.
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 0c75965fefb7c..585b6beec71bb 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -886,20 +887,41 @@ static void hub_tt_work(struct work_struct *work)
> int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
> int port1, bool set)
> {
> - int ret;
> + struct usb_port *pwrseq_port = hub->ports[port1 - 1];
> + int ret = 0;
> +
> + /* non-SuperSpeed USB port holds pwrseq descriptor reference. */
> + if (hub->ports[port1 - 1]->is_superspeed && hub->ports[port1 - 1]->peer)
> + pwrseq_port = hub->ports[port1 - 1]->peer;
> +
> + if (set && !pwrseq_port->pwrseq_on)
> + ret = pwrseq_power_on(pwrseq_port->pwrseq);
> + else if (!set && pwrseq_port->pwrseq_on)
> + ret = pwrseq_power_off(pwrseq_port->pwrseq);
[Severity: High]
Will this prematurely cut physical power to the M.2 slot if the HiSpeed
logical port suspends?
A physical M.2 connector has both a SuperSpeed and HiSpeed logical port.
This patch binds the power sequencing descriptor only to the HiSpeed port
and shares a single pwrseq_on boolean for both logical ports.
If a SuperSpeed device is connected, the SuperSpeed port remains active,
but the HiSpeed port suspends via usb_port_runtime_suspend() since it detects
no active HiSpeed device. Suspending the HiSpeed port invokes
usb_hub_set_port_power(..., false) which immediately calls
pwrseq_power_off() here since pwrseq_on is true.
This would abruptly cut physical power to the M.2 slot and drop the active
SuperSpeed device, because the boolean flag bypasses the power sequencing
framework's internal reference counting and ignores the active state of the
SuperSpeed port.
> + if (ret)
> + return ret;
>
> if (set)
> ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> else
> ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
>
> - if (ret)
> + if (ret) {
> + if (set && !pwrseq_port->pwrseq_on)
> + pwrseq_power_off(pwrseq_port->pwrseq);
> + else if (!set && pwrseq_port->pwrseq_on)
> + pwrseq_power_on(pwrseq_port->pwrseq);
> return ret;
> + }
>
> - if (set)
> + if (set) {
> set_bit(port1, hub->power_bits);
> - else
> + pwrseq_port->pwrseq_on = 1;
> + } else {
> clear_bit(port1, hub->power_bits);
> + pwrseq_port->pwrseq_on = 0;
> + }
[Severity: High]
Could modifying this bitfield without holding usb_lock_port() cause a data race?
Since pwrseq_on is packed alongside other 1-bit fields in struct usb_port
(like ignore_event, early_stop, and usb3_lpm_u1_permit), modifying it here
in usb_hub_set_port_power() without synchronization can cause a
read-modify-write data race.
If sysfs (like usb3_lpm_u1_permit_store) or hub event workqueues modify
adjacent bits under their respective locks concurrently, one thread's update
could silently overwrite the other's, corrupting the port state.
[ ... ]
> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index d9d3e2bb8f251..a5e7fbf4aa6e2 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -803,10 +846,25 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
> goto err_put_kn;
> }
>
[Severity: Medium]
Does port creation leak an fwnode reference here?
Earlier in usb_hub_create_port_device(), the call to
fwnode_graph_get_port_by_id() returns a firmware node with an incremented
reference count. This node is passed to device_set_node(), which assigns it
but does not take ownership of the reference.
Neither the error paths in usb_hub_create_port_device(), nor
usb_hub_remove_port_device() call fwnode_handle_put() to release it, causing
a reference leak every time a usb port is enumerated.
> + port_dev->pwrseq = usb_hub_port_pwrseq_get(port_dev);
> + if (IS_ERR(port_dev->pwrseq)) {
> + retval = PTR_ERR(port_dev->pwrseq);
> + dev_err_probe(&port_dev->dev, retval,
> + "failed to get power sequencing descriptor\n");
> + goto err_put_kn;
> + }
> +
> + retval = pwrseq_power_on(port_dev->pwrseq);
> + if (retval) {
> + dev_err_probe(&port_dev->dev, retval, "failed to enable power\n");
> + goto err_put_pwrseq;
> + }
[Severity: Critical]
Will this fail port creation for all usb ports when power sequencing
is disabled?
If the kernel is built without power sequencing enabled,
usb_hub_port_pwrseq_get() deliberately returns NULL.
However, pwrseq_power_on(NULL) unconditionally returns -ENOSYS when the
feature is disabled. Treating -ENOSYS as a hard failure here will abort port
creation, causing the entire usb subsystem to fail enumerating any ports on
systems where power sequencing is disabled.
> + port_dev->pwrseq_on = 1;
> +
> retval = component_add(&port_dev->dev, &connector_ops);
> if (retval) {
> dev_warn(&port_dev->dev, "failed to add component\n");
> - goto err_put_kn;
> + goto err_pwrseq_off;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=7
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2026-06-10 9:03 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint() Chen-Yu Tsai
2026-06-10 8:57 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 9:00 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 04/16] usb: hub: Return actual error from hub_configure() in hub_probe() Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device Chen-Yu Tsai
2026-06-10 8:56 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 06/16] usb: hub: Pass |struct usb_port*| to usb_port_is_power_on() Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 08/16] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP" Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 09/16] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 10/16] power: sequencing: pcie-m2: support matching on remote "port" node Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 11/16] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 12/16] arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 13/16] arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: " Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 15/16] arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot Chen-Yu Tsai
2026-06-10 9:02 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox