All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs
@ 2026-11-02  7:18 Muthusamy Ramalingam
  2026-11-02  7:18 ` [PATCH 01/26] platform/x86/amd/hsmp: Drop _input from socket sysfs names Muthusamy Ramalingam
                   ` (25 more replies)
  0 siblings, 26 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:18 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

This series extends the AMD HSMP sysfs interface on both the ACPI and
platform drivers. It starts with socket attribute naming cleanup and a
parser-friendly store error helper, then adds the remaining
message-backed socket and per-CPU attributes used on server platforms.

Later patches cover link/bandwidth, DIMM, SVI3, power-efficiency, and
per-CPU files. Attribute visibility follows the enabled-message bitmaps.
Probe-time discovery for optional DIMM/IO/xGMI hardware is quieted so
expected firmware misses do not flood dmesg.

The series ends with socket_temperature (HSMP_GET_TEMP_MONITOR).


Muthusamy Ramalingam (26):
  platform/x86/amd/hsmp: Drop _input from socket sysfs names
  platform/x86/amd/hsmp: Rename clk_fmax and clk_fmin sysfs files
  platform/x86/amd/hsmp: Add hsmp_err helper for parser-friendly store
    errors
  platform/x86/amd/hsmp: Treat socket_power_limit as firmware-clamped
  platform/x86/amd/hsmp: Print protocol_version as hexadecimal
  platform/x86/amd/hsmp: Add sdps_limit sysfs file
  platform/x86/amd/hsmp: Add df_pstate_range sysfs file
  platform/x86/amd/hsmp: Add xgmi_width sysfs file
  platform/x86/amd/hsmp: Add gmi3_link_width sysfs file
  platform/x86/amd/hsmp: Add pcie_link_rate sysfs file
  platform/x86/amd/hsmp: Add lclk DPM sysfs files
  platform/x86/amd/hsmp: Add io_bw and xgmi_bw sysfs files
  platform/x86/amd/hsmp: Add DIMM sideband sysfs files
  platform/x86/amd/hsmp: Add per-CPU floor limit sysfs files
  platform/x86/amd/hsmp: Add metric_version sysfs file
  platform/x86/amd/hsmp: Add enabled command sysfs files
  platform/x86/amd/hsmp: Add DIMM power and temperature sysfs files
  platform/x86/amd/hsmp: Add SVI3 temperature sysfs files
  platform/x86/amd/hsmp: Add cclk_floor_limit sysfs file
  platform/x86/amd/hsmp: Add xgmi_pstate_range sysfs file
  platform/x86/amd/hsmp: Quiet probe-time firmware status dmesg spam
  platform/x86/amd/hsmp: Add powereff_mode sysfs file
  platform/x86/amd/hsmp: Add svi_power sysfs file
  platform/x86/amd/hsmp: Add per-CPU ccd_power sysfs file
  platform/x86/amd/hsmp: Add per-CPU freq_limit sysfs file
  platform/x86/amd/hsmp: Add socket_temperature sysfs file

 Documentation/arch/x86/amd_hsmp.rst   |  116 +-
 arch/x86/include/asm/amd/hsmp.h       |    7 +
 arch/x86/include/uapi/asm/amd_hsmp.h  |   11 +-
 drivers/platform/x86/amd/hsmp/acpi.c  |  645 ++++++-
 drivers/platform/x86/amd/hsmp/hsmp.c  |  298 +++-
 drivers/platform/x86/amd/hsmp/hsmp.h  |   31 +
 drivers/platform/x86/amd/hsmp/plat.c  | 2346 +++++++++++++++++++++++--
 drivers/platform/x86/amd/hsmp/sysfs.c | 1858 +++++++++++++++++++-
 drivers/platform/x86/amd/hsmp/sysfs.h |  116 +-
 9 files changed, 5260 insertions(+), 168 deletions(-)

This series is rebased on top of https://lore.kernel.org/platform-driver-x86/20261014111430.23156-1-suma.hegde@amd.com/T/#t
-- 
2.34.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 01/26] platform/x86/amd/hsmp: Drop _input from socket sysfs names
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
@ 2026-11-02  7:18 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 02/26] platform/x86/amd/hsmp: Rename clk_fmax and clk_fmin sysfs files Muthusamy Ramalingam
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:18 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

These socket files are not hwmon attributes. Name them for the value
they report.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst  |  12 +--
 drivers/platform/x86/amd/hsmp/acpi.c |  24 +++---
 drivers/platform/x86/amd/hsmp/plat.c | 112 +++++++++++++--------------
 3 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index bd29ab9dd2385..6384935e7fe16 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -97,19 +97,19 @@ directory under amd_hsmp/socket/.
 A file that is normally readable and writable is created read-only or
 write-only when the platform enables only that direction of the message.
 
-* c0_residency_input: Percentage of cores in C0 state.
+* c0_residency: Percentage of cores in C0 state.
 * prochot_status: Reports 1 if the processor is at thermal threshold value,
   0 otherwise.
 * smu_fw_version: SMU firmware version.
 * protocol_version: HSMP interface version.
 * ddr_max_bw: Theoretical maximum DDR bandwidth in GB/s.
-* ddr_utilised_bw_input: Current utilized DDR bandwidth in GB/s.
-* ddr_utilised_bw_perc_input(%): Percentage of current utilized DDR bandwidth.
-* mclk_input: Memory clock in MHz.
-* fclk_input: Fabric clock in MHz.
+* ddr_utilised_bw: Current utilized DDR bandwidth in GB/s.
+* ddr_utilised_bw_perc: Percentage of current utilized DDR bandwidth.
+* mclk: Memory clock in MHz.
+* fclk: Fabric clock in MHz.
 * clk_fmax: Maximum frequency of socket in MHz.
 * clk_fmin: Minimum frequency of socket in MHz.
-* cclk_freq_limit_input: Core clock frequency limit per socket in MHz.
+* cclk_freq_limit: Core clock frequency limit per socket in MHz.
 * pwr_current_active_freq_limit: Current active frequency limit of socket
   in MHz.
 * pwr_current_active_freq_limit_source: Source of current active frequency
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 9da4d9fb88be2..d7a7c40e40ccf 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -515,16 +515,16 @@ static const struct bin_attribute *hsmp_attr_list[] = {
 	HSMP_SYS_ATTR(_name, _name, _mode, NULL, _store, U16_MAX,	\
 		      _msg_id, _msg_id)
 
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
 HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
 HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
 HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
 HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
@@ -552,16 +552,16 @@ HSMP_DEV_ATTR_RW(rail_iso_freq_policy, HSMP_CPU_RAIL_ISO_FREQ_POLICY,
 		 hsmp_rail_iso_freq_policy_show, hsmp_rail_iso_freq_policy_store, 0644);
 
 static struct attribute *hsmp_dev_attr_list[] = {
-	&hattr_c0_residency_input.dattr.attr,
+	&hattr_c0_residency.dattr.attr,
 	&hattr_prochot_status.dattr.attr,
 	&hattr_smu_fw_version.dattr.attr,
 	&hattr_protocol_version.dattr.attr,
-	&hattr_cclk_freq_limit_input.dattr.attr,
+	&hattr_cclk_freq_limit.dattr.attr,
 	&hattr_ddr_max_bw.dattr.attr,
-	&hattr_ddr_utilised_bw_input.dattr.attr,
-	&hattr_ddr_utilised_bw_perc_input.dattr.attr,
-	&hattr_fclk_input.dattr.attr,
-	&hattr_mclk_input.dattr.attr,
+	&hattr_ddr_utilised_bw.dattr.attr,
+	&hattr_ddr_utilised_bw_perc.dattr.attr,
+	&hattr_fclk.dattr.attr,
+	&hattr_mclk.dattr.attr,
 	&hattr_clk_fmax.dattr.attr,
 	&hattr_clk_fmin.dattr.attr,
 	&hattr_pwr_current_active_freq_limit.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 2385827b7ae8a..c246a996e2d4c 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -215,14 +215,14 @@ HSMP_DEV_ATTR_W(_name, _msg_id, _store, _mode, 5); \
 HSMP_DEV_ATTR_W(_name, _msg_id, _store, _mode, 6); \
 HSMP_DEV_ATTR_W(_name, _msg_id, _store, _mode, 7)
 
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 0);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 1);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 2);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 3);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 4);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 5);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 6);
-HSMP_DEV_ATTR(c0_residency_input, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 7);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 0);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 1);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 2);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 3);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 4);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 5);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 6);
+HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444, 7);
 
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444, 0);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444, 1);
@@ -260,58 +260,58 @@ HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444, 5)
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444, 6);
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444, 7);
 
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 0);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 1);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 2);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 3);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 4);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 5);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 6);
-HSMP_DEV_ATTR(ddr_utilised_bw_input, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 7);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 0);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 1);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 2);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 3);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 4);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 5);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 6);
+HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444, 7);
 
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 0);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 1);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 2);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 3);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 4);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 5);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 6);
-HSMP_DEV_ATTR(ddr_utilised_bw_perc_input, HSMP_GET_DDR_BANDWIDTH,
+HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH,
 	      hsmp_ddr_util_bw_perc_show, 0444, 7);
 
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 0);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 1);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 2);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 3);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 4);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 5);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 6);
-HSMP_DEV_ATTR(cclk_freq_limit_input, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 7);
-
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 0);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 1);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 2);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 3);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 4);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 5);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 6);
-HSMP_DEV_ATTR(fclk_input, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 7);
-
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 0);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 1);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 2);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 3);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 4);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 5);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 6);
-HSMP_DEV_ATTR(mclk_input, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 7);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 0);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 1);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 2);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 3);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 4);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 5);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 6);
+HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444, 7);
+
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 0);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 1);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 2);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 3);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 4);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 5);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 6);
+HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444, 7);
+
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 0);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 1);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 2);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 3);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 4);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 5);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 6);
+HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 7);
 
 HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 0);
 HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 1);
@@ -391,16 +391,16 @@ HSMP_DEV_ATTR_RW_X8(rail_iso_freq_policy, HSMP_CPU_RAIL_ISO_FREQ_POLICY,
 
 #define HSMP_DEV_ATTR_LIST(_name, _sock_ind)				       \
 static struct attribute _name[] = {					       \
-	&hattr_c0_residency_input##_sock_ind.dattr.attr,		       \
+	&hattr_c0_residency##_sock_ind.dattr.attr,		       \
 	&hattr_prochot_status##_sock_ind.dattr.attr,			       \
 	&hattr_smu_fw_version##_sock_ind.dattr.attr,			       \
 	&hattr_protocol_version##_sock_ind.dattr.attr,			       \
-	&hattr_cclk_freq_limit_input##_sock_ind.dattr.attr,		       \
+	&hattr_cclk_freq_limit##_sock_ind.dattr.attr,		       \
 	&hattr_ddr_max_bw##_sock_ind.dattr.attr,			       \
-	&hattr_ddr_utilised_bw_input##_sock_ind.dattr.attr,		       \
-	&hattr_ddr_utilised_bw_perc_input##_sock_ind.dattr.attr,	       \
-	&hattr_fclk_input##_sock_ind.dattr.attr,			       \
-	&hattr_mclk_input##_sock_ind.dattr.attr,			       \
+	&hattr_ddr_utilised_bw##_sock_ind.dattr.attr,		       \
+	&hattr_ddr_utilised_bw_perc##_sock_ind.dattr.attr,	       \
+	&hattr_fclk##_sock_ind.dattr.attr,			       \
+	&hattr_mclk##_sock_ind.dattr.attr,			       \
 	&hattr_clk_fmax##_sock_ind.dattr.attr,				       \
 	&hattr_clk_fmin##_sock_ind.dattr.attr,				       \
 	&hattr_pwr_current_active_freq_limit##_sock_ind.dattr.attr,	       \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 02/26] platform/x86/amd/hsmp: Rename clk_fmax and clk_fmin sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
  2026-11-02  7:18 ` [PATCH 01/26] platform/x86/amd/hsmp: Drop _input from socket sysfs names Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 03/26] platform/x86/amd/hsmp: Add hsmp_err helper for parser-friendly store errors Muthusamy Ramalingam
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

These report the socket core-clock limits, so name them cclk_fmax and
cclk_fmin.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  4 +--
 drivers/platform/x86/amd/hsmp/acpi.c  |  8 +++---
 drivers/platform/x86/amd/hsmp/plat.c  | 38 +++++++++++++--------------
 drivers/platform/x86/amd/hsmp/sysfs.c |  8 +++---
 drivers/platform/x86/amd/hsmp/sysfs.h |  8 +++---
 5 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 6384935e7fe16..a1964c5f12023 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -107,8 +107,8 @@ write-only when the platform enables only that direction of the message.
 * ddr_utilised_bw_perc: Percentage of current utilized DDR bandwidth.
 * mclk: Memory clock in MHz.
 * fclk: Fabric clock in MHz.
-* clk_fmax: Maximum frequency of socket in MHz.
-* clk_fmin: Minimum frequency of socket in MHz.
+* cclk_fmax: Maximum frequency of socket in MHz.
+* cclk_fmin: Minimum frequency of socket in MHz.
 * cclk_freq_limit: Core clock frequency limit per socket in MHz.
 * pwr_current_active_freq_limit: Current active frequency limit of socket
   in MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index d7a7c40e40ccf..a74fb274ee652 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -525,8 +525,8 @@ HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 04
 HSMP_DEV_ATTR(ddr_utilised_bw_perc, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_perc_show, 0444);
 HSMP_DEV_ATTR(fclk, HSMP_GET_FCLK_MCLK, hsmp_fclk_show, 0444);
 HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444);
 HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
 	      hsmp_freq_limit_show, 0444);
 HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
@@ -562,8 +562,8 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_ddr_utilised_bw_perc.dattr.attr,
 	&hattr_fclk.dattr.attr,
 	&hattr_mclk.dattr.attr,
-	&hattr_clk_fmax.dattr.attr,
-	&hattr_clk_fmin.dattr.attr,
+	&hattr_cclk_fmax.dattr.attr,
+	&hattr_cclk_fmin.dattr.attr,
 	&hattr_pwr_current_active_freq_limit.dattr.attr,
 	&hattr_pwr_current_active_freq_limit_source.dattr.attr,
 	&hattr_socket_power_limit_max.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index c246a996e2d4c..49a0c01f6dd1b 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -313,23 +313,23 @@ HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 5);
 HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 6);
 HSMP_DEV_ATTR(mclk, HSMP_GET_FCLK_MCLK, hsmp_mclk_show, 0444, 7);
 
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 0);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 1);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 2);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 3);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 4);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 5);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 6);
-HSMP_DEV_ATTR(clk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmax_show, 0444, 7);
-
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 0);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 1);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 2);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 3);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 4);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 5);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 6);
-HSMP_DEV_ATTR(clk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_clk_fmin_show, 0444, 7);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 0);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 1);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 2);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 3);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 4);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 5);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 6);
+HSMP_DEV_ATTR(cclk_fmax, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmax_show, 0444, 7);
+
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 0);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 1);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 2);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 3);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 4);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 5);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 6);
+HSMP_DEV_ATTR(cclk_fmin, HSMP_GET_SOCKET_FMAX_FMIN, hsmp_cclk_fmin_show, 0444, 7);
 
 HSMP_DEV_ATTR(pwr_current_active_freq_limit, HSMP_GET_SOCKET_FREQ_LIMIT,
 	      hsmp_freq_limit_show, 0444, 0);
@@ -401,8 +401,8 @@ static struct attribute _name[] = {					       \
 	&hattr_ddr_utilised_bw_perc##_sock_ind.dattr.attr,	       \
 	&hattr_fclk##_sock_ind.dattr.attr,			       \
 	&hattr_mclk##_sock_ind.dattr.attr,			       \
-	&hattr_clk_fmax##_sock_ind.dattr.attr,				       \
-	&hattr_clk_fmin##_sock_ind.dattr.attr,				       \
+	&hattr_cclk_fmax##_sock_ind.dattr.attr,				       \
+	&hattr_cclk_fmin##_sock_ind.dattr.attr,				       \
 	&hattr_pwr_current_active_freq_limit##_sock_ind.dattr.attr,	       \
 	&hattr_pwr_current_active_freq_limit_source##_sock_ind.dattr.attr,     \
 	&hattr_socket_power_limit_max##_sock_ind.dattr.attr,		       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index ac2ae9f2774a8..1f6448380214a 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -155,8 +155,8 @@ ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(buf, "%u\n", data[1]);
 }
 
-ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
+ssize_t hsmp_cclk_fmax_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
 	u32 data;
@@ -169,8 +169,8 @@ ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(buf, "%lu\n", FIELD_GET(FMAX_MASK, data));
 }
 
-ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
-			   char *buf)
+ssize_t hsmp_cclk_fmin_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
 	u32 data;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index d25225c3160ce..9381498420f5a 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -66,10 +66,10 @@ ssize_t hsmp_fclk_show(struct device *dev, struct device_attribute *attr,
 		       char *buf);
 ssize_t hsmp_mclk_show(struct device *dev, struct device_attribute *attr,
 		       char *buf);
-ssize_t hsmp_clk_fmax_show(struct device *dev, struct device_attribute *attr,
-			   char *buf);
-ssize_t hsmp_clk_fmin_show(struct device *dev, struct device_attribute *attr,
-			   char *buf);
+ssize_t hsmp_cclk_fmax_show(struct device *dev, struct device_attribute *attr,
+			    char *buf);
+ssize_t hsmp_cclk_fmin_show(struct device *dev, struct device_attribute *attr,
+			    char *buf);
 ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 03/26] platform/x86/amd/hsmp: Add hsmp_err helper for parser-friendly store errors
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
  2026-11-02  7:18 ` [PATCH 01/26] platform/x86/amd/hsmp: Drop _input from socket sysfs names Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 02/26] platform/x86/amd/hsmp: Rename clk_fmax and clk_fmin sysfs files Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 04/26] platform/x86/amd/hsmp: Treat socket_power_limit as firmware-clamped Muthusamy Ramalingam
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Introduce hsmp_err() and the closed reason-code set (parse, argc, range,
order, hw) used by sysfs store handlers to log stable, tokenizable errors.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 drivers/platform/x86/amd/hsmp/sysfs.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 1f6448380214a..243acb9e37252 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -29,6 +29,21 @@ struct hsmp_cpu_info {
 
 static struct hsmp_cpu_info cpu_kobj_info[NR_CPUS];
 
+/*
+ * Parser-friendly sysfs store error, logged as:
+ *   "<attr>: err=<reason> <key=value ...>"
+ * reason is one of: parse, argc, range, order, hw.
+ */
+#define hsmp_err(dev, attr, reason, fmt, ...) \
+	dev_err(dev, "%s: err=%s " fmt "\n", attr, reason, ##__VA_ARGS__)
+
+/* hsmp_err() reason codes - keep in sync with the comment above */
+#define HSMP_ERR_PARSE	"parse"
+#define HSMP_ERR_ARGC	"argc"
+#define HSMP_ERR_RANGE	"range"
+#define HSMP_ERR_ORDER	"order"
+#define HSMP_ERR_HW	"hw"
+
 static const char * const freqlimit_srcnames[] = {
 	"cHTC-Active",
 	"PROCHOT",
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 04/26] platform/x86/amd/hsmp: Treat socket_power_limit as firmware-clamped
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (2 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 03/26] platform/x86/amd/hsmp: Add hsmp_err helper for parser-friendly store errors Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 05/26] platform/x86/amd/hsmp: Print protocol_version as hexadecimal Muthusamy Ramalingam
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Stop rejecting writes outside 1000-1000000 mW; the field is 32-bit and
firmware clamps to the platform range. Wire hsmp_err() into
hsmp_socket_power_limit_store() and update the documentation.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  4 ++--
 drivers/platform/x86/amd/hsmp/sysfs.c | 19 +++++++++++++++----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index a1964c5f12023..e14925896a3e9 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -115,8 +115,8 @@ write-only when the platform enables only that direction of the message.
 * pwr_current_active_freq_limit_source: Source of current active frequency
   limit.
 * socket_power: Average package power in mWatts (read only).
-* socket_power_limit: Current socket power limit in mWatts. Write accepts
-  1000-1000000 mWatts.
+* socket_power_limit: Current socket power limit in mWatts. A write is a
+  32-bit value. Firmware clamps it to the platform range.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 243acb9e37252..f7c90680a4ff6 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -582,12 +582,20 @@ ssize_t hsmp_socket_power_limit_store(struct device *dev,
 	int ret;
 
 	ret = kstrtoul(buf, 10, &val);
-	if (ret)
+	if (ret) {
+		hsmp_err(dev, "socket_power_limit", HSMP_ERR_PARSE, "unit=mW");
 		return ret;
+	}
 
-	/* Validate input: power limit should be reasonable (1W to 1000W in mWatts) */
-	if (val < 1000 || val > 1000000)
+	/*
+	 * Power limit is a 32-bit mW field; firmware clamps to the platform
+	 * min/max, so only reject values that overflow the field.
+	 */
+	if (val > U32_MAX) {
+		hsmp_err(dev, "socket_power_limit", HSMP_ERR_RANGE,
+			 "got=%lu valid=0-%u unit=mW", val, U32_MAX);
 		return -EINVAL;
+	}
 
 	/* Set socket power limit using HSMP_SET_SOCKET_POWER_LIMIT */
 	msg.msg_id = HSMP_SET_SOCKET_POWER_LIMIT;
@@ -597,8 +605,11 @@ ssize_t hsmp_socket_power_limit_store(struct device *dev,
 	msg.args[0] = val;  /* power limit value in mWatts */
 
 	ret = hsmp_send_message(&msg);
-	if (ret)
+	if (ret) {
+		hsmp_err(dev, "socket_power_limit", HSMP_ERR_HW,
+			 "val=%lu unit=mW rc=%d", val, ret);
 		return ret;
+	}
 
 	return count;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 05/26] platform/x86/amd/hsmp: Print protocol_version as hexadecimal
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (3 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 04/26] platform/x86/amd/hsmp: Treat socket_power_limit as firmware-clamped Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 06/26] platform/x86/amd/hsmp: Add sdps_limit sysfs file Muthusamy Ramalingam
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Switch the protocol_version sysfs file on both drivers to
hsmp_msg_resp32_hex_show so the HSMP interface version is reported as
eight hexadecimal digits, matching metric_version.

Introduce hsmp_msg_resp32_hex_show for that formatting.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 +-
 drivers/platform/x86/amd/hsmp/acpi.c  |  2 +-
 drivers/platform/x86/amd/hsmp/plat.c  | 16 ++++++++--------
 drivers/platform/x86/amd/hsmp/sysfs.c | 15 +++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  2 ++
 5 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index e14925896a3e9..44a7da87e5907 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -101,7 +101,7 @@ write-only when the platform enables only that direction of the message.
 * prochot_status: Reports 1 if the processor is at thermal threshold value,
   0 otherwise.
 * smu_fw_version: SMU firmware version.
-* protocol_version: HSMP interface version.
+* protocol_version: HSMP interface version, as eight hexadecimal digits.
 * ddr_max_bw: Theoretical maximum DDR bandwidth in GB/s.
 * ddr_utilised_bw: Current utilized DDR bandwidth in GB/s.
 * ddr_utilised_bw_perc: Percentage of current utilized DDR bandwidth.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index a74fb274ee652..6bbcc2f7e6a30 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -518,7 +518,7 @@ static const struct bin_attribute *hsmp_attr_list[] = {
 HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444);
 HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
 HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 49a0c01f6dd1b..ba8274e5bfb4a 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -233,14 +233,14 @@ HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444, 5);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444, 6);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444, 7);
 
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 0);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 1);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 2);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 3);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 4);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 5);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 6);
-HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_show, 0444, 7);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 0);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 1);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 2);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 3);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 4);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 5);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 6);
+HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 7);
 
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 0);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 1);
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index f7c90680a4ff6..bc1b349468978 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -83,6 +83,21 @@ ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
 	return sysfs_emit(buf, "%u\n", data);
 }
 
+/* Print a 32-bit response as 8 hex digits (protocol_version, metric_version). */
+ssize_t hsmp_msg_resp32_hex_show(struct device *dev, struct device_attribute *attr,
+				 char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(hsmp_sysfs_sock_ind(dev, hattr), hattr->msg_id, &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "0x%08x\n", data);
+}
+
 ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 9381498420f5a..aae932079ab70 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -54,6 +54,8 @@ static struct hsmp_sys_attr hattr_##_var = {				\
 
 ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
+ssize_t hsmp_msg_resp32_hex_show(struct device *dev, struct device_attribute *attr,
+				 char *buf);
 ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 06/26] platform/x86/amd/hsmp: Add sdps_limit sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (4 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 05/26] platform/x86/amd/hsmp: Print protocol_version as hexadecimal Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 07/26] platform/x86/amd/hsmp: Add df_pstate_range " Muthusamy Ramalingam
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SDPS_LIMIT as a read/write socket file on both the ACPI
and platform drivers. For a read, set bit 31. For a write, reset bit
31 and store the limit in bits [30:0]. A write accepts any value that
fits in that field. Firmware clamps it to the platform range.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 +
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 ++
 drivers/platform/x86/amd/hsmp/plat.c  |  3 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 67 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  4 ++
 5 files changed, 79 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 44a7da87e5907..1fc4727b48726 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -117,6 +117,8 @@ write-only when the platform enables only that direction of the message.
 * socket_power: Average package power in mWatts (read only).
 * socket_power_limit: Current socket power limit in mWatts. A write is a
   32-bit value. Firmware clamps it to the platform range.
+* sdps_limit: Read/write SDPS limit in mWatts. A write uses bits [30:0].
+  Firmware clamps it to the platform range.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 6bbcc2f7e6a30..4c9f6c6843304 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -537,6 +537,8 @@ HSMP_DEV_ATTR(tdelta, HSMP_READ_TDELTA, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		 HSMP_SET_SOCKET_POWER_LIMIT,
 		 hsmp_socket_power_limit_show, hsmp_socket_power_limit_store, 0644);
+HSMP_DEV_ATTR_RW(sdps_limit, HSMP_SDPS_LIMIT, HSMP_SDPS_LIMIT,
+		 hsmp_sdps_limit_show, hsmp_sdps_limit_store, 0644);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -568,6 +570,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_pwr_current_active_freq_limit_source.dattr.attr,
 	&hattr_socket_power_limit_max.dattr.attr,
 	&hattr_socket_power_limit.dattr.attr,
+	&hattr_sdps_limit.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index ba8274e5bfb4a..6f4250cfc1f4a 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -371,6 +371,8 @@ HSMP_DEV_ATTR_RW_X8(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		    HSMP_SET_SOCKET_POWER_LIMIT,
 		    hsmp_socket_power_limit_show,
 		    hsmp_socket_power_limit_store, 0644);
+HSMP_DEV_ATTR_RW_X8(sdps_limit, HSMP_SDPS_LIMIT, HSMP_SDPS_LIMIT,
+		    hsmp_sdps_limit_show, hsmp_sdps_limit_store, 0644);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -407,6 +409,7 @@ static struct attribute _name[] = {					       \
 	&hattr_pwr_current_active_freq_limit_source##_sock_ind.dattr.attr,     \
 	&hattr_socket_power_limit_max##_sock_ind.dattr.attr,		       \
 	&hattr_socket_power_limit##_sock_ind.dattr.attr,		       \
+	&hattr_sdps_limit##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index bc1b349468978..01363b0b92fd7 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -629,6 +629,73 @@ ssize_t hsmp_socket_power_limit_store(struct device *dev,
 	return count;
 }
 
+/* SDPS limit show function - reads current SDPS limit */
+ssize_t hsmp_sdps_limit_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	int ret;
+
+	/* Set bit 31 to indicate GET operation for HSMP_SET_GET type messages */
+	msg.msg_id = HSMP_SDPS_LIMIT;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = BIT(31);  /* GET operation */
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	/* Return current SDPS limit in mWatts (bits [30:0]) */
+	return sysfs_emit(buf, "%lu\n", msg.args[0] & GENMASK(30, 0));
+}
+
+/* SDPS limit store function - sets SDPS limit */
+ssize_t hsmp_sdps_limit_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret) {
+		hsmp_err(dev, "sdps_limit", HSMP_ERR_PARSE, "unit=mW");
+		return ret;
+	}
+
+	/*
+	 * The SDPS limit occupies bits [30:0]. Firmware clamps it to the
+	 * platform minimum and maximum, so reject only a field overflow.
+	 */
+	if (val > GENMASK(30, 0)) {
+		hsmp_err(dev, "sdps_limit", HSMP_ERR_RANGE,
+			 "got=%lu valid=0-2147483647 unit=mW", val);
+		return -EINVAL;
+	}
+
+	/* Clear bit 31 for SET operation, set SDPS limit value in bits [30:0] */
+	msg.msg_id = HSMP_SDPS_LIMIT;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = val & GENMASK(30, 0);
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "sdps_limit", HSMP_ERR_HW,
+			 "val=%lu unit=mW rc=%d", val, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index aae932079ab70..bf5bac77102d3 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -106,6 +106,10 @@ ssize_t hsmp_socket_power_limit_show(struct device *dev,
 ssize_t hsmp_socket_power_limit_store(struct device *dev,
 				      struct device_attribute *attr,
 				      const char *buf, size_t count);
+ssize_t hsmp_sdps_limit_show(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+ssize_t hsmp_sdps_limit_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 07/26] platform/x86/amd/hsmp: Add df_pstate_range sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (5 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 06/26] platform/x86/amd/hsmp: Add sdps_limit sysfs file Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 08/26] platform/x86/amd/hsmp: Add xgmi_width " Muthusamy Ramalingam
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SET_PSTATE_MAX_MIN as a read/write socket file on both the
ACPI and platform drivers. Read and write are differentiated by bit 31.
Setting the bit selects a read, and resetting it selects a write. A
read returns the minimum and maximum DF P-states. A write takes
"min max". Each value is an 8-bit field. Extra arguments are rejected.
Firmware rejects unsupported P-states.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   3 +
 drivers/platform/x86/amd/hsmp/acpi.c  |   3 +
 drivers/platform/x86/amd/hsmp/plat.c  |   5 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 116 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |   5 ++
 5 files changed, 132 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 1fc4727b48726..694997308ffa9 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -119,6 +119,9 @@ write-only when the platform enables only that direction of the message.
   32-bit value. Firmware clamps it to the platform range.
 * sdps_limit: Read/write SDPS limit in mWatts. A write uses bits [30:0].
   Firmware clamps it to the platform range.
+* df_pstate_range: Read/write DF P-state range as "min max". Each value
+  is an 8-bit field. 0 is the highest performance. Extra arguments are
+  rejected. Firmware rejects unsupported P-states.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 4c9f6c6843304..417fca04a722f 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -539,6 +539,8 @@ HSMP_DEV_ATTR_RW(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		 hsmp_socket_power_limit_show, hsmp_socket_power_limit_store, 0644);
 HSMP_DEV_ATTR_RW(sdps_limit, HSMP_SDPS_LIMIT, HSMP_SDPS_LIMIT,
 		 hsmp_sdps_limit_show, hsmp_sdps_limit_store, 0644);
+HSMP_DEV_ATTR_RW(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN, HSMP_SET_PSTATE_MAX_MIN,
+		 hsmp_df_pstate_range_show, hsmp_df_pstate_range_store, 0644);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -571,6 +573,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_socket_power_limit_max.dattr.attr,
 	&hattr_socket_power_limit.dattr.attr,
 	&hattr_sdps_limit.dattr.attr,
+	&hattr_df_pstate_range.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 6f4250cfc1f4a..3deb5480495dc 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -373,6 +373,10 @@ HSMP_DEV_ATTR_RW_X8(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		    hsmp_socket_power_limit_store, 0644);
 HSMP_DEV_ATTR_RW_X8(sdps_limit, HSMP_SDPS_LIMIT, HSMP_SDPS_LIMIT,
 		    hsmp_sdps_limit_show, hsmp_sdps_limit_store, 0644);
+HSMP_DEV_ATTR_RW_X8(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN,
+		    HSMP_SET_PSTATE_MAX_MIN,
+		    hsmp_df_pstate_range_show, hsmp_df_pstate_range_store,
+		    0644);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -410,6 +414,7 @@ static struct attribute _name[] = {					       \
 	&hattr_socket_power_limit_max##_sock_ind.dattr.attr,		       \
 	&hattr_socket_power_limit##_sock_ind.dattr.attr,		       \
 	&hattr_sdps_limit##_sock_ind.dattr.attr,			       \
+	&hattr_df_pstate_range##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 01363b0b92fd7..8f10281cb97c1 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -14,6 +14,7 @@
 #include <linux/kstrtox.h>
 #include <linux/limits.h>
 #include <linux/smp.h>
+#include <linux/string.h>
 #include <linux/sysfs.h>
 #include <linux/topology.h>
 
@@ -696,6 +697,121 @@ ssize_t hsmp_sdps_limit_store(struct device *dev,
 	return count;
 }
 
+/* Multi-field stores copy the write into this buffer before tokenizing. */
+#define HSMP_PARSE_BUFSZ	80
+
+/*
+ * Parse exactly @n whitespace-separated unsigned integers. base 10 accepts
+ * decimal. base 0 also accepts 0x hex and leading-zero octal. Too few
+ * tokens, extra tokens, and a value that does not fit in u32 are rejected.
+ * On failure, *@got is the number of whitespace-separated tokens present.
+ */
+static int hsmp_parse_u32_args(const char *buf, u32 *vals, int n,
+			       unsigned int base, int *got)
+{
+	char tmp[HSMP_PARSE_BUFSZ];
+	char *s, *tok;
+	int i = 0;
+
+	*got = 0;
+	if (strscpy(tmp, buf, sizeof(tmp)) < 0)
+		return -EINVAL;
+
+	s = tmp;
+	while ((tok = strsep(&s, " \t\n")) != NULL) {
+		if (*tok == '\0')
+			continue;
+		(*got)++;
+		if (i < n && !kstrtou32(tok, base, &vals[i]))
+			i++;
+	}
+
+	return (i == n && *got == n) ? 0 : -EINVAL;
+}
+
+/* DF P-state range show function - reads current min and max DF P-states */
+ssize_t hsmp_df_pstate_range_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = { 0 };
+	u32 min_pstate, max_pstate;
+	int ret;
+
+	/* Set bit 31 to indicate GET operation for HSMP_SET_GET type messages */
+	msg.msg_id = HSMP_SET_PSTATE_MAX_MIN;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = BIT(31);  /* GET operation */
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	/* Extract min DF P-state[15:8] and max DF P-state[7:0] */
+	min_pstate = (msg.args[0] >> 8) & 0xFF;
+	max_pstate = msg.args[0] & 0xFF;
+
+	return sysfs_emit(buf, "%u %u\n", min_pstate, max_pstate);
+}
+
+/* DF P-state range store function - sets min and max DF P-states */
+ssize_t hsmp_df_pstate_range_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = { 0 };
+	u32 min_pstate, max_pstate;
+	u32 vals[2];
+	int ret;
+	int got;
+
+	/* Parse input in format: "min_pstate max_pstate" */
+	ret = hsmp_parse_u32_args(buf, vals, 2, 10, &got);
+	if (ret) {
+		hsmp_err(dev, "df_pstate_range", HSMP_ERR_ARGC,
+			 "want=2 got=%d fmt=\"min max\"", got);
+		return -EINVAL;
+	}
+	min_pstate = vals[0];
+	max_pstate = vals[1];
+
+	/* Min and max are 8-bit fields. Firmware rejects unsupported P-states. */
+	if (min_pstate > 0xFF || max_pstate > 0xFF) {
+		hsmp_err(dev, "df_pstate_range", HSMP_ERR_RANGE,
+			 "min=%u max=%u valid=0-255", min_pstate, max_pstate);
+		return -EINVAL;
+	}
+
+	/* Clear bit 31 for SET operation, pack min[15:8] and max[7:0] */
+	msg.msg_id = HSMP_SET_PSTATE_MAX_MIN;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = (min_pstate << 8) | max_pstate;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		if (max_pstate > min_pstate)
+			hsmp_err(dev, "df_pstate_range", HSMP_ERR_ORDER,
+				 "min=%u max=%u rule=max<=min rc=%d",
+				  min_pstate, max_pstate, ret);
+		else if (min_pstate > 2 || max_pstate > 2)
+			hsmp_err(dev, "df_pstate_range", HSMP_ERR_RANGE,
+				 "min=%u max=%u valid=0-2 rc=%d",
+				  min_pstate, max_pstate, ret);
+		else
+			hsmp_err(dev, "df_pstate_range", HSMP_ERR_HW,
+				 "min=%u max=%u rc=%d", min_pstate, max_pstate, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index bf5bac77102d3..9631b9067c142 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -110,6 +110,11 @@ ssize_t hsmp_sdps_limit_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_sdps_limit_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count);
+ssize_t hsmp_df_pstate_range_show(struct device *dev,
+				  struct device_attribute *attr, char *buf);
+ssize_t hsmp_df_pstate_range_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 08/26] platform/x86/amd/hsmp: Add xgmi_width sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (6 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 07/26] platform/x86/amd/hsmp: Add df_pstate_range " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 09/26] platform/x86/amd/hsmp: Add gmi3_link_width " Muthusamy Ramalingam
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Add a read/write socket file for the xGMI link-width range on both the
ACPI and platform drivers.

Read and write are differentiated by bit 31. Setting the bit selects a
read, and resetting it selects a write. A read returns the minimum and
maximum widths. A write takes "min max", with the minimum in bits
[15:8] and the maximum in bits [7:0]. 0 is x4, 1 is x8, and 2 is x16.
Each value is an 8-bit field. Extra arguments are rejected. Firmware
rejects an unsupported width.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  3 +
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 +
 drivers/platform/x86/amd/hsmp/plat.c  |  4 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 79 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  4 ++
 5 files changed, 93 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 694997308ffa9..134c94e71b006 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -122,6 +122,9 @@ write-only when the platform enables only that direction of the message.
 * df_pstate_range: Read/write DF P-state range as "min max". Each value
   is an 8-bit field. 0 is the highest performance. Extra arguments are
   rejected. Firmware rejects unsupported P-states.
