* [PATCH v6 0/2] AMD Promontory 21 xHCI temperature sensor support @ 2026-05-17 13:04 Jihong Min 2026-05-17 13:04 ` [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue Jihong Min 2026-05-17 13:04 ` [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support Jihong Min 0 siblings, 2 replies; 12+ messages in thread From: Jihong Min @ 2026-05-17 13:04 UTC (permalink / raw) To: Greg Kroah-Hartman, Mathias Nyman Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Jihong Min Hi, This series adds temperature monitoring for AMD Promontory 21 (PROM21) xHCI PCI functions. Patch 1 adds a small PROM21-specific xHCI PCI glue driver. USB host operation is delegated to the common xhci-pci code, while the PROM21 glue publishes an auxiliary device for optional sensor support. Patch 2 adds an auxiliary-bus hwmon driver that binds to that auxiliary device and exposes the PROM21 xHCI temperature value as temp1_input. The hwmon driver reads the sensor through a vendor index/data register pair in the xHCI PCI MMIO BAR. It does not wake the parent PCI device for hwmon reads; if the parent is suspended, the read returns -ENODATA. Changes in v6: - Make USB_XHCI_PCI_PROM21 a hidden tristate that follows USB_XHCI_PCI, so the PROM21 PCI glue is built in with a built-in xhci-pci core and built as a module with a modular xhci-pci core. - Use an IDA-allocated auxiliary device id instead of encoding the PCI domain/BDF into the auxiliary id. - Use a 32-bit read for the PROM21 vendor data register and mask the low byte instead of using readb(). Jihong Min (2): usb: xhci-pci: add AMD Promontory 21 PCI glue hwmon: add AMD Promontory 21 xHCI temperature sensor support Documentation/hwmon/index.rst | 1 + Documentation/hwmon/prom21-xhci.rst | 101 ++++++++ drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/prom21-xhci.c | 239 ++++++++++++++++++ drivers/usb/host/Kconfig | 7 + drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-pci-prom21.c | 136 ++++++++++ drivers/usb/host/xhci-pci.c | 11 + drivers/usb/host/xhci-pci.h | 3 + include/linux/platform_data/usb-xhci-prom21.h | 22 ++ 11 files changed, 532 insertions(+) create mode 100644 Documentation/hwmon/prom21-xhci.rst create mode 100644 drivers/hwmon/prom21-xhci.c create mode 100644 drivers/usb/host/xhci-pci-prom21.c create mode 100644 include/linux/platform_data/usb-xhci-prom21.h -- 2.53.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-17 13:04 [PATCH v6 0/2] AMD Promontory 21 xHCI temperature sensor support Jihong Min @ 2026-05-17 13:04 ` Jihong Min 2026-05-17 21:21 ` Michal Pecio 2026-05-17 13:04 ` [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support Jihong Min 1 sibling, 1 reply; 12+ messages in thread From: Jihong Min @ 2026-05-17 13:04 UTC (permalink / raw) To: Greg Kroah-Hartman, Mathias Nyman Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Jihong Min, Mario Limonciello (AMD), Yaroslav Isakov AMD Promontory 21 (PROM21) xHCI controllers use generic xHCI operation, but the PCI function also exposes optional controller-specific sensor functionality. Add a small PROM21 PCI glue driver for AMD 1022:43fc and 1022:43fd controllers. The driver delegates USB host operation to the common xhci-pci core, collects the parent-provided MMIO resource data, and creates a "hwmon" auxiliary device for optional child drivers. Failure to create the auxiliary device is logged but does not fail the xHCI probe, since the auxiliary device is only needed for sensor support. Make the PROM21 PCI glue a hidden Kconfig tristate that follows USB_XHCI_PCI. This keeps the glue built in with a built-in xhci-pci core and builds it as a module with a modular xhci-pci core. A built-in xhci-pci core must not hand PROM21 controllers to a PROM21 glue driver that is only available as a module, otherwise USB behind those controllers can be unavailable during initramfs and PROM21 temperature sensor support may not appear until the controller is rebound after the module loads. Assisted-by: Codex:gpt-5.5 Signed-off-by: Jihong Min <hurryman2212@gmail.com> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> --- drivers/usb/host/Kconfig | 7 + drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-pci-prom21.c | 136 ++++++++++++++++++ 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..89bf262235e1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -42,6 +42,13 @@ config USB_XHCI_PCI depends on USB_PCI default y +config USB_XHCI_PCI_PROM21 + tristate + depends on X86 + depends on USB_XHCI_PCI + default USB_XHCI_PCI + 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..be0933ca5c62 --- /dev/null +++ b/drivers/usb/host/xhci-pci-prom21.c @@ -0,0 +1,136 @@ +// 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@gmail.com> + */ + +#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); + + if (!hcd) + return -ENODEV; + + 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) { + int ret = prom21_auxdev->id; + + devres_free(prom21_auxdev); + return ret; + } + + prom21_auxdev->auxdev = auxiliary_device_create(&pdev->dev, + KBUILD_MODNAME, "hwmon", + &prom21_auxdev->pdata, + prom21_auxdev->id); + if (!prom21_auxdev->auxdev) { + ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id); + devres_free(prom21_auxdev); + return -ENOMEM; + } + + devres_add(&pdev->dev, prom21_auxdev); + return 0; +} + +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@gmail.com>"); +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@gmail.com> + */ + +#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 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-17 13:04 ` [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue Jihong Min @ 2026-05-17 21:21 ` Michal Pecio 2026-05-18 10:55 ` Guenter Roeck 2026-05-18 20:30 ` Jihong Min 0 siblings, 2 replies; 12+ messages in thread From: Michal Pecio @ 2026-05-17 21:21 UTC (permalink / raw) To: Jihong Min Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On Sun, 17 May 2026 22:04:06 +0900, Jihong Min wrote: > AMD Promontory 21 (PROM21) xHCI controllers use generic xHCI > operation, but the PCI function also exposes optional > controller-specific sensor functionality. Add a small PROM21 PCI glue > driver for AMD 1022:43fc and 1022:43fd controllers. > > The driver delegates USB host operation to the common xhci-pci core, > collects the parent-provided MMIO resource data, and creates a "hwmon" > auxiliary device for optional child drivers. Failure to create the > auxiliary device is logged but does not fail the xHCI probe, since the > auxiliary device is only needed for sensor support. > > Make the PROM21 PCI glue a hidden Kconfig tristate that follows > USB_XHCI_PCI. This keeps the glue built in with a built-in xhci-pci core > and builds it as a module with a modular xhci-pci core. A built-in > xhci-pci core must not hand PROM21 controllers to a PROM21 glue driver > that is only available as a module, otherwise USB behind those controllers > can be unavailable during initramfs and PROM21 temperature sensor support > may not appear until the controller is rebound after the module loads. > > Assisted-by: Codex:gpt-5.5 > Signed-off-by: Jihong Min <hurryman2212@gmail.com> > Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> > Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> > --- > drivers/usb/host/Kconfig | 7 + > drivers/usb/host/Makefile | 1 + > drivers/usb/host/xhci-pci-prom21.c | 136 ++++++++++++++++++ > 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..89bf262235e1 100644 > --- a/drivers/usb/host/Kconfig > +++ b/drivers/usb/host/Kconfig > @@ -42,6 +42,13 @@ config USB_XHCI_PCI > depends on USB_PCI > default y > > +config USB_XHCI_PCI_PROM21 > + tristate > + depends on X86 > + depends on USB_XHCI_PCI > + default USB_XHCI_PCI > + select AUXILIARY_BUS > + Instead of the X86 heuristic, would it be possible to build glue code if and only if SENSORS_PROM21_XHCI is enabled? This seems to work: config SENSORS_PROM21_XHCI tristate "AMD Promontory 21 xHCI temperature sensor" - depends on USB_XHCI_PCI_PROM21 + depends on USB_XHCI_PCI config USB_XHCI_PCI_PROM21 tristate - depends on X86 depends on USB_XHCI_PCI - default USB_XHCI_PCI + default USB_XHCI_PCI if SENSORS_PROM21_XHCI != 'n' select AUXILIARY_BUS I don't know if it's the best way, perhaps it would be preferable for the hwmon driver to select the glue, but then I'm not sure how to force glue to become 'y' when xhci-pci is 'y'. > 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..be0933ca5c62 > --- /dev/null > +++ b/drivers/usb/host/xhci-pci-prom21.c > @@ -0,0 +1,136 @@ > +// 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@gmail.com> > + */ > + > +#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); > + > + if (!hcd) > + return -ENODEV; Shouldn't be necessary after successful xhci_pci_common_probe(). > + > + 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) { > + int ret = prom21_auxdev->id; > + > + devres_free(prom21_auxdev); > + return ret; > + } > + > + prom21_auxdev->auxdev = auxiliary_device_create(&pdev->dev, > + KBUILD_MODNAME, "hwmon", > + &prom21_auxdev->pdata, > + prom21_auxdev->id); > + if (!prom21_auxdev->auxdev) { > + ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id); > + devres_free(prom21_auxdev); > + return -ENOMEM; The usual "goto error" pattern could be used instead of increasingly long sequences of xxx_free() calls. > + } > + > + devres_add(&pdev->dev, prom21_auxdev); > + return 0; > +} > + > +static void prom21_xhci_destroy_auxdev(struct pci_dev *pdev) > +{ > + devres_release(&pdev->dev, prom21_xhci_auxdev_release, NULL, NULL); > +} > + It seems that these three functions above are everything that you truly want to add; the rest is boilerplate required by this two-module scheme to work, plus ID tables which must be duplicated and kept in sync. I wonder if a separate module is really justified, as opposed to simply linking this file into xhci_pci.ko when directed by Kconfig. The downside would be slightly higher memory usage on systems where the hwmon driver is enabled but not needed. OTOH, same systems would likely see reduced disk waste. > +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@gmail.com>"); > +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@gmail.com> > + */ > + > +#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 > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-17 21:21 ` Michal Pecio @ 2026-05-18 10:55 ` Guenter Roeck 2026-05-18 20:34 ` Michal Pecio 2026-05-18 20:30 ` Jihong Min 1 sibling, 1 reply; 12+ messages in thread From: Guenter Roeck @ 2026-05-18 10:55 UTC (permalink / raw) To: Michal Pecio, Jihong Min Cc: Greg Kroah-Hartman, Mathias Nyman, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/17/26 14:21, Michal Pecio wrote: > On Sun, 17 May 2026 22:04:06 +0900, Jihong Min wrote: >> AMD Promontory 21 (PROM21) xHCI controllers use generic xHCI >> operation, but the PCI function also exposes optional >> controller-specific sensor functionality. Add a small PROM21 PCI glue >> driver for AMD 1022:43fc and 1022:43fd controllers. >> >> The driver delegates USB host operation to the common xhci-pci core, >> collects the parent-provided MMIO resource data, and creates a "hwmon" >> auxiliary device for optional child drivers. Failure to create the >> auxiliary device is logged but does not fail the xHCI probe, since the >> auxiliary device is only needed for sensor support. >> >> Make the PROM21 PCI glue a hidden Kconfig tristate that follows >> USB_XHCI_PCI. This keeps the glue built in with a built-in xhci-pci core >> and builds it as a module with a modular xhci-pci core. A built-in >> xhci-pci core must not hand PROM21 controllers to a PROM21 glue driver >> that is only available as a module, otherwise USB behind those controllers >> can be unavailable during initramfs and PROM21 temperature sensor support >> may not appear until the controller is rebound after the module loads. >> >> Assisted-by: Codex:gpt-5.5 >> Signed-off-by: Jihong Min <hurryman2212@gmail.com> >> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> >> Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> >> --- >> drivers/usb/host/Kconfig | 7 + >> drivers/usb/host/Makefile | 1 + >> drivers/usb/host/xhci-pci-prom21.c | 136 ++++++++++++++++++ >> 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..89bf262235e1 100644 >> --- a/drivers/usb/host/Kconfig >> +++ b/drivers/usb/host/Kconfig >> @@ -42,6 +42,13 @@ config USB_XHCI_PCI >> depends on USB_PCI >> default y >> >> +config USB_XHCI_PCI_PROM21 >> + tristate >> + depends on X86 >> + depends on USB_XHCI_PCI >> + default USB_XHCI_PCI >> + select AUXILIARY_BUS >> + > > Instead of the X86 heuristic, would it be possible to build glue > code if and only if SENSORS_PROM21_XHCI is enabled? > > This seems to work: > > config SENSORS_PROM21_XHCI > tristate "AMD Promontory 21 xHCI temperature sensor" > - depends on USB_XHCI_PCI_PROM21 > + depends on USB_XHCI_PCI > > config USB_XHCI_PCI_PROM21 > tristate > - depends on X86 > depends on USB_XHCI_PCI > - default USB_XHCI_PCI > + default USB_XHCI_PCI if SENSORS_PROM21_XHCI != 'n' > select AUXILIARY_BUS > > I don't know if it's the best way, perhaps it would be preferable for > the hwmon driver to select the glue, but then I'm not sure how to force > glue to become 'y' when xhci-pci is 'y'. > Unless I am missing something, that would disable the entire controller if the hwmon device is not enabled. That seems a bit draconian to me. Guenter ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-18 10:55 ` Guenter Roeck @ 2026-05-18 20:34 ` Michal Pecio 0 siblings, 0 replies; 12+ messages in thread From: Michal Pecio @ 2026-05-18 20:34 UTC (permalink / raw) To: Guenter Roeck Cc: Jihong Min, Greg Kroah-Hartman, Mathias Nyman, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On Mon, 18 May 2026 03:55:52 -0700, Guenter Roeck wrote: > On 5/17/26 14:21, Michal Pecio wrote: > > Instead of the X86 heuristic, would it be possible to build glue > > code if and only if SENSORS_PROM21_XHCI is enabled? > > > > This seems to work: > > > > config SENSORS_PROM21_XHCI > > tristate "AMD Promontory 21 xHCI temperature sensor" > > - depends on USB_XHCI_PCI_PROM21 > > + depends on USB_XHCI_PCI > > > > config USB_XHCI_PCI_PROM21 > > tristate > > - depends on X86 > > depends on USB_XHCI_PCI > > - default USB_XHCI_PCI > > + default USB_XHCI_PCI if SENSORS_PROM21_XHCI != 'n' > > select AUXILIARY_BUS > > > > I don't know if it's the best way, perhaps it would be preferable for > > the hwmon driver to select the glue, but then I'm not sure how to force > > glue to become 'y' when xhci-pci is 'y'. > > > > Unless I am missing something, that would disable the entire controller > if the hwmon device is not enabled. That seems a bit draconian to me. I haven't tested (I don't have this chipset), but it should work like the similar xhci-pci-renesas module, which I'm familiar with. When the special unicorn module is disabled by Kconfig, xhci-pci no longer rejects its devices and works with them normally, like it always did before the unicorn module even existed. It should be the same with xhci-pci-prom21. You don't need to enable this module to use USB, only for the special functions. So if hwmon is disabled then you can disable it too. I always found this dual-driver solution (for Renesas) rather ugly and confusing, but so far it's the least bad option tried. Hmm, maybe the next iteration should be an aux bus interface for FW loaders... Regards, Michal ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-17 21:21 ` Michal Pecio 2026-05-18 10:55 ` Guenter Roeck @ 2026-05-18 20:30 ` Jihong Min 2026-05-18 21:37 ` Michal Pecio 2026-05-18 23:07 ` Jihong Min 1 sibling, 2 replies; 12+ messages in thread From: Jihong Min @ 2026-05-18 20:30 UTC (permalink / raw) To: Michal Pecio Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/18/26 06:21, Michal Pecio wrote: > Instead of the X86 heuristic, would it be possible to build glue > code if and only if SENSORS_PROM21_XHCI is enabled? > > This seems to work: > > config SENSORS_PROM21_XHCI > tristate "AMD Promontory 21 xHCI temperature sensor" > - depends on USB_XHCI_PCI_PROM21 > + depends on USB_XHCI_PCI > > config USB_XHCI_PCI_PROM21 > tristate > - depends on X86 > depends on USB_XHCI_PCI > - default USB_XHCI_PCI > + default USB_XHCI_PCI if SENSORS_PROM21_XHCI != 'n' > select AUXILIARY_BUS > > I don't know if it's the best way, perhaps it would be preferable for > the hwmon driver to select the glue, but then I'm not sure how to force > glue to become 'y' when xhci-pci is 'y'. I think I should keep the current hidden glue option for now. The PROM21 PCI glue is part of the PCI binding path for the xHCI controller when enabled, while SENSORS_PROM21_XHCI is only the optional user-visible hwmon driver. Tying the glue to the hwmon option would make the sensor option affect which driver binds the USB controller. As Guenter pointed out, that would be too strong; the USB controller should not depend on whether the optional hwmon driver is enabled. So I would prefer to keep USB_XHCI_PCI_PROM21 as hidden plumbing that follows USB_XHCI_PCI, and keep SENSORS_PROM21_XHCI as the user-visible sensor option. > +static int prom21_xhci_create_auxdev(struct pci_dev *pdev) > +{ > + struct prom21_xhci_auxdev *prom21_auxdev; > + struct usb_hcd *hcd = pci_get_drvdata(pdev); > + > + if (!hcd) > + return -ENODEV; > > Shouldn't be necessary after successful xhci_pci_common_probe(). Agreed. I removed the unnecessary NULL check from prom21_xhci_create_auxdev() locally for v7. > + prom21_auxdev->id = ida_alloc(&prom21_xhci_auxdev_ida, GFP_KERNEL); > + if (prom21_auxdev->id < 0) { > + int ret = prom21_auxdev->id; > + > + devres_free(prom21_auxdev); > + return ret; > + } > + > + prom21_auxdev->auxdev = auxiliary_device_create(&pdev->dev, > + KBUILD_MODNAME, "hwmon", > + &prom21_auxdev->pdata, > + prom21_auxdev->id); > + if (!prom21_auxdev->auxdev) { > + ida_free(&prom21_xhci_auxdev_ida, prom21_auxdev->id); > + devres_free(prom21_auxdev); > + return -ENOMEM; > > The usual "goto error" pattern could be used instead of increasingly > long sequences of xxx_free() calls. Agreed. I changed prom21_xhci_create_auxdev() to use a goto-based cleanup path locally for v7. > It seems that these three functions above are everything that you truly > want to add; the rest is boilerplate required by this two-module scheme > to work, plus ID tables which must be duplicated and kept in sync. > > I wonder if a separate module is really justified, as opposed to simply > linking this file into xhci_pci.ko when directed by Kconfig. > > The downside would be slightly higher memory usage on systems where the > hwmon driver is enabled but not needed. OTOH, same systems would likely > see reduced disk waste. I understand the concern. Linking the PROM21 auxiliary-device publisher into xhci_pci.ko would reduce some boilerplate and avoid the extra PCI driver, while still keeping the hwmon driver itself separate. The reason I kept the current split is that the earlier review direction was to keep the hwmon functionality out of xhci-pci and bind a drivers/hwmon driver through an auxiliary device. The current PROM21 PCI glue keeps the PROM21-specific auxiliary-device lifetime handling outside the common xhci-pci driver and leaves xhci-pci.c with only the PCI ID handoff, similar in spirit to the Renesas handoff path. That said, I agree this is a tradeoff. If Mathias or the USB maintainers prefer the PROM21 auxiliary-device publisher to be linked into xhci_pci.ko instead of being a separate PCI glue driver, I can rework it in that direction while still keeping the hwmon driver under drivers/hwmon and bound through the auxiliary bus. Sincerely, Jihong Min ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-18 20:30 ` Jihong Min @ 2026-05-18 21:37 ` Michal Pecio 2026-05-18 23:06 ` Jihong Min 2026-05-18 23:07 ` Jihong Min 1 sibling, 1 reply; 12+ messages in thread From: Michal Pecio @ 2026-05-18 21:37 UTC (permalink / raw) To: Jihong Min Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On Tue, 19 May 2026 05:30:47 +0900, Jihong Min wrote: > On 5/18/26 06:21, Michal Pecio wrote: > > Instead of the X86 heuristic, would it be possible to build glue > > code if and only if SENSORS_PROM21_XHCI is enabled? > > > > This seems to work: > > > > config SENSORS_PROM21_XHCI > > tristate "AMD Promontory 21 xHCI temperature sensor" > > - depends on USB_XHCI_PCI_PROM21 > > + depends on USB_XHCI_PCI > > > > config USB_XHCI_PCI_PROM21 > > tristate > > - depends on X86 > > depends on USB_XHCI_PCI > > - default USB_XHCI_PCI > > + default USB_XHCI_PCI if SENSORS_PROM21_XHCI != 'n' > > select AUXILIARY_BUS > > > > I don't know if it's the best way, perhaps it would be preferable > > for the hwmon driver to select the glue, but then I'm not sure how > > to force glue to become 'y' when xhci-pci is 'y'. > > I think I should keep the current hidden glue option for now. > > The PROM21 PCI glue is part of the PCI binding path for the xHCI > controller when enabled, while SENSORS_PROM21_XHCI is only the > optional user-visible hwmon driver. Tying the glue to the hwmon > option would make the sensor option affect which driver binds the USB > controller. That's true. Making this possible is the whole purpose of "if IS_ENABLED" here: > 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); > } Currently, you have a weird situation where xhci-pci-prom21 always binds on x86 and xhci-pci on other platforms (with the unofficial PCIe card you mentioned), plus the sensor cannot work on other platforms. > As Guenter pointed out, that would be too strong; the USB controller > should not depend on whether the optional hwmon driver is enabled. One could further argue that neither should it care whether some hwmon driver exists at all, or which kernel releases it exists in :) Regards, Michal ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-18 21:37 ` Michal Pecio @ 2026-05-18 23:06 ` Jihong Min 2026-05-18 23:25 ` Guenter Roeck 0 siblings, 1 reply; 12+ messages in thread From: Jihong Min @ 2026-05-18 23:06 UTC (permalink / raw) To: Michal Pecio Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/19/26 06:37, Michal Pecio wrote: > That's true. > Making this possible is the whole purpose of "if IS_ENABLED" here: I re-checked the Kconfig cases, and I think you are right here. The two cases I was trying to avoid are: 1. the sensor driver is built as a module, or loads only after the initramfs stage, but the PROM21 controller has already been bound by the generic xhci-pci driver, so no auxiliary device exists for the sensor driver to bind to; 2. the built-in generic xhci-pci driver rejects the PROM21 controller, but xhci-pci-prom21 is only available as a module and is not present during initramfs, leaving USB behind that controller unavailable at that stage. Looking at your proposed Kconfig shape again, it handles both cases. If SENSORS_PROM21_XHCI=n, then no sensor support is requested and USB_XHCI_PCI_PROM21 can stay disabled. In that case generic xhci-pci binds the controller, which is fine because there is no sensor driver that needs an auxiliary device. If SENSORS_PROM21_XHCI=m or y and USB_XHCI_PCI=y, then USB_XHCI_PCI_PROM21 follows USB_XHCI_PCI and becomes y. That means the PROM21 glue is available during early boot, creates the auxiliary device, and the hwmon driver can still bind later if it is built as a module. If USB_XHCI_PCI=m, then xhci-pci itself is modular. In that case needing the PROM21 glue module in initramfs is not a PROM21-specific built-in/module split problem; it is the normal requirement for a modular xHCI PCI setup. So I agree that tying the hidden glue option to whether SENSORS_PROM21_XHCI is enabled is reasonable. > Currently, you have a weird situation where xhci-pci-prom21 always > binds on x86 and xhci-pci on other platforms (with the unofficial PCIe > card you mentioned), plus the sensor cannot work on other platforms. Agreed. I also agree that the X86 dependency is only a heuristic and is not a good restriction for a PCI ID based driver. PROM21 is mainly used on AMD x86 desktop platforms today, but the unofficial PCIe card example shows that the device can exist outside the normal AMD x86 chipset topology. I do not know whether other PROM21-related functionality is supported on non-x86 platforms, but this driver does not need to prevent the xHCI temperature sensor path from being built there. > One could further argue that neither should it care whether some hwmon > driver exists at all, or which kernel releases it exists in :) Right. I think the cleanest result is: - generic xhci-pci handles PROM21 when no sensor support is requested; - xhci-pci-prom21 handles PROM21 only when the sensor path is enabled; - the hwmon driver remains the user-visible option. Unless Guenter or the USB maintainers object, I plan to change the next revision in that direction and test the Kconfig combinations locally. Sincerely, Jihong Min ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-18 23:06 ` Jihong Min @ 2026-05-18 23:25 ` Guenter Roeck 0 siblings, 0 replies; 12+ messages in thread From: Guenter Roeck @ 2026-05-18 23:25 UTC (permalink / raw) To: Jihong Min, Michal Pecio Cc: Greg Kroah-Hartman, Mathias Nyman, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/18/26 16:06, Jihong Min wrote: > > > On 5/19/26 06:37, Michal Pecio wrote: >> That's true. >> Making this possible is the whole purpose of "if IS_ENABLED" here: > > I re-checked the Kconfig cases, and I think you are right here. > > The two cases I was trying to avoid are: > > 1. the sensor driver is built as a module, or loads only after the > initramfs stage, but the PROM21 controller has already been bound by > the generic xhci-pci driver, so no auxiliary device exists for the > sensor driver to bind to; > > 2. the built-in generic xhci-pci driver rejects the PROM21 controller, but > xhci-pci-prom21 is only available as a module and is not present during > initramfs, leaving USB behind that controller unavailable at that > stage. > > Looking at your proposed Kconfig shape again, it handles both cases. > > If SENSORS_PROM21_XHCI=n, then no sensor support is requested and > USB_XHCI_PCI_PROM21 can stay disabled. In that case generic xhci-pci binds > the controller, which is fine because there is no sensor driver that > needs an > auxiliary device. > > If SENSORS_PROM21_XHCI=m or y and USB_XHCI_PCI=y, then > USB_XHCI_PCI_PROM21 follows USB_XHCI_PCI and becomes y. That means the > PROM21 > glue is available during early boot, creates the auxiliary device, and the > hwmon driver can still bind later if it is built as a module. > > If USB_XHCI_PCI=m, then xhci-pci itself is modular. In that case needing the > PROM21 glue module in initramfs is not a PROM21-specific built-in/module > split > problem; it is the normal requirement for a modular xHCI PCI setup. > > So I agree that tying the hidden glue option to whether > SENSORS_PROM21_XHCI is enabled is reasonable. > >> Currently, you have a weird situation where xhci-pci-prom21 always >> binds on x86 and xhci-pci on other platforms (with the unofficial PCIe >> card you mentioned), plus the sensor cannot work on other platforms. > > Agreed. I also agree that the X86 dependency is only a heuristic and is > not a > good restriction for a PCI ID based driver. PROM21 is mainly used on AMD x86 > desktop platforms today, but the unofficial PCIe card example shows that the > device can exist outside the normal AMD x86 chipset topology. > > I do not know whether other PROM21-related functionality is supported on > non-x86 platforms, but this driver does not need to prevent the xHCI > temperature sensor path from being built there. > >> One could further argue that neither should it care whether some hwmon >> driver exists at all, or which kernel releases it exists in :) > > Right. I think the cleanest result is: > > - generic xhci-pci handles PROM21 when no sensor support is requested; > - xhci-pci-prom21 handles PROM21 only when the sensor path is enabled; > - the hwmon driver remains the user-visible option. > > Unless Guenter or the USB maintainers object, I plan to change the next > revision in that direction and test the Kconfig combinations locally. > Ok with me if you are sure that it works. When you send a new revision, you might want to also change the error path as suggested. Thanks, Guenter ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue 2026-05-18 20:30 ` Jihong Min 2026-05-18 21:37 ` Michal Pecio @ 2026-05-18 23:07 ` Jihong Min 1 sibling, 0 replies; 12+ messages in thread From: Jihong Min @ 2026-05-18 23:07 UTC (permalink / raw) To: Michal Pecio Cc: Greg Kroah-Hartman, Mathias Nyman, Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/19/26 05:30, Jihong Min wrote: > It seems that these three functions above are everything that you truly > want to add; the rest is boilerplate required by this two-module scheme > to work, plus ID tables which must be duplicated and kept in sync. > > I wonder if a separate module is really justified, as opposed to simply > linking this file into xhci_pci.ko when directed by Kconfig. > > The downside would be slightly higher memory usage on systems where the > hwmon driver is enabled but not needed. OTOH, same systems would likely > see reduced disk waste. One clarification about this part: In my previous reply I said that I could rework this either way depending on the USB maintainer preference. After thinking about it again, I think the current direction is the better one. Mathias's earlier review pushed this series away from adding PROM21-specific hwmon support directly into the common xhci-pci path. I agree with that direction. The common xhci-pci driver should not grow PROM21-specific sensor logic. The current split keeps the PROM21-specific auxiliary-device lifetime handling in xhci-pci-prom21.c, keeps the hwmon implementation in drivers/hwmon, and leaves xhci-pci.c with only the PCI ID handoff. That is also the closest match to the existing Renesas handoff approach. So, while I previously phrased this as something I would leave entirely to the USB maintainers, my current preference is to keep the separate PROM21 PCI glue driver unless Mathias or another USB maintainer specifically asks for a different structure. Sincerely, Jihong Min ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support 2026-05-17 13:04 [PATCH v6 0/2] AMD Promontory 21 xHCI temperature sensor support Jihong Min 2026-05-17 13:04 ` [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue Jihong Min @ 2026-05-17 13:04 ` Jihong Min 2026-05-18 10:58 ` Guenter Roeck 1 sibling, 1 reply; 12+ messages in thread From: Jihong Min @ 2026-05-17 13:04 UTC (permalink / raw) To: Greg Kroah-Hartman, Mathias Nyman Cc: Guenter Roeck, Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Jihong Min, Mario Limonciello (AMD), Yaroslav Isakov Add an auxiliary-bus hwmon driver for the temperature sensor exposed by AMD Promontory 21 (PROM21) xHCI PCI functions. The driver binds to the "hwmon" auxiliary device published by the PROM21 xHCI PCI glue and exposes the sensor as temp1_input under the prom21_xhci hwmon device. The sensor is accessed through a PROM21 vendor index/data register pair in the xHCI PCI MMIO BAR. The driver consumes parent-provided MMIO data from the PROM21 PCI glue instead of inspecting the parent PCI driver's drvdata. The read path restores the previous vendor index value after sampling and does not runtime-resume the parent PCI device; reads from a suspended parent return -ENODATA. Document the supported device, register access, runtime PM behavior, and sysfs lookup method. The documentation also records the observation method used to identify the register pair and derive the conversion formula. Assisted-by: Codex:gpt-5.5 Signed-off-by: Jihong Min <hurryman2212@gmail.com> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> --- Documentation/hwmon/index.rst | 1 + Documentation/hwmon/prom21-xhci.rst | 101 ++++++++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/prom21-xhci.c | 239 ++++++++++++++++++++++++++++ 5 files changed, 352 insertions(+) create mode 100644 Documentation/hwmon/prom21-xhci.rst create mode 100644 drivers/hwmon/prom21-xhci.c diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index 8b655e5d6b68..324208f1faa2 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -216,6 +216,7 @@ Hardware Monitoring Kernel Drivers pmbus powerz powr1220 + prom21-xhci pt5161l pxe1610 pwm-fan diff --git a/Documentation/hwmon/prom21-xhci.rst b/Documentation/hwmon/prom21-xhci.rst new file mode 100644 index 000000000000..7984fb187bd8 --- /dev/null +++ b/Documentation/hwmon/prom21-xhci.rst @@ -0,0 +1,101 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Kernel driver prom21-xhci +========================= + +Supported chips: + + * AMD Promontory 21 (PROM21) xHCI USB host controller + + Prefix: 'prom21_xhci' + + PCI IDs: 1022:43fc, 1022:43fd + +Author: + + - Jihong Min <hurryman2212@gmail.com> + +Description +----------- + +This driver exposes the temperature sensor in AMD PROM21 xHCI controllers. + +The driver binds to an auxiliary device created by the xHCI PCI driver for +supported controllers. The sensor value is accessed through a vendor-specific +index/data register pair in the controller's PCI MMIO BAR. +The auxiliary device is created by the ``xhci-pci-prom21`` PCI glue driver. +USB host operation is otherwise delegated to the common ``xhci-pci`` code. + +PROM21 is an AMD chipset IP used in single-chip or daisy-chained configurations +to build AMD 6xx/8xx series chipsets. Since the xHCI controllers are +integrated in PROM21, this temperature can also be used as a monitor for a +temperature close to the AMD chipset temperature. + +Register access +--------------- + +The temperature value is read through a vendor-specific index/data register +pair in the xHCI PCI MMIO BAR. The driver uses the following byte offsets from +the MMIO BAR base: + +======================= ===================================================== +0x3000 Vendor index register +0x3008 Vendor data register +======================= ===================================================== + +The driver saves the current vendor index register value, writes the +temperature selector ``0x0001e520`` to the vendor index register, reads the +vendor data register, and restores the previous vendor index value before +returning. The raw temperature value is the low 8 bits of the vendor data +register value. + +The hwmon core serializes this driver's callbacks, and the driver restores the +previous index value after each read. This does not provide synchronization +with firmware, SMM, ACPI AML, or any other user outside this driver. + +No public AMD reference is available for the register pair or the raw value. +The register pair was identified on an X870E system with two PROM21 xHCI +controllers. One controller was passed through to a Windows VM, and the same +controller's PCI MMIO BAR was observed from the Linux host while HWiNFO64 was +reporting the PROM21 xHCI temperature. In the test environment, the reported +temperature was very stable at idle and the displayed sensor resolution was +low, which made it possible to look for a consistently repeating MMIO response +for the same reported temperature. During observation, offset 0x3000 repeatedly +contained selector ``0x0001e520``. Writing the same selector to offset 0x3000 +from Linux and then reading offset 0x3008 reproduced the same raw value, so the +offsets are treated as a vendor index/data register pair. + +The conversion formula was empirically inferred by matching observed raw +8-bit values against HWiNFO64's reported PROM21 xHCI temperature for the same +controller. The observed mapping is: + + temp[C] = raw * 0.9066 - 78.624 + +Runtime PM +---------- + +The driver does not wake the xHCI PCI device for hwmon reads. It reads the +temperature only when the parent device is already active. A read from a +suspended device returns ``-ENODATA``. After a successful read, the driver +drops its active-only runtime PM reference and lets the PM core re-evaluate the +idle state. + +Sysfs entries +------------- + +======================= ===================================================== +temp1_input Temperature in millidegrees Celsius +======================= ===================================================== + +The hwmon device name is ``prom21_xhci``. The sysfs path depends on the hwmon +device number assigned by the kernel. Userspace can locate the device by +matching the ``name`` attribute: + +.. code-block:: sh + + for hwmon in /sys/class/hwmon/hwmon*; do + [ "$(cat "$hwmon/name")" = "prom21_xhci" ] || continue + cat "$hwmon/temp1_input" + done + +If the raw register value is invalid, ``temp1_input`` returns ``-ENODATA``. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 14e4cea48acc..fe0f14e247b5 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -951,6 +951,16 @@ config SENSORS_POWR1220 This driver can also be built as a module. If so, the module will be called powr1220. +config SENSORS_PROM21_XHCI + tristate "AMD Promontory 21 xHCI temperature sensor" + depends on USB_XHCI_PCI_PROM21 + help + If you say yes here you get support for the AMD Promontory 21 + (PROM21) xHCI temperature sensor. + + This driver can also be built as a module. If so, the module + will be called prom21-xhci. + config SENSORS_LAN966X tristate "Microchip LAN966x Hardware Monitoring" depends on SOC_LAN966 || COMPILE_TEST diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 982ee2c6f9de..f833aed890d8 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -196,6 +196,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_POWERZ) += powerz.o obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o +obj-$(CONFIG_SENSORS_PROM21_XHCI) += prom21-xhci.o obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o diff --git a/drivers/hwmon/prom21-xhci.c b/drivers/hwmon/prom21-xhci.c new file mode 100644 index 000000000000..d40d0c53ce45 --- /dev/null +++ b/drivers/hwmon/prom21-xhci.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AMD Promontory 21 xHCI Hwmon Implementation + * (only temperature monitoring is supported) + * + * This can be effectively used as the alternative chipset temperature monitor. + * + * Copyright (C) 2026 Jihong Min <hurryman2212@gmail.com> + */ + +#include <linux/auxiliary_bus.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/hwmon.h> +#include <linux/io.h> +#include <linux/math.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_data/usb-xhci-prom21.h> +#include <linux/pm_runtime.h> + +#define PROM21_XHCI_INDEX_OFFSET 0x3000 +#define PROM21_XHCI_DATA_OFFSET 0x3008 +#define PROM21_XHCI_TEMP_SELECTOR 0x0001e520 + +struct prom21_xhci { + struct pci_dev *pdev; + struct device *hwmon_dev; + void __iomem *regs; +}; + +static int prom21_xhci_pm_get(struct prom21_xhci *hwmon) +{ + struct device *dev = &hwmon->pdev->dev; + int ret; + + /* + * PROM21 temperature register access does not return a valid value while + * the parent xHCI PCI function is suspended. Do not wake the device from + * a hwmon read. On success, hold a usage reference without changing the + * runtime PM state; if runtime PM is disabled, allow the read unless the + * device is still marked suspended. + */ + ret = pm_runtime_get_if_active(dev); + if (ret > 0) + return 0; + + if (ret == -EINVAL) { + if (pm_runtime_status_suspended(dev)) + return -ENODATA; + + pm_runtime_get_noresume(dev); + return 0; + } + + if (!ret) + return -ENODATA; + + return ret; +} + +/* + * This is not a pure MMIO read. The PROM21 vendor data register is selected + * by temporarily writing PROM21_XHCI_TEMP_SELECTOR to the vendor index + * register. + * The hwmon core already serializes this driver's callbacks, so this driver + * does not need an additional private lock. That does not synchronize with + * firmware, SMM, ACPI, or other possible users. Keep the sequence short and + * restore the previous index before returning. + */ +static int prom21_xhci_read_temp_raw_restore_index(struct prom21_xhci *hwmon, + u8 *raw) +{ + struct device *dev = &hwmon->pdev->dev; + u32 index; + u8 data; + int ret; + + ret = prom21_xhci_pm_get(hwmon); + if (ret) + return ret; + + index = readl(hwmon->regs + PROM21_XHCI_INDEX_OFFSET); + /* Select the PROM21 temperature register through the vendor index. */ + writel(PROM21_XHCI_TEMP_SELECTOR, + hwmon->regs + PROM21_XHCI_INDEX_OFFSET); + /* Use a 32-bit read for PCI MMIO register access. */ + data = readl(hwmon->regs + PROM21_XHCI_DATA_OFFSET) & 0xff; + /* Restore the previous vendor index register value. */ + writel(index, hwmon->regs + PROM21_XHCI_INDEX_OFFSET); + readl(hwmon->regs + PROM21_XHCI_INDEX_OFFSET); + + /* + * Drop the usage reference taken by prom21_xhci_pm_get(). This is + * enough because the read path never resumes the device; use the normal + * put path so the PM core can re-evaluate idle state after the read. + * Otherwise, a racing xHCI autosuspend attempt can see a nonzero + * runtime PM usage count and skip autosuspend, and a later + * pm_runtime_put_noidle(), which does not check for an idle device, + * would leave the device active. + */ + pm_runtime_put(dev); + + if (!data) + return -ENODATA; + + *raw = data; + return 0; +} + +static long prom21_xhci_raw_to_millicelsius(u8 raw) +{ + /* + * No public AMD reference is available for this value. + * The scale was derived from observed PROM21 xHCI temperature readings: + * temp[C] = raw * 0.9066 - 78.624 + */ + return DIV_ROUND_CLOSEST(raw * 9066, 10) - 78624; +} + +static umode_t prom21_xhci_is_visible(const void *drvdata, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + return 0444; + default: + return 0; + } +} + +static int prom21_xhci_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct prom21_xhci *hwmon = dev_get_drvdata(dev); + u8 raw; + int ret; + + if (type != hwmon_temp || attr != hwmon_temp_input) + return -EOPNOTSUPP; + + ret = prom21_xhci_read_temp_raw_restore_index(hwmon, &raw); + if (ret) + return ret; + + *val = prom21_xhci_raw_to_millicelsius(raw); + return 0; +} + +static const struct hwmon_ops prom21_xhci_ops = { + .is_visible = prom21_xhci_is_visible, + .read = prom21_xhci_read, +}; + +static const struct hwmon_channel_info *const prom21_xhci_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), + NULL, +}; + +static const struct hwmon_chip_info prom21_xhci_chip_info = { + .ops = &prom21_xhci_ops, + .info = prom21_xhci_info, +}; + +static int prom21_xhci_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct device *dev = &auxdev->dev; + const struct prom21_xhci_pdata *pdata = dev_get_platdata(dev); + struct prom21_xhci *hwmon; + + if (!pdata) + return dev_err_probe(dev, -ENODEV, + "platform data unavailable\n"); + + if (!pdata->regs || + pdata->rsrc_len < PROM21_XHCI_DATA_OFFSET + sizeof(u32)) + return dev_err_probe(dev, -ENODEV, "invalid MMIO resource\n"); + + hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + hwmon->pdev = pdata->pdev; + hwmon->regs = pdata->regs; + auxiliary_set_drvdata(auxdev, hwmon); + + /* + * Parent the hwmon device to the PCI function because the temperature + * value is read from that function's MMIO BAR, and systems may contain + * multiple PROM21 xHCI functions. This lets userspace identify the PCI + * endpoint for each reading. The auxiliary driver still owns the hwmon + * lifetime and unregisters it before HCD teardown. + */ + hwmon->hwmon_dev = + hwmon_device_register_with_info(&pdata->pdev->dev, "prom21_xhci", + hwmon, &prom21_xhci_chip_info, + NULL); + if (IS_ERR(hwmon->hwmon_dev)) + return PTR_ERR(hwmon->hwmon_dev); + + return 0; +} + +static void prom21_xhci_remove(struct auxiliary_device *auxdev) +{ + struct prom21_xhci *hwmon = auxiliary_get_drvdata(auxdev); + + /* + * The PROM21 PCI glue destroys the auxiliary device before HCD teardown. + * Unregister the hwmon device here so sysfs removes the attributes, + * stops new reads, and drains active hwmon callbacks before the xHCI + * MMIO mapping is released. + */ + hwmon_device_unregister(hwmon->hwmon_dev); +} + +static const struct auxiliary_device_id prom21_xhci_id_table[] = { + { .name = "xhci_pci_prom21.hwmon" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, prom21_xhci_id_table); + +static struct auxiliary_driver prom21_xhci_driver = { + .name = "prom21-xhci", + .probe = prom21_xhci_probe, + .remove = prom21_xhci_remove, + .id_table = prom21_xhci_id_table, +}; +module_auxiliary_driver(prom21_xhci_driver); + +MODULE_AUTHOR("Jihong Min <hurryman2212@gmail.com>"); +MODULE_DESCRIPTION("AMD Promontory 21 xHCI temperature sensor driver"); +MODULE_LICENSE("GPL"); -- 2.53.0 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support 2026-05-17 13:04 ` [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support Jihong Min @ 2026-05-18 10:58 ` Guenter Roeck 0 siblings, 0 replies; 12+ messages in thread From: Guenter Roeck @ 2026-05-18 10:58 UTC (permalink / raw) To: Jihong Min, Greg Kroah-Hartman, Mathias Nyman Cc: Jonathan Corbet, Shuah Khan, Mario Limonciello, Basavaraj Natikar, linux-usb, linux-hwmon, linux-doc, linux-pci, linux-kernel, Mario Limonciello (AMD), Yaroslav Isakov On 5/17/26 06:04, Jihong Min wrote: > Add an auxiliary-bus hwmon driver for the temperature sensor exposed by > AMD Promontory 21 (PROM21) xHCI PCI functions. The driver binds to the > "hwmon" auxiliary device published by the PROM21 xHCI PCI glue and > exposes the sensor as temp1_input under the prom21_xhci hwmon device. > > The sensor is accessed through a PROM21 vendor index/data register pair > in the xHCI PCI MMIO BAR. The driver consumes parent-provided MMIO data > from the PROM21 PCI glue instead of inspecting the parent PCI driver's > drvdata. The read path restores the previous vendor index value after > sampling and does not runtime-resume the parent PCI device; reads from a > suspended parent return -ENODATA. > > Document the supported device, register access, runtime PM behavior, and > sysfs lookup method. The documentation also records the observation > method used to identify the register pair and derive the conversion > formula. > > Assisted-by: Codex:gpt-5.5 > Signed-off-by: Jihong Min <hurryman2212@gmail.com> > Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> > Tested-by: Yaroslav Isakov <yaroslav.isakov@gmail.com> For my reference: Reviewed-by: Guenter Roeck <linux@roeck-us.net> I'll need an Acked-by: from a maintainer on the first patch to apply both patches, or this patch can be applied through some other tree. I am fine with both. Thanks, Guenter ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-05-18 23:25 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-17 13:04 [PATCH v6 0/2] AMD Promontory 21 xHCI temperature sensor support Jihong Min 2026-05-17 13:04 ` [PATCH v6 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue Jihong Min 2026-05-17 21:21 ` Michal Pecio 2026-05-18 10:55 ` Guenter Roeck 2026-05-18 20:34 ` Michal Pecio 2026-05-18 20:30 ` Jihong Min 2026-05-18 21:37 ` Michal Pecio 2026-05-18 23:06 ` Jihong Min 2026-05-18 23:25 ` Guenter Roeck 2026-05-18 23:07 ` Jihong Min 2026-05-17 13:04 ` [PATCH v6 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support Jihong Min 2026-05-18 10:58 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox