From nobody Mon May 25 04:35:09 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 70F65128395 for ; Tue, 19 May 2026 00:07:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779149275; cv=none; b=LyjiAuEAAi8vXAzyBoljhfNp2fgNS4/fhvcYjjpqfwsyyoJXGLUo9WcnXWHYCr83PnGoRRzQRlk5xfdY2OJJqMcxbCbq+sfxLjeFBU3TC5Qx2utm2O4kF1IH3kuJ+UwQejiNO0tP8SorqIxENXk9z5Djtqm1N60VXCxk8CjiFZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779149275; c=relaxed/simple; bh=Kc8+aK64Ly1xvXuCc8InpT0SC3CasoBFQHQnMVAiLqg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FFeYE4pllZuF0Rke50HVCe2muxaIKpFw6EK/rkSXOfYjN3WC7M0sZFnGyXtBt1RjQr9JT8+MV/VyqkXY9h0G02SXTlFVyoUFhYf/3oTj5jY7y2Tz9tGeHmTxak2CuhjElH1BeKbDppzvV2Nfm9BJH1cTexK+VoGqOFfBhuMC5S4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=oCdACxmj; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oCdACxmj" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2ba17c8cfacso28159855ad.2 for ; Mon, 18 May 2026 17:07:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779149273; x=1779754073; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=M6tltDGo+5vtt2DKrFq/NSjTt1IvEImZu/p4oBxOfcM=; b=oCdACxmjZG+y3KojZnY+meoLmhW74BQYIn/99LBMNodfzeTs/K8xWoN0mN3Qspu+X7 TdKRotk5X44rBNtEQ+wxIGSZqmB70c5K79OiVu0NZsfcxciQP8Z1jR8aQyB/TZAfoqLO fuCx3DN/LBwaSpKyCBio2S/cZii/yf6XnpDic2l6RK08UZN11rdVvgMNpuF+Gd5FDwU3 3HEoGygPVBDKaFMNYLngHPYvSP++70aoDxMaPuT7IDVSqQFSnnnYEbDy59Wtyle7rQ6i XDAuT5OH8COP4YXeWm8L7NVjGkJzR0n3rYWUarCeUodp1xt649GdVOSjtqHDdvj0BjZJ nMXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779149273; x=1779754073; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=M6tltDGo+5vtt2DKrFq/NSjTt1IvEImZu/p4oBxOfcM=; b=UJk+Mw6TitbFgvvTRL9brZS4Vh4YgYa4OpfvlcdqiCCkACRaokrtdJQqH5a4UwQ5Ah B/Hy9DkwxIoybcB1kMF/Ns01Hcgn0FSrAMVX4SQSPnlfnNRFidB+XFqJiD+rsEN/DjWP JawkIXeiUb8aIBsIf8kMoUqa7M9KgLjEnyVINtPx5WYc2lGeG4QXw1Ser15ateEPFo9q fBHy/eqe0LFnBkN2McCNAE3sON5C8sqwt2UzY51Az91DpCSJHsFw7SB68u8EW9TOrztn tPqPq2mEBxngtEZ8nGddHFoWGcO0fLXXA8UhrrTIFIqs30sLE1GiLVmAI87A88SD9FHO 3mHg== X-Forwarded-Encrypted: i=1; AFNElJ/HzjZLhNSdR7KYDJPWEtPAFlI+4oi9mY5UY/yMPn/3eruhYYVT3/qX4THFAMfILv5jrF6oZp0k8SaGZd4=@vger.kernel.org X-Gm-Message-State: AOJu0YwiMR8ffvEw0kpdPFRsEbc0wVEatSTdIBsM8lHP81bMDIGr3d2H cgTfy3SsoTRLf+SNqGByvO6NHBsueTdNjPHI1S2BM5DYZ7e4bkzHsb6BAfQBQbUKl+M= X-Gm-Gg: Acq92OH4fOrrOp+Jtqf+OHI7gcvghhdXxc6LA0277DCN3md3ehmp1vd1bXApsI4gGfW ozAQdkkhvJEAYqf+/GvRiDyNtP9X1wC6az5BTOnnU0ErzFMOlo1N+ReXnzXg1RDHSHugJh3qDIa g4CeITNnfLevPsvaVISbGKygA0bPnjq/0PJYwKlpH49quof2qMKymggMhrHtl+m+mRbG8IbuPdr 2txuDs/lum97UtBQ5wrqwUX99ilLvdbghkoj/oBqVRzrMZXVw49lPqEF9Ani0VnrnyrH9vWRwsV HZ0W8jSGHblfKIfGjPjEe4E+GWHOARZYU+doxUk6uZsppQfac5hKCwvs7Vt/A+2i25TlieDIKkH HTQoWXI9dA4+ksQtIYEPAnu6Uz8iQRwTMSj3V7E48zCjKxVTwiA9XD2n7PemtjI0BDAtqHyrHKM 9cemeU84gFmYkq1pguAwedcQ== X-Received: by 2002:a17:902:f647:b0:2b2:4cd2:e162 with SMTP id d9443c01a7336-2bd7e93872bmr191189345ad.34.1779149272692; Mon, 18 May 2026 17:07:52 -0700 (PDT) Received: from mincom1 ([119.214.48.64]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bdc58575dfsm79021755ad.20.2026.05.18.17.07.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 May 2026 17:07:52 -0700 (PDT) From: Jihong Min To: Greg Kroah-Hartman , Mathias Nyman Cc: Guenter Roeck , Jonathan Corbet , Shuah Khan , Mario Limonciello , Basavaraj Natikar , Michal Pecio , Mario Limonciello , Yaroslav Isakov , linux-usb@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Jihong Min Subject: [PATCH v7 1/2] usb: xhci-pci: add AMD Promontory 21 PCI glue Date: Tue, 19 May 2026 09:07:31 +0900 Message-ID: <20260519000732.2334711-2-hurryman2212@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260519000732.2334711-1-hurryman2212@gmail.com> References: <20260519000732.2334711-1-hurryman2212@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Mario Limonciello (AMD) Tested-by: Yaroslav Isakov Acked-by: Guenter Roeck --- 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 =20 +config USB_XHCI_PCI_PROM21 + tristate + depends on USB_XHCI_PCI + default USB_XHCI_PCI if SENSORS_PROM21_XHCI !=3D 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) +=3D uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) +=3D fhci.o obj-$(CONFIG_USB_XHCI_HCD) +=3D xhci-hcd.o obj-$(CONFIG_USB_XHCI_PCI) +=3D xhci-pci.o +obj-$(CONFIG_USB_XHCI_PCI_PROM21) +=3D xhci-pci-prom21.o obj-$(CONFIG_USB_XHCI_PCI_RENESAS) +=3D xhci-pci-renesas.o obj-$(CONFIG_USB_XHCI_PLATFORM) +=3D xhci-plat-hcd.o obj-$(CONFIG_USB_XHCI_HISTB) +=3D 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 suppor= t. + * + * Copyright (C) 2026 Jihong Min + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D 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 =3D pci_get_drvdata(pdev); + int ret; + + prom21_auxdev =3D devres_alloc(prom21_xhci_auxdev_release, + sizeof(*prom21_auxdev), GFP_KERNEL); + if (!prom21_auxdev) + return -ENOMEM; + + prom21_auxdev->pdata.pdev =3D pdev; + prom21_auxdev->pdata.regs =3D hcd->regs; + prom21_auxdev->pdata.rsrc_len =3D hcd->rsrc_len; + + prom21_auxdev->id =3D ida_alloc(&prom21_xhci_auxdev_ida, GFP_KERNEL); + if (prom21_auxdev->id < 0) { + ret =3D prom21_auxdev->id; + goto err_free_devres; + } + + prom21_auxdev->auxdev =3D auxiliary_device_create(&pdev->dev, + KBUILD_MODNAME, "hwmon", + &prom21_auxdev->pdata, + prom21_auxdev->id); + if (!prom21_auxdev->auxdev) { + ret =3D -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 =3D xhci_pci_common_probe(dev, id); + if (retval) + return retval; + + retval =3D 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[] =3D { + { 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 =3D { + .name =3D "xhci-pci-prom21", + .id_table =3D pci_ids, + + .probe =3D prom21_xhci_probe, + .remove =3D prom21_xhci_remove, + + .shutdown =3D usb_hcd_pci_shutdown, + .driver =3D { + .pm =3D pm_ptr(&usb_hcd_pci_pm_ops), + }, +}; +module_pci_driver(prom21_xhci_driver); + +MODULE_AUTHOR("Jihong Min "); +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[] = =3D { { /* end: all zeroes */ } }; =20 +/* handled by xhci-pci-prom21 if enabled */ +static const struct pci_device_id pci_ids_prom21[] =3D { + { 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; =20 + if (IS_ENABLED(CONFIG_USB_XHCI_PCI_PROM21) && + pci_match_id(pci_ids_prom21, dev)) + return -ENODEV; + return xhci_pci_common_probe(dev, id); } =20 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 =20 +#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); =20 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 + */ + +#ifndef _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H +#define _LINUX_PLATFORM_DATA_USB_XHCI_PROM21_H + +#include +#include + +struct pci_dev; + +struct prom21_xhci_pdata { + struct pci_dev *pdev; + void __iomem *regs; + resource_size_t rsrc_len; +}; + +#endif --=20 2.53.0 From nobody Mon May 25 04:35:09 2026 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2118C4AEEF for ; Tue, 19 May 2026 00:07:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779149280; cv=none; b=pbvuH/6j/GE42t6DcmWPHtcLVfwRPYsfdp/V9rt5+wMWae6dnMdT1TDZ3TAopmCZ2oB1JLxIWW849ZJpk6q+GNnLWvCd9KL16WTu1SwBQnVa9nzmoV3oSZcnjnYpXwh2wQryic7NXSnsp/WSQgt7dXF2DgPlDfMbn0o0rN6ukZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779149280; c=relaxed/simple; bh=B9osKUrtRag8dtNM/J+awtHqk7IngzgmolC3NDcI6Qo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lf2+GrWtWzSX4TSM6YRKmdrnmb1SOK68xJtei8gjtNqZhZp+mMYWZWVN+1TZDyrywoVdX9OAnn+WRLQ0lpXJ3s4nBv5TZTiBza3R155xJ1reDHxYxptGr+Ou8Am9BZyAOT/cqev+rAc7vKRFBmyHrvSJOTIhmGu66uJW37V673Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NQsm6TvE; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NQsm6TvE" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-2b458ca2296so20615065ad.0 for ; Mon, 18 May 2026 17:07:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779149276; x=1779754076; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=D6ziD8m7WKgKCsBYKM0LVOj0fx6FtMzc9DWoHsTlFww=; b=NQsm6TvE9p/ddCKUXucvAzPMYUJl14u6tfjviGiJSpoMa3P3hD/QEYAyUQF6WkWZQA Li+WQ3sXcdSxGxaRuIKHfEM9nWjSIpSI/A8nqm939M6AvhMaaniiDKpvw/pMNcdNFbFZ qxF/9zADl3MYGcRINp2PbObmek1r82lylIxY4rwIGN7mbVdZ9fmYOpUgeOfwR1Jc1Wap amkAlPJM9bGlrfmk0etWyr4ydK4qhZ/SOA8J5+rXukA/4HzkxtsIa0176+mBHmUCGtnX qGQrR0Z0xqVmRW5/XZG+eQjJ2BIJJCPwbJYzmZgMV/YGOyjBz87jc88eJ8bM66rDVZiG 2a3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779149276; x=1779754076; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=D6ziD8m7WKgKCsBYKM0LVOj0fx6FtMzc9DWoHsTlFww=; b=Tky2G49T7m4TuDwctX7iy8KSxOxTFa45jHZpruaaQaDp8cx67bRLMFzv2hJO0a825C azQ3VpUsQLaTaKYgm19B4l5yS9N/N1H9P09tMv9roxwzGdcDKo44T9zc3lnPd5izy5pK vi3rjQ6OAKNnX5YFSVMrG2rdJ3aN2HJJTjqSWPIYvYkTTyu3qV7oVWawW9W++2GFbqwQ 6Zn3HUZ6UWkvPnEEmojyU/d65r3T/fLTBLVqnjrxq0V3P2B5IhImTCgR0BbJcBQjs4iO 1Xgi/yE/JM2vp/F9jTP93CK8FqKK4RZ0eGlBAsv9Kn5X2xrpYl+2VRWAjvY6NeXa1Prn V1EQ== X-Forwarded-Encrypted: i=1; AFNElJ+LRh9GxEWref+s4QxpCoeU0srAxkKGxsoBovqpoL+35wMBen1cbmA+1AbuK5U8EyvxDrplBqEwjOrsNWs=@vger.kernel.org X-Gm-Message-State: AOJu0YxddcAFrppqMYdCCL43rNwCdorqYdZS3n2UFM5IFgc6pwZAO+/n gwhekFfPRx+P77cfkewy7dj85i864mXc0ZEzhYFUmheVwVPvQMhgdDaS X-Gm-Gg: Acq92OGKnjdEyr4emJI735eUbCTF8m2rROAnH4mcJFO7e5u7arh3B5jpG/TbFndPp5A jDwX8j1bIcJhsEU31uA5uiPXETwZB3k4l0Ox67KQ0j36Cdv1NZDZTD0yk1C99S9YUp+wXjkzUE6 ZueJDS6mJ33lgPLi/YFtGOTepO9mBVAkCevk+4ej4ucNMuIg1ecULxP/KHS1fYOuI/AOBK+xc00 cCKofZ+8gkLmk3OdgUQ/mcZI5sX+5b6Sgpw8lEIir0tNRhqMB+KBrnOW6SAresaKXepx996GeQC 1DYV2yaNcumxYOZNMfuDRsP/QszuOVV6quofI9NsxyK+qIheDdJ6VEheQ+0fyo6SQsQPD981lng rS5nQ3aGbT+T5AgF0Gm68wZpgnTuwHiahsQeAJxpKKw1irfuX2vAp7iy9aJ1V/mum6Vly98xJea +6Wlh4zfA73YLZtbh+onE3gg== X-Received: by 2002:a17:903:1b45:b0:2bd:93b0:2c1c with SMTP id d9443c01a7336-2bd93b02ea0mr142388835ad.3.1779149276393; Mon, 18 May 2026 17:07:56 -0700 (PDT) Received: from mincom1 ([119.214.48.64]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bdc58575dfsm79021755ad.20.2026.05.18.17.07.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 May 2026 17:07:55 -0700 (PDT) From: Jihong Min To: Greg Kroah-Hartman , Mathias Nyman Cc: Guenter Roeck , Jonathan Corbet , Shuah Khan , Mario Limonciello , Basavaraj Natikar , Michal Pecio , Mario Limonciello , Yaroslav Isakov , linux-usb@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Jihong Min Subject: [PATCH v7 2/2] hwmon: add AMD Promontory 21 xHCI temperature sensor support Date: Tue, 19 May 2026 09:07:32 +0900 Message-ID: <20260519000732.2334711-3-hurryman2212@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260519000732.2334711-1-hurryman2212@gmail.com> References: <20260519000732.2334711-1-hurryman2212@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Mario Limonciello (AMD) Tested-by: Yaroslav Isakov Reviewed-by: Guenter Roeck --- 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/prom= 21-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 +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +Supported chips: + + * AMD Promontory 21 (PROM21) xHCI USB host controller + + Prefix: 'prom21_xhci' + + PCI IDs: 1022:43fc, 1022:43fd + +Author: + + - Jihong Min + +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-speci= fic +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 configura= tions +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: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D +0x3000 Vendor index register +0x3008 Vendor data register +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + +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 valu= e. +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 sa= me +controller's PCI MMIO BAR was observed from the Linux host while HWiNFO64 = was +reporting the PROM21 xHCI temperature. In the test environment, the report= ed +temperature was very stable at idle and the displayed sensor resolution was +low, which made it possible to look for a consistently repeating MMIO resp= onse +for the same reported temperature. During observation, offset 0x3000 repea= tedly +contained selector ``0x0001e520``. Writing the same selector to offset 0x3= 000 +from Linux and then reading offset 0x3008 reproduced the same raw value, s= o 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 s= ame +controller. The observed mapping is: + + temp[C] =3D 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-evaluat= e the +idle state. + +Sysfs entries +------------- + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D +temp1_input Temperature in millidegrees Celsius +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D + +The hwmon device name is ``prom21_xhci``. The sysfs path depends on the hw= mon +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")" =3D "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..1e770b548810 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. =20 +config SENSORS_PROM21_XHCI + tristate "AMD Promontory 21 xHCI temperature sensor" + depends on USB_XHCI_PCI + 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) +=3D pc87427.o obj-$(CONFIG_SENSORS_PCF8591) +=3D pcf8591.o obj-$(CONFIG_SENSORS_POWERZ) +=3D powerz.o obj-$(CONFIG_SENSORS_POWR1220) +=3D powr1220.o +obj-$(CONFIG_SENSORS_PROM21_XHCI) +=3D prom21-xhci.o obj-$(CONFIG_SENSORS_PT5161L) +=3D pt5161l.o obj-$(CONFIG_SENSORS_PWM_FAN) +=3D pwm-fan.o obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) +=3D 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 mon= itor. + * + * Copyright (C) 2026 Jihong Min + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D &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 =3D pm_runtime_get_if_active(dev); + if (ret > 0) + return 0; + + if (ret =3D=3D -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 select= ed + * by temporarily writing PROM21_XHCI_TEMP_SELECTOR to the vendor index + * register. + * The hwmon core already serializes this driver's callbacks, so this driv= er + * does not need an additional private lock. That does not synchronize with + * firmware, SMM, ACPI, or other possible users. Keep the sequence short a= nd + * restore the previous index before returning. + */ +static int prom21_xhci_read_temp_raw_restore_index(struct prom21_xhci *hwm= on, + u8 *raw) +{ + struct device *dev =3D &hwmon->pdev->dev; + u32 index; + u8 data; + int ret; + + ret =3D prom21_xhci_pm_get(hwmon); + if (ret) + return ret; + + index =3D 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 =3D 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 =3D 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] =3D 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 !=3D 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 ty= pe, + u32 attr, int channel, long *val) +{ + struct prom21_xhci *hwmon =3D dev_get_drvdata(dev); + u8 raw; + int ret; + + if (type !=3D hwmon_temp || attr !=3D hwmon_temp_input) + return -EOPNOTSUPP; + + ret =3D prom21_xhci_read_temp_raw_restore_index(hwmon, &raw); + if (ret) + return ret; + + *val =3D prom21_xhci_raw_to_millicelsius(raw); + return 0; +} + +static const struct hwmon_ops prom21_xhci_ops =3D { + .is_visible =3D prom21_xhci_is_visible, + .read =3D prom21_xhci_read, +}; + +static const struct hwmon_channel_info *const prom21_xhci_info[] =3D { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), + NULL, +}; + +static const struct hwmon_chip_info prom21_xhci_chip_info =3D { + .ops =3D &prom21_xhci_ops, + .info =3D prom21_xhci_info, +}; + +static int prom21_xhci_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct device *dev =3D &auxdev->dev; + const struct prom21_xhci_pdata *pdata =3D 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 =3D devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + hwmon->pdev =3D pdata->pdev; + hwmon->regs =3D 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 =3D + 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 =3D 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[] =3D { + { .name =3D "xhci_pci_prom21.hwmon" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, prom21_xhci_id_table); + +static struct auxiliary_driver prom21_xhci_driver =3D { + .name =3D "prom21-xhci", + .probe =3D prom21_xhci_probe, + .remove =3D prom21_xhci_remove, + .id_table =3D prom21_xhci_id_table, +}; +module_auxiliary_driver(prom21_xhci_driver); + +MODULE_AUTHOR("Jihong Min "); +MODULE_DESCRIPTION("AMD Promontory 21 xHCI temperature sensor driver"); +MODULE_LICENSE("GPL"); --=20 2.53.0