+* xgmi_width: Read/write xGMI link width range as "min max".
+  0 is x4, 1 is x8, and 2 is x16. Each value is an 8-bit field.
+  Extra arguments are rejected. Firmware rejects unsupported widths.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 417fca04a722f..4f4170d191850 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -541,6 +541,8 @@ HSMP_DEV_ATTR_RW(sdps_limit, HSMP_SDPS_LIMIT, HSMP_SDPS_LIMIT,
 		 hsmp_sdps_limit_show, hsmp_sdps_limit_store, 0644);
 HSMP_DEV_ATTR_RW(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN, HSMP_SET_PSTATE_MAX_MIN,
 		 hsmp_df_pstate_range_show, hsmp_df_pstate_range_store, 0644);
+HSMP_DEV_ATTR_RW(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH, HSMP_SET_XGMI_LINK_WIDTH,
+		 hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -574,6 +576,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_socket_power_limit.dattr.attr,
 	&hattr_sdps_limit.dattr.attr,
 	&hattr_df_pstate_range.dattr.attr,
+	&hattr_xgmi_width.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 3deb5480495dc..2c09a48b70471 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -377,6 +377,9 @@ HSMP_DEV_ATTR_RW_X8(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN,
 		    HSMP_SET_PSTATE_MAX_MIN,
 		    hsmp_df_pstate_range_show, hsmp_df_pstate_range_store,
 		    0644);
+HSMP_DEV_ATTR_RW_X8(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH,
+		    HSMP_SET_XGMI_LINK_WIDTH,
+		    hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -415,6 +418,7 @@ static struct attribute _name[] = {					       \
 	&hattr_socket_power_limit##_sock_ind.dattr.attr,		       \
 	&hattr_sdps_limit##_sock_ind.dattr.attr,			       \
 	&hattr_df_pstate_range##_sock_ind.dattr.attr,			       \
+	&hattr_xgmi_width##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 8f10281cb97c1..4726b3dcdda3d 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -812,6 +812,85 @@ ssize_t hsmp_df_pstate_range_store(struct device *dev,
 	return count;
 }
 
+/* xGMI width show function - reads current min and max link width */
+ssize_t hsmp_xgmi_width_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_width, max_width;
+	int ret;
+
+	/* Set bit 31 to indicate GET operation for HSMP_SET_GET type messages */
+	msg.msg_id = HSMP_SET_XGMI_LINK_WIDTH;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = BIT(31);  /* GET operation */
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	/* Extract min width[15:8] and max width[7:0] */
+	min_width = (msg.args[0] >> 8) & 0xFF;
+	max_width = msg.args[0] & 0xFF;
+
+	return sysfs_emit(buf, "%u %u\n", min_width, max_width);
+}
+
+/* xGMI width store function - sets min and max link width */
+ssize_t hsmp_xgmi_width_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_width, max_width;
+	u32 vals[2];
+	int ret;
+	int got;
+
+	/* Parse input in format: "min_width max_width" */
+	ret = hsmp_parse_u32_args(buf, vals, 2, 10, &got);
+	if (ret) {
+		hsmp_err(dev, "xgmi_width", HSMP_ERR_ARGC,
+			 "want=2 got=%d fmt=\"min max\"", got);
+		return -EINVAL;
+	}
+	min_width = vals[0];
+	max_width = vals[1];
+
+	/* Min and max are 8-bit fields. Firmware rejects unsupported widths. */
+	if (min_width > 0xFF || max_width > 0xFF) {
+		hsmp_err(dev, "xgmi_width", HSMP_ERR_RANGE,
+			 "min=%u max=%u valid=0-255", min_width, max_width);
+		return -EINVAL;
+	}
+
+	/* Clear bit 31 for SET operation, pack min[15:8] and max[7:0] */
+	msg.msg_id = HSMP_SET_XGMI_LINK_WIDTH;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = (min_width << 8) | max_width;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		if (max_width < min_width)
+			hsmp_err(dev, "xgmi_width", HSMP_ERR_ORDER,
+				 "min=%u max=%u rule=max>=min rc=%d",
+				  min_width, max_width, ret);
+		else
+			hsmp_err(dev, "xgmi_width", HSMP_ERR_HW,
+				 "min=%u max=%u rc=%d", min_width, max_width, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 9631b9067c142..58340e0544af6 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -115,6 +115,10 @@ ssize_t hsmp_df_pstate_range_show(struct device *dev,
 ssize_t hsmp_df_pstate_range_store(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count);
+ssize_t hsmp_xgmi_width_show(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+ssize_t hsmp_xgmi_width_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 09/26] platform/x86/amd/hsmp: Add gmi3_link_width sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (7 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 08/26] platform/x86/amd/hsmp: Add xgmi_width " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 10/26] platform/x86/amd/hsmp: Add pcie_link_rate " Muthusamy Ramalingam
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SET_GMI3_WIDTH as a write-only socket file on both the ACPI
and platform drivers. A write accepts "min max", where each value is
an 8-bit field. Extra arguments are rejected. Firmware rejects unsupported
widths.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  3 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 ++
 drivers/platform/x86/amd/hsmp/plat.c  |  3 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 60 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  3 ++
 5 files changed, 72 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 134c94e71b006..d7c4653f4f2f2 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -125,6 +125,9 @@ write-only when the platform enables only that direction of the message.
 * xgmi_width: Read/write xGMI link width range as "min max".
   0 is x4, 1 is x8, and 2 is x16. Each value is an 8-bit field.
   Extra arguments are rejected. Firmware rejects unsupported widths.
+* gmi3_link_width: Write-only. Sets the GMI3 link width range as
+  "min max". Each value is an 8-bit field. Extra arguments are rejected.
+  Firmware rejects unsupported widths.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 4f4170d191850..2f9228622fba4 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -543,6 +543,8 @@ HSMP_DEV_ATTR_RW(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN, HSMP_SET_PSTATE_MAX_M
 		 hsmp_df_pstate_range_show, hsmp_df_pstate_range_store, 0644);
 HSMP_DEV_ATTR_RW(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH, HSMP_SET_XGMI_LINK_WIDTH,
 		 hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
+HSMP_DEV_ATTR_W(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
+		hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -577,6 +579,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_sdps_limit.dattr.attr,
 	&hattr_df_pstate_range.dattr.attr,
 	&hattr_xgmi_width.dattr.attr,
+	&hattr_gmi3_link_width.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 2c09a48b70471..ca4aa13bfc4bc 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -380,6 +380,8 @@ HSMP_DEV_ATTR_RW_X8(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN,
 HSMP_DEV_ATTR_RW_X8(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH,
 		    HSMP_SET_XGMI_LINK_WIDTH,
 		    hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
+HSMP_DEV_ATTR_W_X8(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
+		   hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -419,6 +421,7 @@ static struct attribute _name[] = {					       \
 	&hattr_sdps_limit##_sock_ind.dattr.attr,			       \
 	&hattr_df_pstate_range##_sock_ind.dattr.attr,			       \
 	&hattr_xgmi_width##_sock_ind.dattr.attr,			       \
+	&hattr_gmi3_link_width##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 4726b3dcdda3d..4c193fbcab013 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -45,6 +45,9 @@ static struct hsmp_cpu_info cpu_kobj_info[NR_CPUS];
 #define HSMP_ERR_ORDER	"order"
 #define HSMP_ERR_HW	"hw"
 
+/* GMI3 link width encodes 3 levels (0-2); upper bound for range diagnostics */
+#define HSMP_GMI3_LINK_WIDTH_MAX		2
+
 static const char * const freqlimit_srcnames[] = {
 	"cHTC-Active",
 	"PROCHOT",
@@ -891,6 +894,63 @@ ssize_t hsmp_xgmi_width_store(struct device *dev,
 	return count;
 }
 
+/* GMI3 link width store function - sets min and max link width */
+ssize_t hsmp_gmi3_link_width_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_width, max_width;
+	u32 vals[2];
+	int ret;
+	int got;
+
+	/* Parse input in format: "min max" */
+	ret = hsmp_parse_u32_args(buf, vals, 2, 10, &got);
+	if (ret) {
+		hsmp_err(dev, "gmi3_link_width", HSMP_ERR_ARGC,
+			 "want=2 got=%d fmt=\"min max\"", got);
+		return -EINVAL;
+	}
+	min_width = vals[0];
+	max_width = vals[1];
+
+	/* Min and max are 8-bit fields. Firmware rejects unsupported widths. */
+	if (min_width > 0xFF || max_width > 0xFF) {
+		hsmp_err(dev, "gmi3_link_width", HSMP_ERR_RANGE,
+			 "min=%u max=%u valid=0-255", min_width, max_width);
+		return -EINVAL;
+	}
+
+	/* Pack min link width[15:8] and max link width[7:0] */
+	msg.msg_id = HSMP_SET_GMI3_WIDTH;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 0;
+	msg.args[0] = (min_width << 8) | max_width;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		if (max_width < min_width)
+			hsmp_err(dev, "gmi3_link_width", HSMP_ERR_ORDER,
+				 "min=%u max=%u rule=max>=min rc=%d",
+				  min_width, max_width, ret);
+		else if (min_width > HSMP_GMI3_LINK_WIDTH_MAX ||
+			 max_width > HSMP_GMI3_LINK_WIDTH_MAX)
+			hsmp_err(dev, "gmi3_link_width", HSMP_ERR_RANGE,
+				 "min=%u max=%u valid=0-%u rc=%d",
+				  min_width, max_width, HSMP_GMI3_LINK_WIDTH_MAX,
+				  ret);
+		else
+			hsmp_err(dev, "gmi3_link_width", HSMP_ERR_HW,
+				 "min=%u max=%u rc=%d", min_width, max_width, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 58340e0544af6..1831d817a6834 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -119,6 +119,9 @@ ssize_t hsmp_xgmi_width_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_xgmi_width_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count);
+ssize_t hsmp_gmi3_link_width_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 10/26] platform/x86/amd/hsmp: Add pcie_link_rate sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (8 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 09/26] platform/x86/amd/hsmp: Add gmi3_link_width " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 11/26] platform/x86/amd/hsmp: Add lclk DPM sysfs files Muthusamy Ramalingam
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SET_PCI_RATE as a write-only socket file on both the ACPI
and platform drivers. A write sets the PCIe link rate control value.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 +++
 drivers/platform/x86/amd/hsmp/plat.c  |  3 +++
 drivers/platform/x86/amd/hsmp/sysfs.c | 32 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  3 +++
 5 files changed, 43 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index d7c4653f4f2f2..037029d1fdadd 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -128,6 +128,8 @@ write-only when the platform enables only that direction of the message.
 * gmi3_link_width: Write-only. Sets the GMI3 link width range as
   "min max". Each value is an 8-bit field. Extra arguments are rejected.
   Firmware rejects unsupported widths.
+* pcie_link_rate: Write-only. Sets the PCIe link rate control value
+  (HSMP_SET_PCI_RATE).
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 2f9228622fba4..beddcf30f252c 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -545,6 +545,8 @@ HSMP_DEV_ATTR_RW(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH, HSMP_SET_XGMI_LINK_WIDTH,
 		 hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
 HSMP_DEV_ATTR_W(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		hsmp_gmi3_link_width_store, 0200);
+HSMP_DEV_ATTR_W(pcie_link_rate, HSMP_SET_PCI_RATE,
+		hsmp_pcie_link_rate_store, 0200);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -580,6 +582,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_df_pstate_range.dattr.attr,
 	&hattr_xgmi_width.dattr.attr,
 	&hattr_gmi3_link_width.dattr.attr,
+	&hattr_pcie_link_rate.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index ca4aa13bfc4bc..479e6e9b90574 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -382,6 +382,8 @@ HSMP_DEV_ATTR_RW_X8(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH,
 		    hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
 HSMP_DEV_ATTR_W_X8(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		   hsmp_gmi3_link_width_store, 0200);
+HSMP_DEV_ATTR_W_X8(pcie_link_rate, HSMP_SET_PCI_RATE,
+		   hsmp_pcie_link_rate_store, 0200);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -422,6 +424,7 @@ static struct attribute _name[] = {					       \
 	&hattr_df_pstate_range##_sock_ind.dattr.attr,			       \
 	&hattr_xgmi_width##_sock_ind.dattr.attr,			       \
 	&hattr_gmi3_link_width##_sock_ind.dattr.attr,			       \
+	&hattr_pcie_link_rate##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 4c193fbcab013..dbc534ffeba20 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -951,6 +951,38 @@ ssize_t hsmp_gmi3_link_width_store(struct device *dev,
 	return count;
 }
 
+/* PCIe link rate store function - sets the link rate control value */
+ssize_t hsmp_pcie_link_rate_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 ctrl_rate;
+	int ret;
+
+	ret = kstrtou32(buf, 10, &ctrl_rate);
+	if (ret) {
+		hsmp_err(dev, "pcie_link_rate", HSMP_ERR_PARSE, "unit=ctrl_rate");
+		return ret;
+	}
+
+	msg.msg_id = HSMP_SET_PCI_RATE;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = ctrl_rate;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "pcie_link_rate", HSMP_ERR_HW,
+			 "ctrl_rate=%u rc=%d", ctrl_rate, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 1831d817a6834..62954a46970cc 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -122,6 +122,9 @@ ssize_t hsmp_xgmi_width_store(struct device *dev, struct device_attribute *attr,
 ssize_t hsmp_gmi3_link_width_store(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count);
+ssize_t hsmp_pcie_link_rate_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 11/26] platform/x86/amd/hsmp: Add lclk DPM sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (9 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 10/26] platform/x86/amd/hsmp: Add pcie_link_rate " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 12/26] platform/x86/amd/hsmp: Add io_bw and xgmi_bw " Muthusamy Ramalingam
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose read/write lclk_dpm_range/lclk_0 through lclk_dpm_range/lclk_3
on both drivers. Each file reads HSMP_GET_NBIO_DPM_LEVEL for one NBIO
and prints "min max". A write accepts "min max" (the NBIO id is the N
in lclk_N). Extra arguments are rejected. Firmware
rejects an inverted range. Hide the directory when that message is not
enabled.

Make each platform socketN directory a kobject so it can hold the
nested lclk_dpm_range group. Attribute groups can only add one
directory level.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   5 +
 drivers/platform/x86/amd/hsmp/acpi.c  |  39 ++++++
 drivers/platform/x86/amd/hsmp/plat.c  | 166 ++++++++++++++++++++++----
 drivers/platform/x86/amd/hsmp/sysfs.c | 153 ++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  16 +++
 5 files changed, 359 insertions(+), 20 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 037029d1fdadd..c63fc52316361 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -125,6 +125,11 @@ write-only when the platform enables only that direction of the message.
 * xgmi_width: Read/write xGMI link width range as "min max".
   0 is x4, 1 is x8, and 2 is x16. Each value is an 8-bit field.
   Extra arguments are rejected. Firmware rejects unsupported widths.
+* lclk_dpm_range/lclk_0, lclk_dpm_range/lclk_1,
+  lclk_dpm_range/lclk_2, lclk_dpm_range/lclk_3: Read/write LCLK DPM
+  range for NBIO 0-3. Read returns "min max". Write accepts "min max"
+  (the NBIO id is the N in lclk_N). Extra arguments
+  are rejected. Firmware rejects an inverted range.
 * gmi3_link_width: Write-only. Sets the GMI3 link width range as
   "min max". Each value is an 8-bit field. Extra arguments are rejected.
   Firmware rejects unsupported widths.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index beddcf30f252c..89c9e944b5537 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -547,6 +547,14 @@ HSMP_DEV_ATTR_W(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W(pcie_link_rate, HSMP_SET_PCI_RATE,
 		hsmp_pcie_link_rate_store, 0200);
+HSMP_DEV_ATTR_RW(lclk_0, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		 hsmp_lclk_0_show, hsmp_lclk_0_store, 0644);
+HSMP_DEV_ATTR_RW(lclk_1, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		 hsmp_lclk_1_show, hsmp_lclk_1_store, 0644);
+HSMP_DEV_ATTR_RW(lclk_2, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		 hsmp_lclk_2_show, hsmp_lclk_2_store, 0644);
+HSMP_DEV_ATTR_RW(lclk_3, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		 hsmp_lclk_3_show, hsmp_lclk_3_store, 0644);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -594,6 +602,36 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	NULL
 };
 
+static struct attribute *lclk_attrs[] = {
+	&hattr_lclk_0.dattr.attr,
+	&hattr_lclk_1.dattr.attr,
+	&hattr_lclk_2.dattr.attr,
+	&hattr_lclk_3.dattr.attr,
+	NULL
+};
+
+static umode_t hsmp_lclk_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int id)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct hsmp_socket *sock;
+
+	if (is_client_platform())
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	sock = dev_get_drvdata(dev);
+	if (!sock || !is_read_msg_enabled(sock, HSMP_GET_NBIO_DPM_LEVEL))
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	return attr->mode;
+}
+
+static const struct attribute_group lclk_group = {
+	.name = "lclk_dpm_range",
+	.attrs = lclk_attrs,
+	.is_visible = hsmp_lclk_is_visible,
+};
+
 static const struct attribute_group hsmp_attr_grp = {
 	.bin_attrs = hsmp_attr_list,
 	.attrs = hsmp_dev_attr_list,
@@ -603,6 +641,7 @@ static const struct attribute_group hsmp_attr_grp = {
 
 static const struct attribute_group *hsmp_groups[] = {
 	&hsmp_attr_grp,
+	&lclk_group,
 	NULL
 };
 
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 479e6e9b90574..162a5b1468a76 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -44,8 +44,9 @@
 
 static struct hsmp_plat_device *hsmp_pdev;
 
-/* Parent for per-socket attribute groups: amd_hsmp/socket/socketN/ */
+/* Parent for per-socket kobjects: amd_hsmp/socket/socketN/ */
 static struct kobject *hsmp_sock_kobj;
+static struct kobject *hsmp_plat_sock_kobj[MAX_AMD_NUM_NODES];
 /* Parent for per-CPU attributes: amd_hsmp/cpu/cpuX/ */
 static struct kobject *hsmp_cpu_kobj;
 
@@ -384,6 +385,14 @@ HSMP_DEV_ATTR_W_X8(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		   hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W_X8(pcie_link_rate, HSMP_SET_PCI_RATE,
 		   hsmp_pcie_link_rate_store, 0200);
+HSMP_DEV_ATTR_RW_X8(lclk_0, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		    hsmp_lclk_0_show, hsmp_lclk_0_store, 0644);
+HSMP_DEV_ATTR_RW_X8(lclk_1, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		    hsmp_lclk_1_show, hsmp_lclk_1_store, 0644);
+HSMP_DEV_ATTR_RW_X8(lclk_2, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		    hsmp_lclk_2_show, hsmp_lclk_2_store, 0644);
+HSMP_DEV_ATTR_RW_X8(lclk_3, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
+		    hsmp_lclk_3_show, hsmp_lclk_3_store, 0644);
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -445,25 +454,75 @@ HSMP_DEV_ATTR_LIST(*sock5_dev_attr_list, 5);
 HSMP_DEV_ATTR_LIST(*sock6_dev_attr_list, 6);
 HSMP_DEV_ATTR_LIST(*sock7_dev_attr_list, 7);
 
-#define HSMP_ATTR_GRP(index, _list, _name, _dlist)		\
+#define HSMP_ATTR_GRP(index, _list, _dlist)			\
 static const struct attribute_group sock##index##_attr_grp = {	\
 	.bin_attrs = _list,					\
 	.attrs = _dlist,					\
 	.is_bin_visible = hsmp_is_sock_attr_visible,		\
 	.is_visible = hsmp_is_sock_dev_attr_visible,		\
-	.name = #_name,						\
 }
 
-HSMP_ATTR_GRP(0, sock0_attr_list, socket0, sock0_dev_attr_list);
-HSMP_ATTR_GRP(1, sock1_attr_list, socket1, sock1_dev_attr_list);
-HSMP_ATTR_GRP(2, sock2_attr_list, socket2, sock2_dev_attr_list);
-HSMP_ATTR_GRP(3, sock3_attr_list, socket3, sock3_dev_attr_list);
-HSMP_ATTR_GRP(4, sock4_attr_list, socket4, sock4_dev_attr_list);
-HSMP_ATTR_GRP(5, sock5_attr_list, socket5, sock5_dev_attr_list);
-HSMP_ATTR_GRP(6, sock6_attr_list, socket6, sock6_dev_attr_list);
-HSMP_ATTR_GRP(7, sock7_attr_list, socket7, sock7_dev_attr_list);
+HSMP_ATTR_GRP(0, sock0_attr_list, sock0_dev_attr_list);
+HSMP_ATTR_GRP(1, sock1_attr_list, sock1_dev_attr_list);
+HSMP_ATTR_GRP(2, sock2_attr_list, sock2_dev_attr_list);
+HSMP_ATTR_GRP(3, sock3_attr_list, sock3_dev_attr_list);
+HSMP_ATTR_GRP(4, sock4_attr_list, sock4_dev_attr_list);
+HSMP_ATTR_GRP(5, sock5_attr_list, sock5_dev_attr_list);
+HSMP_ATTR_GRP(6, sock6_attr_list, sock6_dev_attr_list);
+HSMP_ATTR_GRP(7, sock7_attr_list, sock7_dev_attr_list);
+
+#define HSMP_LCLK_ATTR_LIST(_sock_ind)					\
+static struct attribute *sock##_sock_ind##_lclk_attrs[] = {		\
+	&hattr_lclk_0##_sock_ind.dattr.attr,				\
+	&hattr_lclk_1##_sock_ind.dattr.attr,				\
+	&hattr_lclk_2##_sock_ind.dattr.attr,				\
+	&hattr_lclk_3##_sock_ind.dattr.attr,				\
+	NULL								\
+}
+
+HSMP_LCLK_ATTR_LIST(0);
+HSMP_LCLK_ATTR_LIST(1);
+HSMP_LCLK_ATTR_LIST(2);
+HSMP_LCLK_ATTR_LIST(3);
+HSMP_LCLK_ATTR_LIST(4);
+HSMP_LCLK_ATTR_LIST(5);
+HSMP_LCLK_ATTR_LIST(6);
+HSMP_LCLK_ATTR_LIST(7);
+
+static umode_t hsmp_lclk_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int id)
+{
+	struct device_attribute *dattr = container_of(attr, struct device_attribute, attr);
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(dattr);
+	struct hsmp_socket *sock;
+
+	if (hattr->sock_ind >= hsmp_pdev->num_sockets)
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
 
-static const struct attribute_group *hsmp_groups[] = {
+	sock = &hsmp_pdev->sock[hattr->sock_ind];
+	if (!is_read_msg_enabled(sock, hattr->msg_id))
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	return attr->mode;
+}
+
+#define HSMP_LCLK_GRP(index)						\
+static const struct attribute_group sock##index##_lclk_grp = {		\
+	.name = "lclk_dpm_range",					\
+	.attrs = sock##index##_lclk_attrs,				\
+	.is_visible = hsmp_lclk_is_visible,				\
+}
+
+HSMP_LCLK_GRP(0);
+HSMP_LCLK_GRP(1);
+HSMP_LCLK_GRP(2);
+HSMP_LCLK_GRP(3);
+HSMP_LCLK_GRP(4);
+HSMP_LCLK_GRP(5);
+HSMP_LCLK_GRP(6);
+HSMP_LCLK_GRP(7);
+
+static const struct attribute_group *hsmp_sock_attr_grps[] = {
 	&sock0_attr_grp,
 	&sock1_attr_grp,
 	&sock2_attr_grp,
@@ -472,7 +531,17 @@ static const struct attribute_group *hsmp_groups[] = {
 	&sock5_attr_grp,
 	&sock6_attr_grp,
 	&sock7_attr_grp,
-	NULL
+};
+
+static const struct attribute_group *hsmp_sock_lclk_grps[] = {
+	&sock0_lclk_grp,
+	&sock1_lclk_grp,
+	&sock2_lclk_grp,
+	&sock3_lclk_grp,
+	&sock4_lclk_grp,
+	&sock5_lclk_grp,
+	&sock6_lclk_grp,
+	&sock7_lclk_grp,
 };
 
 static inline bool is_f1a_m0h(void)
@@ -599,8 +668,29 @@ static int hsmp_create_cpu_sysfs(struct device *dev)
 	return 0;
 }
 
+static const char * const hsmp_plat_sock_names[] = {
+	"socket0", "socket1", "socket2", "socket3",
+	"socket4", "socket5", "socket6", "socket7",
+};
+
+static void hsmp_remove_plat_sock_kobjs(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_AMD_NUM_NODES; i++) {
+		if (!hsmp_plat_sock_kobj[i])
+			continue;
+
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_lclk_grps[i]);
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_attr_grps[i]);
+		kobject_put(hsmp_plat_sock_kobj[i]);
+		hsmp_plat_sock_kobj[i] = NULL;
+	}
+}
+
 static int hsmp_create_socket_sysfs(struct device *dev)
 {
+	unsigned int i;
 	int ret;
 
 	hsmp_sock_kobj = kobject_create_and_add("socket", &dev->kobj);
@@ -609,15 +699,51 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 		return -ENOMEM;
 	}
 
-	ret = sysfs_create_groups(hsmp_sock_kobj, hsmp_groups);
-	if (ret) {
-		dev_err(dev, "Failed to create socket attribute groups\n");
-		kobject_put(hsmp_sock_kobj);
-		hsmp_sock_kobj = NULL;
-		return ret;
+	/*
+	 * socketN is a kobject so it can hold both the socket attributes and
+	 * an lclk_dpm_range/ subdirectory. Attribute groups can only add one
+	 * directory level under a kobject.
+	 */
+	for (i = 0; i < hsmp_pdev->num_sockets; i++) {
+		hsmp_plat_sock_kobj[i] = kobject_create_and_add(hsmp_plat_sock_names[i],
+								hsmp_sock_kobj);
+		if (!hsmp_plat_sock_kobj[i]) {
+			dev_err(dev, "Failed to create %s kobject\n",
+				hsmp_plat_sock_names[i]);
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
+					 hsmp_sock_attr_grps[i]);
+		if (ret) {
+			dev_err(dev, "Failed to create %s attributes\n",
+				hsmp_plat_sock_names[i]);
+			kobject_put(hsmp_plat_sock_kobj[i]);
+			hsmp_plat_sock_kobj[i] = NULL;
+			goto err;
+		}
+
+		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
+					 hsmp_sock_lclk_grps[i]);
+		if (ret) {
+			dev_err(dev, "Failed to create %s lclk attributes\n",
+				hsmp_plat_sock_names[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_attr_grps[i]);
+			kobject_put(hsmp_plat_sock_kobj[i]);
+			hsmp_plat_sock_kobj[i] = NULL;
+			goto err;
+		}
 	}
 
 	return 0;
+
+err:
+	hsmp_remove_plat_sock_kobjs();
+	kobject_put(hsmp_sock_kobj);
+	hsmp_sock_kobj = NULL;
+	return ret;
 }
 
 static void hsmp_destroy_socket_sysfs(void)
@@ -625,7 +751,7 @@ static void hsmp_destroy_socket_sysfs(void)
 	if (!hsmp_sock_kobj)
 		return;
 
-	sysfs_remove_groups(hsmp_sock_kobj, hsmp_groups);
+	hsmp_remove_plat_sock_kobjs();
 	kobject_del(hsmp_sock_kobj);
 	kobject_put(hsmp_sock_kobj);
 	hsmp_sock_kobj = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index dbc534ffeba20..77bb9c70c1c7f 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -47,6 +47,9 @@ static struct hsmp_cpu_info cpu_kobj_info[NR_CPUS];
 
 /* GMI3 link width encodes 3 levels (0-2); upper bound for range diagnostics */
 #define HSMP_GMI3_LINK_WIDTH_MAX		2
+/* LCLK DPM level upper bound: protocol v6 supports levels 0-2, others 0-3 */
+#define HSMP_LCLK_DPM_LEVEL_MAX_VER6	2
+#define HSMP_LCLK_DPM_LEVEL_MAX_DEFAULT	3
 
 static const char * const freqlimit_srcnames[] = {
 	"cHTC-Active",
@@ -983,6 +986,156 @@ ssize_t hsmp_pcie_link_rate_store(struct device *dev,
 	return count;
 }
 
+static ssize_t hsmp_lclk_nbio_show(struct device *dev,
+				   struct device_attribute *attr,
+				   u8 nbio_id, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_dpm, max_dpm;
+	u16 sock_ind;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	/*
+	 * HSMP_GET_NBIO_DPM_LEVEL: input args[0] = nbioid[23:16]
+	 * output args[0] = max dpm[15:8] + min dpm[7:0]
+	 */
+	msg.msg_id = HSMP_GET_NBIO_DPM_LEVEL;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = (u32)nbio_id << 16;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	max_dpm = (msg.args[0] >> 8) & 0xFF;
+	min_dpm = msg.args[0] & 0xFF;
+
+	return sysfs_emit(buf, "%u %u\n", min_dpm, max_dpm);
+}
+
+static ssize_t hsmp_lclk_nbio_store(struct device *dev,
+				    struct device_attribute *attr,
+				    u8 nbio_id, const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_dpm, max_dpm;
+	u32 vals[2];
+	u16 sock_ind;
+	int ret;
+	int got;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	/* Parse input in format: "min_dpm max_dpm" (NBIO id from filename) */
+	ret = hsmp_parse_u32_args(buf, vals, 2, 10, &got);
+	if (ret) {
+		hsmp_err(dev, "lclk_dpm_range", HSMP_ERR_ARGC,
+			 "want=2 got=%d fmt=\"min max\" valid=0-255", got);
+		return -EINVAL;
+	}
+	min_dpm = vals[0];
+	max_dpm = vals[1];
+
+	/* Max and min are 8-bit fields */
+	if (min_dpm > 0xFF || max_dpm > 0xFF) {
+		hsmp_err(dev, "lclk_dpm_range", HSMP_ERR_RANGE,
+			 "nbio_id=%u min=%u max=%u valid=0-255",
+			  nbio_id, min_dpm, max_dpm);
+		return -EINVAL;
+	}
+
+	msg.msg_id = HSMP_SET_NBIO_DPM_LEVEL;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 0;
+	/* args[0] = nbioid[23:16] | max_dpm[15:8] | min_dpm[7:0] */
+	msg.args[0] = ((u32)nbio_id << 16) | (max_dpm << 8) | min_dpm;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		struct hsmp_plat_device *pdev = get_hsmp_pdev();
+		u32 max_dpm_level = HSMP_LCLK_DPM_LEVEL_MAX_DEFAULT;
+
+		if (pdev && sock_ind < pdev->num_sockets &&
+		    pdev->sock[sock_ind].proto_ver == HSMP_PROTO_VER6)
+			max_dpm_level = HSMP_LCLK_DPM_LEVEL_MAX_VER6;
+
+		if (max_dpm < min_dpm)
+			hsmp_err(dev, "lclk_dpm_range", HSMP_ERR_ORDER,
+				 "min=%u max=%u rule=max>=min rc=%d",
+				  min_dpm, max_dpm, ret);
+		else if (min_dpm > max_dpm_level || max_dpm > max_dpm_level)
+			hsmp_err(dev, "lclk_dpm_range", HSMP_ERR_RANGE,
+				 "min=%u max=%u valid=0-%u rc=%d",
+				  min_dpm, max_dpm, max_dpm_level, ret);
+		else
+			hsmp_err(dev, "lclk_dpm_range", HSMP_ERR_HW,
+				 "nbio_id=%u min=%u max=%u rc=%d",
+				  nbio_id, min_dpm, max_dpm, ret);
+		return ret;
+	}
+
+	return count;
+}
+
+ssize_t hsmp_lclk_0_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return hsmp_lclk_nbio_show(dev, attr, 0, buf);
+}
+
+ssize_t hsmp_lclk_0_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	return hsmp_lclk_nbio_store(dev, attr, 0, buf, count);
+}
+
+ssize_t hsmp_lclk_1_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return hsmp_lclk_nbio_show(dev, attr, 1, buf);
+}
+
+ssize_t hsmp_lclk_1_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	return hsmp_lclk_nbio_store(dev, attr, 1, buf, count);
+}
+
+ssize_t hsmp_lclk_2_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return hsmp_lclk_nbio_show(dev, attr, 2, buf);
+}
+
+ssize_t hsmp_lclk_2_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	return hsmp_lclk_nbio_store(dev, attr, 2, buf, count);
+}
+
+ssize_t hsmp_lclk_3_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	return hsmp_lclk_nbio_show(dev, attr, 3, buf);
+}
+
+ssize_t hsmp_lclk_3_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	return hsmp_lclk_nbio_store(dev, attr, 3, buf, count);
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 62954a46970cc..eb364fbc338bd 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -125,6 +125,22 @@ ssize_t hsmp_gmi3_link_width_store(struct device *dev,
 ssize_t hsmp_pcie_link_rate_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count);
+ssize_t hsmp_lclk_0_show(struct device *dev, struct device_attribute *attr,
+			 char *buf);
+ssize_t hsmp_lclk_0_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count);
+ssize_t hsmp_lclk_1_show(struct device *dev, struct device_attribute *attr,
+			 char *buf);
+ssize_t hsmp_lclk_1_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count);
+ssize_t hsmp_lclk_2_show(struct device *dev, struct device_attribute *attr,
+			 char *buf);
+ssize_t hsmp_lclk_2_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count);
+ssize_t hsmp_lclk_3_show(struct device *dev, struct device_attribute *attr,
+			 char *buf);
+ssize_t hsmp_lclk_3_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 12/26] platform/x86/amd/hsmp: Add io_bw and xgmi_bw sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (10 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 11/26] platform/x86/amd/hsmp: Add lclk DPM sysfs files Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 13/26] platform/x86/amd/hsmp: Add DIMM sideband " Muthusamy Ramalingam
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose io_bw and xgmi_bw directories on both drivers. Probe asks
firmware which links accept HSMP_GET_IOLINK_BANDWITH and which link
and bandwidth-type combinations accept HSMP_GET_XGMI_BANDWITH, and
only those files are created. An io_bw read returns that link's
aggregate bandwidth. An xgmi_bw read returns that link's aggregate,
read, or write bandwidth.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  10 +
 drivers/platform/x86/amd/hsmp/acpi.c  | 179 +++++++
 drivers/platform/x86/amd/hsmp/hsmp.c  | 161 ++++++
 drivers/platform/x86/amd/hsmp/hsmp.h  |  22 +
 drivers/platform/x86/amd/hsmp/plat.c  | 678 +++++++++++++++++++++++++-
 drivers/platform/x86/amd/hsmp/sysfs.c |  94 ++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  18 +
 7 files changed, 1159 insertions(+), 3 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index c63fc52316361..516e8391bfbd2 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -135,6 +135,16 @@ write-only when the platform enables only that direction of the message.
   Firmware rejects unsupported widths.
 * pcie_link_rate: Write-only. Sets the PCIe link rate control value
   (HSMP_SET_PCI_RATE).
+* io_bw/: Read-only IO link bandwidth in Mbps. Files are io_p0 through
+  io_p5 and io_g0 through io_g7. A read returns the aggregate bandwidth.
+  Probe keeps only the links firmware accepts for this platform. The
+  directory is absent when none respond.
+* xgmi_bw/: Read-only xGMI link bandwidth in Mbps. For each link p0
+  through p5 and g0 through g7, the files are xgmi_<link>_agg,
+  xgmi_<link>_rd, and xgmi_<link>_wr. A read returns that link's
+  aggregate, read, or write bandwidth. Probe keeps only the link and
+  type combinations firmware accepts. The directory is absent when
+  none respond.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 89c9e944b5537..d6bb8a849cca7 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -440,6 +440,9 @@ static int init_acpi(struct device *dev)
 			dev_err(dev, "Failed to get enabled HSMP messages on this platform\n");
 			return ret;
 		}
+
+		hsmp_scan_io_bw(sock);
+		hsmp_scan_xgmi_bw(sock);
 	}
 
 	if ((is_client_platform() &&
@@ -555,6 +558,85 @@ HSMP_DEV_ATTR_RW(lclk_2, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		 hsmp_lclk_2_show, hsmp_lclk_2_store, 0644);
 HSMP_DEV_ATTR_RW(lclk_3, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		 hsmp_lclk_3_show, hsmp_lclk_3_store, 0644);
+
+#define HSMP_IO_LINK(_name, _id)					\
+	HSMP_SYS_ATTR_PRIV(_name, _name, hsmp_io_link_bw_show, U16_MAX,	\
+			   HSMP_GET_IOLINK_BANDWITH, _id)
+
+HSMP_IO_LINK(io_p0, 0);
+HSMP_IO_LINK(io_p1, 1);
+HSMP_IO_LINK(io_p2, 2);
+HSMP_IO_LINK(io_p3, 3);
+HSMP_IO_LINK(io_p4, 4);
+HSMP_IO_LINK(io_p5, 5);
+HSMP_IO_LINK(io_g0, 6);
+HSMP_IO_LINK(io_g1, 7);
+HSMP_IO_LINK(io_g2, 8);
+HSMP_IO_LINK(io_g3, 9);
+HSMP_IO_LINK(io_g4, 10);
+HSMP_IO_LINK(io_g5, 11);
+HSMP_IO_LINK(io_g6, 12);
+HSMP_IO_LINK(io_g7, 13);
+#undef HSMP_IO_LINK
+
+#define HSMP_XGMI_AGG(_link, _base)					\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_agg, xgmi_##_link##_agg,	\
+			   hsmp_xgmi_link_bw_show, U16_MAX,		\
+			   HSMP_GET_XGMI_BANDWITH, (_base))
+#define HSMP_XGMI_RD(_link, _base)					\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_rd, xgmi_##_link##_rd,	\
+			   hsmp_xgmi_link_bw_show, U16_MAX,		\
+			   HSMP_GET_XGMI_BANDWITH, (_base) + 1)
+#define HSMP_XGMI_WR(_link, _base)					\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_wr, xgmi_##_link##_wr,	\
+			   hsmp_xgmi_link_bw_show, U16_MAX,		\
+			   HSMP_GET_XGMI_BANDWITH, (_base) + 2)
+
+HSMP_XGMI_AGG(p0, 0);
+HSMP_XGMI_RD(p0, 0);
+HSMP_XGMI_WR(p0, 0);
+HSMP_XGMI_AGG(p1, 3);
+HSMP_XGMI_RD(p1, 3);
+HSMP_XGMI_WR(p1, 3);
+HSMP_XGMI_AGG(p2, 6);
+HSMP_XGMI_RD(p2, 6);
+HSMP_XGMI_WR(p2, 6);
+HSMP_XGMI_AGG(p3, 9);
+HSMP_XGMI_RD(p3, 9);
+HSMP_XGMI_WR(p3, 9);
+HSMP_XGMI_AGG(p4, 12);
+HSMP_XGMI_RD(p4, 12);
+HSMP_XGMI_WR(p4, 12);
+HSMP_XGMI_AGG(p5, 15);
+HSMP_XGMI_RD(p5, 15);
+HSMP_XGMI_WR(p5, 15);
+HSMP_XGMI_AGG(g0, 18);
+HSMP_XGMI_RD(g0, 18);
+HSMP_XGMI_WR(g0, 18);
+HSMP_XGMI_AGG(g1, 21);
+HSMP_XGMI_RD(g1, 21);
+HSMP_XGMI_WR(g1, 21);
+HSMP_XGMI_AGG(g2, 24);
+HSMP_XGMI_RD(g2, 24);
+HSMP_XGMI_WR(g2, 24);
+HSMP_XGMI_AGG(g3, 27);
+HSMP_XGMI_RD(g3, 27);
+HSMP_XGMI_WR(g3, 27);
+HSMP_XGMI_AGG(g4, 30);
+HSMP_XGMI_RD(g4, 30);
+HSMP_XGMI_WR(g4, 30);
+HSMP_XGMI_AGG(g5, 33);
+HSMP_XGMI_RD(g5, 33);
+HSMP_XGMI_WR(g5, 33);
+HSMP_XGMI_AGG(g6, 36);
+HSMP_XGMI_RD(g6, 36);
+HSMP_XGMI_WR(g6, 36);
+HSMP_XGMI_AGG(g7, 39);
+HSMP_XGMI_RD(g7, 39);
+HSMP_XGMI_WR(g7, 39);
+#undef HSMP_XGMI_AGG
+#undef HSMP_XGMI_RD
+#undef HSMP_XGMI_WR
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -632,6 +714,101 @@ static const struct attribute_group lclk_group = {
 	.is_visible = hsmp_lclk_is_visible,
 };
 
+static struct attribute *io_bw_attrs[] = {
+	&hattr_io_p0.dattr.attr,
+	&hattr_io_p1.dattr.attr,
+	&hattr_io_p2.dattr.attr,
+	&hattr_io_p3.dattr.attr,
+	&hattr_io_p4.dattr.attr,
+	&hattr_io_p5.dattr.attr,
+	&hattr_io_g0.dattr.attr,
+	&hattr_io_g1.dattr.attr,
+	&hattr_io_g2.dattr.attr,
+	&hattr_io_g3.dattr.attr,
+	&hattr_io_g4.dattr.attr,
+	&hattr_io_g5.dattr.attr,
+	&hattr_io_g6.dattr.attr,
+	&hattr_io_g7.dattr.attr,
+	NULL
+};
+
+static umode_t hsmp_io_bw_is_visible(struct kobject *kobj,
+				     struct attribute *attr __always_unused,
+				     int id)
+{
+	return hsmp_io_bw_file_visible(dev_get_drvdata(kobj_to_dev(kobj)), id);
+}
+
+static const struct attribute_group io_bw_group = {
+	.name = "io_bw",
+	.attrs = io_bw_attrs,
+	.is_visible = hsmp_io_bw_is_visible,
+};
+
+#define HSMP_XGMI_ATTR(_link, _kind)					\
+	(&hattr_xgmi_##_link##_##_kind.dattr.attr)
+
+static struct attribute *xgmi_bw_attrs[] = {
+	HSMP_XGMI_ATTR(p0, agg),
+	HSMP_XGMI_ATTR(p0, rd),
+	HSMP_XGMI_ATTR(p0, wr),
+	HSMP_XGMI_ATTR(p1, agg),
+	HSMP_XGMI_ATTR(p1, rd),
+	HSMP_XGMI_ATTR(p1, wr),
+	HSMP_XGMI_ATTR(p2, agg),
+	HSMP_XGMI_ATTR(p2, rd),
+	HSMP_XGMI_ATTR(p2, wr),
+	HSMP_XGMI_ATTR(p3, agg),
+	HSMP_XGMI_ATTR(p3, rd),
+	HSMP_XGMI_ATTR(p3, wr),
+	HSMP_XGMI_ATTR(p4, agg),
+	HSMP_XGMI_ATTR(p4, rd),
+	HSMP_XGMI_ATTR(p4, wr),
+	HSMP_XGMI_ATTR(p5, agg),
+	HSMP_XGMI_ATTR(p5, rd),
+	HSMP_XGMI_ATTR(p5, wr),
+	HSMP_XGMI_ATTR(g0, agg),
+	HSMP_XGMI_ATTR(g0, rd),
+	HSMP_XGMI_ATTR(g0, wr),
+	HSMP_XGMI_ATTR(g1, agg),
+	HSMP_XGMI_ATTR(g1, rd),
+	HSMP_XGMI_ATTR(g1, wr),
+	HSMP_XGMI_ATTR(g2, agg),
+	HSMP_XGMI_ATTR(g2, rd),
+	HSMP_XGMI_ATTR(g2, wr),
+	HSMP_XGMI_ATTR(g3, agg),
+	HSMP_XGMI_ATTR(g3, rd),
+	HSMP_XGMI_ATTR(g3, wr),
+	HSMP_XGMI_ATTR(g4, agg),
+	HSMP_XGMI_ATTR(g4, rd),
+	HSMP_XGMI_ATTR(g4, wr),
+	HSMP_XGMI_ATTR(g5, agg),
+	HSMP_XGMI_ATTR(g5, rd),
+	HSMP_XGMI_ATTR(g5, wr),
+	HSMP_XGMI_ATTR(g6, agg),
+	HSMP_XGMI_ATTR(g6, rd),
+	HSMP_XGMI_ATTR(g6, wr),
+	HSMP_XGMI_ATTR(g7, agg),
+	HSMP_XGMI_ATTR(g7, rd),
+	HSMP_XGMI_ATTR(g7, wr),
+	NULL
+};
+
+#undef HSMP_XGMI_ATTR
+
+static umode_t hsmp_xgmi_bw_is_visible(struct kobject *kobj,
+				       struct attribute *attr __always_unused,
+				       int id)
+{
+	return hsmp_xgmi_bw_file_visible(dev_get_drvdata(kobj_to_dev(kobj)), id);
+}
+
+static const struct attribute_group xgmi_bw_group = {
+	.name = "xgmi_bw",
+	.attrs = xgmi_bw_attrs,
+	.is_visible = hsmp_xgmi_bw_is_visible,
+};
+
 static const struct attribute_group hsmp_attr_grp = {
 	.bin_attrs = hsmp_attr_list,
 	.attrs = hsmp_dev_attr_list,
@@ -642,6 +819,8 @@ static const struct attribute_group hsmp_attr_grp = {
 static const struct attribute_group *hsmp_groups[] = {
 	&hsmp_attr_grp,
 	&lclk_group,
+	&io_bw_group,
+	&xgmi_bw_group,
 	NULL
 };
 
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index 4f23ae836a900..80721b13074d2 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -12,6 +12,7 @@
 #include <linux/acpi.h>
 #include <linux/array_size.h>
 #include <linux/bitmap.h>
+#include <linux/bits.h>
 #include <linux/build_bug.h>
 #include <linux/cleanup.h>
 #include <linux/compiler.h>
@@ -23,6 +24,7 @@
 #include <linux/rwsem.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
 
@@ -918,6 +920,165 @@ static int hsmp_set_default_msg_bitmap(u16 sock_ind)
 	return hsmp_fetch_write_enabled_msgs(sock_ind, sock->enabled_write_msg_ids);
 }
 
+struct hsmp_io_link_enc {
+	const char *name;
+	u16 enc;
+};
+
+/* Protocol 5 and 7: one-hot link encoding. */
+static const struct hsmp_io_link_enc io_links_onehot[] = {
+	{ "p0", BIT(0) }, { "p1", BIT(1) }, { "p2", BIT(2) }, { "p3", BIT(3) },
+	{ "p4", BIT(8) }, { "p5", BIT(9) },
+	{ "g0", BIT(4) }, { "g1", BIT(5) }, { "g2", BIT(6) }, { "g3", BIT(7) },
+};
+
+/* MI300 (family 0x19, models 0x90-0x9F): index encoding. */
+static const struct hsmp_io_link_enc io_links_mi300[] = {
+	{ "p2", 0x3 }, { "p3", 0x4 }, { "g0", 0x8 }, { "g1", 0x9 },
+	{ "g2", 0xA }, { "g3", 0xB }, { "g4", 0xC }, { "g5", 0xD },
+	{ "g6", 0xE }, { "g7", 0xF },
+};
+
+/* Bit index is the io_bw attribute id. */
+static const char * const io_link_names[HSMP_IO_LINK_COUNT] = {
+	"p0", "p1", "p2", "p3", "p4", "p5",
+	"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
+};
+
+static bool hsmp_io_link_is_mi300(void)
+{
+	return boot_cpu_data.x86 == 0x19 &&
+	       boot_cpu_data.x86_model >= 0x90 &&
+	       boot_cpu_data.x86_model <= 0x9F;
+}
+
+static const struct hsmp_io_link_enc *hsmp_io_link_table(size_t *n)
+{
+	if (hsmp_io_link_is_mi300()) {
+		*n = ARRAY_SIZE(io_links_mi300);
+		return io_links_mi300;
+	}
+
+	*n = ARRAY_SIZE(io_links_onehot);
+	return io_links_onehot;
+}
+
+int hsmp_io_link_encode(unsigned int id, u16 *enc)
+{
+	const struct hsmp_io_link_enc *tbl;
+	size_t i, n;
+
+	if (!enc || id >= HSMP_IO_LINK_COUNT)
+		return -EINVAL;
+
+	tbl = hsmp_io_link_table(&n);
+	for (i = 0; i < n; i++) {
+		if (!strcmp(io_link_names[id], tbl[i].name)) {
+			*enc = tbl[i].enc;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_io_link_encode, "AMD_HSMP");
+
+/*
+ * Probe each candidate link and record the ones firmware accepts.
+ * Caller holds hsmp_sock_rwsem for write.
+ */
+void hsmp_scan_io_bw(struct hsmp_socket *sock)
+{
+	unsigned int i;
+
+	if (!sock)
+		return;
+
+	sock->io_bw_valid = 0;
+	if (is_client_platform() ||
+	    !is_read_msg_enabled(sock, HSMP_GET_IOLINK_BANDWITH))
+		return;
+
+	for (i = 0; i < HSMP_IO_LINK_COUNT; i++) {
+		struct hsmp_message msg = {};
+		u16 enc;
+
+		if (hsmp_io_link_encode(i, &enc))
+			continue;
+
+		msg.msg_id = HSMP_GET_IOLINK_BANDWITH;
+		msg.sock_ind = sock->sock_ind;
+		msg.num_args = 1;
+		msg.response_sz = 1;
+		/* Aggregate bandwidth type in [2:0], link encoding in [15:8]. */
+		msg.args[0] = 1 | ((u32)enc << 8);
+		if (!hsmp_send_message_locked(&msg))
+			sock->io_bw_valid |= BIT(i);
+	}
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_scan_io_bw, "AMD_HSMP");
+
+/* Bandwidth type in args[0][2:0]: aggregate, read, then write. */
+static const u8 xgmi_bw_types[HSMP_XGMI_BW_TYPES] = {
+	BIT(0), BIT(1), BIT(2),
+};
+
+/*
+ * Pack HSMP_GET_XGMI_BANDWITH args[0] for xgmi_bw attribute @id.
+ * Link encoding is the same as io_bw; the type sits in [2:0].
+ */
+int hsmp_xgmi_bw_arg(unsigned int id, u32 *arg)
+{
+	unsigned int link, type;
+	u16 enc;
+	int ret;
+
+	if (!arg || id >= HSMP_XGMI_BW_COUNT)
+		return -EINVAL;
+
+	link = id / HSMP_XGMI_BW_TYPES;
+	type = id % HSMP_XGMI_BW_TYPES;
+	ret = hsmp_io_link_encode(link, &enc);
+	if (ret)
+		return ret;
+
+	*arg = xgmi_bw_types[type] | ((u32)enc << 8);
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_xgmi_bw_arg, "AMD_HSMP");
+
+/*
+ * Probe each candidate link and bandwidth type. Record the ones
+ * firmware accepts. Caller holds hsmp_sock_rwsem for write.
+ */
+void hsmp_scan_xgmi_bw(struct hsmp_socket *sock)
+{
+	unsigned int i;
+
+	if (!sock)
+		return;
+
+	sock->xgmi_bw_valid = 0;
+	if (is_client_platform() ||
+	    !is_read_msg_enabled(sock, HSMP_GET_XGMI_BANDWITH))
+		return;
+
+	for (i = 0; i < HSMP_XGMI_BW_COUNT; i++) {
+		struct hsmp_message msg = {};
+
+		if (hsmp_xgmi_bw_arg(i, &msg.args[0]))
+			continue;
+
+		msg.msg_id = HSMP_GET_XGMI_BANDWITH;
+		msg.sock_ind = sock->sock_ind;
+		msg.num_args = 1;
+		msg.response_sz = 1;
+		if (!hsmp_send_message_locked(&msg))
+			sock->xgmi_bw_valid |= BIT_ULL(i);
+	}
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_scan_xgmi_bw, "AMD_HSMP");
+
 static void hsmp_dynamic_bitmap_zen6(u16 sock_ind)
 {
 	struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind];
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h
index e67bbdd2b9bee..b41080c0f9555 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.h
+++ b/drivers/platform/x86/amd/hsmp/hsmp.h
@@ -83,6 +83,17 @@ struct hsmp_socket {
 	u32 proto_ver;
 	DECLARE_BITMAP(enabled_read_msg_ids, HSMP_MAX_MSGS);
 	DECLARE_BITMAP(enabled_write_msg_ids, HSMP_MAX_MSGS);
+	/*
+	 * Links that answered HSMP_GET_IOLINK_BANDWITH at probe.
+	 * Bit index matches io_bw/io_p0 .. io_g7 attribute order.
+	 */
+	u16 io_bw_valid;
+	/*
+	 * Link and bandwidth-type combinations that answered
+	 * HSMP_GET_XGMI_BANDWITH at probe. Bit index is
+	 * link * 3 + type, matching xgmi_bw/xgmi_<link>_{agg,rd,wr}.
+	 */
+	u64 xgmi_bw_valid;
 	int (*amd_hsmp_rdwr)(struct hsmp_socket *sock, u32 off, u32 *val, bool rw);
 };
 
@@ -131,6 +142,17 @@ static inline int hsmp_create_sensor(struct device *dev, u16 sock_ind) { return
 #endif
 int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args);
 
+/* io_bw attribute order: p0 p1 p2 p3 p4 p5 g0 g1 g2 g3 g4 g5 g6 g7. */
+#define HSMP_IO_LINK_COUNT	14
+int hsmp_io_link_encode(unsigned int id, u16 *enc);
+void hsmp_scan_io_bw(struct hsmp_socket *sock);
+
+/* xgmi_bw files per link: aggregate, read, write. */
+#define HSMP_XGMI_BW_TYPES	3
+#define HSMP_XGMI_BW_COUNT	(HSMP_IO_LINK_COUNT * HSMP_XGMI_BW_TYPES)
+int hsmp_xgmi_bw_arg(unsigned int id, u32 *arg);
+void hsmp_scan_xgmi_bw(struct hsmp_socket *sock);
+
 /*
  * Gates the HSMP data plane: hsmp_send_message() takes it for read; probe and
  * remove take it for write to bring sockets up and tear them down.
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 162a5b1468a76..3af94db6fd5b7 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -393,6 +393,476 @@ HSMP_DEV_ATTR_RW_X8(lclk_2, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		    hsmp_lclk_2_show, hsmp_lclk_2_store, 0644);
 HSMP_DEV_ATTR_RW_X8(lclk_3, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		    hsmp_lclk_3_show, hsmp_lclk_3_store, 0644);
+
+#define HSMP_IO_LINK(_name, _id, _sock)					\
+	HSMP_SYS_ATTR_PRIV(_name##_##_sock, _name, hsmp_io_link_bw_show, \
+			   _sock, HSMP_GET_IOLINK_BANDWITH, _id)
+
+HSMP_IO_LINK(io_p0, 0, 0);
+HSMP_IO_LINK(io_p0, 0, 1);
+HSMP_IO_LINK(io_p0, 0, 2);
+HSMP_IO_LINK(io_p0, 0, 3);
+HSMP_IO_LINK(io_p0, 0, 4);
+HSMP_IO_LINK(io_p0, 0, 5);
+HSMP_IO_LINK(io_p0, 0, 6);
+HSMP_IO_LINK(io_p0, 0, 7);
+HSMP_IO_LINK(io_p1, 1, 0);
+HSMP_IO_LINK(io_p1, 1, 1);
+HSMP_IO_LINK(io_p1, 1, 2);
+HSMP_IO_LINK(io_p1, 1, 3);
+HSMP_IO_LINK(io_p1, 1, 4);
+HSMP_IO_LINK(io_p1, 1, 5);
+HSMP_IO_LINK(io_p1, 1, 6);
+HSMP_IO_LINK(io_p1, 1, 7);
+HSMP_IO_LINK(io_p2, 2, 0);
+HSMP_IO_LINK(io_p2, 2, 1);
+HSMP_IO_LINK(io_p2, 2, 2);
+HSMP_IO_LINK(io_p2, 2, 3);
+HSMP_IO_LINK(io_p2, 2, 4);
+HSMP_IO_LINK(io_p2, 2, 5);
+HSMP_IO_LINK(io_p2, 2, 6);
+HSMP_IO_LINK(io_p2, 2, 7);
+HSMP_IO_LINK(io_p3, 3, 0);
+HSMP_IO_LINK(io_p3, 3, 1);
+HSMP_IO_LINK(io_p3, 3, 2);
+HSMP_IO_LINK(io_p3, 3, 3);
+HSMP_IO_LINK(io_p3, 3, 4);
+HSMP_IO_LINK(io_p3, 3, 5);
+HSMP_IO_LINK(io_p3, 3, 6);
+HSMP_IO_LINK(io_p3, 3, 7);
+HSMP_IO_LINK(io_p4, 4, 0);
+HSMP_IO_LINK(io_p4, 4, 1);
+HSMP_IO_LINK(io_p4, 4, 2);
+HSMP_IO_LINK(io_p4, 4, 3);
+HSMP_IO_LINK(io_p4, 4, 4);
+HSMP_IO_LINK(io_p4, 4, 5);
+HSMP_IO_LINK(io_p4, 4, 6);
+HSMP_IO_LINK(io_p4, 4, 7);
+HSMP_IO_LINK(io_p5, 5, 0);
+HSMP_IO_LINK(io_p5, 5, 1);
+HSMP_IO_LINK(io_p5, 5, 2);
+HSMP_IO_LINK(io_p5, 5, 3);
+HSMP_IO_LINK(io_p5, 5, 4);
+HSMP_IO_LINK(io_p5, 5, 5);
+HSMP_IO_LINK(io_p5, 5, 6);
+HSMP_IO_LINK(io_p5, 5, 7);
+HSMP_IO_LINK(io_g0, 6, 0);
+HSMP_IO_LINK(io_g0, 6, 1);
+HSMP_IO_LINK(io_g0, 6, 2);
+HSMP_IO_LINK(io_g0, 6, 3);
+HSMP_IO_LINK(io_g0, 6, 4);
+HSMP_IO_LINK(io_g0, 6, 5);
+HSMP_IO_LINK(io_g0, 6, 6);
+HSMP_IO_LINK(io_g0, 6, 7);
+HSMP_IO_LINK(io_g1, 7, 0);
+HSMP_IO_LINK(io_g1, 7, 1);
+HSMP_IO_LINK(io_g1, 7, 2);
+HSMP_IO_LINK(io_g1, 7, 3);
+HSMP_IO_LINK(io_g1, 7, 4);
+HSMP_IO_LINK(io_g1, 7, 5);
+HSMP_IO_LINK(io_g1, 7, 6);
+HSMP_IO_LINK(io_g1, 7, 7);
+HSMP_IO_LINK(io_g2, 8, 0);
+HSMP_IO_LINK(io_g2, 8, 1);
+HSMP_IO_LINK(io_g2, 8, 2);
+HSMP_IO_LINK(io_g2, 8, 3);
+HSMP_IO_LINK(io_g2, 8, 4);
+HSMP_IO_LINK(io_g2, 8, 5);
+HSMP_IO_LINK(io_g2, 8, 6);
+HSMP_IO_LINK(io_g2, 8, 7);
+HSMP_IO_LINK(io_g3, 9, 0);
+HSMP_IO_LINK(io_g3, 9, 1);
+HSMP_IO_LINK(io_g3, 9, 2);
+HSMP_IO_LINK(io_g3, 9, 3);
+HSMP_IO_LINK(io_g3, 9, 4);
+HSMP_IO_LINK(io_g3, 9, 5);
+HSMP_IO_LINK(io_g3, 9, 6);
+HSMP_IO_LINK(io_g3, 9, 7);
+HSMP_IO_LINK(io_g4, 10, 0);
+HSMP_IO_LINK(io_g4, 10, 1);
+HSMP_IO_LINK(io_g4, 10, 2);
+HSMP_IO_LINK(io_g4, 10, 3);
+HSMP_IO_LINK(io_g4, 10, 4);
+HSMP_IO_LINK(io_g4, 10, 5);
+HSMP_IO_LINK(io_g4, 10, 6);
+HSMP_IO_LINK(io_g4, 10, 7);
+HSMP_IO_LINK(io_g5, 11, 0);
+HSMP_IO_LINK(io_g5, 11, 1);
+HSMP_IO_LINK(io_g5, 11, 2);
+HSMP_IO_LINK(io_g5, 11, 3);
+HSMP_IO_LINK(io_g5, 11, 4);
+HSMP_IO_LINK(io_g5, 11, 5);
+HSMP_IO_LINK(io_g5, 11, 6);
+HSMP_IO_LINK(io_g5, 11, 7);
+HSMP_IO_LINK(io_g6, 12, 0);
+HSMP_IO_LINK(io_g6, 12, 1);
+HSMP_IO_LINK(io_g6, 12, 2);
+HSMP_IO_LINK(io_g6, 12, 3);
+HSMP_IO_LINK(io_g6, 12, 4);
+HSMP_IO_LINK(io_g6, 12, 5);
+HSMP_IO_LINK(io_g6, 12, 6);
+HSMP_IO_LINK(io_g6, 12, 7);
+HSMP_IO_LINK(io_g7, 13, 0);
+HSMP_IO_LINK(io_g7, 13, 1);
+HSMP_IO_LINK(io_g7, 13, 2);
+HSMP_IO_LINK(io_g7, 13, 3);
+HSMP_IO_LINK(io_g7, 13, 4);
+HSMP_IO_LINK(io_g7, 13, 5);
+HSMP_IO_LINK(io_g7, 13, 6);
+HSMP_IO_LINK(io_g7, 13, 7);
+#undef HSMP_IO_LINK
+#define HSMP_XGMI_AGG(_link, _base, _sock)				\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_agg_##_sock,			\
+			   xgmi_##_link##_agg, hsmp_xgmi_link_bw_show,	\
+			   _sock, HSMP_GET_XGMI_BANDWITH, (_base))
+#define HSMP_XGMI_RD(_link, _base, _sock)				\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_rd_##_sock,			\
+			   xgmi_##_link##_rd, hsmp_xgmi_link_bw_show,	\
+			   _sock, HSMP_GET_XGMI_BANDWITH, (_base) + 1)
+#define HSMP_XGMI_WR(_link, _base, _sock)				\
+	HSMP_SYS_ATTR_PRIV(xgmi_##_link##_wr_##_sock,			\
+			   xgmi_##_link##_wr, hsmp_xgmi_link_bw_show,	\
+			   _sock, HSMP_GET_XGMI_BANDWITH, (_base) + 2)
+
+HSMP_XGMI_AGG(p0, 0, 0);
+HSMP_XGMI_RD(p0, 0, 0);
+HSMP_XGMI_WR(p0, 0, 0);
+HSMP_XGMI_AGG(p0, 0, 1);
+HSMP_XGMI_RD(p0, 0, 1);
+HSMP_XGMI_WR(p0, 0, 1);
+HSMP_XGMI_AGG(p0, 0, 2);
+HSMP_XGMI_RD(p0, 0, 2);
+HSMP_XGMI_WR(p0, 0, 2);
+HSMP_XGMI_AGG(p0, 0, 3);
+HSMP_XGMI_RD(p0, 0, 3);
+HSMP_XGMI_WR(p0, 0, 3);
+HSMP_XGMI_AGG(p0, 0, 4);
+HSMP_XGMI_RD(p0, 0, 4);
+HSMP_XGMI_WR(p0, 0, 4);
+HSMP_XGMI_AGG(p0, 0, 5);
+HSMP_XGMI_RD(p0, 0, 5);
+HSMP_XGMI_WR(p0, 0, 5);
+HSMP_XGMI_AGG(p0, 0, 6);
+HSMP_XGMI_RD(p0, 0, 6);
+HSMP_XGMI_WR(p0, 0, 6);
+HSMP_XGMI_AGG(p0, 0, 7);
+HSMP_XGMI_RD(p0, 0, 7);
+HSMP_XGMI_WR(p0, 0, 7);
+HSMP_XGMI_AGG(p1, 3, 0);
+HSMP_XGMI_RD(p1, 3, 0);
+HSMP_XGMI_WR(p1, 3, 0);
+HSMP_XGMI_AGG(p1, 3, 1);
+HSMP_XGMI_RD(p1, 3, 1);
+HSMP_XGMI_WR(p1, 3, 1);
+HSMP_XGMI_AGG(p1, 3, 2);
+HSMP_XGMI_RD(p1, 3, 2);
+HSMP_XGMI_WR(p1, 3, 2);
+HSMP_XGMI_AGG(p1, 3, 3);
+HSMP_XGMI_RD(p1, 3, 3);
+HSMP_XGMI_WR(p1, 3, 3);
+HSMP_XGMI_AGG(p1, 3, 4);
+HSMP_XGMI_RD(p1, 3, 4);
+HSMP_XGMI_WR(p1, 3, 4);
+HSMP_XGMI_AGG(p1, 3, 5);
+HSMP_XGMI_RD(p1, 3, 5);
+HSMP_XGMI_WR(p1, 3, 5);
+HSMP_XGMI_AGG(p1, 3, 6);
+HSMP_XGMI_RD(p1, 3, 6);
+HSMP_XGMI_WR(p1, 3, 6);
+HSMP_XGMI_AGG(p1, 3, 7);
+HSMP_XGMI_RD(p1, 3, 7);
+HSMP_XGMI_WR(p1, 3, 7);
+HSMP_XGMI_AGG(p2, 6, 0);
+HSMP_XGMI_RD(p2, 6, 0);
+HSMP_XGMI_WR(p2, 6, 0);
+HSMP_XGMI_AGG(p2, 6, 1);
+HSMP_XGMI_RD(p2, 6, 1);
+HSMP_XGMI_WR(p2, 6, 1);
+HSMP_XGMI_AGG(p2, 6, 2);
+HSMP_XGMI_RD(p2, 6, 2);
+HSMP_XGMI_WR(p2, 6, 2);
+HSMP_XGMI_AGG(p2, 6, 3);
+HSMP_XGMI_RD(p2, 6, 3);
+HSMP_XGMI_WR(p2, 6, 3);
+HSMP_XGMI_AGG(p2, 6, 4);
+HSMP_XGMI_RD(p2, 6, 4);
+HSMP_XGMI_WR(p2, 6, 4);
+HSMP_XGMI_AGG(p2, 6, 5);
+HSMP_XGMI_RD(p2, 6, 5);
+HSMP_XGMI_WR(p2, 6, 5);
+HSMP_XGMI_AGG(p2, 6, 6);
+HSMP_XGMI_RD(p2, 6, 6);
+HSMP_XGMI_WR(p2, 6, 6);
+HSMP_XGMI_AGG(p2, 6, 7);
+HSMP_XGMI_RD(p2, 6, 7);
+HSMP_XGMI_WR(p2, 6, 7);
+HSMP_XGMI_AGG(p3, 9, 0);
+HSMP_XGMI_RD(p3, 9, 0);
+HSMP_XGMI_WR(p3, 9, 0);
+HSMP_XGMI_AGG(p3, 9, 1);
+HSMP_XGMI_RD(p3, 9, 1);
+HSMP_XGMI_WR(p3, 9, 1);
+HSMP_XGMI_AGG(p3, 9, 2);
+HSMP_XGMI_RD(p3, 9, 2);
+HSMP_XGMI_WR(p3, 9, 2);
+HSMP_XGMI_AGG(p3, 9, 3);
+HSMP_XGMI_RD(p3, 9, 3);
+HSMP_XGMI_WR(p3, 9, 3);
+HSMP_XGMI_AGG(p3, 9, 4);
+HSMP_XGMI_RD(p3, 9, 4);
+HSMP_XGMI_WR(p3, 9, 4);
+HSMP_XGMI_AGG(p3, 9, 5);
+HSMP_XGMI_RD(p3, 9, 5);
+HSMP_XGMI_WR(p3, 9, 5);
+HSMP_XGMI_AGG(p3, 9, 6);
+HSMP_XGMI_RD(p3, 9, 6);
+HSMP_XGMI_WR(p3, 9, 6);
+HSMP_XGMI_AGG(p3, 9, 7);
+HSMP_XGMI_RD(p3, 9, 7);
+HSMP_XGMI_WR(p3, 9, 7);
+HSMP_XGMI_AGG(p4, 12, 0);
+HSMP_XGMI_RD(p4, 12, 0);
+HSMP_XGMI_WR(p4, 12, 0);
+HSMP_XGMI_AGG(p4, 12, 1);
+HSMP_XGMI_RD(p4, 12, 1);
+HSMP_XGMI_WR(p4, 12, 1);
+HSMP_XGMI_AGG(p4, 12, 2);
+HSMP_XGMI_RD(p4, 12, 2);
+HSMP_XGMI_WR(p4, 12, 2);
+HSMP_XGMI_AGG(p4, 12, 3);
+HSMP_XGMI_RD(p4, 12, 3);
+HSMP_XGMI_WR(p4, 12, 3);
+HSMP_XGMI_AGG(p4, 12, 4);
+HSMP_XGMI_RD(p4, 12, 4);
+HSMP_XGMI_WR(p4, 12, 4);
+HSMP_XGMI_AGG(p4, 12, 5);
+HSMP_XGMI_RD(p4, 12, 5);
+HSMP_XGMI_WR(p4, 12, 5);
+HSMP_XGMI_AGG(p4, 12, 6);
+HSMP_XGMI_RD(p4, 12, 6);
+HSMP_XGMI_WR(p4, 12, 6);
+HSMP_XGMI_AGG(p4, 12, 7);
+HSMP_XGMI_RD(p4, 12, 7);
+HSMP_XGMI_WR(p4, 12, 7);
+HSMP_XGMI_AGG(p5, 15, 0);
+HSMP_XGMI_RD(p5, 15, 0);
+HSMP_XGMI_WR(p5, 15, 0);
+HSMP_XGMI_AGG(p5, 15, 1);
+HSMP_XGMI_RD(p5, 15, 1);
+HSMP_XGMI_WR(p5, 15, 1);
+HSMP_XGMI_AGG(p5, 15, 2);
+HSMP_XGMI_RD(p5, 15, 2);
+HSMP_XGMI_WR(p5, 15, 2);
+HSMP_XGMI_AGG(p5, 15, 3);
+HSMP_XGMI_RD(p5, 15, 3);
+HSMP_XGMI_WR(p5, 15, 3);
+HSMP_XGMI_AGG(p5, 15, 4);
+HSMP_XGMI_RD(p5, 15, 4);
+HSMP_XGMI_WR(p5, 15, 4);
+HSMP_XGMI_AGG(p5, 15, 5);
+HSMP_XGMI_RD(p5, 15, 5);
+HSMP_XGMI_WR(p5, 15, 5);
+HSMP_XGMI_AGG(p5, 15, 6);
+HSMP_XGMI_RD(p5, 15, 6);
+HSMP_XGMI_WR(p5, 15, 6);
+HSMP_XGMI_AGG(p5, 15, 7);
+HSMP_XGMI_RD(p5, 15, 7);
+HSMP_XGMI_WR(p5, 15, 7);
+HSMP_XGMI_AGG(g0, 18, 0);
+HSMP_XGMI_RD(g0, 18, 0);
+HSMP_XGMI_WR(g0, 18, 0);
+HSMP_XGMI_AGG(g0, 18, 1);
+HSMP_XGMI_RD(g0, 18, 1);
+HSMP_XGMI_WR(g0, 18, 1);
+HSMP_XGMI_AGG(g0, 18, 2);
+HSMP_XGMI_RD(g0, 18, 2);
+HSMP_XGMI_WR(g0, 18, 2);
+HSMP_XGMI_AGG(g0, 18, 3);
+HSMP_XGMI_RD(g0, 18, 3);
+HSMP_XGMI_WR(g0, 18, 3);
+HSMP_XGMI_AGG(g0, 18, 4);
+HSMP_XGMI_RD(g0, 18, 4);
+HSMP_XGMI_WR(g0, 18, 4);
+HSMP_XGMI_AGG(g0, 18, 5);
+HSMP_XGMI_RD(g0, 18, 5);
+HSMP_XGMI_WR(g0, 18, 5);
+HSMP_XGMI_AGG(g0, 18, 6);
+HSMP_XGMI_RD(g0, 18, 6);
+HSMP_XGMI_WR(g0, 18, 6);
+HSMP_XGMI_AGG(g0, 18, 7);
+HSMP_XGMI_RD(g0, 18, 7);
+HSMP_XGMI_WR(g0, 18, 7);
+HSMP_XGMI_AGG(g1, 21, 0);
+HSMP_XGMI_RD(g1, 21, 0);
+HSMP_XGMI_WR(g1, 21, 0);
+HSMP_XGMI_AGG(g1, 21, 1);
+HSMP_XGMI_RD(g1, 21, 1);
+HSMP_XGMI_WR(g1, 21, 1);
+HSMP_XGMI_AGG(g1, 21, 2);
+HSMP_XGMI_RD(g1, 21, 2);
+HSMP_XGMI_WR(g1, 21, 2);
+HSMP_XGMI_AGG(g1, 21, 3);
+HSMP_XGMI_RD(g1, 21, 3);
+HSMP_XGMI_WR(g1, 21, 3);
+HSMP_XGMI_AGG(g1, 21, 4);
+HSMP_XGMI_RD(g1, 21, 4);
+HSMP_XGMI_WR(g1, 21, 4);
+HSMP_XGMI_AGG(g1, 21, 5);
+HSMP_XGMI_RD(g1, 21, 5);
+HSMP_XGMI_WR(g1, 21, 5);
+HSMP_XGMI_AGG(g1, 21, 6);
+HSMP_XGMI_RD(g1, 21, 6);
+HSMP_XGMI_WR(g1, 21, 6);
+HSMP_XGMI_AGG(g1, 21, 7);
+HSMP_XGMI_RD(g1, 21, 7);
+HSMP_XGMI_WR(g1, 21, 7);
+HSMP_XGMI_AGG(g2, 24, 0);
+HSMP_XGMI_RD(g2, 24, 0);
+HSMP_XGMI_WR(g2, 24, 0);
+HSMP_XGMI_AGG(g2, 24, 1);
+HSMP_XGMI_RD(g2, 24, 1);
+HSMP_XGMI_WR(g2, 24, 1);
+HSMP_XGMI_AGG(g2, 24, 2);
+HSMP_XGMI_RD(g2, 24, 2);
+HSMP_XGMI_WR(g2, 24, 2);
+HSMP_XGMI_AGG(g2, 24, 3);
+HSMP_XGMI_RD(g2, 24, 3);
+HSMP_XGMI_WR(g2, 24, 3);
+HSMP_XGMI_AGG(g2, 24, 4);
+HSMP_XGMI_RD(g2, 24, 4);
+HSMP_XGMI_WR(g2, 24, 4);
+HSMP_XGMI_AGG(g2, 24, 5);
+HSMP_XGMI_RD(g2, 24, 5);
+HSMP_XGMI_WR(g2, 24, 5);
+HSMP_XGMI_AGG(g2, 24, 6);
+HSMP_XGMI_RD(g2, 24, 6);
+HSMP_XGMI_WR(g2, 24, 6);
+HSMP_XGMI_AGG(g2, 24, 7);
+HSMP_XGMI_RD(g2, 24, 7);
+HSMP_XGMI_WR(g2, 24, 7);
+HSMP_XGMI_AGG(g3, 27, 0);
+HSMP_XGMI_RD(g3, 27, 0);
+HSMP_XGMI_WR(g3, 27, 0);
+HSMP_XGMI_AGG(g3, 27, 1);
+HSMP_XGMI_RD(g3, 27, 1);
+HSMP_XGMI_WR(g3, 27, 1);
+HSMP_XGMI_AGG(g3, 27, 2);
+HSMP_XGMI_RD(g3, 27, 2);
+HSMP_XGMI_WR(g3, 27, 2);
+HSMP_XGMI_AGG(g3, 27, 3);
+HSMP_XGMI_RD(g3, 27, 3);
+HSMP_XGMI_WR(g3, 27, 3);
+HSMP_XGMI_AGG(g3, 27, 4);
+HSMP_XGMI_RD(g3, 27, 4);
+HSMP_XGMI_WR(g3, 27, 4);
+HSMP_XGMI_AGG(g3, 27, 5);
+HSMP_XGMI_RD(g3, 27, 5);
+HSMP_XGMI_WR(g3, 27, 5);
+HSMP_XGMI_AGG(g3, 27, 6);
+HSMP_XGMI_RD(g3, 27, 6);
+HSMP_XGMI_WR(g3, 27, 6);
+HSMP_XGMI_AGG(g3, 27, 7);
+HSMP_XGMI_RD(g3, 27, 7);
+HSMP_XGMI_WR(g3, 27, 7);
+HSMP_XGMI_AGG(g4, 30, 0);
+HSMP_XGMI_RD(g4, 30, 0);
+HSMP_XGMI_WR(g4, 30, 0);
+HSMP_XGMI_AGG(g4, 30, 1);
+HSMP_XGMI_RD(g4, 30, 1);
+HSMP_XGMI_WR(g4, 30, 1);
+HSMP_XGMI_AGG(g4, 30, 2);
+HSMP_XGMI_RD(g4, 30, 2);
+HSMP_XGMI_WR(g4, 30, 2);
+HSMP_XGMI_AGG(g4, 30, 3);
+HSMP_XGMI_RD(g4, 30, 3);
+HSMP_XGMI_WR(g4, 30, 3);
+HSMP_XGMI_AGG(g4, 30, 4);
+HSMP_XGMI_RD(g4, 30, 4);
+HSMP_XGMI_WR(g4, 30, 4);
+HSMP_XGMI_AGG(g4, 30, 5);
+HSMP_XGMI_RD(g4, 30, 5);
+HSMP_XGMI_WR(g4, 30, 5);
+HSMP_XGMI_AGG(g4, 30, 6);
+HSMP_XGMI_RD(g4, 30, 6);
+HSMP_XGMI_WR(g4, 30, 6);
+HSMP_XGMI_AGG(g4, 30, 7);
+HSMP_XGMI_RD(g4, 30, 7);
+HSMP_XGMI_WR(g4, 30, 7);
+HSMP_XGMI_AGG(g5, 33, 0);
+HSMP_XGMI_RD(g5, 33, 0);
+HSMP_XGMI_WR(g5, 33, 0);
+HSMP_XGMI_AGG(g5, 33, 1);
+HSMP_XGMI_RD(g5, 33, 1);
+HSMP_XGMI_WR(g5, 33, 1);
+HSMP_XGMI_AGG(g5, 33, 2);
+HSMP_XGMI_RD(g5, 33, 2);
+HSMP_XGMI_WR(g5, 33, 2);
+HSMP_XGMI_AGG(g5, 33, 3);
+HSMP_XGMI_RD(g5, 33, 3);
+HSMP_XGMI_WR(g5, 33, 3);
+HSMP_XGMI_AGG(g5, 33, 4);
+HSMP_XGMI_RD(g5, 33, 4);
+HSMP_XGMI_WR(g5, 33, 4);
+HSMP_XGMI_AGG(g5, 33, 5);
+HSMP_XGMI_RD(g5, 33, 5);
+HSMP_XGMI_WR(g5, 33, 5);
+HSMP_XGMI_AGG(g5, 33, 6);
+HSMP_XGMI_RD(g5, 33, 6);
+HSMP_XGMI_WR(g5, 33, 6);
+HSMP_XGMI_AGG(g5, 33, 7);
+HSMP_XGMI_RD(g5, 33, 7);
+HSMP_XGMI_WR(g5, 33, 7);
+HSMP_XGMI_AGG(g6, 36, 0);
+HSMP_XGMI_RD(g6, 36, 0);
+HSMP_XGMI_WR(g6, 36, 0);
+HSMP_XGMI_AGG(g6, 36, 1);
+HSMP_XGMI_RD(g6, 36, 1);
+HSMP_XGMI_WR(g6, 36, 1);
+HSMP_XGMI_AGG(g6, 36, 2);
+HSMP_XGMI_RD(g6, 36, 2);
+HSMP_XGMI_WR(g6, 36, 2);
+HSMP_XGMI_AGG(g6, 36, 3);
+HSMP_XGMI_RD(g6, 36, 3);
+HSMP_XGMI_WR(g6, 36, 3);
+HSMP_XGMI_AGG(g6, 36, 4);
+HSMP_XGMI_RD(g6, 36, 4);
+HSMP_XGMI_WR(g6, 36, 4);
+HSMP_XGMI_AGG(g6, 36, 5);
+HSMP_XGMI_RD(g6, 36, 5);
+HSMP_XGMI_WR(g6, 36, 5);
+HSMP_XGMI_AGG(g6, 36, 6);
+HSMP_XGMI_RD(g6, 36, 6);
+HSMP_XGMI_WR(g6, 36, 6);
+HSMP_XGMI_AGG(g6, 36, 7);
+HSMP_XGMI_RD(g6, 36, 7);
+HSMP_XGMI_WR(g6, 36, 7);
+HSMP_XGMI_AGG(g7, 39, 0);
+HSMP_XGMI_RD(g7, 39, 0);
+HSMP_XGMI_WR(g7, 39, 0);
+HSMP_XGMI_AGG(g7, 39, 1);
+HSMP_XGMI_RD(g7, 39, 1);
+HSMP_XGMI_WR(g7, 39, 1);
+HSMP_XGMI_AGG(g7, 39, 2);
+HSMP_XGMI_RD(g7, 39, 2);
+HSMP_XGMI_WR(g7, 39, 2);
+HSMP_XGMI_AGG(g7, 39, 3);
+HSMP_XGMI_RD(g7, 39, 3);
+HSMP_XGMI_WR(g7, 39, 3);
+HSMP_XGMI_AGG(g7, 39, 4);
+HSMP_XGMI_RD(g7, 39, 4);
+HSMP_XGMI_WR(g7, 39, 4);
+HSMP_XGMI_AGG(g7, 39, 5);
+HSMP_XGMI_RD(g7, 39, 5);
+HSMP_XGMI_WR(g7, 39, 5);
+HSMP_XGMI_AGG(g7, 39, 6);
+HSMP_XGMI_RD(g7, 39, 6);
+HSMP_XGMI_WR(g7, 39, 6);
+HSMP_XGMI_AGG(g7, 39, 7);
+HSMP_XGMI_RD(g7, 39, 7);
+HSMP_XGMI_WR(g7, 39, 7);
+#undef HSMP_XGMI_AGG
+#undef HSMP_XGMI_RD
+#undef HSMP_XGMI_WR
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -544,6 +1014,174 @@ static const struct attribute_group *hsmp_sock_lclk_grps[] = {
 	&sock7_lclk_grp,
 };
 
+#define HSMP_IO_BW_LIST(_s)						\
+static struct attribute *sock##_s##_iobw_attrs[] = {			\
+	&hattr_io_p0_##_s.dattr.attr,					\
+	&hattr_io_p1_##_s.dattr.attr,					\
+	&hattr_io_p2_##_s.dattr.attr,					\
+	&hattr_io_p3_##_s.dattr.attr,					\
+	&hattr_io_p4_##_s.dattr.attr,					\
+	&hattr_io_p5_##_s.dattr.attr,					\
+	&hattr_io_g0_##_s.dattr.attr,					\
+	&hattr_io_g1_##_s.dattr.attr,					\
+	&hattr_io_g2_##_s.dattr.attr,					\
+	&hattr_io_g3_##_s.dattr.attr,					\
+	&hattr_io_g4_##_s.dattr.attr,					\
+	&hattr_io_g5_##_s.dattr.attr,					\
+	&hattr_io_g6_##_s.dattr.attr,					\
+	&hattr_io_g7_##_s.dattr.attr,					\
+	NULL								\
+}
+
+HSMP_IO_BW_LIST(0);
+HSMP_IO_BW_LIST(1);
+HSMP_IO_BW_LIST(2);
+HSMP_IO_BW_LIST(3);
+HSMP_IO_BW_LIST(4);
+HSMP_IO_BW_LIST(5);
+HSMP_IO_BW_LIST(6);
+HSMP_IO_BW_LIST(7);
+#undef HSMP_IO_BW_LIST
+
+static umode_t hsmp_plat_io_bw_is_visible(struct kobject *kobj __always_unused,
+					  struct attribute *attr, int id)
+{
+	struct device_attribute *dattr = container_of(attr, struct device_attribute, attr);
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(dattr);
+	struct hsmp_socket *sock = NULL;
+
+	if (hsmp_pdev && hattr->sock_ind < hsmp_pdev->num_sockets)
+		sock = &hsmp_pdev->sock[hattr->sock_ind];
+
+	return hsmp_io_bw_file_visible(sock, id);
+}
+
+#define HSMP_IO_BW_GRP(index)						\
+static const struct attribute_group sock##index##_iobw_grp = {		\
+	.name = "io_bw",						\
+	.attrs = sock##index##_iobw_attrs,				\
+	.is_visible = hsmp_plat_io_bw_is_visible,			\
+}
+
+HSMP_IO_BW_GRP(0);
+HSMP_IO_BW_GRP(1);
+HSMP_IO_BW_GRP(2);
+HSMP_IO_BW_GRP(3);
+HSMP_IO_BW_GRP(4);
+HSMP_IO_BW_GRP(5);
+HSMP_IO_BW_GRP(6);
+HSMP_IO_BW_GRP(7);
+#undef HSMP_IO_BW_GRP
+
+static const struct attribute_group *hsmp_sock_iobw_grps[] = {
+	&sock0_iobw_grp,
+	&sock1_iobw_grp,
+	&sock2_iobw_grp,
+	&sock3_iobw_grp,
+	&sock4_iobw_grp,
+	&sock5_iobw_grp,
+	&sock6_iobw_grp,
+	&sock7_iobw_grp,
+};
+
+#define HSMP_XGMI_BW_LIST(_s)						\
+static struct attribute *sock##_s##_xgmibw_attrs[] = {			\
+	&hattr_xgmi_p0_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p0_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p0_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_p1_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p1_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p1_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_p2_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p2_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p2_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_p3_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p3_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p3_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_p4_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p4_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p4_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_p5_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_p5_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_p5_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g0_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g0_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g0_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g1_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g1_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g1_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g2_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g2_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g2_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g3_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g3_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g3_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g4_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g4_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g4_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g5_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g5_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g5_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g6_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g6_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g6_wr_##_s.dattr.attr,				\
+	&hattr_xgmi_g7_agg_##_s.dattr.attr,				\
+	&hattr_xgmi_g7_rd_##_s.dattr.attr,				\
+	&hattr_xgmi_g7_wr_##_s.dattr.attr,				\
+	NULL								\
+}
+
+HSMP_XGMI_BW_LIST(0);
+HSMP_XGMI_BW_LIST(1);
+HSMP_XGMI_BW_LIST(2);
+HSMP_XGMI_BW_LIST(3);
+HSMP_XGMI_BW_LIST(4);
+HSMP_XGMI_BW_LIST(5);
+HSMP_XGMI_BW_LIST(6);
+HSMP_XGMI_BW_LIST(7);
+#undef HSMP_XGMI_BW_LIST
+
+static umode_t hsmp_plat_xgmi_bw_is_visible(struct kobject *kobj __always_unused,
+					    struct attribute *attr, int id)
+{
+	struct device_attribute *dattr = container_of(attr, struct device_attribute, attr);
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(dattr);
+	struct hsmp_socket *sock = NULL;
+
+	if (hsmp_pdev && hattr->sock_ind < hsmp_pdev->num_sockets)
+		sock = &hsmp_pdev->sock[hattr->sock_ind];
+
+	return hsmp_xgmi_bw_file_visible(sock, id);
+}
+
+#define HSMP_XGMI_BW_GRP(index)						\
+static const struct attribute_group sock##index##_xgmibw_grp = {	\
+	.name = "xgmi_bw",						\
+	.attrs = sock##index##_xgmibw_attrs,				\
+	.is_visible = hsmp_plat_xgmi_bw_is_visible,			\
+}
+
+HSMP_XGMI_BW_GRP(0);
+HSMP_XGMI_BW_GRP(1);
+HSMP_XGMI_BW_GRP(2);
+HSMP_XGMI_BW_GRP(3);
+HSMP_XGMI_BW_GRP(4);
+HSMP_XGMI_BW_GRP(5);
+HSMP_XGMI_BW_GRP(6);
+HSMP_XGMI_BW_GRP(7);
+#undef HSMP_XGMI_BW_GRP
+
+static const struct attribute_group *hsmp_sock_xgmibw_grps[] = {
+	&sock0_xgmibw_grp,
+	&sock1_xgmibw_grp,
+	&sock2_xgmibw_grp,
+	&sock3_xgmibw_grp,
+	&sock4_xgmibw_grp,
+	&sock5_xgmibw_grp,
+	&sock6_xgmibw_grp,
+	&sock7_xgmibw_grp,
+};
+
 static inline bool is_f1a_m0h(void)
 {
 	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
@@ -603,6 +1241,9 @@ static int init_platform_device(struct device *dev)
 				dev_err(dev, "Failed to get enabled HSMP messages on this platform\n");
 				return ret;
 			}
+
+			hsmp_scan_io_bw(sock);
+			hsmp_scan_xgmi_bw(sock);
 		}
 
 		if (sock->proto_ver == HSMP_PROTO_VER6) {
@@ -681,6 +1322,8 @@ static void hsmp_remove_plat_sock_kobjs(void)
 		if (!hsmp_plat_sock_kobj[i])
 			continue;
 
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_xgmibw_grps[i]);
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_iobw_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_lclk_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_attr_grps[i]);
 		kobject_put(hsmp_plat_sock_kobj[i]);
@@ -700,9 +1343,9 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 	}
 
 	/*
-	 * socketN is a kobject so it can hold both the socket attributes and
-	 * an lclk_dpm_range/ subdirectory. Attribute groups can only add one
-	 * directory level under a kobject.
+	 * socketN is a kobject so it can hold the socket attributes and the
+	 * nested lclk_dpm_range, io_bw, and xgmi_bw directories. Attribute
+	 * groups add one directory level under that kobject.
 	 */
 	for (i = 0; i < hsmp_pdev->num_sockets; i++) {
 		hsmp_plat_sock_kobj[i] = kobject_create_and_add(hsmp_plat_sock_names[i],
@@ -735,6 +1378,35 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 			hsmp_plat_sock_kobj[i] = NULL;
 			goto err;
 		}
+
+		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
+					 hsmp_sock_iobw_grps[i]);
+		if (ret) {
+			dev_err(dev, "Failed to create %s io_bw attributes\n",
+				hsmp_plat_sock_names[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_lclk_grps[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_attr_grps[i]);
+			kobject_put(hsmp_plat_sock_kobj[i]);
+			hsmp_plat_sock_kobj[i] = NULL;
+			goto err;
+		}
+		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
+					 hsmp_sock_xgmibw_grps[i]);
+		if (ret) {
+			dev_err(dev, "Failed to create %s xgmi_bw attributes\n",
+				hsmp_plat_sock_names[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_iobw_grps[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_lclk_grps[i]);
+			sysfs_remove_group(hsmp_plat_sock_kobj[i],
+					   hsmp_sock_attr_grps[i]);
+			kobject_put(hsmp_plat_sock_kobj[i]);
+			hsmp_plat_sock_kobj[i] = NULL;
+			goto err;
+		}
 	}
 
 	return 0;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 77bb9c70c1c7f..73010a889eaca 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -986,6 +986,100 @@ ssize_t hsmp_pcie_link_rate_store(struct device *dev,
 	return count;
 }
 
+
+/* IO link bandwidth. priv is the io_bw attribute index. */
+ssize_t hsmp_io_link_bw_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u16 sock_ind, enc;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	ret = hsmp_io_link_encode(hattr->priv, &enc);
+	if (ret)
+		return ret;
+
+	/*
+	 * HSMP_GET_IOLINK_BANDWITH: link encoding in [15:8], aggregate
+	 * bandwidth type 1 in [2:0]. Output is bandwidth in Mbps.
+	 */
+	msg.msg_id = HSMP_GET_IOLINK_BANDWITH;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = 1 | ((u32)enc << 8);
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0]);
+}
+
+umode_t hsmp_io_bw_file_visible(const struct hsmp_socket *sock, int id)
+{
+	if (!sock || is_client_platform() ||
+	    !is_read_msg_enabled(sock, HSMP_GET_IOLINK_BANDWITH) ||
+	    !sock->io_bw_valid)
+		return id ? 0 : SYSFS_GROUP_INVISIBLE;
+
+	if (id < 0 || id >= HSMP_IO_LINK_COUNT)
+		return 0;
+
+	return (sock->io_bw_valid & BIT(id)) ? 0444 : 0;
+}
+
+/* xGMI link bandwidth. priv is link * 3 + type (agg, rd, wr). */
+ssize_t hsmp_xgmi_link_bw_show(struct device *dev, struct device_attribute *attr,
+			       char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u16 sock_ind;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	/*
+	 * HSMP_GET_XGMI_BANDWITH: link encoding in [15:8], bandwidth
+	 * type in [2:0]. Output is bandwidth in Mbps.
+	 */
+	ret = hsmp_xgmi_bw_arg(hattr->priv, &msg.args[0]);
+	if (ret)
+		return ret;
+
+	msg.msg_id = HSMP_GET_XGMI_BANDWITH;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0]);
+}
+
+umode_t hsmp_xgmi_bw_file_visible(const struct hsmp_socket *sock, int id)
+{
+	if (!sock || is_client_platform() ||
+	    !is_read_msg_enabled(sock, HSMP_GET_XGMI_BANDWITH) ||
+	    !sock->xgmi_bw_valid)
+		return id ? 0 : SYSFS_GROUP_INVISIBLE;
+
+	if (id < 0 || id >= HSMP_XGMI_BW_COUNT)
+		return 0;
+
+	return (sock->xgmi_bw_valid & BIT_ULL(id)) ? 0444 : 0;
+}
+
 static ssize_t hsmp_lclk_nbio_show(struct device *dev,
 				   struct device_attribute *attr,
 				   u8 nbio_id, char *buf)
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index eb364fbc338bd..83358304da97b 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -23,6 +23,7 @@ struct hsmp_sys_attr {
 	u16 sock_ind;
 	u32 msg_id;	/* message ID used for read / GET enable checks */
 	u32 wr_msg_id;	/* message ID used for write / SET enable checks */
+	unsigned int priv;
 };
 
 #define DDR_MAX_BW_MASK		GENMASK(31, 20)
@@ -52,6 +53,16 @@ static struct hsmp_sys_attr hattr_##_var = {				\
 	.wr_msg_id = _wr_msg_id,					\
 }
 
+/* Read-only attribute with a private index in @priv. */
+#define HSMP_SYS_ATTR_PRIV(_var, _name, _show, _sock_ind, _msg_id, _priv) \
+static struct hsmp_sys_attr hattr_##_var = {				\
+	.dattr = __ATTR(_name, 0444, _show, NULL),			\
+	.sock_ind = _sock_ind,						\
+	.msg_id = _msg_id,						\
+	.wr_msg_id = _msg_id,						\
+	.priv = _priv,							\
+}
+
 ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_msg_resp32_hex_show(struct device *dev, struct device_attribute *attr,
@@ -141,6 +152,13 @@ ssize_t hsmp_lclk_3_show(struct device *dev, struct device_attribute *attr,
 			 char *buf);
 ssize_t hsmp_lclk_3_store(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count);
+ssize_t hsmp_io_link_bw_show(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+umode_t hsmp_io_bw_file_visible(const struct hsmp_socket *sock, int id);
+ssize_t hsmp_xgmi_link_bw_show(struct device *dev, struct device_attribute *attr,
+			       char *buf);
+umode_t hsmp_xgmi_bw_file_visible(const struct hsmp_socket *sock, int id);
+
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 13/26] platform/x86/amd/hsmp: Add DIMM sideband sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (11 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 12/26] platform/x86/amd/hsmp: Add io_bw and xgmi_bw " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 14/26] platform/x86/amd/hsmp: Add per-CPU floor limit " Muthusamy Ramalingam
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose dimm_sb_get and dimm_sb_set on both drivers. dimm_sb_get issues
HSMP_DIMM_SB_RD and caches the request and data. A read returns that
request and its data. Both stores reject extra arguments. dimm_sb_set
writes a register with HSMP_DIMM_SB_WR.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  10 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  11 +-
 drivers/platform/x86/amd/hsmp/plat.c  |  11 +-
 drivers/platform/x86/amd/hsmp/sysfs.c | 190 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  11 ++
 5 files changed, 231 insertions(+), 2 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 516e8391bfbd2..67f4c3b71f5e0 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -145,6 +145,16 @@ write-only when the platform enables only that direction of the message.
   aggregate, read, or write bandwidth. Probe keeps only the link and
   type combinations firmware accepts. The directory is absent when
   none respond.
+* dimm_sb_get: Read/write DIMM sideband read. Write
+  "<dimm_addr> <lid> <reg_offset> <reg_space>". Decimal and hexadecimal
+  values are accepted, and extra arguments are rejected. dimm_addr is
+  0-255, lid is 0-15, reg_offset is 0-2047, and reg_space is 0 or 1.
+  A read returns the last request and its data as
+  "0xAA 0xL 0xOFF S 0xDATA", or fails with -ENODATA until a read succeeds.
+* dimm_sb_set: Write-only DIMM sideband write. Write
+  "<dimm_addr> <lid> <reg_offset> <reg_space> <write_data>".
+  write_data is 0-255. Extra arguments are rejected. Field ranges match
+  dimm_sb_get.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index d6bb8a849cca7..f2bd4d5369df5 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -358,8 +358,12 @@ static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
 	if (readable && writable) {
 		if (is_read_msg_enabled(sock, hattr->msg_id))
 			mode_updated |= mode & 0444;
-		if (is_write_msg_enabled(sock, hattr->wr_msg_id))
+		if (hsmp_sysfs_write_follows_read(hattr)) {
+			if (is_read_msg_enabled(sock, hattr->msg_id))
+				mode_updated |= 0200;
+		} else if (is_write_msg_enabled(sock, hattr->wr_msg_id)) {
 			mode_updated |= 0200;
+		}
 		return mode_updated;
 	}
 
@@ -550,6 +554,9 @@ HSMP_DEV_ATTR_W(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W(pcie_link_rate, HSMP_SET_PCI_RATE,
 		hsmp_pcie_link_rate_store, 0200);
+HSMP_DEV_ATTR_RW(dimm_sb_get, HSMP_DIMM_SB_RD, HSMP_DIMM_SB_RD,
+		 hsmp_dimm_sb_get_show, hsmp_dimm_sb_get_store, 0644);
+HSMP_DEV_ATTR_W(dimm_sb_set, HSMP_DIMM_SB_WR, hsmp_dimm_sb_set_store, 0200);
 HSMP_DEV_ATTR_RW(lclk_0, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		 hsmp_lclk_0_show, hsmp_lclk_0_store, 0644);
 HSMP_DEV_ATTR_RW(lclk_1, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
@@ -673,6 +680,8 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_xgmi_width.dattr.attr,
 	&hattr_gmi3_link_width.dattr.attr,
 	&hattr_pcie_link_rate.dattr.attr,
+	&hattr_dimm_sb_get.dattr.attr,
+	&hattr_dimm_sb_set.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 3af94db6fd5b7..46676d9f90633 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -124,8 +124,12 @@ static umode_t hsmp_is_sock_dev_attr_visible(struct kobject *kobj,
 	if (readable && writable) {
 		if (is_read_msg_enabled(sock, hattr->msg_id))
 			mode_updated |= mode & 0444;
-		if (is_write_msg_enabled(sock, hattr->wr_msg_id))
+		if (hsmp_sysfs_write_follows_read(hattr)) {
+			if (is_read_msg_enabled(sock, hattr->msg_id))
+				mode_updated |= 0200;
+		} else if (is_write_msg_enabled(sock, hattr->wr_msg_id)) {
 			mode_updated |= 0200;
+		}
 		return mode_updated;
 	}
 
@@ -385,6 +389,9 @@ HSMP_DEV_ATTR_W_X8(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		   hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W_X8(pcie_link_rate, HSMP_SET_PCI_RATE,
 		   hsmp_pcie_link_rate_store, 0200);
+HSMP_DEV_ATTR_RW_X8(dimm_sb_get, HSMP_DIMM_SB_RD, HSMP_DIMM_SB_RD,
+		    hsmp_dimm_sb_get_show, hsmp_dimm_sb_get_store, 0644);
+HSMP_DEV_ATTR_W_X8(dimm_sb_set, HSMP_DIMM_SB_WR, hsmp_dimm_sb_set_store, 0200);
 HSMP_DEV_ATTR_RW_X8(lclk_0, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
 		    hsmp_lclk_0_show, hsmp_lclk_0_store, 0644);
 HSMP_DEV_ATTR_RW_X8(lclk_1, HSMP_GET_NBIO_DPM_LEVEL, HSMP_SET_NBIO_DPM_LEVEL,
@@ -904,6 +911,8 @@ static struct attribute _name[] = {					       \
 	&hattr_xgmi_width##_sock_ind.dattr.attr,			       \
 	&hattr_gmi3_link_width##_sock_ind.dattr.attr,			       \
 	&hattr_pcie_link_rate##_sock_ind.dattr.attr,			       \
+	&hattr_dimm_sb_get##_sock_ind.dattr.attr,			       \
+	&hattr_dimm_sb_set##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 73010a889eaca..bcf1b802b3287 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -7,6 +7,8 @@
  * Common sysfs helpers shared by ACPI and platform HSMP drivers.
  */
 
+#include <asm/amd/node.h>
+
 #include <linux/array_size.h>
 #include <linux/bitfield.h>
 #include <linux/bits.h>
@@ -986,6 +988,14 @@ ssize_t hsmp_pcie_link_rate_store(struct device *dev,
 	return count;
 }
 
+bool hsmp_sysfs_write_follows_read(const struct hsmp_sys_attr *hattr)
+{
+	/*
+	 * dimm_sb_get's store issues HSMP_DIMM_SB_RD, which is a GET, so
+	 * the write bit follows the GET message bitmap.
+	 */
+	return hattr->msg_id == HSMP_DIMM_SB_RD;
+}
 
 /* IO link bandwidth. priv is the io_bw attribute index. */
 ssize_t hsmp_io_link_bw_show(struct device *dev, struct device_attribute *attr,
@@ -1080,6 +1090,186 @@ umode_t hsmp_xgmi_bw_file_visible(const struct hsmp_socket *sock, int id)
 	return (sock->xgmi_bw_valid & BIT_ULL(id)) ? 0444 : 0;
 }
 
+struct dimm_sb_cfg {
+	u8 addr;
+	u8 lid;
+	u16 reg_offset;
+	u8 reg_space;
+	u16 result;
+	bool configured;
+};
+
+static struct dimm_sb_cfg dimm_sb[MAX_AMD_NUM_NODES];
+
+static struct dimm_sb_cfg *dimm_sb_state(struct device *dev,
+					 struct device_attribute *attr)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	u16 sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+
+	if (sock_ind >= MAX_AMD_NUM_NODES)
+		return NULL;
+
+	return &dimm_sb[sock_ind];
+}
+
+static int dimm_sb_parse(struct device *dev, const char *attr_name,
+			 const char *buf, bool with_data, int *addr, int *lid,
+			 int *off, int *space, int *data)
+{
+	u32 vals[5];
+	int n = with_data ? 5 : 4;
+	int ret;
+	int got;
+
+	/* Accept decimal and 0x-prefixed hexadecimal. */
+	ret = hsmp_parse_u32_args(buf, vals, n, 0, &got);
+	if (ret) {
+		if (with_data)
+			hsmp_err(dev, attr_name, HSMP_ERR_ARGC,
+				 "want=5 got=%d fmt=\"dimm_addr lid reg_offset reg_space write_data\" input=hex_or_dec",
+				  got);
+		else
+			hsmp_err(dev, attr_name, HSMP_ERR_ARGC,
+				 "want=4 got=%d fmt=\"dimm_addr lid reg_offset reg_space\" input=hex_or_dec",
+				  got);
+		return -EINVAL;
+	}
+
+	if (vals[0] > 255 || vals[1] > 15 || vals[2] > 2047 || vals[3] > 1 ||
+	    (with_data && vals[4] > 255)) {
+		if (with_data)
+			hsmp_err(dev, attr_name, HSMP_ERR_RANGE,
+				 "dimm_addr=0x%x lid=0x%x reg_offset=0x%x reg_space=%u write_data=%u valid_dimm_addr=0-255 valid_lid=0-15 valid_reg_offset=0-2047 valid_reg_space=0-1 valid_write_data=0-255",
+				  vals[0], vals[1], vals[2], vals[3], vals[4]);
+		else
+			hsmp_err(dev, attr_name, HSMP_ERR_RANGE,
+				 "dimm_addr=0x%x lid=0x%x reg_offset=0x%x reg_space=%u valid_dimm_addr=0-255 valid_lid=0-15 valid_reg_offset=0-2047 valid_reg_space=0-1",
+				  vals[0], vals[1], vals[2], vals[3]);
+		return -EINVAL;
+	}
+
+	*addr = vals[0];
+	*lid = vals[1];
+	*off = vals[2];
+	*space = vals[3];
+	if (with_data)
+		*data = vals[4];
+
+	return 0;
+}
+
+static u32 dimm_sb_pack(int addr, int lid, int off, int space, int data)
+{
+	return (addr & 0xff) |
+	       ((lid & 0xf) << 8) |
+	       ((off & 0x7ff) << 12) |
+	       ((space & 1) << 23) |
+	       ((data & 0xff) << 24);
+}
+
+/*
+ * Last DIMM sideband read request and its data, or -ENODATA if none has
+ * succeeded. Fields are address, LID, offset, reg space, and data.
+ */
+ssize_t hsmp_dimm_sb_get_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct dimm_sb_cfg *cfg = dimm_sb_state(dev, attr);
+
+	if (!cfg)
+		return -EINVAL;
+	if (!cfg->configured)
+		return -ENODATA;
+
+	return sysfs_emit(buf, "0x%x 0x%x 0x%x %u 0x%x\n",
+			  cfg->addr, cfg->lid, cfg->reg_offset, cfg->reg_space,
+			  cfg->result);
+}
+
+/* Issue HSMP_DIMM_SB_RD and cache the request and the returned data. */
+ssize_t hsmp_dimm_sb_get_store(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct dimm_sb_cfg *cfg = dimm_sb_state(dev, attr);
+	struct hsmp_message msg = {};
+	int addr, lid, off, space;
+	int ret;
+
+	if (!cfg)
+		return -EINVAL;
+
+	ret = dimm_sb_parse(dev, "dimm_sb_get", buf, false, &addr, &lid, &off, &space, NULL);
+	if (ret)
+		return ret;
+
+	/*
+	 * HSMP_DIMM_SB_RD: reg space[23] + reg offset[22:12] +
+	 * LID[11:8] + DIMM address[7:0].
+	 */
+	msg.msg_id = HSMP_DIMM_SB_RD;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, to_hsmp_sys_attr(attr));
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = dimm_sb_pack(addr, lid, off, space, 0);
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "dimm_sb_get", HSMP_ERR_HW,
+			 "dimm_addr=0x%x lid=0x%x reg_offset=0x%x reg_space=%u rc=%d",
+			  addr, lid, off, space, ret);
+		return ret;
+	}
+
+	cfg->addr = addr;
+	cfg->lid = lid;
+	cfg->reg_offset = off;
+	cfg->reg_space = space;
+	cfg->result = msg.args[0] & 0xffff;
+	cfg->configured = true;
+
+	return count;
+}
+
+/* Write one DIMM sideband register via HSMP_DIMM_SB_WR. */
+ssize_t hsmp_dimm_sb_set_store(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	int addr, lid, off, space, data;
+	u16 sock_ind;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind >= MAX_AMD_NUM_NODES)
+		return -EINVAL;
+
+	ret = dimm_sb_parse(dev, "dimm_sb_set", buf, true, &addr, &lid, &off, &space, &data);
+	if (ret)
+		return ret;
+
+	/*
+	 * HSMP_DIMM_SB_WR: write data[31:24] + reg space[23] +
+	 * reg offset[22:12] + LID[11:8] + DIMM address[7:0].
+	 */
+	msg.msg_id = HSMP_DIMM_SB_WR;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 0;
+	msg.args[0] = dimm_sb_pack(addr, lid, off, space, data);
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "dimm_sb_set", HSMP_ERR_HW,
+			 "dimm_addr=0x%x lid=0x%x reg_offset=0x%x reg_space=%u write_data=%u rc=%d",
+			  addr, lid, off, space, data, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 static ssize_t hsmp_lclk_nbio_show(struct device *dev,
 				   struct device_attribute *attr,
 				   u8 nbio_id, char *buf)
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 83358304da97b..2e7064df871bb 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -158,7 +158,18 @@ umode_t hsmp_io_bw_file_visible(const struct hsmp_socket *sock, int id);
 ssize_t hsmp_xgmi_link_bw_show(struct device *dev, struct device_attribute *attr,
 			       char *buf);
 umode_t hsmp_xgmi_bw_file_visible(const struct hsmp_socket *sock, int id);
+ssize_t hsmp_dimm_sb_get_show(struct device *dev, struct device_attribute *attr,
+			      char *buf);
+ssize_t hsmp_dimm_sb_get_store(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count);
+ssize_t hsmp_dimm_sb_set_store(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count);
 
+/*
+ * True when the attribute store issues a GET, or only records state for
+ * a later GET. The write bit then follows the GET message bitmap.
+ */
+bool hsmp_sysfs_write_follows_read(const struct hsmp_sys_attr *hattr);
 
 void hsmp_create_per_cpu_kobjects(struct device *dev, struct kobject *cpu_parent,
 				  struct hsmp_socket *sock);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 14/26] platform/x86/amd/hsmp: Add per-CPU floor limit sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (12 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 13/26] platform/x86/amd/hsmp: Add DIMM sideband " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 15/26] platform/x86/amd/hsmp: Add metric_version sysfs file Muthusamy Ramalingam
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose floor_limit and floor_limit_eff under cpu/cpuX on both drivers.
floor_limit reads and sets the per-core floor frequency through
HSMP_SET_GET_FLOOR_LIMIT. floor_limit_eff returns the effective floor.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   4 +
 drivers/platform/x86/amd/hsmp/sysfs.c | 127 ++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 67f4c3b71f5e0..3cbc4bee058ec 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -174,6 +174,10 @@ drivers.
 
 * boost_limit: Get/set the per-CPU boost limit in MHz (HSMP_GET_BOOST_LIMIT /
   HSMP_SET_BOOST_LIMIT). Writable range is 100-10000 MHz.
+* floor_limit: Get/set the per-CPU floor frequency in MHz via
+  HSMP_SET_GET_FLOOR_LIMIT. Writable range is 100-10000 MHz.
+* floor_limit_eff: Read-only effective per-CPU floor frequency in MHz via
+  HSMP_SET_GET_FLOOR_LIMIT.
 
 ACPI device object format
 =========================
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index bcf1b802b3287..b0a939071b575 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -1420,6 +1420,127 @@ ssize_t hsmp_lclk_3_store(struct device *dev, struct device_attribute *attr,
 	return hsmp_lclk_nbio_store(dev, attr, 3, buf, count);
 }
 
+static struct hsmp_cpu_info *hsmp_cpu_from_kobj(struct kobject *kobj)
+{
+	unsigned int cpu;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu_kobj_info[cpu].kobj == kobj)
+			return &cpu_kobj_info[cpu];
+	}
+
+	return NULL;
+}
+
+/*
+ * HSMP_SET_GET_FLOOR_LIMIT args[0]:
+ * op[31:30] + apic id[27:16] + floor frequency MHz[15:0].
+ * op 0 sets the per-core floor, op 2 reads it, op 3 reads the
+ * effective floor. The frequency field is reserved on a get.
+ */
+static u32 hsmp_floor_arg(u32 op, u32 apic_id, u32 mhz)
+{
+	return (op << 30) | ((apic_id & 0xfff) << 16) | (mhz & 0xffff);
+}
+
+static ssize_t floor_limit_show(struct kobject *kobj, struct kobj_attribute *attr,
+				char *buf)
+{
+	struct hsmp_cpu_info *cpu_info = hsmp_cpu_from_kobj(kobj);
+	struct hsmp_message msg = {};
+	int ret;
+
+	if (!cpu_info)
+		return -ENODEV;
+
+	msg.msg_id = HSMP_SET_GET_FLOOR_LIMIT;
+	msg.sock_ind = cpu_info->socket_id;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = hsmp_floor_arg(2, cpu_info->apic_id, 0);
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0] & 0xffff);
+}
+
+static struct device *hsmp_cpu_sock_dev(const struct hsmp_cpu_info *cpu_info)
+{
+	struct hsmp_plat_device *pdev = get_hsmp_pdev();
+
+	if (!cpu_info || !pdev || cpu_info->socket_id >= pdev->num_sockets)
+		return NULL;
+
+	return pdev->sock[cpu_info->socket_id].dev;
+}
+
+static ssize_t floor_limit_store(struct kobject *kobj, struct kobj_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct hsmp_cpu_info *cpu_info;
+	struct hsmp_message msg = {};
+	struct device *dev;
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	cpu_info = hsmp_cpu_from_kobj(kobj);
+	if (!cpu_info)
+		return -ENODEV;
+
+	dev = hsmp_cpu_sock_dev(cpu_info);
+	if (val < 100 || val > 10000) {
+		if (dev)
+			hsmp_err(dev, "floor_limit", HSMP_ERR_RANGE,
+				 "got=%lu valid=100-10000 unit=MHz", val);
+		return -EINVAL;
+	}
+
+	msg.msg_id = HSMP_SET_GET_FLOOR_LIMIT;
+	msg.sock_ind = cpu_info->socket_id;
+	msg.num_args = 1;
+	msg.response_sz = 0;
+	msg.args[0] = hsmp_floor_arg(0, cpu_info->apic_id, val);
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		if (dev)
+			hsmp_err(dev, "floor_limit", HSMP_ERR_HW,
+				 "val=%lu unit=MHz rc=%d", val, ret);
+		return ret;
+	}
+
+	return count;
+}
+
+static ssize_t floor_limit_eff_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	struct hsmp_cpu_info *cpu_info = hsmp_cpu_from_kobj(kobj);
+	struct hsmp_message msg = {};
+	int ret;
+
+	if (!cpu_info)
+		return -ENODEV;
+
+	msg.msg_id = HSMP_SET_GET_FLOOR_LIMIT;
+	msg.sock_ind = cpu_info->socket_id;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = hsmp_floor_arg(3, cpu_info->apic_id, 0);
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0] & 0xffff);
+}
+
 static ssize_t boost_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	struct hsmp_cpu_info *cpu_info = NULL;
@@ -1508,9 +1629,15 @@ static umode_t cpu_kobj_is_visible(struct kobject *kobj, struct attribute *attr,
 
 static struct kobj_attribute boost_limit_kattr =
 	__ATTR(boost_limit, 0644, boost_limit_show, boost_limit_store);
+static struct kobj_attribute floor_limit_kattr =
+	__ATTR(floor_limit, 0644, floor_limit_show, floor_limit_store);
+static struct kobj_attribute floor_limit_eff_kattr =
+	__ATTR(floor_limit_eff, 0444, floor_limit_eff_show, NULL);
 
 static struct attribute *cpu_kobj_attrs[] = {
 	&boost_limit_kattr.attr,
+	&floor_limit_kattr.attr,
+	&floor_limit_eff_kattr.attr,
 	NULL,
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 15/26] platform/x86/amd/hsmp: Add metric_version sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (13 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 14/26] platform/x86/amd/hsmp: Add per-CPU floor limit " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 16/26] platform/x86/amd/hsmp: Add enabled command sysfs files Muthusamy Ramalingam
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose a read-only metric_version file on both drivers. It reports the
metrics table version from HSMP_GET_METRIC_TABLE_VER as eight hexadecimal
digits.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst  | 1 +
 drivers/platform/x86/amd/hsmp/acpi.c | 2 ++
 drivers/platform/x86/amd/hsmp/plat.c | 4 ++++
 3 files changed, 7 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 3cbc4bee058ec..b298906a32970 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -102,6 +102,7 @@ write-only when the platform enables only that direction of the message.
   0 otherwise.
 * smu_fw_version: SMU firmware version.
 * protocol_version: HSMP interface version, as eight hexadecimal digits.
+* metric_version: Metrics table version, as eight hexadecimal digits.
 * ddr_max_bw: Theoretical maximum DDR bandwidth in GB/s.
 * ddr_utilised_bw: Current utilized DDR bandwidth in GB/s.
 * ddr_utilised_bw_perc: Percentage of current utilized DDR bandwidth.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index f2bd4d5369df5..6ce8b138277a0 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -526,6 +526,7 @@ HSMP_DEV_ATTR(c0_residency, HSMP_GET_C0_PERCENT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
 HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444);
+HSMP_DEV_ATTR(metric_version, HSMP_GET_METRIC_TABLE_VER, hsmp_msg_resp32_hex_show, 0444);
 HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
 HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
@@ -663,6 +664,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_prochot_status.dattr.attr,
 	&hattr_smu_fw_version.dattr.attr,
 	&hattr_protocol_version.dattr.attr,
+	&hattr_metric_version.dattr.attr,
 	&hattr_cclk_freq_limit.dattr.attr,
 	&hattr_ddr_max_bw.dattr.attr,
 	&hattr_ddr_utilised_bw.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 46676d9f90633..bb3c0791362ef 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -247,6 +247,9 @@ HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 04
 HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 6);
 HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444, 7);
 
+HSMP_DEV_ATTR_X8(metric_version, HSMP_GET_METRIC_TABLE_VER,
+		 hsmp_msg_resp32_hex_show, 0444);
+
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 0);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 1);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 2);
@@ -894,6 +897,7 @@ static struct attribute _name[] = {					       \
 	&hattr_prochot_status##_sock_ind.dattr.attr,			       \
 	&hattr_smu_fw_version##_sock_ind.dattr.attr,			       \
 	&hattr_protocol_version##_sock_ind.dattr.attr,			       \
+	&hattr_metric_version##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_freq_limit##_sock_ind.dattr.attr,		       \
 	&hattr_ddr_max_bw##_sock_ind.dattr.attr,			       \
 	&hattr_ddr_utilised_bw##_sock_ind.dattr.attr,		       \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 16/26] platform/x86/amd/hsmp: Add enabled command sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (14 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 15/26] platform/x86/amd/hsmp: Add metric_version sysfs file Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 17/26] platform/x86/amd/hsmp: Add DIMM power and temperature " Muthusamy Ramalingam
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose read-only enabled_read_commands and enabled_write_commands on
both drivers. Each prints the three firmware bitmasks returned by
HSMP_GET_ENABLED_HSMP_CMDS.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  3 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  6 ++++
 drivers/platform/x86/amd/hsmp/hsmp.c  |  3 --
 drivers/platform/x86/amd/hsmp/hsmp.h  |  4 +++
 drivers/platform/x86/amd/hsmp/plat.c  |  6 ++++
 drivers/platform/x86/amd/hsmp/sysfs.c | 43 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  4 +++
 7 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index b298906a32970..28cdb9d9ec645 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -103,6 +103,9 @@ write-only when the platform enables only that direction of the message.
 * smu_fw_version: SMU firmware version.
 * protocol_version: HSMP interface version, as eight hexadecimal digits.
 * metric_version: Metrics table version, as eight hexadecimal digits.
+* enabled_read_commands, enabled_write_commands: Read-only. Three
+  space-separated 32-bit hexadecimal masks of the HSMP commands firmware
+  enables for read and write.
 * ddr_max_bw: Theoretical maximum DDR bandwidth in GB/s.
 * ddr_utilised_bw: Current utilized DDR bandwidth in GB/s.
 * ddr_utilised_bw_perc: Percentage of current utilized DDR bandwidth.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 6ce8b138277a0..ee9fb3ed74dc6 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -527,6 +527,10 @@ HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(smu_fw_version, HSMP_GET_SMU_VER, hsmp_msg_fw_ver_show, 0444);
 HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 0444);
 HSMP_DEV_ATTR(metric_version, HSMP_GET_METRIC_TABLE_VER, hsmp_msg_resp32_hex_show, 0444);
+HSMP_DEV_ATTR(enabled_read_commands, HSMP_GET_ENABLED_HSMP_CMDS,
+	      hsmp_enabled_read_commands_show, 0444);
+HSMP_DEV_ATTR(enabled_write_commands, HSMP_GET_ENABLED_HSMP_CMDS,
+	      hsmp_enabled_write_commands_show, 0444);
 HSMP_DEV_ATTR(cclk_freq_limit, HSMP_GET_CCLK_THROTTLE_LIMIT, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(ddr_max_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_max_bw_show, 0444);
 HSMP_DEV_ATTR(ddr_utilised_bw, HSMP_GET_DDR_BANDWIDTH, hsmp_ddr_util_bw_show, 0444);
@@ -665,6 +669,8 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_smu_fw_version.dattr.attr,
 	&hattr_protocol_version.dattr.attr,
 	&hattr_metric_version.dattr.attr,
+	&hattr_enabled_read_commands.dattr.attr,
+	&hattr_enabled_write_commands.dattr.attr,
 	&hattr_cclk_freq_limit.dattr.attr,
 	&hattr_ddr_max_bw.dattr.attr,
 	&hattr_ddr_utilised_bw.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index 80721b13074d2..c690234a25426 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -869,9 +869,6 @@ static const u32 write_bitmap_zen6_variants[] = {0x00047320, 0x070007c6, 0x00000
 #define set_write_enabled_msg_bitmap(sock, src)	\
 	bitmap_from_arr32((sock)->enabled_write_msg_ids, (src), HSMP_MAX_MSGS)
 
-#define HSMP_GET_ENABLED_CMD_READ_MASK	1
-#define HSMP_GET_ENABLED_CMD_WRITE_MASK	0
-
 static int hsmp_fetch_read_enabled_msgs(u16 sock_ind, unsigned long *read_msg_bmap)
 {
 	struct hsmp_message msg = {};
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h
index b41080c0f9555..582913812e060 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.h
+++ b/drivers/platform/x86/amd/hsmp/hsmp.h
@@ -30,6 +30,10 @@
 
 #define HSMP_MAX_MSGS			96
 
+/* args[0] bit 0 of HSMP_GET_ENABLED_HSMP_CMDS selects the bitmap. */
+#define HSMP_GET_ENABLED_CMD_READ_MASK	1
+#define HSMP_GET_ENABLED_CMD_WRITE_MASK	0
+
 #define HSMP_METRICS_TABLE_NAME	"metrics_bin"
 
 #define HSMP_ATTR_GRP_NAME_SIZE	10
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index bb3c0791362ef..61f7747c782ea 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -249,6 +249,10 @@ HSMP_DEV_ATTR(protocol_version, HSMP_GET_PROTO_VER, hsmp_msg_resp32_hex_show, 04
 
 HSMP_DEV_ATTR_X8(metric_version, HSMP_GET_METRIC_TABLE_VER,
 		 hsmp_msg_resp32_hex_show, 0444);
+HSMP_DEV_ATTR_X8(enabled_read_commands, HSMP_GET_ENABLED_HSMP_CMDS,
+		 hsmp_enabled_read_commands_show, 0444);
+HSMP_DEV_ATTR_X8(enabled_write_commands, HSMP_GET_ENABLED_HSMP_CMDS,
+		 hsmp_enabled_write_commands_show, 0444);
 
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 0);
 HSMP_DEV_ATTR(prochot_status, HSMP_GET_PROC_HOT, hsmp_msg_resp32_show, 0444, 1);
@@ -898,6 +902,8 @@ static struct attribute _name[] = {					       \
 	&hattr_smu_fw_version##_sock_ind.dattr.attr,			       \
 	&hattr_protocol_version##_sock_ind.dattr.attr,			       \
 	&hattr_metric_version##_sock_ind.dattr.attr,			       \
+	&hattr_enabled_read_commands##_sock_ind.dattr.attr,		       \
+	&hattr_enabled_write_commands##_sock_ind.dattr.attr,		       \
 	&hattr_cclk_freq_limit##_sock_ind.dattr.attr,		       \
 	&hattr_ddr_max_bw##_sock_ind.dattr.attr,			       \
 	&hattr_ddr_utilised_bw##_sock_ind.dattr.attr,		       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index b0a939071b575..62d5b6c90ea47 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -107,6 +107,49 @@ ssize_t hsmp_msg_resp32_hex_show(struct device *dev, struct device_attribute *at
 	return sysfs_emit(buf, "0x%08x\n", data);
 }
 
+static ssize_t hsmp_enabled_cmds_show(struct device *dev,
+				      struct device_attribute *attr,
+				      u32 mask, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u16 sock_ind;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	/*
+	 * HSMP_GET_ENABLED_HSMP_CMDS: args[0] bit 0 selects the read (1)
+	 * or write (0) bitmap. The response is three 32-bit masks.
+	 */
+	msg.msg_id = HSMP_GET_ENABLED_HSMP_CMDS;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 3;
+	msg.args[0] = mask;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "0x%08X 0x%08X 0x%08X\n",
+			  msg.args[0], msg.args[1], msg.args[2]);
+}
+
+ssize_t hsmp_enabled_read_commands_show(struct device *dev,
+					struct device_attribute *attr, char *buf)
+{
+	return hsmp_enabled_cmds_show(dev, attr, HSMP_GET_ENABLED_CMD_READ_MASK, buf);
+}
+
+ssize_t hsmp_enabled_write_commands_show(struct device *dev,
+					 struct device_attribute *attr, char *buf)
+{
+	return hsmp_enabled_cmds_show(dev, attr, HSMP_GET_ENABLED_CMD_WRITE_MASK, buf);
+}
+
 ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 2e7064df871bb..2b14c4135212d 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -67,6 +67,10 @@ ssize_t hsmp_msg_resp32_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_msg_resp32_hex_show(struct device *dev, struct device_attribute *attr,
 				 char *buf);
+ssize_t hsmp_enabled_read_commands_show(struct device *dev,
+					struct device_attribute *attr, char *buf);
+ssize_t hsmp_enabled_write_commands_show(struct device *dev,
+					 struct device_attribute *attr, char *buf);
 ssize_t hsmp_ddr_max_bw_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_ddr_util_bw_show(struct device *dev, struct device_attribute *attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 17/26] platform/x86/amd/hsmp: Add DIMM power and temperature sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (15 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 16/26] platform/x86/amd/hsmp: Add enabled command sysfs files Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 18/26] platform/x86/amd/hsmp: Add SVI3 " Muthusamy Ramalingam
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose dimm_power, dimm_temperature, and dimm_temperature_range on
both drivers. Probe records which DIMMs respond, and each directory
shows only those addresses plus the socket-wide aggregate files.

dimm_temperature/ always reports a sensor type (TS0/TS1/SPDHub). Protocol
7.2 and later supply it from firmware; older protocols derive TS0/TS1 from
address bit 6. Socket-wide max temperature falls back to SPDHub when the
protocol omits the sensor.

dimm_temperature_range/ is UMC-channel granularity only (dimm_0x80-0x8f);
unlike dimm_power/, 0x90-0x9F does not apply to HSMP_GET_DIMM_TEMP_RANGE.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   23 +
 drivers/platform/x86/amd/hsmp/acpi.c  |  297 ++++++
 drivers/platform/x86/amd/hsmp/hsmp.c  |   57 ++
 drivers/platform/x86/amd/hsmp/hsmp.h  |    5 +
 drivers/platform/x86/amd/hsmp/plat.c  | 1272 ++++++++++++++++++++++++-
 drivers/platform/x86/amd/hsmp/sysfs.c |  356 +++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |   17 +
 7 files changed, 1982 insertions(+), 45 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 28cdb9d9ec645..1a2fd95e21ac1 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -159,6 +159,29 @@ write-only when the platform enables only that direction of the message.
   "<dimm_addr> <lid> <reg_offset> <reg_space> <write_data>".
   write_data is 0-255. Extra arguments are rejected. Field ranges match
   dimm_sb_get.
+* dimm_power/: Read-only DIMM power. dimm_0x80 through dimm_0x8f and
+  dimm_0x90 through dimm_0x9f are created for DIMMs that respond during
+  probe. A read returns "<power_mW> <update_rate_ms>". dimm_total_power
+  sums the present DIMMs in the same format, or fails with -ENODATA when
+  none are present. dimm_max_power returns
+  "<power_mW> <update_rate_ms> 0xAA" for the highest-power DIMM.
+* dimm_temperature/: Read-only DIMM temperature. Files are dimm_0x80
+  through dimm_0x8f, dimm_0xc0 through dimm_0xcf, dimm_0x90 through
+  dimm_0x9f, and dimm_0xd0 through dimm_0xdf. The 0xC0 and 0xD0 files
+  share presence with 0x80 and 0x90. A read returns
+  "<degrees> <update_rate_ms> <sensor>" with three fractional digits.
+  The sensor is TS0, TS1, SPDHub, or Reserved. Protocol 7.2 and later
+  reports it from firmware; older protocols derive TS0/TS1 from address
+  bit 6. dimm_max_temperature returns
+  "<degrees> <update_rate_ms> <sensor> 0xAA" for the hottest DIMM
+  (SPDHub when the protocol omits the sensor), or fails with -ENODATA
+  when none respond.
+* dimm_temperature_range/: Read-only temperature range and DDR refresh
+  mode. HSMP_GET_DIMM_TEMP_RANGE is UMC-channel granularity only, so
+  address files are dimm_0x80-0x8f (one per channel). A read returns
+  "<range> <1x|2x>". The directory is absent when no channel responds.
+  dimm_max_temperature_range returns "<range> <1x|2x> 0xAA" for the
+  hottest channel, or fails with -ENODATA when none respond.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index ee9fb3ed74dc6..2028c1e8fc1c3 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -445,6 +445,7 @@ static int init_acpi(struct device *dev)
 			return ret;
 		}
 
+		hsmp_scan_dimms(sock);
 		hsmp_scan_io_bw(sock);
 		hsmp_scan_xgmi_bw(sock);
 	}
@@ -663,6 +664,131 @@ HSMP_DEV_ATTR_RW(rail_iso_freq_policy, HSMP_CPU_RAIL_ISO_FREQ_POLICY,
 		 HSMP_CPU_RAIL_ISO_FREQ_POLICY,
 		 hsmp_rail_iso_freq_policy_show, hsmp_rail_iso_freq_policy_store, 0644);
 
+#define HSMP_DIMM_RO(_var, _name, _show, _msg, _priv)			\
+	HSMP_SYS_ATTR_PRIV(_var, _name, _show, U16_MAX, _msg, _priv)
+
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0);
+
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0);
+
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0);
+
+#undef HSMP_DIMM_RO
+
 static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_c0_residency.dattr.attr,
 	&hattr_prochot_status.dattr.attr,
@@ -826,6 +952,174 @@ static const struct attribute_group xgmi_bw_group = {
 	.is_visible = hsmp_xgmi_bw_is_visible,
 };
 
+static struct attribute *dimm_power_attrs[] = {
+	&hattr_dpwr_80.dattr.attr,
+	&hattr_dpwr_81.dattr.attr,
+	&hattr_dpwr_82.dattr.attr,
+	&hattr_dpwr_83.dattr.attr,
+	&hattr_dpwr_84.dattr.attr,
+	&hattr_dpwr_85.dattr.attr,
+	&hattr_dpwr_86.dattr.attr,
+	&hattr_dpwr_87.dattr.attr,
+	&hattr_dpwr_88.dattr.attr,
+	&hattr_dpwr_89.dattr.attr,
+	&hattr_dpwr_8a.dattr.attr,
+	&hattr_dpwr_8b.dattr.attr,
+	&hattr_dpwr_8c.dattr.attr,
+	&hattr_dpwr_8d.dattr.attr,
+	&hattr_dpwr_8e.dattr.attr,
+	&hattr_dpwr_8f.dattr.attr,
+	&hattr_dpwr_90.dattr.attr,
+	&hattr_dpwr_91.dattr.attr,
+	&hattr_dpwr_92.dattr.attr,
+	&hattr_dpwr_93.dattr.attr,
+	&hattr_dpwr_94.dattr.attr,
+	&hattr_dpwr_95.dattr.attr,
+	&hattr_dpwr_96.dattr.attr,
+	&hattr_dpwr_97.dattr.attr,
+	&hattr_dpwr_98.dattr.attr,
+	&hattr_dpwr_99.dattr.attr,
+	&hattr_dpwr_9a.dattr.attr,
+	&hattr_dpwr_9b.dattr.attr,
+	&hattr_dpwr_9c.dattr.attr,
+	&hattr_dpwr_9d.dattr.attr,
+	&hattr_dpwr_9e.dattr.attr,
+	&hattr_dpwr_9f.dattr.attr,
+	&hattr_dpwr_total.dattr.attr,
+	&hattr_dpwr_max.dattr.attr,
+	NULL
+};
+
+static struct attribute *dimm_temperature_attrs[] = {
+	&hattr_dt_80.dattr.attr,
+	&hattr_dt_81.dattr.attr,
+	&hattr_dt_82.dattr.attr,
+	&hattr_dt_83.dattr.attr,
+	&hattr_dt_84.dattr.attr,
+	&hattr_dt_85.dattr.attr,
+	&hattr_dt_86.dattr.attr,
+	&hattr_dt_87.dattr.attr,
+	&hattr_dt_88.dattr.attr,
+	&hattr_dt_89.dattr.attr,
+	&hattr_dt_8a.dattr.attr,
+	&hattr_dt_8b.dattr.attr,
+	&hattr_dt_8c.dattr.attr,
+	&hattr_dt_8d.dattr.attr,
+	&hattr_dt_8e.dattr.attr,
+	&hattr_dt_8f.dattr.attr,
+	&hattr_dt_c0.dattr.attr,
+	&hattr_dt_c1.dattr.attr,
+	&hattr_dt_c2.dattr.attr,
+	&hattr_dt_c3.dattr.attr,
+	&hattr_dt_c4.dattr.attr,
+	&hattr_dt_c5.dattr.attr,
+	&hattr_dt_c6.dattr.attr,
+	&hattr_dt_c7.dattr.attr,
+	&hattr_dt_c8.dattr.attr,
+	&hattr_dt_c9.dattr.attr,
+	&hattr_dt_ca.dattr.attr,
+	&hattr_dt_cb.dattr.attr,
+	&hattr_dt_cc.dattr.attr,
+	&hattr_dt_cd.dattr.attr,
+	&hattr_dt_ce.dattr.attr,
+	&hattr_dt_cf.dattr.attr,
+	&hattr_dt_90.dattr.attr,
+	&hattr_dt_91.dattr.attr,
+	&hattr_dt_92.dattr.attr,
+	&hattr_dt_93.dattr.attr,
+	&hattr_dt_94.dattr.attr,
+	&hattr_dt_95.dattr.attr,
+	&hattr_dt_96.dattr.attr,
+	&hattr_dt_97.dattr.attr,
+	&hattr_dt_98.dattr.attr,
+	&hattr_dt_99.dattr.attr,
+	&hattr_dt_9a.dattr.attr,
+	&hattr_dt_9b.dattr.attr,
+	&hattr_dt_9c.dattr.attr,
+	&hattr_dt_9d.dattr.attr,
+	&hattr_dt_9e.dattr.attr,
+	&hattr_dt_9f.dattr.attr,
+	&hattr_dt_d0.dattr.attr,
+	&hattr_dt_d1.dattr.attr,
+	&hattr_dt_d2.dattr.attr,
+	&hattr_dt_d3.dattr.attr,
+	&hattr_dt_d4.dattr.attr,
+	&hattr_dt_d5.dattr.attr,
+	&hattr_dt_d6.dattr.attr,
+	&hattr_dt_d7.dattr.attr,
+	&hattr_dt_d8.dattr.attr,
+	&hattr_dt_d9.dattr.attr,
+	&hattr_dt_da.dattr.attr,
+	&hattr_dt_db.dattr.attr,
+	&hattr_dt_dc.dattr.attr,
+	&hattr_dt_dd.dattr.attr,
+	&hattr_dt_de.dattr.attr,
+	&hattr_dt_df.dattr.attr,
+	&hattr_dt_max.dattr.attr,
+	NULL
+};
+
+static struct attribute *dimm_temperature_range_attrs[] = {
+	&hattr_dtr_80.dattr.attr,
+	&hattr_dtr_81.dattr.attr,
+	&hattr_dtr_82.dattr.attr,
+	&hattr_dtr_83.dattr.attr,
+	&hattr_dtr_84.dattr.attr,
+	&hattr_dtr_85.dattr.attr,
+	&hattr_dtr_86.dattr.attr,
+	&hattr_dtr_87.dattr.attr,
+	&hattr_dtr_88.dattr.attr,
+	&hattr_dtr_89.dattr.attr,
+	&hattr_dtr_8a.dattr.attr,
+	&hattr_dtr_8b.dattr.attr,
+	&hattr_dtr_8c.dattr.attr,
+	&hattr_dtr_8d.dattr.attr,
+	&hattr_dtr_8e.dattr.attr,
+	&hattr_dtr_8f.dattr.attr,
+	&hattr_dtr_max.dattr.attr,
+	NULL
+};
+
+static umode_t hsmp_dimm_power_is_visible(struct kobject *kobj,
+					  struct attribute *attr __always_unused,
+					  int id)
+{
+	return hsmp_dimm_power_file_visible(dev_get_drvdata(kobj_to_dev(kobj)), id);
+}
+
+static umode_t hsmp_dimm_temp_is_visible(struct kobject *kobj,
+					 struct attribute *attr __always_unused,
+					 int id)
+{
+	return hsmp_dimm_temp_file_visible(dev_get_drvdata(kobj_to_dev(kobj)), id);
+}
+
+static umode_t hsmp_dimm_temp_range_is_visible(struct kobject *kobj,
+					       struct attribute *attr __always_unused,
+					       int id)
+{
+	return hsmp_dimm_temp_range_file_visible(dev_get_drvdata(kobj_to_dev(kobj)),
+						 id);
+}
+
+static const struct attribute_group dimm_power_group = {
+	.name = "dimm_power",
+	.attrs = dimm_power_attrs,
+	.is_visible = hsmp_dimm_power_is_visible,
+};
+
+static const struct attribute_group dimm_temperature_group = {
+	.name = "dimm_temperature",
+	.attrs = dimm_temperature_attrs,
+	.is_visible = hsmp_dimm_temp_is_visible,
+};
+
+static const struct attribute_group dimm_temperature_range_group = {
+	.name = "dimm_temperature_range",
+	.attrs = dimm_temperature_range_attrs,
+	.is_visible = hsmp_dimm_temp_range_is_visible,
+};
+
 static const struct attribute_group hsmp_attr_grp = {
 	.bin_attrs = hsmp_attr_list,
 	.attrs = hsmp_dev_attr_list,
@@ -838,6 +1132,9 @@ static const struct attribute_group *hsmp_groups[] = {
 	&lclk_group,
 	&io_bw_group,
 	&xgmi_bw_group,
+	&dimm_power_group,
+	&dimm_temperature_group,
+	&dimm_temperature_range_group,
 	NULL
 };
 
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index c690234a25426..d6a4a79118e80 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -903,6 +903,63 @@ static int hsmp_fetch_write_enabled_msgs(u16 sock_ind, unsigned long *write_msg_
 	return ret;
 }
 
+static void hsmp_scan_dimm_range(struct hsmp_socket *sock, u32 msg_id, u32 *mask,
+				 bool scan_9x)
+{
+	u32 addr;
+
+	*mask = 0;
+	if (!is_read_msg_enabled(sock, msg_id))
+		return;
+
+	for (addr = 0x80; addr <= 0x8F; addr++) {
+		struct hsmp_message msg = {};
+
+		msg.msg_id = msg_id;
+		msg.sock_ind = sock->sock_ind;
+		msg.num_args = 1;
+		msg.response_sz = 1;
+		msg.args[0] = addr;
+		if (!hsmp_send_message_locked(&msg))
+			*mask |= BIT(addr - 0x80);
+	}
+
+	if (!scan_9x)
+		return;
+
+	for (addr = 0x90; addr <= 0x9F; addr++) {
+		struct hsmp_message msg = {};
+
+		msg.msg_id = msg_id;
+		msg.sock_ind = sock->sock_ind;
+		msg.num_args = 1;
+		msg.response_sz = 1;
+		msg.args[0] = addr;
+		if (!hsmp_send_message_locked(&msg))
+			*mask |= BIT(addr - 0x90 + 16);
+	}
+}
+
+/*
+ * Probe DIMM power/thermal at 0x80-0x8F and 0x90-0x9F. dimm_temperature/
+ * 0xC0 and 0xD0 aliases share the thermal validity bits. HSMP_GET_DIMM_TEMP_RANGE
+ * is UMC-channel granularity only (0x80-0x8F); 0x90-0x9F does not apply.
+ * Caller holds hsmp_sock_rwsem for write.
+ */
+void hsmp_scan_dimms(struct hsmp_socket *sock)
+{
+	if (!sock || is_client_platform())
+		return;
+
+	hsmp_scan_dimm_range(sock, HSMP_GET_DIMM_POWER, &sock->dimm_power_valid,
+			     true);
+	hsmp_scan_dimm_range(sock, HSMP_GET_DIMM_THERMAL, &sock->dimm_temp_valid,
+			     true);
+	hsmp_scan_dimm_range(sock, HSMP_GET_DIMM_TEMP_RANGE,
+			     &sock->dimm_temp_range_valid, false);
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_scan_dimms, "AMD_HSMP");
+
 static int hsmp_set_default_msg_bitmap(u16 sock_ind)
 {
 	struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind];
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h
index 582913812e060..ce54170ab3b75 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.h
+++ b/drivers/platform/x86/amd/hsmp/hsmp.h
@@ -87,6 +87,10 @@ struct hsmp_socket {
 	u32 proto_ver;
 	DECLARE_BITMAP(enabled_read_msg_ids, HSMP_MAX_MSGS);
 	DECLARE_BITMAP(enabled_write_msg_ids, HSMP_MAX_MSGS);
+	/* Bits 0-15: addresses 0x80-0x8F. Bits 16-31: addresses 0x90-0x9F. */
+	u32 dimm_power_valid;
+	u32 dimm_temp_valid;
+	u32 dimm_temp_range_valid;
 	/*
 	 * Links that answered HSMP_GET_IOLINK_BANDWITH at probe.
 	 * Bit index matches io_bw/io_p0 .. io_g7 attribute order.
@@ -156,6 +160,7 @@ void hsmp_scan_io_bw(struct hsmp_socket *sock);
 #define HSMP_XGMI_BW_COUNT	(HSMP_IO_LINK_COUNT * HSMP_XGMI_BW_TYPES)
 int hsmp_xgmi_bw_arg(unsigned int id, u32 *arg);
 void hsmp_scan_xgmi_bw(struct hsmp_socket *sock);
+void hsmp_scan_dimms(struct hsmp_socket *sock);
 
 /*
  * Gates the HSMP data plane: hsmp_send_message() takes it for read; probe and
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 61f7747c782ea..809dd2cbb9948 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -12,6 +12,7 @@
 #include <asm/amd/hsmp.h>
 
 #include <linux/acpi.h>
+#include <linux/array_size.h>
 #include <linux/build_bug.h>
 #include <linux/cleanup.h>
 #include <linux/container_of.h>
@@ -877,6 +878,949 @@ HSMP_XGMI_WR(g7, 39, 7);
 #undef HSMP_XGMI_AGG
 #undef HSMP_XGMI_RD
 #undef HSMP_XGMI_WR
+#define HSMP_DIMM_RO(_var, _name, _show, _msg, _priv, _sock)		\
+	HSMP_SYS_ATTR_PRIV(_var##_##_sock, _name, _show, _sock, _msg, _priv)
+
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 0);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 1);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 2);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 3);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 4);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 5);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 6);
+HSMP_DIMM_RO(dpwr_80, dimm_0x80, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x80, 7);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 0);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 1);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 2);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 3);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 4);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 5);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 6);
+HSMP_DIMM_RO(dpwr_81, dimm_0x81, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x81, 7);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 0);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 1);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 2);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 3);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 4);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 5);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 6);
+HSMP_DIMM_RO(dpwr_82, dimm_0x82, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x82, 7);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 0);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 1);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 2);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 3);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 4);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 5);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 6);
+HSMP_DIMM_RO(dpwr_83, dimm_0x83, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x83, 7);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 0);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 1);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 2);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 3);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 4);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 5);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 6);
+HSMP_DIMM_RO(dpwr_84, dimm_0x84, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x84, 7);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 0);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 1);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 2);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 3);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 4);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 5);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 6);
+HSMP_DIMM_RO(dpwr_85, dimm_0x85, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x85, 7);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 0);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 1);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 2);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 3);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 4);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 5);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 6);
+HSMP_DIMM_RO(dpwr_86, dimm_0x86, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x86, 7);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 0);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 1);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 2);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 3);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 4);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 5);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 6);
+HSMP_DIMM_RO(dpwr_87, dimm_0x87, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x87, 7);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 0);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 1);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 2);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 3);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 4);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 5);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 6);
+HSMP_DIMM_RO(dpwr_88, dimm_0x88, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x88, 7);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 0);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 1);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 2);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 3);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 4);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 5);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 6);
+HSMP_DIMM_RO(dpwr_89, dimm_0x89, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x89, 7);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 0);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 1);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 2);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 3);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 4);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 5);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 6);
+HSMP_DIMM_RO(dpwr_8a, dimm_0x8a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8a, 7);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 0);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 1);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 2);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 3);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 4);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 5);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 6);
+HSMP_DIMM_RO(dpwr_8b, dimm_0x8b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8b, 7);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 0);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 1);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 2);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 3);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 4);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 5);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 6);
+HSMP_DIMM_RO(dpwr_8c, dimm_0x8c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8c, 7);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 0);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 1);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 2);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 3);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 4);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 5);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 6);
+HSMP_DIMM_RO(dpwr_8d, dimm_0x8d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8d, 7);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 0);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 1);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 2);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 3);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 4);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 5);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 6);
+HSMP_DIMM_RO(dpwr_8e, dimm_0x8e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8e, 7);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 0);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 1);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 2);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 3);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 4);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 5);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 6);
+HSMP_DIMM_RO(dpwr_8f, dimm_0x8f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x8f, 7);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 0);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 1);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 2);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 3);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 4);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 5);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 6);
+HSMP_DIMM_RO(dpwr_90, dimm_0x90, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x90, 7);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 0);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 1);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 2);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 3);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 4);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 5);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 6);
+HSMP_DIMM_RO(dpwr_91, dimm_0x91, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x91, 7);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 0);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 1);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 2);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 3);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 4);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 5);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 6);
+HSMP_DIMM_RO(dpwr_92, dimm_0x92, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x92, 7);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 0);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 1);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 2);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 3);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 4);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 5);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 6);
+HSMP_DIMM_RO(dpwr_93, dimm_0x93, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x93, 7);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 0);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 1);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 2);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 3);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 4);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 5);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 6);
+HSMP_DIMM_RO(dpwr_94, dimm_0x94, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x94, 7);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 0);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 1);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 2);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 3);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 4);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 5);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 6);
+HSMP_DIMM_RO(dpwr_95, dimm_0x95, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x95, 7);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 0);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 1);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 2);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 3);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 4);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 5);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 6);
+HSMP_DIMM_RO(dpwr_96, dimm_0x96, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x96, 7);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 0);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 1);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 2);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 3);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 4);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 5);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 6);
+HSMP_DIMM_RO(dpwr_97, dimm_0x97, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x97, 7);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 0);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 1);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 2);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 3);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 4);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 5);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 6);
+HSMP_DIMM_RO(dpwr_98, dimm_0x98, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x98, 7);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 0);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 1);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 2);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 3);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 4);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 5);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 6);
+HSMP_DIMM_RO(dpwr_99, dimm_0x99, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x99, 7);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 0);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 1);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 2);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 3);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 4);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 5);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 6);
+HSMP_DIMM_RO(dpwr_9a, dimm_0x9a, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9a, 7);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 0);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 1);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 2);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 3);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 4);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 5);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 6);
+HSMP_DIMM_RO(dpwr_9b, dimm_0x9b, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9b, 7);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 0);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 1);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 2);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 3);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 4);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 5);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 6);
+HSMP_DIMM_RO(dpwr_9c, dimm_0x9c, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9c, 7);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 0);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 1);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 2);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 3);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 4);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 5);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 6);
+HSMP_DIMM_RO(dpwr_9d, dimm_0x9d, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9d, 7);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 0);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 1);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 2);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 3);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 4);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 5);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 6);
+HSMP_DIMM_RO(dpwr_9e, dimm_0x9e, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9e, 7);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 0);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 1);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 2);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 3);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 4);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 5);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 6);
+HSMP_DIMM_RO(dpwr_9f, dimm_0x9f, hsmp_dimm_power_show, HSMP_GET_DIMM_POWER, 0x9f, 7);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 0);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 1);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 2);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 3);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 4);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 5);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 6);
+HSMP_DIMM_RO(dpwr_total, dimm_total_power, hsmp_dimm_total_power_show, HSMP_GET_DIMM_POWER, 0, 7);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 0);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 1);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 2);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 3);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 4);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 5);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 6);
+HSMP_DIMM_RO(dpwr_max, dimm_max_power, hsmp_dimm_max_power_show, HSMP_GET_DIMM_POWER, 0, 7);
+
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 0);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 1);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 2);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 3);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 4);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 5);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 6);
+HSMP_DIMM_RO(dt_80, dimm_0x80, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x80, 7);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 0);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 1);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 2);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 3);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 4);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 5);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 6);
+HSMP_DIMM_RO(dt_81, dimm_0x81, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x81, 7);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 0);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 1);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 2);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 3);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 4);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 5);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 6);
+HSMP_DIMM_RO(dt_82, dimm_0x82, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x82, 7);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 0);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 1);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 2);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 3);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 4);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 5);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 6);
+HSMP_DIMM_RO(dt_83, dimm_0x83, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x83, 7);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 0);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 1);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 2);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 3);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 4);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 5);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 6);
+HSMP_DIMM_RO(dt_84, dimm_0x84, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x84, 7);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 0);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 1);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 2);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 3);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 4);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 5);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 6);
+HSMP_DIMM_RO(dt_85, dimm_0x85, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x85, 7);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 0);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 1);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 2);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 3);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 4);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 5);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 6);
+HSMP_DIMM_RO(dt_86, dimm_0x86, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x86, 7);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 0);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 1);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 2);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 3);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 4);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 5);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 6);
+HSMP_DIMM_RO(dt_87, dimm_0x87, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x87, 7);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 0);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 1);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 2);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 3);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 4);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 5);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 6);
+HSMP_DIMM_RO(dt_88, dimm_0x88, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x88, 7);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 0);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 1);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 2);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 3);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 4);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 5);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 6);
+HSMP_DIMM_RO(dt_89, dimm_0x89, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x89, 7);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 0);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 1);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 2);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 3);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 4);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 5);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 6);
+HSMP_DIMM_RO(dt_8a, dimm_0x8a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8a, 7);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 0);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 1);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 2);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 3);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 4);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 5);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 6);
+HSMP_DIMM_RO(dt_8b, dimm_0x8b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8b, 7);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 0);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 1);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 2);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 3);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 4);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 5);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 6);
+HSMP_DIMM_RO(dt_8c, dimm_0x8c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8c, 7);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 0);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 1);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 2);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 3);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 4);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 5);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 6);
+HSMP_DIMM_RO(dt_8d, dimm_0x8d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8d, 7);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 0);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 1);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 2);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 3);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 4);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 5);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 6);
+HSMP_DIMM_RO(dt_8e, dimm_0x8e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8e, 7);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 0);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 1);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 2);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 3);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 4);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 5);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 6);
+HSMP_DIMM_RO(dt_8f, dimm_0x8f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x8f, 7);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 0);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 1);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 2);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 3);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 4);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 5);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 6);
+HSMP_DIMM_RO(dt_c0, dimm_0xc0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc0, 7);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 0);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 1);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 2);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 3);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 4);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 5);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 6);
+HSMP_DIMM_RO(dt_c1, dimm_0xc1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc1, 7);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 0);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 1);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 2);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 3);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 4);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 5);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 6);
+HSMP_DIMM_RO(dt_c2, dimm_0xc2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc2, 7);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 0);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 1);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 2);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 3);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 4);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 5);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 6);
+HSMP_DIMM_RO(dt_c3, dimm_0xc3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc3, 7);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 0);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 1);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 2);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 3);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 4);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 5);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 6);
+HSMP_DIMM_RO(dt_c4, dimm_0xc4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc4, 7);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 0);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 1);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 2);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 3);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 4);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 5);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 6);
+HSMP_DIMM_RO(dt_c5, dimm_0xc5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc5, 7);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 0);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 1);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 2);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 3);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 4);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 5);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 6);
+HSMP_DIMM_RO(dt_c6, dimm_0xc6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc6, 7);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 0);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 1);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 2);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 3);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 4);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 5);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 6);
+HSMP_DIMM_RO(dt_c7, dimm_0xc7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc7, 7);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 0);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 1);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 2);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 3);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 4);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 5);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 6);
+HSMP_DIMM_RO(dt_c8, dimm_0xc8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc8, 7);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 0);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 1);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 2);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 3);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 4);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 5);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 6);
+HSMP_DIMM_RO(dt_c9, dimm_0xc9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xc9, 7);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 0);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 1);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 2);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 3);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 4);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 5);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 6);
+HSMP_DIMM_RO(dt_ca, dimm_0xca, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xca, 7);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 0);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 1);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 2);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 3);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 4);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 5);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 6);
+HSMP_DIMM_RO(dt_cb, dimm_0xcb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcb, 7);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 0);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 1);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 2);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 3);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 4);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 5);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 6);
+HSMP_DIMM_RO(dt_cc, dimm_0xcc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcc, 7);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 0);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 1);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 2);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 3);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 4);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 5);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 6);
+HSMP_DIMM_RO(dt_cd, dimm_0xcd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcd, 7);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 0);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 1);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 2);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 3);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 4);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 5);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 6);
+HSMP_DIMM_RO(dt_ce, dimm_0xce, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xce, 7);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 0);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 1);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 2);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 3);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 4);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 5);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 6);
+HSMP_DIMM_RO(dt_cf, dimm_0xcf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xcf, 7);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 0);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 1);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 2);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 3);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 4);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 5);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 6);
+HSMP_DIMM_RO(dt_90, dimm_0x90, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x90, 7);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 0);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 1);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 2);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 3);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 4);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 5);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 6);
+HSMP_DIMM_RO(dt_91, dimm_0x91, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x91, 7);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 0);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 1);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 2);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 3);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 4);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 5);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 6);
+HSMP_DIMM_RO(dt_92, dimm_0x92, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x92, 7);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 0);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 1);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 2);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 3);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 4);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 5);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 6);
+HSMP_DIMM_RO(dt_93, dimm_0x93, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x93, 7);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 0);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 1);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 2);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 3);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 4);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 5);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 6);
+HSMP_DIMM_RO(dt_94, dimm_0x94, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x94, 7);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 0);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 1);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 2);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 3);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 4);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 5);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 6);
+HSMP_DIMM_RO(dt_95, dimm_0x95, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x95, 7);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 0);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 1);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 2);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 3);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 4);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 5);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 6);
+HSMP_DIMM_RO(dt_96, dimm_0x96, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x96, 7);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 0);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 1);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 2);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 3);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 4);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 5);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 6);
+HSMP_DIMM_RO(dt_97, dimm_0x97, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x97, 7);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 0);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 1);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 2);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 3);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 4);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 5);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 6);
+HSMP_DIMM_RO(dt_98, dimm_0x98, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x98, 7);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 0);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 1);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 2);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 3);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 4);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 5);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 6);
+HSMP_DIMM_RO(dt_99, dimm_0x99, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x99, 7);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 0);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 1);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 2);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 3);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 4);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 5);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 6);
+HSMP_DIMM_RO(dt_9a, dimm_0x9a, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9a, 7);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 0);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 1);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 2);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 3);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 4);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 5);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 6);
+HSMP_DIMM_RO(dt_9b, dimm_0x9b, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9b, 7);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 0);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 1);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 2);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 3);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 4);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 5);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 6);
+HSMP_DIMM_RO(dt_9c, dimm_0x9c, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9c, 7);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 0);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 1);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 2);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 3);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 4);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 5);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 6);
+HSMP_DIMM_RO(dt_9d, dimm_0x9d, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9d, 7);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 0);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 1);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 2);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 3);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 4);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 5);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 6);
+HSMP_DIMM_RO(dt_9e, dimm_0x9e, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9e, 7);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 0);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 1);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 2);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 3);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 4);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 5);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 6);
+HSMP_DIMM_RO(dt_9f, dimm_0x9f, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0x9f, 7);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 0);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 1);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 2);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 3);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 4);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 5);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 6);
+HSMP_DIMM_RO(dt_d0, dimm_0xd0, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd0, 7);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 0);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 1);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 2);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 3);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 4);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 5);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 6);
+HSMP_DIMM_RO(dt_d1, dimm_0xd1, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd1, 7);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 0);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 1);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 2);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 3);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 4);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 5);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 6);
+HSMP_DIMM_RO(dt_d2, dimm_0xd2, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd2, 7);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 0);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 1);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 2);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 3);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 4);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 5);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 6);
+HSMP_DIMM_RO(dt_d3, dimm_0xd3, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd3, 7);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 0);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 1);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 2);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 3);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 4);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 5);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 6);
+HSMP_DIMM_RO(dt_d4, dimm_0xd4, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd4, 7);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 0);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 1);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 2);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 3);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 4);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 5);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 6);
+HSMP_DIMM_RO(dt_d5, dimm_0xd5, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd5, 7);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 0);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 1);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 2);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 3);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 4);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 5);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 6);
+HSMP_DIMM_RO(dt_d6, dimm_0xd6, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd6, 7);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 0);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 1);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 2);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 3);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 4);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 5);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 6);
+HSMP_DIMM_RO(dt_d7, dimm_0xd7, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd7, 7);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 0);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 1);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 2);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 3);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 4);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 5);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 6);
+HSMP_DIMM_RO(dt_d8, dimm_0xd8, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd8, 7);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 0);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 1);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 2);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 3);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 4);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 5);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 6);
+HSMP_DIMM_RO(dt_d9, dimm_0xd9, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xd9, 7);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 0);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 1);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 2);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 3);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 4);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 5);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 6);
+HSMP_DIMM_RO(dt_da, dimm_0xda, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xda, 7);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 0);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 1);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 2);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 3);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 4);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 5);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 6);
+HSMP_DIMM_RO(dt_db, dimm_0xdb, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdb, 7);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 0);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 1);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 2);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 3);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 4);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 5);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 6);
+HSMP_DIMM_RO(dt_dc, dimm_0xdc, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdc, 7);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 0);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 1);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 2);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 3);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 4);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 5);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 6);
+HSMP_DIMM_RO(dt_dd, dimm_0xdd, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdd, 7);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 0);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 1);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 2);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 3);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 4);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 5);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 6);
+HSMP_DIMM_RO(dt_de, dimm_0xde, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xde, 7);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 0);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 1);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 2);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 3);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 4);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 5);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 6);
+HSMP_DIMM_RO(dt_df, dimm_0xdf, hsmp_dimm_temp_show, HSMP_GET_DIMM_THERMAL, 0xdf, 7);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 0);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 1);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 2);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 3);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 4);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 5);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 6);
+HSMP_DIMM_RO(dt_max, dimm_max_temperature, hsmp_dimm_max_temp_show, HSMP_GET_DIMM_THERMAL, 0, 7);
+
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 0);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 1);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 2);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 3);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 4);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 5);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 6);
+HSMP_DIMM_RO(dtr_80, dimm_0x80, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x80, 7);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 0);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 1);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 2);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 3);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 4);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 5);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 6);
+HSMP_DIMM_RO(dtr_81, dimm_0x81, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x81, 7);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 0);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 1);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 2);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 3);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 4);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 5);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 6);
+HSMP_DIMM_RO(dtr_82, dimm_0x82, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x82, 7);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 0);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 1);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 2);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 3);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 4);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 5);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 6);
+HSMP_DIMM_RO(dtr_83, dimm_0x83, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x83, 7);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 0);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 1);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 2);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 3);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 4);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 5);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 6);
+HSMP_DIMM_RO(dtr_84, dimm_0x84, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x84, 7);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 0);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 1);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 2);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 3);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 4);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 5);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 6);
+HSMP_DIMM_RO(dtr_85, dimm_0x85, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x85, 7);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 0);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 1);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 2);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 3);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 4);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 5);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 6);
+HSMP_DIMM_RO(dtr_86, dimm_0x86, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x86, 7);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 0);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 1);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 2);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 3);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 4);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 5);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 6);
+HSMP_DIMM_RO(dtr_87, dimm_0x87, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x87, 7);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 0);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 1);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 2);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 3);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 4);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 5);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 6);
+HSMP_DIMM_RO(dtr_88, dimm_0x88, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x88, 7);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 0);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 1);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 2);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 3);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 4);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 5);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 6);
+HSMP_DIMM_RO(dtr_89, dimm_0x89, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x89, 7);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 0);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 1);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 2);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 3);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 4);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 5);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 6);
+HSMP_DIMM_RO(dtr_8a, dimm_0x8a, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8a, 7);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 0);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 1);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 2);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 3);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 4);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 5);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 6);
+HSMP_DIMM_RO(dtr_8b, dimm_0x8b, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8b, 7);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 0);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 1);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 2);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 3);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 4);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 5);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 6);
+HSMP_DIMM_RO(dtr_8c, dimm_0x8c, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8c, 7);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 0);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 1);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 2);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 3);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 4);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 5);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 6);
+HSMP_DIMM_RO(dtr_8d, dimm_0x8d, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8d, 7);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 0);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 1);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 2);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 3);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 4);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 5);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 6);
+HSMP_DIMM_RO(dtr_8e, dimm_0x8e, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8e, 7);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 0);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 1);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 2);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 3);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 4);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 5);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 6);
+HSMP_DIMM_RO(dtr_8f, dimm_0x8f, hsmp_dimm_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0x8f, 7);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 0);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 1);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 2);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 3);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 4);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 5);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 6);
+HSMP_DIMM_RO(dtr_max, dimm_max_temperature_range,
+	     hsmp_dimm_max_temp_range_show, HSMP_GET_DIMM_TEMP_RANGE, 0, 7);
+
+#undef HSMP_DIMM_RO
 HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
@@ -1201,6 +2145,263 @@ static const struct attribute_group *hsmp_sock_xgmibw_grps[] = {
 	&sock7_xgmibw_grp,
 };
 
+#define HSMP_DIMM_PWR_LIST(_s)						\
+static struct attribute *sock##_s##_dpwr_attrs[] = {		\
+	&hattr_dpwr_80_##_s.dattr.attr,				\
+	&hattr_dpwr_81_##_s.dattr.attr,				\
+	&hattr_dpwr_82_##_s.dattr.attr,				\
+	&hattr_dpwr_83_##_s.dattr.attr,				\
+	&hattr_dpwr_84_##_s.dattr.attr,				\
+	&hattr_dpwr_85_##_s.dattr.attr,				\
+	&hattr_dpwr_86_##_s.dattr.attr,				\
+	&hattr_dpwr_87_##_s.dattr.attr,				\
+	&hattr_dpwr_88_##_s.dattr.attr,				\
+	&hattr_dpwr_89_##_s.dattr.attr,				\
+	&hattr_dpwr_8a_##_s.dattr.attr,				\
+	&hattr_dpwr_8b_##_s.dattr.attr,				\
+	&hattr_dpwr_8c_##_s.dattr.attr,				\
+	&hattr_dpwr_8d_##_s.dattr.attr,				\
+	&hattr_dpwr_8e_##_s.dattr.attr,				\
+	&hattr_dpwr_8f_##_s.dattr.attr,				\
+	&hattr_dpwr_90_##_s.dattr.attr,				\
+	&hattr_dpwr_91_##_s.dattr.attr,				\
+	&hattr_dpwr_92_##_s.dattr.attr,				\
+	&hattr_dpwr_93_##_s.dattr.attr,				\
+	&hattr_dpwr_94_##_s.dattr.attr,				\
+	&hattr_dpwr_95_##_s.dattr.attr,				\
+	&hattr_dpwr_96_##_s.dattr.attr,				\
+	&hattr_dpwr_97_##_s.dattr.attr,				\
+	&hattr_dpwr_98_##_s.dattr.attr,				\
+	&hattr_dpwr_99_##_s.dattr.attr,				\
+	&hattr_dpwr_9a_##_s.dattr.attr,				\
+	&hattr_dpwr_9b_##_s.dattr.attr,				\
+	&hattr_dpwr_9c_##_s.dattr.attr,				\
+	&hattr_dpwr_9d_##_s.dattr.attr,				\
+	&hattr_dpwr_9e_##_s.dattr.attr,				\
+	&hattr_dpwr_9f_##_s.dattr.attr,				\
+	&hattr_dpwr_total_##_s.dattr.attr,				\
+	&hattr_dpwr_max_##_s.dattr.attr,				\
+	NULL							\
+}
+
+#define HSMP_DIMM_TEMP_LIST(_s)						\
+static struct attribute *sock##_s##_dtemp_attrs[] = {		\
+	&hattr_dt_80_##_s.dattr.attr,				\
+	&hattr_dt_81_##_s.dattr.attr,				\
+	&hattr_dt_82_##_s.dattr.attr,				\
+	&hattr_dt_83_##_s.dattr.attr,				\
+	&hattr_dt_84_##_s.dattr.attr,				\
+	&hattr_dt_85_##_s.dattr.attr,				\
+	&hattr_dt_86_##_s.dattr.attr,				\
+	&hattr_dt_87_##_s.dattr.attr,				\
+	&hattr_dt_88_##_s.dattr.attr,				\
+	&hattr_dt_89_##_s.dattr.attr,				\
+	&hattr_dt_8a_##_s.dattr.attr,				\
+	&hattr_dt_8b_##_s.dattr.attr,				\
+	&hattr_dt_8c_##_s.dattr.attr,				\
+	&hattr_dt_8d_##_s.dattr.attr,				\
+	&hattr_dt_8e_##_s.dattr.attr,				\
+	&hattr_dt_8f_##_s.dattr.attr,				\
+	&hattr_dt_c0_##_s.dattr.attr,				\
+	&hattr_dt_c1_##_s.dattr.attr,				\
+	&hattr_dt_c2_##_s.dattr.attr,				\
+	&hattr_dt_c3_##_s.dattr.attr,				\
+	&hattr_dt_c4_##_s.dattr.attr,				\
+	&hattr_dt_c5_##_s.dattr.attr,				\
+	&hattr_dt_c6_##_s.dattr.attr,				\
+	&hattr_dt_c7_##_s.dattr.attr,				\
+	&hattr_dt_c8_##_s.dattr.attr,				\
+	&hattr_dt_c9_##_s.dattr.attr,				\
+	&hattr_dt_ca_##_s.dattr.attr,				\
+	&hattr_dt_cb_##_s.dattr.attr,				\
+	&hattr_dt_cc_##_s.dattr.attr,				\
+	&hattr_dt_cd_##_s.dattr.attr,				\
+	&hattr_dt_ce_##_s.dattr.attr,				\
+	&hattr_dt_cf_##_s.dattr.attr,				\
+	&hattr_dt_90_##_s.dattr.attr,				\
+	&hattr_dt_91_##_s.dattr.attr,				\
+	&hattr_dt_92_##_s.dattr.attr,				\
+	&hattr_dt_93_##_s.dattr.attr,				\
+	&hattr_dt_94_##_s.dattr.attr,				\
+	&hattr_dt_95_##_s.dattr.attr,				\
+	&hattr_dt_96_##_s.dattr.attr,				\
+	&hattr_dt_97_##_s.dattr.attr,				\
+	&hattr_dt_98_##_s.dattr.attr,				\
+	&hattr_dt_99_##_s.dattr.attr,				\
+	&hattr_dt_9a_##_s.dattr.attr,				\
+	&hattr_dt_9b_##_s.dattr.attr,				\
+	&hattr_dt_9c_##_s.dattr.attr,				\
+	&hattr_dt_9d_##_s.dattr.attr,				\
+	&hattr_dt_9e_##_s.dattr.attr,				\
+	&hattr_dt_9f_##_s.dattr.attr,				\
+	&hattr_dt_d0_##_s.dattr.attr,				\
+	&hattr_dt_d1_##_s.dattr.attr,				\
+	&hattr_dt_d2_##_s.dattr.attr,				\
+	&hattr_dt_d3_##_s.dattr.attr,				\
+	&hattr_dt_d4_##_s.dattr.attr,				\
+	&hattr_dt_d5_##_s.dattr.attr,				\
+	&hattr_dt_d6_##_s.dattr.attr,				\
+	&hattr_dt_d7_##_s.dattr.attr,				\
+	&hattr_dt_d8_##_s.dattr.attr,				\
+	&hattr_dt_d9_##_s.dattr.attr,				\
+	&hattr_dt_da_##_s.dattr.attr,				\
+	&hattr_dt_db_##_s.dattr.attr,				\
+	&hattr_dt_dc_##_s.dattr.attr,				\
+	&hattr_dt_dd_##_s.dattr.attr,				\
+	&hattr_dt_de_##_s.dattr.attr,				\
+	&hattr_dt_df_##_s.dattr.attr,				\
+	&hattr_dt_max_##_s.dattr.attr,				\
+	NULL							\
+}
+
+#define HSMP_DIMM_RANGE_LIST(_s)						\
+static struct attribute *sock##_s##_drange_attrs[] = {		\
+	&hattr_dtr_80_##_s.dattr.attr,				\
+	&hattr_dtr_81_##_s.dattr.attr,				\
+	&hattr_dtr_82_##_s.dattr.attr,				\
+	&hattr_dtr_83_##_s.dattr.attr,				\
+	&hattr_dtr_84_##_s.dattr.attr,				\
+	&hattr_dtr_85_##_s.dattr.attr,				\
+	&hattr_dtr_86_##_s.dattr.attr,				\
+	&hattr_dtr_87_##_s.dattr.attr,				\
+	&hattr_dtr_88_##_s.dattr.attr,				\
+	&hattr_dtr_89_##_s.dattr.attr,				\
+	&hattr_dtr_8a_##_s.dattr.attr,				\
+	&hattr_dtr_8b_##_s.dattr.attr,				\
+	&hattr_dtr_8c_##_s.dattr.attr,				\
+	&hattr_dtr_8d_##_s.dattr.attr,				\
+	&hattr_dtr_8e_##_s.dattr.attr,				\
+	&hattr_dtr_8f_##_s.dattr.attr,				\
+	&hattr_dtr_max_##_s.dattr.attr,				\
+	NULL							\
+}
+
+HSMP_DIMM_PWR_LIST(0);
+HSMP_DIMM_PWR_LIST(1);
+HSMP_DIMM_PWR_LIST(2);
+HSMP_DIMM_PWR_LIST(3);
+HSMP_DIMM_PWR_LIST(4);
+HSMP_DIMM_PWR_LIST(5);
+HSMP_DIMM_PWR_LIST(6);
+HSMP_DIMM_PWR_LIST(7);
+
+HSMP_DIMM_TEMP_LIST(0);
+HSMP_DIMM_TEMP_LIST(1);
+HSMP_DIMM_TEMP_LIST(2);
+HSMP_DIMM_TEMP_LIST(3);
+HSMP_DIMM_TEMP_LIST(4);
+HSMP_DIMM_TEMP_LIST(5);
+HSMP_DIMM_TEMP_LIST(6);
+HSMP_DIMM_TEMP_LIST(7);
+
+HSMP_DIMM_RANGE_LIST(0);
+HSMP_DIMM_RANGE_LIST(1);
+HSMP_DIMM_RANGE_LIST(2);
+HSMP_DIMM_RANGE_LIST(3);
+HSMP_DIMM_RANGE_LIST(4);
+HSMP_DIMM_RANGE_LIST(5);
+HSMP_DIMM_RANGE_LIST(6);
+HSMP_DIMM_RANGE_LIST(7);
+
+#undef HSMP_DIMM_PWR_LIST
+#undef HSMP_DIMM_TEMP_LIST
+#undef HSMP_DIMM_RANGE_LIST
+
+static umode_t hsmp_plat_dimm_visible(struct attribute *attr, int id,
+				      umode_t (*file_visible)(const struct hsmp_socket *sock,
+							      int id))
+{
+	struct device_attribute *dattr;
+	struct hsmp_sys_attr *hattr;
+	struct hsmp_socket *sock = NULL;
+
+	dattr = container_of(attr, struct device_attribute, attr);
+	hattr = to_hsmp_sys_attr(dattr);
+	if (hsmp_pdev && hattr->sock_ind < hsmp_pdev->num_sockets)
+		sock = &hsmp_pdev->sock[hattr->sock_ind];
+
+	return file_visible(sock, id);
+}
+
+static umode_t hsmp_plat_dimm_power_is_visible(struct kobject *kobj __always_unused,
+					       struct attribute *attr, int id)
+{
+	return hsmp_plat_dimm_visible(attr, id, hsmp_dimm_power_file_visible);
+}
+
+static umode_t hsmp_plat_dimm_temp_is_visible(struct kobject *kobj __always_unused,
+					      struct attribute *attr, int id)
+{
+	return hsmp_plat_dimm_visible(attr, id, hsmp_dimm_temp_file_visible);
+}
+
+static umode_t
+hsmp_plat_dimm_temp_range_is_visible(struct kobject *kobj __always_unused,
+				     struct attribute *attr, int id)
+{
+	return hsmp_plat_dimm_visible(attr, id, hsmp_dimm_temp_range_file_visible);
+}
+
+#define HSMP_DIMM_GRP(_idx)						\
+static const struct attribute_group sock##_idx##_dpwr_grp = {	\
+	.name = "dimm_power",					\
+	.attrs = sock##_idx##_dpwr_attrs,			\
+	.is_visible = hsmp_plat_dimm_power_is_visible,		\
+};								\
+static const struct attribute_group sock##_idx##_dtemp_grp = {\
+	.name = "dimm_temperature",				\
+	.attrs = sock##_idx##_dtemp_attrs,			\
+	.is_visible = hsmp_plat_dimm_temp_is_visible,	\
+};								\
+static const struct attribute_group sock##_idx##_drange_grp = {\
+	.name = "dimm_temperature_range",			\
+	.attrs = sock##_idx##_drange_attrs,			\
+	.is_visible = hsmp_plat_dimm_temp_range_is_visible,\
+}
+
+HSMP_DIMM_GRP(0);
+HSMP_DIMM_GRP(1);
+HSMP_DIMM_GRP(2);
+HSMP_DIMM_GRP(3);
+HSMP_DIMM_GRP(4);
+HSMP_DIMM_GRP(5);
+HSMP_DIMM_GRP(6);
+HSMP_DIMM_GRP(7);
+
+#undef HSMP_DIMM_GRP
+
+static const struct attribute_group *hsmp_sock_dpwr_grps[] = {
+	&sock0_dpwr_grp,
+	&sock1_dpwr_grp,
+	&sock2_dpwr_grp,
+	&sock3_dpwr_grp,
+	&sock4_dpwr_grp,
+	&sock5_dpwr_grp,
+	&sock6_dpwr_grp,
+	&sock7_dpwr_grp,
+};
+
+static const struct attribute_group *hsmp_sock_dtemp_grps[] = {
+	&sock0_dtemp_grp,
+	&sock1_dtemp_grp,
+	&sock2_dtemp_grp,
+	&sock3_dtemp_grp,
+	&sock4_dtemp_grp,
+	&sock5_dtemp_grp,
+	&sock6_dtemp_grp,
+	&sock7_dtemp_grp,
+};
+
+static const struct attribute_group *hsmp_sock_drange_grps[] = {
+	&sock0_drange_grp,
+	&sock1_drange_grp,
+	&sock2_drange_grp,
+	&sock3_drange_grp,
+	&sock4_drange_grp,
+	&sock5_drange_grp,
+	&sock6_drange_grp,
+	&sock7_drange_grp,
+};
 static inline bool is_f1a_m0h(void)
 {
 	if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F)
@@ -1261,6 +2462,7 @@ static int init_platform_device(struct device *dev)
 				return ret;
 			}
 
+			hsmp_scan_dimms(sock);
 			hsmp_scan_io_bw(sock);
 			hsmp_scan_xgmi_bw(sock);
 		}
@@ -1341,6 +2543,9 @@ static void hsmp_remove_plat_sock_kobjs(void)
 		if (!hsmp_plat_sock_kobj[i])
 			continue;
 
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_drange_grps[i]);
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_dtemp_grps[i]);
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_dpwr_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_xgmibw_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_iobw_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_lclk_grps[i]);
@@ -1363,10 +2568,21 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 
 	/*
 	 * socketN is a kobject so it can hold the socket attributes and the
-	 * nested lclk_dpm_range, io_bw, and xgmi_bw directories. Attribute
-	 * groups add one directory level under that kobject.
+	 * nested lclk_dpm_range, io_bw, xgmi_bw, and DIMM directories.
+	 * Attribute groups add one directory level under that kobject.
 	 */
 	for (i = 0; i < hsmp_pdev->num_sockets; i++) {
+		const struct attribute_group *grps[] = {
+			hsmp_sock_attr_grps[i],
+			hsmp_sock_lclk_grps[i],
+			hsmp_sock_iobw_grps[i],
+			hsmp_sock_xgmibw_grps[i],
+			hsmp_sock_dpwr_grps[i],
+			hsmp_sock_dtemp_grps[i],
+			hsmp_sock_drange_grps[i],
+		};
+		unsigned int g, created = 0;
+
 		hsmp_plat_sock_kobj[i] = kobject_create_and_add(hsmp_plat_sock_names[i],
 								hsmp_sock_kobj);
 		if (!hsmp_plat_sock_kobj[i]) {
@@ -1376,52 +2592,18 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 			goto err;
 		}
 
-		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
-					 hsmp_sock_attr_grps[i]);
-		if (ret) {
-			dev_err(dev, "Failed to create %s attributes\n",
-				hsmp_plat_sock_names[i]);
-			kobject_put(hsmp_plat_sock_kobj[i]);
-			hsmp_plat_sock_kobj[i] = NULL;
-			goto err;
-		}
-
-		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
-					 hsmp_sock_lclk_grps[i]);
-		if (ret) {
-			dev_err(dev, "Failed to create %s lclk attributes\n",
-				hsmp_plat_sock_names[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_attr_grps[i]);
-			kobject_put(hsmp_plat_sock_kobj[i]);
-			hsmp_plat_sock_kobj[i] = NULL;
-			goto err;
-		}
-
-		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
-					 hsmp_sock_iobw_grps[i]);
-		if (ret) {
-			dev_err(dev, "Failed to create %s io_bw attributes\n",
-				hsmp_plat_sock_names[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_lclk_grps[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_attr_grps[i]);
-			kobject_put(hsmp_plat_sock_kobj[i]);
-			hsmp_plat_sock_kobj[i] = NULL;
-			goto err;
+		for (g = 0; g < ARRAY_SIZE(grps); g++) {
+			ret = sysfs_create_group(hsmp_plat_sock_kobj[i], grps[g]);
+			if (ret)
+				break;
+			created++;
 		}
-		ret = sysfs_create_group(hsmp_plat_sock_kobj[i],
-					 hsmp_sock_xgmibw_grps[i]);
 		if (ret) {
-			dev_err(dev, "Failed to create %s xgmi_bw attributes\n",
+			dev_err(dev, "Failed to create %s attributes\n",
 				hsmp_plat_sock_names[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_iobw_grps[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_lclk_grps[i]);
-			sysfs_remove_group(hsmp_plat_sock_kobj[i],
-					   hsmp_sock_attr_grps[i]);
+			while (created--)
+				sysfs_remove_group(hsmp_plat_sock_kobj[i],
+						   grps[created]);
 			kobject_put(hsmp_plat_sock_kobj[i]);
 			hsmp_plat_sock_kobj[i] = NULL;
 			goto err;
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 62d5b6c90ea47..5a2e79a574022 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -1313,6 +1313,362 @@ ssize_t hsmp_dimm_sb_set_store(struct device *dev, struct device_attribute *attr
 	return count;
 }
 
+static struct hsmp_socket *hsmp_sysfs_socket(struct device *dev,
+					     const struct hsmp_sys_attr *hattr)
+{
+	struct hsmp_plat_device *pdev = get_hsmp_pdev();
+	u16 sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+
+	if (!pdev || sock_ind >= pdev->num_sockets)
+		return NULL;
+
+	return &pdev->sock[sock_ind];
+}
+
+static int hsmp_dimm_query(u16 sock_ind, u32 msg_id, u32 arg, u32 *out)
+{
+	struct hsmp_message msg = {};
+	int ret;
+
+	msg.msg_id = msg_id;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = arg;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	*out = msg.args[0];
+	return 0;
+}
+
+static u32 hsmp_dimm_addr_from_bit(u32 bit)
+{
+	if (bit < 16)
+		return 0x80 + bit;
+
+	return 0x90 + (bit - 16);
+}
+
+static void hsmp_dimm_temp_addrs(u32 bit, u32 addr[2])
+{
+	if (bit < 16) {
+		addr[0] = 0x80 + bit;
+		addr[1] = 0xc0 + bit;
+		return;
+	}
+
+	addr[0] = 0x90 + (bit - 16);
+	addr[1] = 0xd0 + (bit - 16);
+}
+
+ssize_t hsmp_dimm_power_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 raw, power, update_rate;
+	int ret;
+
+	if (!sock)
+		return -ENODEV;
+
+	ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_POWER, hattr->priv,
+			      &raw);
+	if (ret)
+		return ret;
+
+	power = (raw >> 17) & 0x7fff;
+	update_rate = (raw >> 8) & 0x1ff;
+
+	return sysfs_emit(buf, "%u %u\n", power, update_rate);
+}
+
+ssize_t hsmp_dimm_total_power_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 total_mw = 0, last_update = 0;
+	u32 valid, bit;
+
+	if (!sock)
+		return -ENODEV;
+
+	valid = sock->dimm_power_valid;
+	if (!valid)
+		return -ENODATA;
+
+	for (bit = 0; bit < 32; bit++) {
+		u32 raw;
+		int ret;
+
+		if (!(valid & BIT(bit)))
+			continue;
+
+		ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_POWER,
+				      hsmp_dimm_addr_from_bit(bit), &raw);
+		if (ret)
+			continue;
+
+		total_mw += (raw >> 17) & 0x7fff;
+		last_update = (raw >> 8) & 0x1ff;
+	}
+
+	return sysfs_emit(buf, "%u %u\n", total_mw, last_update);
+}
+
+ssize_t hsmp_dimm_max_power_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 raw, power, update_rate, addr;
+	int ret;
+
+	if (!sock)
+		return -ENODEV;
+
+	ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_POWER, BIT(30),
+			      &raw);
+	if (ret)
+		return ret;
+
+	power = (raw >> 17) & 0x7fff;
+	update_rate = (raw >> 8) & 0x1ff;
+	addr = raw & 0xff;
+
+	return sysfs_emit(buf, "%u %u 0x%02X\n", power, update_rate, addr);
+}
+
+#define HSMP_PROTO_VER_7_2		0x00070002U
+
+/* Indices into dimm_sensor_type_str[], also used as address-bit-6 fallback. */
+#define DIMM_SENSOR_TS0		0
+#define DIMM_SENSOR_TS1		1
+#define DIMM_SENSOR_SPDHUB	2
+
+static const char * const dimm_sensor_type_str[] = {
+	"TS0", "TS1", "SPDHub", "Reserved",
+};
+
+static s32 hsmp_dimm_temp_milli(u32 raw)
+{
+	u16 temp_raw = (raw >> 21) & 0x7ff;
+
+	if (temp_raw <= 0x3ff)
+		return (s32)temp_raw * 250;
+
+	return ((s32)temp_raw - 0x800) * 250;
+}
+
+/*
+ * Sensor type (TS0/TS1/SPDHub) is only valid on HSMP protocol >= 7.2.
+ * Older protocols omit it; sensor_fallback supplies TS0/TS1 from address
+ * bit 6 for per-DIMM reads, or SPDHub for the socket-wide max.
+ */
+static ssize_t hsmp_emit_dimm_temp(char *buf, u32 raw, u32 proto, bool with_addr,
+				   u32 sensor_fallback)
+{
+	u32 update_rate = (raw >> 8) & 0x1ff;
+	u32 sensor_type;
+	u32 addr = raw & 0xff;
+	s32 milli = hsmp_dimm_temp_milli(raw);
+	bool neg = milli < 0;
+	u32 abs_milli = neg ? (u32)(-milli) : (u32)milli;
+	u32 whole = abs_milli / 1000;
+	u32 frac = abs_milli % 1000;
+
+	if (proto >= HSMP_PROTO_VER_7_2)
+		sensor_type = (raw >> 17) & 0x3;
+	else
+		sensor_type = sensor_fallback;
+
+	if (with_addr && neg)
+		return sysfs_emit(buf, "-%u.%03u %u %s 0x%02X\n",
+				  whole, frac, update_rate,
+				  dimm_sensor_type_str[sensor_type], addr);
+	if (with_addr)
+		return sysfs_emit(buf, "%u.%03u %u %s 0x%02X\n",
+				  whole, frac, update_rate,
+				  dimm_sensor_type_str[sensor_type], addr);
+	if (neg)
+		return sysfs_emit(buf, "-%u.%03u %u %s\n", whole, frac,
+				  update_rate, dimm_sensor_type_str[sensor_type]);
+
+	return sysfs_emit(buf, "%u.%03u %u %s\n", whole, frac, update_rate,
+			  dimm_sensor_type_str[sensor_type]);
+}
+
+ssize_t hsmp_dimm_temp_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 addr = hattr->priv;
+	u32 raw;
+	int ret;
+
+	if (!sock)
+		return -ENODEV;
+
+	ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_THERMAL, addr,
+			      &raw);
+	if (ret)
+		return ret;
+
+	/* 0x80/0x90 = TS0, 0xC0/0xD0 = TS1 when protocol omits sensor type. */
+	return hsmp_emit_dimm_temp(buf, raw, sock->proto_ver, false,
+				   (addr & BIT(6)) ? DIMM_SENSOR_TS1 :
+						     DIMM_SENSOR_TS0);
+}
+
+ssize_t hsmp_dimm_max_temp_show(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	s32 max_milli = -257000;
+	u32 max_raw = 0;
+	u32 valid, bit;
+
+	if (!sock)
+		return -ENODEV;
+
+	valid = sock->dimm_temp_valid;
+	if (!valid)
+		return -ENODATA;
+
+	for (bit = 0; bit < 32; bit++) {
+		u32 addr[2];
+		int i;
+
+		if (!(valid & BIT(bit)))
+			continue;
+
+		hsmp_dimm_temp_addrs(bit, addr);
+		for (i = 0; i < 2; i++) {
+			s32 milli;
+			u32 raw;
+			int ret;
+
+			ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_THERMAL,
+					      addr[i], &raw);
+			if (ret)
+				continue;
+
+			milli = hsmp_dimm_temp_milli(raw);
+			if (milli > max_milli) {
+				max_milli = milli;
+				max_raw = raw;
+			}
+		}
+	}
+
+	if (max_milli == -257000)
+		return -ENODATA;
+
+	/* Aggregate max cannot derive TS0/TS1 reliably on older protocols. */
+	return hsmp_emit_dimm_temp(buf, max_raw, sock->proto_ver, true,
+				   DIMM_SENSOR_SPDHUB);
+}
+
+ssize_t hsmp_dimm_temp_range_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 raw, temp_range;
+	int ret;
+
+	if (!sock)
+		return -ENODEV;
+
+	ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_TEMP_RANGE,
+			      hattr->priv, &raw);
+	if (ret)
+		return ret;
+
+	temp_range = raw & 0x7;
+
+	return sysfs_emit(buf, "%u %s\n", temp_range,
+			   (raw & BIT(3)) ? "2x" : "1x");
+}
+
+ssize_t hsmp_dimm_max_temp_range_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_socket *sock = hsmp_sysfs_socket(dev, hattr);
+	u32 raw, temp_range, addr;
+	int ret;
+
+	if (!sock)
+		return -ENODEV;
+
+	if (!sock->dimm_temp_range_valid)
+		return -ENODATA;
+
+	ret = hsmp_dimm_query(sock->sock_ind, HSMP_GET_DIMM_TEMP_RANGE, BIT(31),
+			      &raw);
+	if (ret)
+		return ret;
+
+	temp_range = raw & 0x7;
+	addr = (raw >> 24) & 0xff;
+
+	return sysfs_emit(buf, "%u %s 0x%02X\n", temp_range,
+			   (raw & BIT(3)) ? "2x" : "1x", addr);
+}
+
+static bool hsmp_dimm_group_hidden(const struct hsmp_socket *sock, u32 msg_id)
+{
+	return !sock || is_client_platform() ||
+	       !is_read_msg_enabled(sock, msg_id);
+}
+
+umode_t hsmp_dimm_power_file_visible(const struct hsmp_socket *sock, int id)
+{
+	if (hsmp_dimm_group_hidden(sock, HSMP_GET_DIMM_POWER))
+		return id ? 0 : SYSFS_GROUP_INVISIBLE;
+
+	if (id >= 32)
+		return 0444;
+
+	return (sock->dimm_power_valid & BIT(id)) ? 0444 : 0;
+}
+
+static int hsmp_dimm_temp_bit(int id)
+{
+	return (id & 0xf) + (id >= 32 ? 16 : 0);
+}
+
+umode_t hsmp_dimm_temp_file_visible(const struct hsmp_socket *sock, int id)
+{
+	if (hsmp_dimm_group_hidden(sock, HSMP_GET_DIMM_THERMAL))
+		return id ? 0 : SYSFS_GROUP_INVISIBLE;
+
+	if (id >= 64)
+		return 0444;
+
+	return (sock->dimm_temp_valid & BIT(hsmp_dimm_temp_bit(id))) ? 0444 : 0;
+}
+
+umode_t hsmp_dimm_temp_range_file_visible(const struct hsmp_socket *sock, int id)
+{
+	if (!sock || !sock->dimm_temp_range_valid ||
+	    hsmp_dimm_group_hidden(sock, HSMP_GET_DIMM_TEMP_RANGE))
+		return id ? 0 : SYSFS_GROUP_INVISIBLE;
+
+	/* id 0..15 = 8x (UMC channel); id >= 16 = max. */
+	if (id >= 16)
+		return 0444;
+
+	return (sock->dimm_temp_range_valid & BIT(id)) ? 0444 : 0;
+}
+
 static ssize_t hsmp_lclk_nbio_show(struct device *dev,
 				   struct device_attribute *attr,
 				   u8 nbio_id, char *buf)
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 2b14c4135212d..f620a58683904 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -168,6 +168,23 @@ ssize_t hsmp_dimm_sb_get_store(struct device *dev, struct device_attribute *attr
 			       const char *buf, size_t count);
 ssize_t hsmp_dimm_sb_set_store(struct device *dev, struct device_attribute *attr,
 			       const char *buf, size_t count);
+ssize_t hsmp_dimm_power_show(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+ssize_t hsmp_dimm_total_power_show(struct device *dev,
+				   struct device_attribute *attr, char *buf);
+ssize_t hsmp_dimm_max_power_show(struct device *dev,
+				 struct device_attribute *attr, char *buf);
+ssize_t hsmp_dimm_temp_show(struct device *dev, struct device_attribute *attr,
+			    char *buf);
+ssize_t hsmp_dimm_max_temp_show(struct device *dev, struct device_attribute *attr,
+				char *buf);
+ssize_t hsmp_dimm_temp_range_show(struct device *dev,
+				  struct device_attribute *attr, char *buf);
+ssize_t hsmp_dimm_max_temp_range_show(struct device *dev,
+				      struct device_attribute *attr, char *buf);
+umode_t hsmp_dimm_power_file_visible(const struct hsmp_socket *sock, int id);
+umode_t hsmp_dimm_temp_file_visible(const struct hsmp_socket *sock, int id);
+umode_t hsmp_dimm_temp_range_file_visible(const struct hsmp_socket *sock, int id);
 
 /*
  * True when the attribute store issues a GET, or only records state for
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 18/26] platform/x86/amd/hsmp: Add SVI3 temperature sysfs files
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (16 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 17/26] platform/x86/amd/hsmp: Add DIMM power and temperature " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 19/26] platform/x86/amd/hsmp: Add cclk_floor_limit sysfs file Muthusamy Ramalingam
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose a read-only svi3_temperature directory on both drivers. The
per-rail files report HSMP_GET_SVI3_VR_CTRL_TEMP. svi3_max_temperature
prints "<degrees> <rail_name>" for the hottest rail. Hide the directory
when that message is not enabled.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   4 +
 drivers/platform/x86/amd/hsmp/acpi.c  |  47 ++++++++++++
 drivers/platform/x86/amd/hsmp/plat.c  | 103 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.c |  75 +++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |   4 +
 5 files changed, 233 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 1a2fd95e21ac1..093468aa52eb2 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -182,6 +182,10 @@ write-only when the platform enables only that direction of the message.
   "<range> <1x|2x>". The directory is absent when no channel responds.
   dimm_max_temperature_range returns "<range> <1x|2x> 0xAA" for the
   hottest channel, or fails with -ENODATA when none respond.
+* svi3_temperature/: Read-only SVI3 regulator temperature in degrees
+  Celsius. vddcr_cpu0, vddcr_cpu1, vddcr_soc, vddio_mem_s3, and vddio
+  each return one rail. svi3_max_temperature returns "<degrees> <rail_name>"
+  for the hottest rail.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 2028c1e8fc1c3..935cca42b642b 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -650,6 +650,20 @@ HSMP_XGMI_WR(g7, 39);
 #undef HSMP_XGMI_AGG
 #undef HSMP_XGMI_RD
 #undef HSMP_XGMI_WR
+#define HSMP_SVI3_ATTR(_name, _rail)					\
+	HSMP_SYS_ATTR_PRIV(_name, _name, hsmp_svi3_temp_show, U16_MAX,	\
+			   HSMP_GET_SVI3_VR_CTRL_TEMP, _rail)
+
+HSMP_SVI3_ATTR(vddcr_cpu0, 0);
+HSMP_SVI3_ATTR(vddcr_cpu1, 1);
+HSMP_SVI3_ATTR(vddcr_soc, 2);
+HSMP_SVI3_ATTR(vddio, 3);
+HSMP_SVI3_ATTR(vddio_mem_s3, 4);
+#undef HSMP_SVI3_ATTR
+
+HSMP_SYS_ATTR(svi3_max_temperature, svi3_max_temperature, 0444,
+	      hsmp_svi3_max_temp_show, NULL, U16_MAX,
+	      HSMP_GET_SVI3_VR_CTRL_TEMP, HSMP_GET_SVI3_VR_CTRL_TEMP);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
@@ -835,6 +849,16 @@ static struct attribute *lclk_attrs[] = {
 	NULL
 };
 
+static struct attribute *svi3_temp_attrs[] = {
+	&hattr_vddcr_cpu0.dattr.attr,
+	&hattr_vddcr_cpu1.dattr.attr,
+	&hattr_vddcr_soc.dattr.attr,
+	&hattr_vddio.dattr.attr,
+	&hattr_vddio_mem_s3.dattr.attr,
+	&hattr_svi3_max_temperature.dattr.attr,
+	NULL
+};
+
 static umode_t hsmp_lclk_is_visible(struct kobject *kobj,
 				    struct attribute *attr, int id)
 {
@@ -952,6 +976,28 @@ static const struct attribute_group xgmi_bw_group = {
 	.is_visible = hsmp_xgmi_bw_is_visible,
 };
 
+static umode_t hsmp_svi3_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int id)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct hsmp_socket *sock;
+
+	if (is_client_platform())
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	sock = dev_get_drvdata(dev);
+	if (!sock || !is_read_msg_enabled(sock, HSMP_GET_SVI3_VR_CTRL_TEMP))
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	return attr->mode;
+}
+
+static const struct attribute_group svi3_temperature_group = {
+	.name = "svi3_temperature",
+	.attrs = svi3_temp_attrs,
+	.is_visible = hsmp_svi3_is_visible,
+};
+
 static struct attribute *dimm_power_attrs[] = {
 	&hattr_dpwr_80.dattr.attr,
 	&hattr_dpwr_81.dattr.attr,
@@ -1132,6 +1178,7 @@ static const struct attribute_group *hsmp_groups[] = {
 	&lclk_group,
 	&io_bw_group,
 	&xgmi_bw_group,
+	&svi3_temperature_group,
 	&dimm_power_group,
 	&dimm_temperature_group,
 	&dimm_temperature_range_group,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 809dd2cbb9948..2c6d460c56d3a 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -878,6 +878,43 @@ HSMP_XGMI_WR(g7, 39, 7);
 #undef HSMP_XGMI_AGG
 #undef HSMP_XGMI_RD
 #undef HSMP_XGMI_WR
+#define HSMP_SVI3_ATTR(_name, _rail, _sock)				\
+	HSMP_SYS_ATTR_PRIV(_name##_sock, _name, hsmp_svi3_temp_show,	\
+			   _sock, HSMP_GET_SVI3_VR_CTRL_TEMP, _rail)
+
+#define HSMP_SVI3_X8(_name, _rail)					\
+	HSMP_SVI3_ATTR(_name, _rail, 0);				\
+	HSMP_SVI3_ATTR(_name, _rail, 1);				\
+	HSMP_SVI3_ATTR(_name, _rail, 2);				\
+	HSMP_SVI3_ATTR(_name, _rail, 3);				\
+	HSMP_SVI3_ATTR(_name, _rail, 4);				\
+	HSMP_SVI3_ATTR(_name, _rail, 5);				\
+	HSMP_SVI3_ATTR(_name, _rail, 6);				\
+	HSMP_SVI3_ATTR(_name, _rail, 7)
+
+HSMP_SVI3_X8(vddcr_cpu0, 0);
+HSMP_SVI3_X8(vddcr_cpu1, 1);
+HSMP_SVI3_X8(vddcr_soc, 2);
+HSMP_SVI3_X8(vddio, 3);
+HSMP_SVI3_X8(vddio_mem_s3, 4);
+#undef HSMP_SVI3_ATTR
+#undef HSMP_SVI3_X8
+
+#define HSMP_SVI3_MAX(_sock)						\
+	HSMP_SYS_ATTR(svi3_max_temperature##_sock, svi3_max_temperature, \
+		      0444, hsmp_svi3_max_temp_show, NULL, _sock,	\
+		      HSMP_GET_SVI3_VR_CTRL_TEMP, HSMP_GET_SVI3_VR_CTRL_TEMP)
+
+HSMP_SVI3_MAX(0);
+HSMP_SVI3_MAX(1);
+HSMP_SVI3_MAX(2);
+HSMP_SVI3_MAX(3);
+HSMP_SVI3_MAX(4);
+HSMP_SVI3_MAX(5);
+HSMP_SVI3_MAX(6);
+HSMP_SVI3_MAX(7);
+#undef HSMP_SVI3_MAX
+
 #define HSMP_DIMM_RO(_var, _name, _show, _msg, _priv, _sock)		\
 	HSMP_SYS_ATTR_PRIV(_var##_##_sock, _name, _show, _sock, _msg, _priv)
 
@@ -1922,6 +1959,26 @@ HSMP_LCLK_ATTR_LIST(5);
 HSMP_LCLK_ATTR_LIST(6);
 HSMP_LCLK_ATTR_LIST(7);
 
+#define HSMP_SVI3_ATTR_LIST(_sock_ind)					\
+static struct attribute *sock##_sock_ind##_svi3_attrs[] = {		\
+	&hattr_vddcr_cpu0##_sock_ind.dattr.attr,			\
+	&hattr_vddcr_cpu1##_sock_ind.dattr.attr,			\
+	&hattr_vddcr_soc##_sock_ind.dattr.attr,				\
+	&hattr_vddio##_sock_ind.dattr.attr,				\
+	&hattr_vddio_mem_s3##_sock_ind.dattr.attr,			\
+	&hattr_svi3_max_temperature##_sock_ind.dattr.attr,		\
+	NULL								\
+}
+
+HSMP_SVI3_ATTR_LIST(0);
+HSMP_SVI3_ATTR_LIST(1);
+HSMP_SVI3_ATTR_LIST(2);
+HSMP_SVI3_ATTR_LIST(3);
+HSMP_SVI3_ATTR_LIST(4);
+HSMP_SVI3_ATTR_LIST(5);
+HSMP_SVI3_ATTR_LIST(6);
+HSMP_SVI3_ATTR_LIST(7);
+
 static umode_t hsmp_lclk_is_visible(struct kobject *kobj,
 				    struct attribute *attr, int id)
 {
@@ -1955,6 +2012,39 @@ HSMP_LCLK_GRP(5);
 HSMP_LCLK_GRP(6);
 HSMP_LCLK_GRP(7);
 
+static umode_t hsmp_svi3_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int id)
+{
+	struct device_attribute *dattr = container_of(attr, struct device_attribute, attr);
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(dattr);
+	struct hsmp_socket *sock;
+
+	if (hattr->sock_ind >= hsmp_pdev->num_sockets)
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	sock = &hsmp_pdev->sock[hattr->sock_ind];
+	if (!is_read_msg_enabled(sock, hattr->msg_id))
+		return id == 0 ? SYSFS_GROUP_INVISIBLE : 0;
+
+	return attr->mode;
+}
+
+#define HSMP_SVI3_GRP(index)						\
+static const struct attribute_group sock##index##_svi3_grp = {		\
+	.name = "svi3_temperature",					\
+	.attrs = sock##index##_svi3_attrs,				\
+	.is_visible = hsmp_svi3_is_visible,				\
+}
+
+HSMP_SVI3_GRP(0);
+HSMP_SVI3_GRP(1);
+HSMP_SVI3_GRP(2);
+HSMP_SVI3_GRP(3);
+HSMP_SVI3_GRP(4);
+HSMP_SVI3_GRP(5);
+HSMP_SVI3_GRP(6);
+HSMP_SVI3_GRP(7);
+
 static const struct attribute_group *hsmp_sock_attr_grps[] = {
 	&sock0_attr_grp,
 	&sock1_attr_grp,
@@ -2145,6 +2235,17 @@ static const struct attribute_group *hsmp_sock_xgmibw_grps[] = {
 	&sock7_xgmibw_grp,
 };
 
+static const struct attribute_group *hsmp_sock_svi3_grps[] = {
+	&sock0_svi3_grp,
+	&sock1_svi3_grp,
+	&sock2_svi3_grp,
+	&sock3_svi3_grp,
+	&sock4_svi3_grp,
+	&sock5_svi3_grp,
+	&sock6_svi3_grp,
+	&sock7_svi3_grp,
+};
+
 #define HSMP_DIMM_PWR_LIST(_s)						\
 static struct attribute *sock##_s##_dpwr_attrs[] = {		\
 	&hattr_dpwr_80_##_s.dattr.attr,				\
@@ -2546,6 +2647,7 @@ static void hsmp_remove_plat_sock_kobjs(void)
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_drange_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_dtemp_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_dpwr_grps[i]);
+		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_svi3_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_xgmibw_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_iobw_grps[i]);
 		sysfs_remove_group(hsmp_plat_sock_kobj[i], hsmp_sock_lclk_grps[i]);
@@ -2577,6 +2679,7 @@ static int hsmp_create_socket_sysfs(struct device *dev)
 			hsmp_sock_lclk_grps[i],
 			hsmp_sock_iobw_grps[i],
 			hsmp_sock_xgmibw_grps[i],
+			hsmp_sock_svi3_grps[i],
 			hsmp_sock_dpwr_grps[i],
 			hsmp_sock_dtemp_grps[i],
 			hsmp_sock_drange_grps[i],
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 5a2e79a574022..8fe67421ef6fc 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -1669,6 +1669,81 @@ umode_t hsmp_dimm_temp_range_file_visible(const struct hsmp_socket *sock, int id
 	return (sock->dimm_temp_range_valid & BIT(id)) ? 0444 : 0;
 }
 
+/* HSMP Table 183. Indices above this range are not named. */
+static const char * const svi3_rail_names[] = {
+	"vddcr_cpu0",
+	"vddcr_cpu1",
+	"vddcr_soc",
+	"vddio",
+	"vddio_mem_s3",
+};
+
+static int hsmp_svi3_query(struct device *dev, struct hsmp_sys_attr *hattr,
+			   u32 arg, u32 *raw)
+{
+	struct hsmp_message msg = {};
+	u16 sock_ind;
+	int ret;
+
+	sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	if (sock_ind == U16_MAX)
+		return -EINVAL;
+
+	/*
+	 * HSMP_GET_SVI3_VR_CTRL_TEMP:
+	 * input args[0] = rail index[3:1] + selection[0]
+	 *   selection 0 asks for the hottest rail, 1 selects the index
+	 * output args[0] = rail index[30:28] + temperature C[27:0]
+	 */
+	msg.msg_id = HSMP_GET_SVI3_VR_CTRL_TEMP;
+	msg.sock_ind = sock_ind;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = arg;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	*raw = msg.args[0];
+	return 0;
+}
+
+ssize_t hsmp_svi3_temp_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	u32 raw;
+	int ret;
+
+	/* selection[0] = 1 selects the rail in index[3:1] */
+	ret = hsmp_svi3_query(dev, hattr, BIT(0) | ((hattr->priv & 0x7) << 1),
+			      &raw);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", raw & 0x0fffffff);
+}
+
+ssize_t hsmp_svi3_max_temp_show(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	u32 raw, rail;
+	int ret;
+
+	ret = hsmp_svi3_query(dev, hattr, 0, &raw);
+	if (ret)
+		return ret;
+
+	rail = (raw >> 28) & 0x7;
+	if (rail >= ARRAY_SIZE(svi3_rail_names))
+		return -ERANGE;
+
+	return sysfs_emit(buf, "%u %s\n", raw & 0x0fffffff,
+			   svi3_rail_names[rail]);
+}
+
 static ssize_t hsmp_lclk_nbio_show(struct device *dev,
 				   struct device_attribute *attr,
 				   u8 nbio_id, char *buf)
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index f620a58683904..716d9e4493a1b 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -185,6 +185,10 @@ ssize_t hsmp_dimm_max_temp_range_show(struct device *dev,
 umode_t hsmp_dimm_power_file_visible(const struct hsmp_socket *sock, int id);
 umode_t hsmp_dimm_temp_file_visible(const struct hsmp_socket *sock, int id);
 umode_t hsmp_dimm_temp_range_file_visible(const struct hsmp_socket *sock, int id);
+ssize_t hsmp_svi3_temp_show(struct device *dev, struct device_attribute *attr,
+			    char *buf);
+ssize_t hsmp_svi3_max_temp_show(struct device *dev, struct device_attribute *attr,
+				char *buf);
 
 /*
  * True when the attribute store issues a GET, or only records state for
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 19/26] platform/x86/amd/hsmp: Add cclk_floor_limit sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (17 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 18/26] platform/x86/amd/hsmp: Add SVI3 " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 20/26] platform/x86/amd/hsmp: Add xgmi_pstate_range " Muthusamy Ramalingam
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SET_GET_FLOOR_LIMIT as a write-only socket file on both the
ACPI and platform drivers. A write uses operation 01 and sets the floor
for every core on the socket. The frequency is a 16-bit MHz field.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 ++
 drivers/platform/x86/amd/hsmp/plat.c  |  3 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 47 +++++++++++++++++++++++++--
 drivers/platform/x86/amd/hsmp/sysfs.h |  3 ++
 5 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 093468aa52eb2..30401c168c503 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -189,6 +189,8 @@ write-only when the platform enables only that direction of the message.
 * socket_power_limit_max: Maximum socket power limit in mWatts (read only).
 * cclk_boost_limit: Socket boost limit in MHz (write only). Accepted range
   is 100-10000 MHz.
+* cclk_floor_limit: Socket floor limit in MHz (write only). A write sets
+  the floor for every core on the socket. It is a 16-bit value.
 * tdelta: Socket thermal behaviour (read only).
 * apb_disable: Read/write. 1 disables APB, 0 enables it.
 * dfc_enable: Read/write DF C-state enable. 1 enables, 0 disables.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 935cca42b642b..35c2085b67e42 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -666,6 +666,8 @@ HSMP_SYS_ATTR(svi3_max_temperature, svi3_max_temperature, 0444,
 	      HSMP_GET_SVI3_VR_CTRL_TEMP, HSMP_GET_SVI3_VR_CTRL_TEMP);
 HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
+HSMP_DEV_ATTR_W(cclk_floor_limit, HSMP_SET_GET_FLOOR_LIMIT,
+		hsmp_cclk_floor_limit_store, 0200);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
 		 hsmp_apb_disable_show, hsmp_apb_disable_store, 0644);
 HSMP_DEV_ATTR_RW(dfc_enable, HSMP_DFC_ENABLE_CTRL, HSMP_DFC_ENABLE_CTRL,
@@ -832,6 +834,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_dimm_sb_set.dattr.attr,
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
+	&hattr_cclk_floor_limit.dattr.attr,
 	&hattr_tdelta.dattr.attr,
 	&hattr_apb_disable.dattr.attr,
 	&hattr_cc6_enable.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 2c6d460c56d3a..aedc71027b28c 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -1862,6 +1862,8 @@ HSMP_DEV_ATTR_X8(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show,
 		 0444);
 HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		   hsmp_cclk_boost_limit_store, 0200);
+HSMP_DEV_ATTR_W_X8(cclk_floor_limit, HSMP_SET_GET_FLOOR_LIMIT,
+		   hsmp_cclk_floor_limit_store, 0200);
 HSMP_DEV_ATTR_X8(tdelta, HSMP_READ_TDELTA, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW_X8(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
 		    hsmp_apb_disable_show, hsmp_apb_disable_store, 0644);
@@ -1906,6 +1908,7 @@ static struct attribute _name[] = {					       \
 	&hattr_dimm_sb_set##_sock_ind.dattr.attr,			       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
+	&hattr_cclk_floor_limit##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
 	&hattr_apb_disable##_sock_ind.dattr.attr,			       \
 	&hattr_cc6_enable##_sock_ind.dattr.attr,			       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 8fe67421ef6fc..8872f63e218df 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -560,6 +560,48 @@ ssize_t hsmp_cclk_boost_limit_store(struct device *dev,
 	return count;
 }
 
+ssize_t hsmp_cclk_floor_limit_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	unsigned long val;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret) {
+		hsmp_err(dev, "cclk_floor_limit", HSMP_ERR_PARSE, "unit=MHz");
+		return ret;
+	}
+
+	/*
+	 * Op 01 sets the floor for every core on the socket. The frequency
+	 * is a 16-bit MHz field. Firmware clamps it to the platform minimum
+	 * and maximum, so reject only a field overflow.
+	 */
+	if (val > U16_MAX) {
+		hsmp_err(dev, "cclk_floor_limit", HSMP_ERR_RANGE,
+			 "got=%lu valid=0-%u unit=MHz", val, U16_MAX);
+		return -EINVAL;
+	}
+
+	msg.msg_id = HSMP_SET_GET_FLOOR_LIMIT;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 0;
+	msg.args[0] = BIT(30) | val;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "cclk_floor_limit", HSMP_ERR_HW,
+			 "val=%lu unit=MHz rc=%d", val, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 /* APB disable show function - reads current APB enable/disable status */
 ssize_t hsmp_apb_disable_show(struct device *dev,
 			      struct device_attribute *attr,
@@ -1909,8 +1951,9 @@ static struct hsmp_cpu_info *hsmp_cpu_from_kobj(struct kobject *kobj)
 /*
  * HSMP_SET_GET_FLOOR_LIMIT args[0]:
  * op[31:30] + apic id[27:16] + floor frequency MHz[15:0].
- * op 0 sets the per-core floor, op 2 reads it, op 3 reads the
- * effective floor. The frequency field is reserved on a get.
+ * op 0 sets the per-core floor, op 1 sets every core on the socket,
+ * op 2 reads the per-core floor, and op 3 reads the effective floor.
+ * The frequency field is reserved on a get.
  */
 static u32 hsmp_floor_arg(u32 op, u32 apic_id, u32 mhz)
 {
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 716d9e4493a1b..8d3a9021ef18e 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -112,6 +112,9 @@ ssize_t hsmp_rail_iso_freq_policy_store(struct device *dev,
 ssize_t hsmp_cclk_boost_limit_store(struct device *dev,
 				       struct device_attribute *attr,
 				       const char *buf, size_t count);
+ssize_t hsmp_cclk_floor_limit_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count);
 ssize_t hsmp_apb_disable_show(struct device *dev, struct device_attribute *attr,
 			      char *buf);
 ssize_t hsmp_apb_disable_store(struct device *dev, struct device_attribute *attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 20/26] platform/x86/amd/hsmp: Add xgmi_pstate_range sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (18 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 19/26] platform/x86/amd/hsmp: Add cclk_floor_limit sysfs file Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 21/26] platform/x86/amd/hsmp: Quiet probe-time firmware status dmesg spam Muthusamy Ramalingam
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Add a read/write socket file for the xGMI P-state range on both the
ACPI and platform drivers.

Read and write are differentiated by bit 31. Setting the bit selects a
read, and resetting it selects a write. A read returns the minimum and
maximum P-states. A write takes "min max", with the minimum in bits
[15:8] and the maximum in bits [7:0]. Each value is an 8-bit field.
Extra arguments are rejected. Firmware rejects unsupported P-states.

Describe the message as get/set with a one-word response so the read
passes validation.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  3 +
 arch/x86/include/uapi/asm/amd_hsmp.h  | 11 ++--
 drivers/platform/x86/amd/hsmp/acpi.c  |  4 ++
 drivers/platform/x86/amd/hsmp/plat.c  |  5 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 79 +++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  5 ++
 6 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 30401c168c503..e1159bbea5991 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -129,6 +129,9 @@ write-only when the platform enables only that direction of the message.
 * xgmi_width: Read/write xGMI link width range as "min max".
   0 is x4, 1 is x8, and 2 is x16. Each value is an 8-bit field.
   Extra arguments are rejected. Firmware rejects unsupported widths.
+* xgmi_pstate_range: Read/write xGMI P-state range as "min max".
+  Each value is an 8-bit field. Extra arguments are rejected. Firmware
+  rejects unsupported P-states.
 * lclk_dpm_range/lclk_0, lclk_dpm_range/lclk_1,
   lclk_dpm_range/lclk_2, lclk_dpm_range/lclk_3: Read/write LCLK DPM
   range for NBIO 0-3. Read returns "min max". Write accepts "min max"
diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h
index dcbe89dc4d2b5..0350089bdae43 100644
--- a/arch/x86/include/uapi/asm/amd_hsmp.h
+++ b/arch/x86/include/uapi/asm/amd_hsmp.h
@@ -56,7 +56,7 @@ enum hsmp_message_ids {
 	HSMP_GET_METRIC_TABLE_VER,	/* 23h Get metrics table version */
 	HSMP_GET_METRIC_TABLE,		/* 24h Get metrics table */
 	HSMP_GET_METRIC_TABLE_DRAM_ADDR,/* 25h Get metrics table dram address */
-	HSMP_SET_XGMI_PSTATE_RANGE,	/* 26h Set xGMI P-state range */
+	HSMP_SET_XGMI_PSTATE_RANGE,	/* 26h Get/Set xGMI P-state range */
 	HSMP_CPU_RAIL_ISO_FREQ_POLICY,	/* 27h Get/Set Cpu Iso frequency policy */
 	HSMP_DFC_ENABLE_CTRL,		/* 28h Enable/Disable DF C-state */
 	HSMP_PC6_ENABLE,		/* 29h Get/Set PC6 enable/disable status */
@@ -395,10 +395,13 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[]
 	{0, 3, HSMP_GET},
 
 	/*
-	 * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 0
-	 * input: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0]
+	 * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 1
+	 * input: args[0] = set/get range[31] (0 = set, 1 = get) +
+	 *                  min xGMI p-state[15:8] + max xGMI p-state[7:0]
+	 *                  (min and max are reserved on GET)
+	 * output: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0]
 	 */
-	{1, 0, HSMP_SET},
+	{1, 1, HSMP_SET_GET},
 
 	/*
 	 * HSMP_CPU_RAIL_ISO_FREQ_POLICY, num_args = 1, response_sz = 1
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 35c2085b67e42..284dc21dfdc37 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -556,6 +556,9 @@ HSMP_DEV_ATTR_RW(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN, HSMP_SET_PSTATE_MAX_M
 		 hsmp_df_pstate_range_show, hsmp_df_pstate_range_store, 0644);
 HSMP_DEV_ATTR_RW(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH, HSMP_SET_XGMI_LINK_WIDTH,
 		 hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
+HSMP_DEV_ATTR_RW(xgmi_pstate_range, HSMP_SET_XGMI_PSTATE_RANGE,
+		 HSMP_SET_XGMI_PSTATE_RANGE,
+		 hsmp_xgmi_pstate_range_show, hsmp_xgmi_pstate_range_store, 0644);
 HSMP_DEV_ATTR_W(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W(pcie_link_rate, HSMP_SET_PCI_RATE,
@@ -828,6 +831,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_sdps_limit.dattr.attr,
 	&hattr_df_pstate_range.dattr.attr,
 	&hattr_xgmi_width.dattr.attr,
+	&hattr_xgmi_pstate_range.dattr.attr,
 	&hattr_gmi3_link_width.dattr.attr,
 	&hattr_pcie_link_rate.dattr.attr,
 	&hattr_dimm_sb_get.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index aedc71027b28c..8207900b8a170 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -393,6 +393,10 @@ HSMP_DEV_ATTR_RW_X8(df_pstate_range, HSMP_SET_PSTATE_MAX_MIN,
 HSMP_DEV_ATTR_RW_X8(xgmi_width, HSMP_SET_XGMI_LINK_WIDTH,
 		    HSMP_SET_XGMI_LINK_WIDTH,
 		    hsmp_xgmi_width_show, hsmp_xgmi_width_store, 0644);
+HSMP_DEV_ATTR_RW_X8(xgmi_pstate_range, HSMP_SET_XGMI_PSTATE_RANGE,
+		    HSMP_SET_XGMI_PSTATE_RANGE,
+		    hsmp_xgmi_pstate_range_show, hsmp_xgmi_pstate_range_store,
+		    0644);
 HSMP_DEV_ATTR_W_X8(gmi3_link_width, HSMP_SET_GMI3_WIDTH,
 		   hsmp_gmi3_link_width_store, 0200);
 HSMP_DEV_ATTR_W_X8(pcie_link_rate, HSMP_SET_PCI_RATE,
@@ -1902,6 +1906,7 @@ static struct attribute _name[] = {					       \
 	&hattr_sdps_limit##_sock_ind.dattr.attr,			       \
 	&hattr_df_pstate_range##_sock_ind.dattr.attr,			       \
 	&hattr_xgmi_width##_sock_ind.dattr.attr,			       \
+	&hattr_xgmi_pstate_range##_sock_ind.dattr.attr,			       \
 	&hattr_gmi3_link_width##_sock_ind.dattr.attr,			       \
 	&hattr_pcie_link_rate##_sock_ind.dattr.attr,			       \
 	&hattr_dimm_sb_get##_sock_ind.dattr.attr,			       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 8872f63e218df..e941574711687 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -984,6 +984,85 @@ ssize_t hsmp_xgmi_width_store(struct device *dev,
 	return count;
 }
 
+/* xGMI P-state range show function - reads current min and max P-states */
+ssize_t hsmp_xgmi_pstate_range_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_pstate, max_pstate;
+	int ret;
+
+	/* Set bit 31 to indicate GET operation for HSMP_SET_GET type messages */
+	msg.msg_id = HSMP_SET_XGMI_PSTATE_RANGE;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = BIT(31);  /* GET operation */
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	/* Extract min P-state[15:8] and max P-state[7:0] */
+	min_pstate = (msg.args[0] >> 8) & 0xFF;
+	max_pstate = msg.args[0] & 0xFF;
+
+	return sysfs_emit(buf, "%u %u\n", min_pstate, max_pstate);
+}
+
+/* xGMI P-state range store function - sets min and max P-states */
+ssize_t hsmp_xgmi_pstate_range_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	struct hsmp_message msg = {};
+	u32 min_pstate, max_pstate;
+	u32 vals[2];
+	int ret;
+	int got;
+
+	/* Parse input in format: "min_pstate max_pstate" */
+	ret = hsmp_parse_u32_args(buf, vals, 2, 10, &got);
+	if (ret) {
+		hsmp_err(dev, "xgmi_pstate_range", HSMP_ERR_ARGC,
+			 "want=2 got=%d fmt=\"min max\"", got);
+		return -EINVAL;
+	}
+	min_pstate = vals[0];
+	max_pstate = vals[1];
+
+	/* Min and max are 8-bit fields. Firmware rejects unsupported P-states. */
+	if (min_pstate > 0xFF || max_pstate > 0xFF) {
+		hsmp_err(dev, "xgmi_pstate_range", HSMP_ERR_RANGE,
+			 "min=%u max=%u valid=0-255", min_pstate, max_pstate);
+		return -EINVAL;
+	}
+
+	/* Clear bit 31 for SET operation, pack min[15:8] and max[7:0] */
+	msg.msg_id = HSMP_SET_XGMI_PSTATE_RANGE;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = (min_pstate << 8) | max_pstate;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		if (max_pstate > min_pstate)
+			hsmp_err(dev, "xgmi_pstate_range", HSMP_ERR_ORDER,
+				 "min=%u max=%u rule=max<=min rc=%d",
+				  min_pstate, max_pstate, ret);
+		else
+			hsmp_err(dev, "xgmi_pstate_range", HSMP_ERR_HW,
+				 "min=%u max=%u rc=%d", min_pstate, max_pstate, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 /* GMI3 link width store function - sets min and max link width */
 ssize_t hsmp_gmi3_link_width_store(struct device *dev,
 				   struct device_attribute *attr,
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 8d3a9021ef18e..36368f13d72f0 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -137,6 +137,11 @@ ssize_t hsmp_xgmi_width_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_xgmi_width_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count);
+ssize_t hsmp_xgmi_pstate_range_show(struct device *dev,
+				    struct device_attribute *attr, char *buf);
+ssize_t hsmp_xgmi_pstate_range_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count);
 ssize_t hsmp_gmi3_link_width_store(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 21/26] platform/x86/amd/hsmp: Quiet probe-time firmware status dmesg spam
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (19 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 20/26] platform/x86/amd/hsmp: Add xgmi_pstate_range " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 22/26] platform/x86/amd/hsmp: Add powereff_mode sysfs file Muthusamy Ramalingam
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Probing for hardware that may legitimately be absent (DIMMs, IO/xGMI
links) causes __hsmp_send_message()
to log a dev_err() for every expected miss, flooding dmesg on module
load.

Add a stateless hsmp_send_message_quiet() entry point alongside the
existing hsmp_send_message(): both funnel into a shared locked helper
that passes an explicit quiet bool into __hsmp_send_message(). Firmware
status failures then use hsmp_status_err() to pick dev_dbg() instead of
dev_err() for expected misses. hsmp_send_message()'s signature, and the
UAPI struct hsmp_message, are both unchanged.

DIMM, io_bw, and xgmi_bw probe paths use the quiet locked send.
Transport-level register errors stay as unconditional dev_err().

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 arch/x86/include/asm/amd/hsmp.h      |  7 +++
 drivers/platform/x86/amd/hsmp/hsmp.c | 85 +++++++++++++++++++++-------
 2 files changed, 72 insertions(+), 20 deletions(-)

diff --git a/arch/x86/include/asm/amd/hsmp.h b/arch/x86/include/asm/amd/hsmp.h
index 2137f62853ed2..b867130e6a8a9 100644
--- a/arch/x86/include/asm/amd/hsmp.h
+++ b/arch/x86/include/asm/amd/hsmp.h
@@ -6,11 +6,18 @@
 
 #if IS_ENABLED(CONFIG_AMD_HSMP)
 int hsmp_send_message(struct hsmp_message *msg);
+/* Same as hsmp_send_message(), but logs probe/discovery misses at dev_dbg(). */
+int hsmp_send_message_quiet(struct hsmp_message *msg);
 #else
 static inline int hsmp_send_message(struct hsmp_message *msg)
 {
 	return -ENODEV;
 }
+
+static inline int hsmp_send_message_quiet(struct hsmp_message *msg)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif /*_ASM_X86_AMD_HSMP_H_*/
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index d6a4a79118e80..86961fe06ea56 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -159,7 +159,24 @@ EXPORT_SYMBOL_NS_GPL(hsmp_sock_rwsem, "AMD_HSMP");
  * Returns 0 for success and populates the requested number of arguments.
  * Returns a negative error code for failure.
  */
-static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg)
+
+/*
+ * Many of these firmware status codes just mean "not applicable here"
+ * (e.g. probing for an absent DIMM/link). hsmp_send_message_quiet() /
+ * locked quiet callers doing that kind of discovery get the miss logged
+ * at dev_dbg() instead of dev_err(), avoiding dmesg spam for an expected
+ * outcome.
+ */
+#define hsmp_status_err(sock, quiet, fmt, ...)				\
+	do {								\
+		if (quiet)						\
+			dev_dbg((sock)->dev, fmt, ##__VA_ARGS__);	\
+		else							\
+			dev_err((sock)->dev, fmt, ##__VA_ARGS__);	\
+	} while (0)
+
+static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *msg,
+			       bool quiet)
 {
 	struct hsmp_mbaddr_info *mbinfo;
 	unsigned long timeout, short_sleep;
@@ -226,28 +243,34 @@ static int __hsmp_send_message(struct hsmp_socket *sock, struct hsmp_message *ms
 	}
 
 	if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) {
-		dev_err(sock->dev, "Message ID 0x%X failure : SMU timeout (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X failure : SMU timeout (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -ETIMEDOUT;
 	} else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) {
-		dev_err(sock->dev, "Message ID 0x%X failure : Invalid message (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X failure : Invalid message (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -ENOMSG;
 	} else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) {
-		dev_err(sock->dev, "Message ID 0x%X failure : Invalid arguments (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X failure : Invalid arguments (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -EINVAL;
 	} else if (unlikely(mbox_status == HSMP_ERR_PREREQ_NOT_SATISFIED)) {
-		dev_err(sock->dev, "Message ID 0x%X failure : Prerequisite not satisfied (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X failure : Prerequisite not satisfied (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -EREMOTEIO;
 	} else if (unlikely(mbox_status == HSMP_ERR_SMU_BUSY)) {
-		dev_err(sock->dev, "Message ID 0x%X failure : SMU BUSY (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X failure : SMU BUSY (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -EBUSY;
 	} else if (unlikely(mbox_status != HSMP_STATUS_OK)) {
-		dev_err(sock->dev, "Message ID 0x%X unknown failure (status = 0x%X)\n",
-			msg->msg_id, mbox_status);
+		hsmp_status_err(sock, quiet,
+				"Message ID 0x%X unknown failure (status = 0x%X)\n",
+				msg->msg_id, mbox_status);
 		return -EIO;
 	}
 
@@ -353,7 +376,7 @@ static int validate_message(struct hsmp_message *msg)
  * senders run under the write lock taken by probe. Holding it here serializes
  * every message against socket teardown, which also holds it for write.
  */
-static int hsmp_send_message_locked(struct hsmp_message *msg)
+static int hsmp_send_message_common_locked(struct hsmp_message *msg, bool quiet)
 {
 	struct hsmp_socket *sock;
 	unsigned int sock_ind;
@@ -398,13 +421,23 @@ static int hsmp_send_message_locked(struct hsmp_message *msg)
 	if (ret < 0)
 		return ret;
 
-	ret = __hsmp_send_message(sock, msg);
+	ret = __hsmp_send_message(sock, msg, quiet);
 
 	up(&sock->hsmp_sem);
 
 	return ret;
 }
 
+static int hsmp_send_message_locked(struct hsmp_message *msg)
+{
+	return hsmp_send_message_common_locked(msg, false);
+}
+
+static int hsmp_send_message_locked_quiet(struct hsmp_message *msg)
+{
+	return hsmp_send_message_common_locked(msg, true);
+}
+
 int hsmp_send_message(struct hsmp_message *msg)
 {
 	/*
@@ -415,10 +448,22 @@ int hsmp_send_message(struct hsmp_message *msg)
 	 */
 	guard(rwsem_read)(&hsmp_sock_rwsem);
 
-	return hsmp_send_message_locked(msg);
+	return hsmp_send_message_common_locked(msg, false);
 }
 EXPORT_SYMBOL_NS_GPL(hsmp_send_message, "AMD_HSMP");
 
+/*
+ * Same as hsmp_send_message(), but used by in-driver probe/discovery
+ * callers so expected misses are logged at dev_dbg() instead of dev_err().
+ */
+int hsmp_send_message_quiet(struct hsmp_message *msg)
+{
+	guard(rwsem_read)(&hsmp_sock_rwsem);
+
+	return hsmp_send_message_common_locked(msg, true);
+}
+EXPORT_SYMBOL_NS_GPL(hsmp_send_message_quiet, "AMD_HSMP");
+
 int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args)
 {
 	struct hsmp_message msg = {};
@@ -920,7 +965,7 @@ static void hsmp_scan_dimm_range(struct hsmp_socket *sock, u32 msg_id, u32 *mask
 		msg.num_args = 1;
 		msg.response_sz = 1;
 		msg.args[0] = addr;
-		if (!hsmp_send_message_locked(&msg))
+		if (!hsmp_send_message_locked_quiet(&msg))
 			*mask |= BIT(addr - 0x80);
 	}
 
@@ -935,7 +980,7 @@ static void hsmp_scan_dimm_range(struct hsmp_socket *sock, u32 msg_id, u32 *mask
 		msg.num_args = 1;
 		msg.response_sz = 1;
 		msg.args[0] = addr;
-		if (!hsmp_send_message_locked(&msg))
+		if (!hsmp_send_message_locked_quiet(&msg))
 			*mask |= BIT(addr - 0x90 + 16);
 	}
 }
@@ -1066,7 +1111,7 @@ void hsmp_scan_io_bw(struct hsmp_socket *sock)
 		msg.response_sz = 1;
 		/* Aggregate bandwidth type in [2:0], link encoding in [15:8]. */
 		msg.args[0] = 1 | ((u32)enc << 8);
-		if (!hsmp_send_message_locked(&msg))
+		if (!hsmp_send_message_locked_quiet(&msg))
 			sock->io_bw_valid |= BIT(i);
 	}
 }
@@ -1127,7 +1172,7 @@ void hsmp_scan_xgmi_bw(struct hsmp_socket *sock)
 		msg.sock_ind = sock->sock_ind;
 		msg.num_args = 1;
 		msg.response_sz = 1;
-		if (!hsmp_send_message_locked(&msg))
+		if (!hsmp_send_message_locked_quiet(&msg))
 			sock->xgmi_bw_valid |= BIT_ULL(i);
 	}
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 22/26] platform/x86/amd/hsmp: Add powereff_mode sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (20 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 21/26] platform/x86/amd/hsmp: Quiet probe-time firmware status dmesg spam Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 23/26] platform/x86/amd/hsmp: Add svi_power " Muthusamy Ramalingam
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_SET_POWER_MODE as a read/write socket file on both the
ACPI and platform drivers. A read returns the current mode name and,
on Venice for modes 4/5, the packed PPT and utilization parameters.
A write takes the mode alone for modes 0-3, or mode plus PPT/util
fields for Venice modes 4/5 (v1 or v2 packing by protocol version).

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |   8 +
 drivers/platform/x86/amd/hsmp/acpi.c  |   3 +
 drivers/platform/x86/amd/hsmp/plat.c  |   3 +
 drivers/platform/x86/amd/hsmp/sysfs.c | 219 ++++++++++++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |   5 +
 5 files changed, 238 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index e1159bbea5991..ef83970492b6b 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -194,6 +194,14 @@ write-only when the platform enables only that direction of the message.
   is 100-10000 MHz.
 * cclk_floor_limit: Socket floor limit in MHz (write only). A write sets
   the floor for every core on the socket. It is a 16-bit value.
