1.. SPDX-License-Identifier: GPL-2.0 2 3Kernel driver prom21-xhci 4========================= 5 6Supported chips: 7 8 * AMD Promontory 21 (PROM21) xHCI USB host controller 9 10 Prefix: 'prom21_xhci' 11 12 PCI IDs: 1022:43fc, 1022:43fd 13 14Author: 15 16 - Jihong Min <hurryman2212@gmail.com> 17 18Description 19----------- 20 21This driver exposes the temperature sensor in AMD PROM21 xHCI controllers. 22 23The driver binds to an auxiliary device created by the xHCI PCI driver for 24supported controllers. The sensor value is accessed through a vendor-specific 25index/data register pair in the controller's PCI MMIO BAR. 26The auxiliary device is created by the ``xhci-pci-prom21`` PCI glue driver. 27USB host operation is otherwise delegated to the common ``xhci-pci`` code. 28 29PROM21 is an AMD chipset IP used in single-chip or daisy-chained configurations 30to build AMD 6xx/8xx series chipsets. Since the xHCI controllers are 31integrated in PROM21, this temperature can also be used as a monitor for a 32temperature close to the AMD chipset temperature. 33 34Register access 35--------------- 36 37The temperature value is read through a vendor-specific index/data register 38pair in the xHCI PCI MMIO BAR. The driver uses the following byte offsets from 39the MMIO BAR base: 40 41======================= ===================================================== 420x3000 Vendor index register 430x3008 Vendor data register 44======================= ===================================================== 45 46The driver saves the current vendor index register value, writes the 47temperature selector ``0x0001e520`` to the vendor index register, reads the 48vendor data register, and restores the previous vendor index value before 49returning. The raw temperature value is the low 8 bits of the vendor data 50register value. 51 52The hwmon core serializes this driver's callbacks, and the driver restores the 53previous index value after each read. This does not provide synchronization 54with firmware, SMM, ACPI AML, or any other user outside this driver. 55 56No public AMD reference is available for the register pair or the raw value. 57The register pair was identified on an X870E system with two PROM21 xHCI 58controllers. One controller was passed through to a Windows VM, and the same 59controller's PCI MMIO BAR was observed from the Linux host while HWiNFO64 was 60reporting the PROM21 xHCI temperature. In the test environment, the reported 61temperature was very stable at idle and the displayed sensor resolution was 62low, which made it possible to look for a consistently repeating MMIO response 63for the same reported temperature. During observation, offset 0x3000 repeatedly 64contained selector ``0x0001e520``. Writing the same selector to offset 0x3000 65from Linux and then reading offset 0x3008 reproduced the same raw value, so the 66offsets are treated as a vendor index/data register pair. 67 68The conversion formula was empirically inferred by matching observed raw 698-bit values against HWiNFO64's reported PROM21 xHCI temperature for the same 70controller. The observed mapping is: 71 72 temp[C] = raw * 0.9066 - 78.624 73 74Runtime PM 75---------- 76 77The driver does not wake the xHCI PCI device for hwmon reads. It reads the 78temperature only when the parent device is already active. A read from a 79suspended device returns ``-ENODATA``. After a successful read, the driver 80drops its active-only runtime PM reference and lets the PM core re-evaluate the 81idle state. 82 83Sysfs entries 84------------- 85 86======================= ===================================================== 87temp1_input Temperature in millidegrees Celsius 88======================= ===================================================== 89 90The hwmon device name is ``prom21_xhci``. The sysfs path depends on the hwmon 91device number assigned by the kernel. Userspace can locate the device by 92matching the ``name`` attribute: 93 94.. code-block:: sh 95 96 for hwmon in /sys/class/hwmon/hwmon*; do 97 [ "$(cat "$hwmon/name")" = "prom21_xhci" ] || continue 98 cat "$hwmon/temp1_input" 99 done 100 101If the raw register value is invalid, ``temp1_input`` returns ``-ENODATA``. 102