[PATCH v7 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue
From: Jihong Min
Date: Mon May 18 2026 - 20:10:01 EST
AMD Promontory 21 (PROM21) xHCI PCI functions use the common xhci-pci
core for USB operation, but also expose controller-specific sensor data.
Add a small PROM21 PCI glue driver for AMD 1022:43fc and 1022:43fd
controllers.
The glue delegates USB host operation to the common xhci-pci core and
publishes a "hwmon" auxiliary device with parent-provided MMIO data.
Auxiliary device creation failure is logged but does not fail the xHCI
probe.
Make the PROM21 glue a hidden Kconfig tristate driven by the user-visible
SENSORS_PROM21_XHCI option. If sensor support is disabled, generic
xhci-pci binds PROM21 controllers normally. If sensor support is enabled,
the glue follows USB_XHCI_PCI.
This keeps the auxiliary device available for a modular sensor driver while
avoiding a built-in xhci-pci core handing PROM21 controllers to a glue
driver that is only available as a module during initramfs.
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@xxxxxxxxx>
Reviewed-by: Mario Limonciello (AMD) <superm1@xxxxxxxxxx>
Tested-by: Yaroslav Isakov <yaroslav.isakov@xxxxxxxxx>
---
drivers/usb/host/Kconfig | 6 +
drivers/usb/host/Makefile | 1 +
drivers/usb/host/xhci-pci-prom21.c | 137 ++++++++++++++++++
drivers/usb/host/xhci-pci.c | 11 ++
drivers/usb/host/xhci-pci.h | 3 +
include/linux/platform_data/usb-xhci-prom21.h | 22 +++
6 files changed, 180 insertions(+)
create mode 100644 drivers/usb/host/xhci-pci-prom21.c
create mode 100644 include/linux/platform_data/usb-xhci-prom21.h
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0a277a07cf70..43f30cd867e4 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -42,6 +42,12 @@ config USB_XHCI_PCI
depends on USB_PCI
default y
+config USB_XHCI_PCI_PROM21
+ tristate
+ depends on USB_XHCI_PCI
+ default USB_XHCI_PCI if SENSORS_PROM21_XHCI != n
+ select AUXILIARY_BUS
+
config USB_XHCI_PCI_RENESAS
tristate "Support for additional Renesas xHCI controller with firmware"
depends on USB_XHCI_PCI
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index a07e7ba9cd53..174580c1281a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
+obj-$(CONFIG_USB_XHCI_PCI_PROM21) += xhci-pci-prom21.o
obj-$(CONFIG_USB_XHCI_PCI_RENESAS) += xhci-pci-renesas.o
obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
obj-$(CONFIG_USB_XHCI_HISTB) += xhci-histb.o
diff --git a/drivers/usb/host/xhci-pci-prom21.c b/drivers/usb/host/xhci-pci-prom21.c
new file mode 100644
index 000000000000..6486f4a09345
--- /dev/null
+++ b/drivers/usb/host/xhci-pci-prom21.c
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD Promontory 21 xHCI host controller PCI Bus Glue.
+ *
+ * This does not add any PROM21-specific USB or xHCI operation. It exists only
+ * to publish an auxiliary device for integrated temperature sensor support.
+ *
+ * Copyright (C) 2026 Jihong Min <hurryman2212@xxxxxxxxx>
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device/devres.h>
+#include <linux/errno.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_data/usb-xhci-prom21.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "xhci-pci.h"
+
+struct prom21_xhci_auxdev {
+ struct auxiliary_device *auxdev;
+ struct prom21_xhci_pdata pdata;
+ int id;
+};
+
+static DEFINE_IDA(prom21_xhci_auxdev_ida);
+
+static void prom21_xhci_auxdev_release(struct device *dev, void *res)
+{
+ struct prom21_xhci_auxdev *prom21_auxdev = res;
+
+ auxiliary_device_destroy(prom21_auxdev->auxdev);
+ ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id);
+}
+
+static int prom21_xhci_create_auxdev(struct pci_dev *pdev)
+{
+ struct prom21_xhci_auxdev *prom21_auxdev;
+ struct usb_hcd *hcd = pci_get_drvdata(pdev);
+ int ret;
+
+ prom21_auxdev = devres_alloc(prom21_xhci_auxdev_release,
+ sizeof(*prom21_auxdev), GFP_KERNEL);
+ if (!prom21_auxdev)
+ return -ENOMEM;
+
+ prom21_auxdev->pdata.pdev = pdev;
+ prom21_auxdev->pdata.regs = hcd->regs;
+ prom21_auxdev->pdata.rsrc_len = hcd->rsrc_len;
+
+ prom21_auxdev->id = ida_alloc(&prom21_xhci_auxdev_ida, GFP_KERNEL);
+ if (prom21_auxdev->id < 0) {
+ ret = prom21_auxdev->id;
+ goto err_free_devres;
+ }
+
+ prom21_auxdev->auxdev = auxiliary_device_create(&pdev->dev,
+ KBUILD_MODNAME, "hwmon",
+ &prom21_auxdev->pdata,
+ prom21_auxdev->id);
+ if (!prom21_auxdev->auxdev) {
+ ret = -ENOMEM;
+ goto err_free_ida;
+ }
+
+ devres_add(&pdev->dev, prom21_auxdev);
+ return 0;
+
+err_free_ida:
+ ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id);
+err_free_devres:
+ devres_free(prom21_auxdev);
+ return ret;
+}
+
+static void prom21_xhci_destroy_auxdev(struct pci_dev *pdev)
+{
+ devres_release(&pdev->dev, prom21_xhci_auxdev_release, NULL, NULL);
+}
+
+static int prom21_xhci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ int retval;
+
+ retval = xhci_pci_common_probe(dev, id);
+ if (retval)
+ return retval;
+
+ retval = prom21_xhci_create_auxdev(dev);
+ if (retval) {
+ /*
+ * The auxiliary device only provides optional temperature sensor
+ * support. Keep the xHCI controller usable if it fails.
+ */
+ dev_err(&dev->dev,
+ "failed to create PROM21 hwmon auxiliary device: %d\n",
+ retval);
+ }
+
+ return 0;
+}
+
+static void prom21_xhci_remove(struct pci_dev *dev)
+{
+ prom21_xhci_destroy_auxdev(dev);
+ xhci_pci_remove(dev);
+}
+
+static const struct pci_device_id pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD) },
+ { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver prom21_xhci_driver = {
+ .name = "xhci-pci-prom21",
+ .id_table = pci_ids,
+
+ .probe = prom21_xhci_probe,
+ .remove = prom21_xhci_remove,
+
+ .shutdown = usb_hcd_pci_shutdown,
+ .driver = {
+ .pm = pm_ptr(&usb_hcd_pci_pm_ops),
+ },
+};
+module_pci_driver(prom21_xhci_driver);
+
+MODULE_AUTHOR("Jihong Min <hurryman2212@xxxxxxxxx>");
+MODULE_DESCRIPTION("AMD Promontory 21 xHCI PCI Host Controller Driver");
+MODULE_IMPORT_NS("xhci");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 585b2f3117b0..039c26b241d0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -696,12 +696,23 @@ static const struct pci_device_id pci_ids_renesas[] = {
{ /* end: all zeroes */ }
};
+/* handled by xhci-pci-prom21 if enabled */
+static const struct pci_device_id pci_ids_prom21[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD) },
+ { /* end: all zeroes */ }
+};
+
static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
if (IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) &&
pci_match_id(pci_ids_renesas, dev))
return -ENODEV;
+ if (IS_ENABLED(CONFIG_USB_XHCI_PCI_PROM21) &&
+ pci_match_id(pci_ids_prom21, dev))
+ return -ENODEV;
+
return xhci_pci_common_probe(dev, id);
}
diff --git a/drivers/usb/host/xhci-pci.h b/drivers/usb/host/xhci-pci.h
index e87c7d9d76b8..11f435f94322 100644
--- a/drivers/usb/host/xhci-pci.h
+++ b/drivers/usb/host/xhci-pci.h
@@ -4,6 +4,9 @@
#ifndef XHCI_PCI_H
#define XHCI_PCI_H
+#define PCI_DEVICE_ID_AMD_PROM21_XHCI_43FC 0x43fc
+#define PCI_DEVICE_ID_AMD_PROM21_XHCI_43FD 0x43fd
+
int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id);
void xhci_pci_remove(struct pci_dev *dev);
diff --git a/include/linux/platform_data/usb-xhci-prom21.h b/include/linux/platform_data/usb-xhci-prom21.h
new file mode 100644
index 000000000000..ee672ad452a8
--- /dev/null
+++ b/include/linux/platform_data/usb-xhci-prom21.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * AMD Promontory 21 xHCI auxiliary device platform data.
+ *
+ * Copyright (C) 2026 Jihong Min <hurryman2212@xxxxxxxxx>
+ */
+
+#ifndef _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H
+#define _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H
+
+#include <linux/compiler_types.h>
+#include <linux/types.h>
+
+struct pci_dev;
+
+struct prom21_xhci_pdata {
+ struct pci_dev *pdev;
+ void __iomem *regs;
+ resource_size_t rsrc_len;
+};
+
+#endif
--
2.53.0