+* powereff_mode: Read/write power-efficiency mode. Modes are
+  0=HighPerformance, 1=PowerEfficiency, 2=IOPerformance,
+  3=BalancedMemory, 4=BalancedCore, 5=BalancedCoreMemory. A read returns
+  "<mode> <name>" and, on Venice for modes 4/5, the packed parameters.
+  Writes accept "<mode>" for modes 0-3 (and for 4/5 on non-Venice). On
+  Venice, modes 4/5 take "<mode> <ppt_W> <util%>" when the protocol is
+  below 7.1, or "<mode> <ppt_W> <low%> <high%>" for protocol 7.1 and
+  later.
 * tdelta: Socket thermal behaviour (read only).
 * apb_disable: Read/write. 1 disables APB, 0 enables it.
 * dfc_enable: Read/write DF C-state enable. 1 enables, 0 disables.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 284dc21dfdc37..e030f3c80721b 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -671,6 +671,8 @@ HSMP_DEV_ATTR_W(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_W(cclk_floor_limit, HSMP_SET_GET_FLOOR_LIMIT,
 		hsmp_cclk_floor_limit_store, 0200);
+HSMP_DEV_ATTR_RW(powereff_mode, HSMP_SET_POWER_MODE, HSMP_SET_POWER_MODE,
+		 hsmp_powereff_mode_show, hsmp_powereff_mode_store, 0644);
 HSMP_DEV_ATTR_RW(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
 		 hsmp_apb_disable_show, hsmp_apb_disable_store, 0644);
 HSMP_DEV_ATTR_RW(dfc_enable, HSMP_DFC_ENABLE_CTRL, HSMP_DFC_ENABLE_CTRL,
@@ -839,6 +841,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_socket_power.dattr.attr,
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_cclk_floor_limit.dattr.attr,
+	&hattr_powereff_mode.dattr.attr,
 	&hattr_tdelta.dattr.attr,
 	&hattr_apb_disable.dattr.attr,
 	&hattr_cc6_enable.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 8207900b8a170..f1ab7f25a29c1 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -1868,6 +1868,8 @@ HSMP_DEV_ATTR_W_X8(cclk_boost_limit, HSMP_SET_BOOST_LIMIT_SOCKET,
 		   hsmp_cclk_boost_limit_store, 0200);
 HSMP_DEV_ATTR_W_X8(cclk_floor_limit, HSMP_SET_GET_FLOOR_LIMIT,
 		   hsmp_cclk_floor_limit_store, 0200);
+HSMP_DEV_ATTR_RW_X8(powereff_mode, HSMP_SET_POWER_MODE, HSMP_SET_POWER_MODE,
+		    hsmp_powereff_mode_show, hsmp_powereff_mode_store, 0644);
 HSMP_DEV_ATTR_X8(tdelta, HSMP_READ_TDELTA, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW_X8(apb_disable, HSMP_SET_DF_PSTATE, HSMP_SET_DF_PSTATE,
 		    hsmp_apb_disable_show, hsmp_apb_disable_store, 0644);
@@ -1914,6 +1916,7 @@ static struct attribute _name[] = {					       \
 	&hattr_socket_power##_sock_ind.dattr.attr,			       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_cclk_floor_limit##_sock_ind.dattr.attr,		       \
+	&hattr_powereff_mode##_sock_ind.dattr.attr,			       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
 	&hattr_apb_disable##_sock_ind.dattr.attr,			       \
 	&hattr_cc6_enable##_sock_ind.dattr.attr,			       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index e941574711687..254ba586da861 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -602,6 +602,225 @@ ssize_t hsmp_cclk_floor_limit_store(struct device *dev,
 	return count;
 }
 
+/* powereff_mode utilization field (7-bit), used by both v1 and v2 layouts */
+#define POWEREFF_UTIL_MASK	0x7F
+/* powereff_mode v2 ppt_W field max (12-bit) */
+#define POWEREFF_PPT_W_MAX	0xFFF
+/* powereff_mode utilization percentage bound */
+#define POWEREFF_UTIL_PCT_MAX	100
+/* powereff_mode v1 ppt_mW field (21-bit) */
+#define POWEREFF_PPT_MW_MASK	0x1FFFFF
+#define POWEREFF_MODE_MAX	5
+/* Modes 4/5 take util/ppt (v1) or low/high util + ppt (v2) on Venice. */
+#define POWEREFF_MODE_EXTRA_MIN	4
+#define HSMP_PROTO_VER_7_1	0x00070001U
+
+static const char * const powereff_mode_names[] = {
+	"HighPerformance",
+	"PowerEfficiency",
+	"IOPerformance",
+	"BalancedMemory",
+	"BalancedCore",
+	"BalancedCoreMemory",
+};
+
+/*
+ * Only Venice (family 0x1A, specific models) accepts power-efficiency mode
+ * parameters for modes 4/5; other families take just the mode.
+ */
+#define HSMP_IS_VENICE_MODEL(m) \
+	(((m) >= 0x50 && (m) <= 0x5F) || \
+	 ((m) >= 0x90 && (m) <= 0x9B) || \
+	 ((m) >= 0xA0 && (m) <= 0xAB) || \
+	 ((m) >= 0xC0 && (m) <= 0xCF))
+#define HSMP_IS_VENICE() \
+	(boot_cpu_data.x86 == 0x1A && HSMP_IS_VENICE_MODEL(boot_cpu_data.x86_model))
+
+static int hsmp_parse_u32_args(const char *buf, u32 *vals, int n,
+			       unsigned int base, int *got);
+
+static u32 hsmp_powereff_proto_ver(struct device *dev,
+				   const struct hsmp_sys_attr *hattr)
+{
+	struct hsmp_plat_device *pdev = get_hsmp_pdev();
+	u16 sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+
+	if (!pdev || sock_ind >= pdev->num_sockets)
+		return 0;
+
+	return pdev->sock[sock_ind].proto_ver;
+}
+
+ssize_t hsmp_powereff_mode_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	bool is_v2 = hsmp_powereff_proto_ver(dev, hattr) >= HSMP_PROTO_VER_7_1;
+	struct hsmp_message msg = {};
+	u32 resp;
+	u8 mode;
+	int ret;
+
+	/* Query firmware for the current mode (bit[31] = get); mode in [2:0]. */
+	msg.msg_id = HSMP_SET_POWER_MODE;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = BIT(31);
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	resp = msg.args[0];
+	mode = resp & 0x7;
+	if (mode > POWEREFF_MODE_MAX)
+		return -ERANGE;
+
+	/*
+	 * Only Venice modes 4/5 carry extra params; decode per proto layout
+	 * (same field packing as the store path).
+	 */
+	if (HSMP_IS_VENICE() && mode >= POWEREFF_MODE_EXTRA_MIN) {
+		if (is_v2) {
+			u32 ppt_w = (resp >> 5) & POWEREFF_PPT_W_MAX;
+			u32 low_util = (resp >> 17) & POWEREFF_UTIL_MASK;
+			u32 high_util = (resp >> 24) & POWEREFF_UTIL_MASK;
+
+			return sysfs_emit(buf, "%u %s %u %u %u\n",
+					  mode, powereff_mode_names[mode],
+					  ppt_w, low_util, high_util);
+		}
+		u32 util = (resp >> 3) & POWEREFF_UTIL_MASK;
+		u32 ppt_mw = (resp >> 10) & POWEREFF_PPT_MW_MASK;
+
+		return sysfs_emit(buf, "%u %s %u %u\n",
+				  mode, powereff_mode_names[mode],
+				  ppt_mw / 1000, util);
+	}
+
+	return sysfs_emit(buf, "%u %s\n", mode, powereff_mode_names[mode]);
+}
+
+ssize_t hsmp_powereff_mode_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	bool is_v2 = hsmp_powereff_proto_ver(dev, hattr) >= HSMP_PROTO_VER_7_1;
+	u32 mode, util = 0, low_util = 0, high_util = 0, ppt_limit = 0;
+	struct hsmp_message msg = {};
+	bool has_params;
+	u32 vals[4];
+	u32 reg_val;
+	int tok_total;
+	int ret;
+	int got;
+
+	/*
+	 * Accept mode-only, Venice v1 (mode ppt_W util), or Venice v2
+	 * (mode ppt_W low_util high_util). Try each exact arity.
+	 */
+	if (!hsmp_parse_u32_args(buf, vals, 1, 10, &got)) {
+		tok_total = 1;
+	} else if (!hsmp_parse_u32_args(buf, vals, 3, 10, &got)) {
+		tok_total = 3;
+	} else if (!hsmp_parse_u32_args(buf, vals, 4, 10, &got)) {
+		tok_total = 4;
+	} else {
+		hsmp_err(dev, "powereff_mode", HSMP_ERR_ARGC,
+			 "field=mode want=1 got=%d valid=0-%u", got,
+			 POWEREFF_MODE_MAX);
+		return -EINVAL;
+	}
+
+	mode = vals[0];
+	if (mode > POWEREFF_MODE_MAX) {
+		hsmp_err(dev, "powereff_mode", HSMP_ERR_RANGE,
+			 "field=mode got=%u valid=0-%u", mode, POWEREFF_MODE_MAX);
+		return -EINVAL;
+	}
+
+	/* Extra params apply only to Venice modes 4/5. */
+	has_params = (mode >= POWEREFF_MODE_EXTRA_MIN) && HSMP_IS_VENICE();
+	reg_val = mode & 0x7; /* bit 31 = 0 for SET */
+
+	if (has_params) {
+		if (is_v2) {
+			if (tok_total != 4) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_ARGC,
+					 "mode=%u want=4 got=%d fmt=\"mode ppt_W low_util high_util\"",
+					 mode, tok_total);
+				return -EINVAL;
+			}
+			ppt_limit = vals[1];
+			low_util = vals[2];
+			high_util = vals[3];
+			if (ppt_limit > POWEREFF_PPT_W_MAX) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_RANGE,
+					 "field=ppt_W got=%u valid=0-%u",
+					 ppt_limit, POWEREFF_PPT_W_MAX);
+				return -EINVAL;
+			}
+			if (low_util > POWEREFF_UTIL_PCT_MAX ||
+			    high_util > POWEREFF_UTIL_PCT_MAX) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_RANGE,
+					 "field=util low=%u high=%u valid=0-%u",
+					 low_util, high_util,
+					 POWEREFF_UTIL_PCT_MAX);
+				return -EINVAL;
+			}
+			reg_val |= (ppt_limit & POWEREFF_PPT_W_MAX) << 5;
+			reg_val |= (low_util & POWEREFF_UTIL_MASK) << 17;
+			reg_val |= (high_util & POWEREFF_UTIL_MASK) << 24;
+		} else {
+			if (tok_total != 3) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_ARGC,
+					 "mode=%u want=3 got=%d fmt=\"mode ppt_W util\"",
+					 mode, tok_total);
+				return -EINVAL;
+			}
+			ppt_limit = vals[1];
+			util = vals[2];
+			if (ppt_limit > POWEREFF_PPT_MW_MASK / 1000) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_RANGE,
+					 "field=ppt_W got=%u valid=0-%u",
+					 ppt_limit, POWEREFF_PPT_MW_MASK / 1000);
+				return -EINVAL;
+			}
+			if (util > POWEREFF_UTIL_PCT_MAX) {
+				hsmp_err(dev, "powereff_mode", HSMP_ERR_RANGE,
+					 "field=util got=%u valid=0-%u",
+					 util, POWEREFF_UTIL_PCT_MAX);
+				return -EINVAL;
+			}
+			reg_val |= (util & POWEREFF_UTIL_MASK) << 3;
+			reg_val |= ((ppt_limit * 1000) & POWEREFF_PPT_MW_MASK) << 10;
+		}
+	} else if (tok_total > 1) {
+		hsmp_err(dev, "powereff_mode", HSMP_ERR_ARGC,
+			 "field=mode want=1 got=%d valid=0-%u", tok_total,
+			 POWEREFF_MODE_MAX);
+		return -EINVAL;
+	}
+
+	msg.msg_id = HSMP_SET_POWER_MODE;
+	msg.sock_ind = hsmp_sysfs_sock_ind(dev, hattr);
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = reg_val;
+
+	ret = hsmp_send_message(&msg);
+	if (ret) {
+		hsmp_err(dev, "powereff_mode", HSMP_ERR_HW,
+			 "op=set_power_mode mode=%u rc=%d", mode, ret);
+		return ret;
+	}
+
+	return count;
+}
+
 /* APB disable show function - reads current APB enable/disable status */
 ssize_t hsmp_apb_disable_show(struct device *dev,
 			      struct device_attribute *attr,
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index 36368f13d72f0..f4cec7459aac2 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -115,6 +115,11 @@ ssize_t hsmp_cclk_boost_limit_store(struct device *dev,
 ssize_t hsmp_cclk_floor_limit_store(struct device *dev,
 				    struct device_attribute *attr,
 				    const char *buf, size_t count);
+ssize_t hsmp_powereff_mode_show(struct device *dev,
+				struct device_attribute *attr, char *buf);
+ssize_t hsmp_powereff_mode_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count);
 ssize_t hsmp_apb_disable_show(struct device *dev, struct device_attribute *attr,
 			      char *buf);
 ssize_t hsmp_apb_disable_store(struct device *dev, struct device_attribute *attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 23/26] platform/x86/amd/hsmp: Add svi_power sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (21 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 22/26] platform/x86/amd/hsmp: Add powereff_mode sysfs file Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 24/26] platform/x86/amd/hsmp: Add per-CPU ccd_power " Muthusamy Ramalingam
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_GET_RAILS_SVI as a read-only socket file on both the ACPI
and platform drivers. It reports SVI-based power telemetry for all
rails in milliwatts via hsmp_msg_resp32_show. Supported on HSMP
protocol versions 5 and 7.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst  | 2 ++
 drivers/platform/x86/amd/hsmp/acpi.c | 2 ++
 drivers/platform/x86/amd/hsmp/plat.c | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index ef83970492b6b..6ff2c154e9958 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -202,6 +202,8 @@ write-only when the platform enables only that direction of the message.
   Venice, modes 4/5 take "<mode> <ppt_W> <util%>" when the protocol is
   below 7.1, or "<mode> <ppt_W> <low%> <high%>" for protocol 7.1 and
   later.
+* svi_power: SVI-based power telemetry for all rails, in milliwatts (read
+  only). Supported on HSMP protocol versions 5 and 7.
 * tdelta: Socket thermal behaviour (read only).
 * apb_disable: Read/write. 1 disables APB, 0 enables it.
 * dfc_enable: Read/write DF C-state enable. 1 enables, 0 disables.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index e030f3c80721b..bb46676b1f6fa 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -546,6 +546,7 @@ HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
 	      hsmp_freq_limit_source_show, 0444);
 HSMP_DEV_ATTR(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(socket_power_limit_max, HSMP_GET_SOCKET_POWER_LIMIT_MAX, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(svi_power, HSMP_GET_RAILS_SVI, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(tdelta, HSMP_READ_TDELTA, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		 HSMP_SET_SOCKET_POWER_LIMIT,
@@ -842,6 +843,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_cclk_boost_limit.dattr.attr,
 	&hattr_cclk_floor_limit.dattr.attr,
 	&hattr_powereff_mode.dattr.attr,
+	&hattr_svi_power.dattr.attr,
 	&hattr_tdelta.dattr.attr,
 	&hattr_apb_disable.dattr.attr,
 	&hattr_cc6_enable.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index f1ab7f25a29c1..54806c0f759c1 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -380,6 +380,7 @@ HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
 
 HSMP_DEV_ATTR_X8(socket_power_limit_max, HSMP_GET_SOCKET_POWER_LIMIT_MAX,
 		 hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR_X8(svi_power, HSMP_GET_RAILS_SVI, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW_X8(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		    HSMP_SET_SOCKET_POWER_LIMIT,
 		    hsmp_socket_power_limit_show,
@@ -1917,6 +1918,7 @@ static struct attribute _name[] = {					       \
 	&hattr_cclk_boost_limit##_sock_ind.dattr.attr,		       \
 	&hattr_cclk_floor_limit##_sock_ind.dattr.attr,		       \
 	&hattr_powereff_mode##_sock_ind.dattr.attr,			       \
+	&hattr_svi_power##_sock_ind.dattr.attr,			       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
 	&hattr_apb_disable##_sock_ind.dattr.attr,			       \
 	&hattr_cc6_enable##_sock_ind.dattr.attr,			       \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 24/26] platform/x86/amd/hsmp: Add per-CPU ccd_power sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (22 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 23/26] platform/x86/amd/hsmp: Add svi_power " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 25/26] platform/x86/amd/hsmp: Add per-CPU freq_limit " Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 26/26] platform/x86/amd/hsmp: Add socket_temperature " Muthusamy Ramalingam
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose read-only ccd_power under cpu/cpuX on both drivers. It reports
average CCD power in milliwatts via HSMP_READ_CCD_POWER, using the CPU's
APIC id to select the CCD.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 6ff2c154e9958..02df9882c0fc4 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -218,6 +218,8 @@ Per-CPU attributes are available under
 /sys/devices/platform/amd_hsmp/cpu/cpuX/ for both the ACPI and platform
 drivers.
 
+* ccd_power: Read-only average CCD power in milliwatts
+  (HSMP_READ_CCD_POWER). The CPU's APIC id selects the CCD.
 * boost_limit: Get/set the per-CPU boost limit in MHz (HSMP_GET_BOOST_LIMIT /
   HSMP_SET_BOOST_LIMIT). Writable range is 100-10000 MHz.
 * floor_limit: Get/set the per-CPU floor frequency in MHz via
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 254ba586da861..709bfa494cd64 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -2258,6 +2258,30 @@ static u32 hsmp_floor_arg(u32 op, u32 apic_id, u32 mhz)
 	return (op << 30) | ((apic_id & 0xfff) << 16) | (mhz & 0xffff);
 }
 
+static ssize_t ccd_power_show(struct kobject *kobj, struct kobj_attribute *attr,
+			      char *buf)
+{
+	struct hsmp_cpu_info *cpu_info = hsmp_cpu_from_kobj(kobj);
+	struct hsmp_message msg = {};
+	int ret;
+
+	if (!cpu_info)
+		return -ENODEV;
+
+	msg.msg_id = HSMP_READ_CCD_POWER;
+	msg.sock_ind = cpu_info->socket_id;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	/* ApicId of a core in the CCD, bits [15:0] */
+	msg.args[0] = cpu_info->apic_id & 0xffff;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0]);
+}
+
 static ssize_t floor_limit_show(struct kobject *kobj, struct kobj_attribute *attr,
 				char *buf)
 {
@@ -2442,6 +2466,8 @@ static umode_t cpu_kobj_is_visible(struct kobject *kobj, struct attribute *attr,
 	return cpu_info ? attr->mode : 0;
 }
 
+static struct kobj_attribute ccd_power_kattr =
+	__ATTR(ccd_power, 0444, ccd_power_show, NULL);
 static struct kobj_attribute boost_limit_kattr =
 	__ATTR(boost_limit, 0644, boost_limit_show, boost_limit_store);
 static struct kobj_attribute floor_limit_kattr =
@@ -2450,6 +2476,7 @@ static struct kobj_attribute floor_limit_eff_kattr =
 	__ATTR(floor_limit_eff, 0444, floor_limit_eff_show, NULL);
 
 static struct attribute *cpu_kobj_attrs[] = {
+	&ccd_power_kattr.attr,
 	&boost_limit_kattr.attr,
 	&floor_limit_kattr.attr,
 	&floor_limit_eff_kattr.attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 25/26] platform/x86/amd/hsmp: Add per-CPU freq_limit sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (23 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 24/26] platform/x86/amd/hsmp: Add per-CPU ccd_power " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  2026-11-02  7:19 ` [PATCH 26/26] platform/x86/amd/hsmp: Add socket_temperature " Muthusamy Ramalingam
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose read-only freq_limit under cpu/cpuX on both drivers. It reports the
per-core CCLK frequency limit in MHz via HSMP_GET_CCLK_CORE_LIMIT.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 ++
 drivers/platform/x86/amd/hsmp/sysfs.c | 26 ++++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 02df9882c0fc4..03c04ff23b1c9 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -220,6 +220,8 @@ drivers.
 
 * ccd_power: Read-only average CCD power in milliwatts
   (HSMP_READ_CCD_POWER). The CPU's APIC id selects the CCD.
+* freq_limit: Read-only per-core CCLK frequency limit in MHz
+  (HSMP_GET_CCLK_CORE_LIMIT).
 * boost_limit: Get/set the per-CPU boost limit in MHz (HSMP_GET_BOOST_LIMIT /
   HSMP_SET_BOOST_LIMIT). Writable range is 100-10000 MHz.
 * floor_limit: Get/set the per-CPU floor frequency in MHz via
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index 709bfa494cd64..e30830c52ea32 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -2282,6 +2282,29 @@ static ssize_t ccd_power_show(struct kobject *kobj, struct kobj_attribute *attr,
 	return sysfs_emit(buf, "%u\n", msg.args[0]);
 }
 
+static ssize_t freq_limit_show(struct kobject *kobj, struct kobj_attribute *attr,
+			       char *buf)
+{
+	struct hsmp_cpu_info *cpu_info = hsmp_cpu_from_kobj(kobj);
+	struct hsmp_message msg = {};
+	int ret;
+
+	if (!cpu_info)
+		return -ENODEV;
+
+	msg.msg_id = HSMP_GET_CCLK_CORE_LIMIT;
+	msg.sock_ind = cpu_info->socket_id;
+	msg.num_args = 1;
+	msg.response_sz = 1;
+	msg.args[0] = cpu_info->apic_id;
+
+	ret = hsmp_send_message(&msg);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%u\n", msg.args[0]);
+}
+
 static ssize_t floor_limit_show(struct kobject *kobj, struct kobj_attribute *attr,
 				char *buf)
 {
@@ -2468,6 +2491,8 @@ static umode_t cpu_kobj_is_visible(struct kobject *kobj, struct attribute *attr,
 
 static struct kobj_attribute ccd_power_kattr =
 	__ATTR(ccd_power, 0444, ccd_power_show, NULL);
+static struct kobj_attribute freq_limit_kattr =
+	__ATTR(freq_limit, 0444, freq_limit_show, NULL);
 static struct kobj_attribute boost_limit_kattr =
 	__ATTR(boost_limit, 0644, boost_limit_show, boost_limit_store);
 static struct kobj_attribute floor_limit_kattr =
@@ -2477,6 +2502,7 @@ static struct kobj_attribute floor_limit_eff_kattr =
 
 static struct attribute *cpu_kobj_attrs[] = {
 	&ccd_power_kattr.attr,
+	&freq_limit_kattr.attr,
 	&boost_limit_kattr.attr,
 	&floor_limit_kattr.attr,
 	&floor_limit_eff_kattr.attr,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH 26/26] platform/x86/amd/hsmp: Add socket_temperature sysfs file
  2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
                   ` (24 preceding siblings ...)
  2026-11-02  7:19 ` [PATCH 25/26] platform/x86/amd/hsmp: Add per-CPU freq_limit " Muthusamy Ramalingam
@ 2026-11-02  7:19 ` Muthusamy Ramalingam
  25 siblings, 0 replies; 27+ messages in thread
From: Muthusamy Ramalingam @ 2026-11-02  7:19 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: ilpo.jarvinen, Suma.Hegde, NaveenKrishna.Chatradhi,
	Muthusamy Ramalingam

Expose HSMP_GET_TEMP_MONITOR as a read-only socket file on both the
ACPI and platform drivers. Integer degrees are in bits [15:8] and
0.125 C steps in bits [7:5], printed as <int>.<frac> C.

Co-developed-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Suma Hegde <Suma.Hegde@amd.com>
Signed-off-by: Muthusamy Ramalingam <Muthusamy.Ramalingam@amd.com>
---
 Documentation/arch/x86/amd_hsmp.rst   |  2 ++
 drivers/platform/x86/amd/hsmp/acpi.c  |  3 +++
 drivers/platform/x86/amd/hsmp/plat.c  |  3 +++
 drivers/platform/x86/amd/hsmp/sysfs.c | 17 +++++++++++++++++
 drivers/platform/x86/amd/hsmp/sysfs.h |  4 ++++
 5 files changed, 29 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index 03c04ff23b1c9..7c8568e2b7298 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -204,6 +204,8 @@ write-only when the platform enables only that direction of the message.
   later.
 * svi_power: SVI-based power telemetry for all rails, in milliwatts (read
   only). Supported on HSMP protocol versions 5 and 7.
+* socket_temperature: Socket temperature in degrees Celsius with three
+  decimals (0.125 C resolution), from HSMP_GET_TEMP_MONITOR (read only).
 * tdelta: Socket thermal behaviour (read only).
 * apb_disable: Read/write. 1 disables APB, 0 enables it.
 * dfc_enable: Read/write DF C-state enable. 1 enables, 0 disables.
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index bb46676b1f6fa..85b1b6819f44c 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -547,6 +547,8 @@ HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
 HSMP_DEV_ATTR(socket_power, HSMP_GET_SOCKET_POWER, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(socket_power_limit_max, HSMP_GET_SOCKET_POWER_LIMIT_MAX, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR(svi_power, HSMP_GET_RAILS_SVI, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR(socket_temperature, HSMP_GET_TEMP_MONITOR,
+	      hsmp_socket_temperature_show, 0444);
 HSMP_DEV_ATTR(tdelta, HSMP_READ_TDELTA, hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_RW(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		 HSMP_SET_SOCKET_POWER_LIMIT,
@@ -844,6 +846,7 @@ static struct attribute *hsmp_dev_attr_list[] = {
 	&hattr_cclk_floor_limit.dattr.attr,
 	&hattr_powereff_mode.dattr.attr,
 	&hattr_svi_power.dattr.attr,
+	&hattr_socket_temperature.dattr.attr,
 	&hattr_tdelta.dattr.attr,
 	&hattr_apb_disable.dattr.attr,
 	&hattr_cc6_enable.dattr.attr,
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index 54806c0f759c1..5ec5bf945b914 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -381,6 +381,8 @@ HSMP_DEV_ATTR(pwr_current_active_freq_limit_source, HSMP_GET_SOCKET_FREQ_LIMIT,
 HSMP_DEV_ATTR_X8(socket_power_limit_max, HSMP_GET_SOCKET_POWER_LIMIT_MAX,
 		 hsmp_msg_resp32_show, 0444);
 HSMP_DEV_ATTR_X8(svi_power, HSMP_GET_RAILS_SVI, hsmp_msg_resp32_show, 0444);
+HSMP_DEV_ATTR_X8(socket_temperature, HSMP_GET_TEMP_MONITOR,
+		 hsmp_socket_temperature_show, 0444);
 HSMP_DEV_ATTR_RW_X8(socket_power_limit, HSMP_GET_SOCKET_POWER_LIMIT,
 		    HSMP_SET_SOCKET_POWER_LIMIT,
 		    hsmp_socket_power_limit_show,
@@ -1919,6 +1921,7 @@ static struct attribute _name[] = {					       \
 	&hattr_cclk_floor_limit##_sock_ind.dattr.attr,		       \
 	&hattr_powereff_mode##_sock_ind.dattr.attr,			       \
 	&hattr_svi_power##_sock_ind.dattr.attr,			       \
+	&hattr_socket_temperature##_sock_ind.dattr.attr,		       \
 	&hattr_tdelta##_sock_ind.dattr.attr,				       \
 	&hattr_apb_disable##_sock_ind.dattr.attr,			       \
 	&hattr_cc6_enable##_sock_ind.dattr.attr,			       \
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.c b/drivers/platform/x86/amd/hsmp/sysfs.c
index e30830c52ea32..58def5cc7bd76 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.c
+++ b/drivers/platform/x86/amd/hsmp/sysfs.c
@@ -305,6 +305,23 @@ ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute
 	return len;
 }
 
+/* Socket temperature in degrees C: integer part [15:8], 0.125 C steps in [7:5]. */
+ssize_t hsmp_socket_temperature_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct hsmp_sys_attr *hattr = to_hsmp_sys_attr(attr);
+	u32 data;
+	int ret;
+
+	ret = hsmp_msg_get_nargs(hsmp_sysfs_sock_ind(dev, hattr), hattr->msg_id,
+				 &data, 1);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu.%03lu\n", FIELD_GET(TEMP_MON_INT_MASK, data),
+			  FIELD_GET(TEMP_MON_FRAC_MASK, data) * 125);
+}
+
 /* DFC enable show function - reads current DF C-state enable status */
 ssize_t hsmp_dfc_enable_show(struct device *dev,
 			     struct device_attribute *attr,
diff --git a/drivers/platform/x86/amd/hsmp/sysfs.h b/drivers/platform/x86/amd/hsmp/sysfs.h
index f4cec7459aac2..9628eb6f322ab 100644
--- a/drivers/platform/x86/amd/hsmp/sysfs.h
+++ b/drivers/platform/x86/amd/hsmp/sysfs.h
@@ -36,6 +36,8 @@ struct hsmp_sys_attr {
 #define FMIN_MASK		GENMASK(15, 0)
 #define FREQ_LIMIT_MASK		GENMASK(31, 16)
 #define FREQ_SRC_IND_MASK	GENMASK(15, 0)
+#define TEMP_MON_INT_MASK	GENMASK(15, 8)
+#define TEMP_MON_FRAC_MASK	GENMASK(7, 5)
 
 #define to_hsmp_sys_attr(_dev_attr) \
 	container_of(_dev_attr, struct hsmp_sys_attr, dattr)
@@ -91,6 +93,8 @@ ssize_t hsmp_freq_limit_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
 ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_attribute *attr,
 				    char *buf);
+ssize_t hsmp_socket_temperature_show(struct device *dev,
+				     struct device_attribute *attr, char *buf);
 
 ssize_t hsmp_dfc_enable_show(struct device *dev, struct device_attribute *attr,
 			     char *buf);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2026-11-02  7:21 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02  7:18 [PATCH 00/26] platform/x86/amd/hsmp: Extend socket and per-CPU sysfs Muthusamy Ramalingam
2026-11-02  7:18 ` [PATCH 01/26] platform/x86/amd/hsmp: Drop _input from socket sysfs names Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 02/26] platform/x86/amd/hsmp: Rename clk_fmax and clk_fmin sysfs files Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 03/26] platform/x86/amd/hsmp: Add hsmp_err helper for parser-friendly store errors Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 04/26] platform/x86/amd/hsmp: Treat socket_power_limit as firmware-clamped Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 05/26] platform/x86/amd/hsmp: Print protocol_version as hexadecimal Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 06/26] platform/x86/amd/hsmp: Add sdps_limit sysfs file Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 07/26] platform/x86/amd/hsmp: Add df_pstate_range " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 08/26] platform/x86/amd/hsmp: Add xgmi_width " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 09/26] platform/x86/amd/hsmp: Add gmi3_link_width " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 10/26] platform/x86/amd/hsmp: Add pcie_link_rate " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 11/26] platform/x86/amd/hsmp: Add lclk DPM sysfs files Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 12/26] platform/x86/amd/hsmp: Add io_bw and xgmi_bw " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 13/26] platform/x86/amd/hsmp: Add DIMM sideband " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 14/26] platform/x86/amd/hsmp: Add per-CPU floor limit " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 15/26] platform/x86/amd/hsmp: Add metric_version sysfs file Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 16/26] platform/x86/amd/hsmp: Add enabled command sysfs files Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 17/26] platform/x86/amd/hsmp: Add DIMM power and temperature " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 18/26] platform/x86/amd/hsmp: Add SVI3 " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 19/26] platform/x86/amd/hsmp: Add cclk_floor_limit sysfs file Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 20/26] platform/x86/amd/hsmp: Add xgmi_pstate_range " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 21/26] platform/x86/amd/hsmp: Quiet probe-time firmware status dmesg spam Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 22/26] platform/x86/amd/hsmp: Add powereff_mode sysfs file Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 23/26] platform/x86/amd/hsmp: Add svi_power " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 24/26] platform/x86/amd/hsmp: Add per-CPU ccd_power " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 25/26] platform/x86/amd/hsmp: Add per-CPU freq_limit " Muthusamy Ramalingam
2026-11-02  7:19 ` [PATCH 26/26] platform/x86/amd/hsmp: Add socket_temperature " Muthusamy Ramalingam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.