* [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support
@ 2026-10-11 10:05 Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 1/8] platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H Shyam Sundar S K
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
This series enables the PMF driver features on the 1AH_M80H platform.
Patch 1 stops sending the legacy DRAM address commands on 1AH_M80H.
Patch 2 adds the static slider support as per APMF 2.03.
Patches 3-5 add per-platform TA ops, the signature size handling for
RSA4K signed policy binaries and the Smart PC builder support for the
new TA.
Patch 6 remaps the metrics table on resume.
Patch 7 passes the custom BIOS inputs to the TA on 1AH_M80H.
Patch 8 shares the TA policy apply code between the TA versions.
Shyam Sundar S K (8):
platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H
platform/x86/amd/pmf: Add 1AH_M80H static slider support
platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table
platform/x86/amd/pmf: Get policy binary signature size from PSP header
platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H
platform/x86/amd/pmf: Remap metrics table on resume for 1AH_M80H
platform/x86/amd/pmf: Add custom BIOS input support for 1AH_M80H
platform/x86/amd/pmf: Share TA policy apply code between TA versions
drivers/platform/x86/amd/pmf/acpi.c | 3 +-
drivers/platform/x86/amd/pmf/core.c | 50 +++--
drivers/platform/x86/amd/pmf/metrics.c | 13 +-
drivers/platform/x86/amd/pmf/pmf.h | 246 ++++++++++++++++++++++++
drivers/platform/x86/amd/pmf/spc.c | 206 ++++++++++++++++++++
drivers/platform/x86/amd/pmf/sps.c | 88 ++++++++-
drivers/platform/x86/amd/pmf/tee-if.c | 252 +++++++++++++++++++++----
7 files changed, 801 insertions(+), 57 deletions(-)
base-commit: 9cdc0dcc1e3677fca59bb314f2ec9e33383136d9
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 2/8] platform/x86/amd/pmf: Add 1AH_M80H static slider support Shyam Sundar S K
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
1AH_M80H gets the metrics table address from PMFW through
GET_1AH_M80H_METRICS_TABLE_DRAM_ADDR and does not support the
SET_DRAM_ADDR_HIGH/LOW commands used by earlier platforms.
amd_pmf_set_dram_addr() is still called on this platform from the
Smart PC init path. It ends up in the default case of the CPU id
switch, allocates a zero sized buffer and sends that address to PMFW
using message IDs that mean something else on 1AH_M80H.
Return early from amd_pmf_set_dram_addr() for platforms that use
accumulator based metrics. Move amd_pmf_supports_accumulator_metrics()
to pmf.h so that it can be used from metrics.c.
Fixes: 641b41a7a125 ("platform/x86/amd/pmf: Add 1AH_M80H metrics table and NPU metrics support")
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/core.c | 10 ----------
drivers/platform/x86/amd/pmf/metrics.c | 4 ++++
drivers/platform/x86/amd/pmf/pmf.h | 10 ++++++++++
3 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index ba9324448586..96e37eb56591 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -68,16 +68,6 @@ static bool smart_pc_support = true;
module_param(smart_pc_support, bool, 0444);
MODULE_PARM_DESC(smart_pc_support, "Smart PC Support (default = true)");
-static bool amd_pmf_supports_accumulator_metrics(struct amd_pmf_dev *pdev)
-{
- switch (pdev->cpu_id) {
- case PCI_DEVICE_ID_AMD_1AH_M80H_ROOT:
- return true;
- default:
- return false;
- }
-}
-
static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
{
struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
diff --git a/drivers/platform/x86/amd/pmf/metrics.c b/drivers/platform/x86/amd/pmf/metrics.c
index 5c0e368ec8df..5510dba95ce5 100644
--- a/drivers/platform/x86/amd/pmf/metrics.c
+++ b/drivers/platform/x86/amd/pmf/metrics.c
@@ -147,6 +147,10 @@ int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev, bool alloc_buffer)
u64 phys_addr;
u32 hi, low;
+ /* Accumulator based platforms get the table address from PMFW instead */
+ if (amd_pmf_supports_accumulator_metrics(dev))
+ return 0;
+
/* Get Metrics Table Address */
if (alloc_buffer) {
switch (dev->cpu_id) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 9f64ab833c08..b29c5192d878 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -1105,6 +1105,16 @@ static inline int amd_pmf_get_power_source(void)
return POWER_SOURCE_DC;
}
+static inline bool amd_pmf_supports_accumulator_metrics(struct amd_pmf_dev *pdev)
+{
+ switch (pdev->cpu_id) {
+ case PCI_DEVICE_ID_AMD_1AH_M80H_ROOT:
+ return true;
+ default:
+ return false;
+ }
+}
+
/**
* fixp_q88_fromint: Convert integer to Q8.8
* @val: input value
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] platform/x86/amd/pmf: Add 1AH_M80H static slider support
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 1/8] platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 3/8] platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table Shyam Sundar S K
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
1AH_M80H follows APMF specification 2.03, which changes the APTS table
layout and uses a different set of SMU message IDs to program the
static slider power limits.
Add the new APTS table structures and use them on 1AH_M80H to read the
slider defaults from the BIOS and to program them with the new SMU
message IDs. Other platforms keep using the existing path.
If reading the APTS defaults fails, return the error from
amd_pmf_init_sps() and do not register the power source notifier, so
that zeroed limits are never sent to the SMU on a power source change.
Key changes include:
- Add the 1AH_M80H SMU message IDs for SPPT, FPPT and STT limits
- Add struct amd_pmf_apts_output_v2 as per APMF 2.03
- Add amd_pmf_load_apts_defaults_sps_v3() and amd_pmf_update_slider_v3()
- Register the power source notifier only when SPS init succeeds
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/core.c | 10 ++--
drivers/platform/x86/amd/pmf/pmf.h | 45 +++++++++++++++
drivers/platform/x86/amd/pmf/sps.c | 88 ++++++++++++++++++++++++++++-
3 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 96e37eb56591..f7df72d3076b 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -356,10 +356,12 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
/* Enable Static Slider */
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
- amd_pmf_init_sps(dev);
- dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
- power_supply_reg_notifier(&dev->pwr_src_notifier);
- dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
+ ret = amd_pmf_init_sps(dev);
+ if (!ret) {
+ dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
+ power_supply_reg_notifier(&dev->pwr_src_notifier);
+ dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
+ }
}
if (smart_pc_support) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index b29c5192d878..73d981b25b38 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -82,8 +82,15 @@ struct cookie_header {
#define SET_PMF_PPT_APU_ONLY 0x26
/* Message IDs for 1AH_M80H platform */
+#define SET_1AH_M80H_STT_MIN_LIMIT 0x06
+#define SET_1AH_M80H_STT_LIMIT_APU 0x07
+#define SET_1AH_M80H_STT_LIMIT_HS2 0x08
#define GET_1AH_M80H_METRICS_TABLE_LOG_SAMPLE 0x0E
#define GET_1AH_M80H_METRICS_TABLE_DRAM_ADDR 0x0F
+#define SET_1AH_M80H_PMF_FPPT_APU_ONLY 0x10
+#define SET_1AH_M80H_PMF_SPPT_APU_ONLY 0x11
+#define SET_1AH_M80H_PMF_FPPT_SPM 0x12
+#define SET_1AH_M80H_PMF_SPPT_SPM 0x13
/* OS slider update notification */
#define DC_BEST_PERF 0
@@ -173,11 +180,34 @@ struct amd_pmf_apts_output {
u8 stt_skin_temp_limit_hs2;
} __packed;
+/* As per APMF Spec 2.03 */
+struct amd_pmf_apts_output_v2 {
+ u16 table_version;
+ u32 fan_table_idx;
+ u32 pmf_slow_ppt;
+ u32 ppt_pmf_apu_only;
+ u32 stt_min_limit;
+ u8 stt_skin_temp_limit_apu;
+ u8 stt_skin_temp_limit_hs2;
+ u32 pmf_fast_ppt;
+ u32 ppt_fast_pmf_apu_only;
+} __packed;
+
+struct amd_pmf_apts_granular_output_v2 {
+ u16 size;
+ struct amd_pmf_apts_output_v2 val;
+} __packed;
+
struct amd_pmf_apts_granular_output {
u16 size;
struct amd_pmf_apts_output val;
} __packed;
+struct amd_pmf_apts_granular_v2 {
+ u16 size;
+ struct amd_pmf_apts_output_v2 val[APTS_MAX_STATES];
+};
+
struct amd_pmf_apts_granular {
u16 size;
struct amd_pmf_apts_output val[APTS_MAX_STATES];
@@ -1115,6 +1145,11 @@ static inline bool amd_pmf_supports_accumulator_metrics(struct amd_pmf_dev *pdev
}
}
+static inline bool is_amd_pmf_1ah_m80h(struct amd_pmf_dev *pdev)
+{
+ return pdev->cpu_id == PCI_DEVICE_ID_AMD_1AH_M80H_ROOT;
+}
+
/**
* fixp_q88_fromint: Convert integer to Q8.8
* @val: input value
@@ -1143,6 +1178,16 @@ const char *amd_pmf_source_as_str(unsigned int state);
int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf);
+static inline int
+apts_get_static_slider_granular_v3(struct amd_pmf_dev *pdev,
+ struct amd_pmf_apts_granular_output_v2 *data, u32 apts_idx)
+{
+ if (!is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+ return -EINVAL;
+
+ return apts_if_call_store_buffer(pdev, apts_idx, data, sizeof(*data));
+}
+
static inline int
apts_get_static_slider_granular_v2(struct amd_pmf_dev *pdev,
struct amd_pmf_apts_granular_output *data, u32 apts_idx)
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index b0031afae33b..8aea73722d4c 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -8,11 +8,16 @@
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
*/
+#include <linux/dev_printk.h>
+#include <linux/printk.h>
+#include <linux/string.h>
+
#include "pmf.h"
static struct amd_pmf_static_slider_granular_v2 config_store_v2;
static struct amd_pmf_static_slider_granular config_store;
static struct amd_pmf_apts_granular apts_config_store;
+static struct amd_pmf_apts_granular_v2 apts_config_store_v2;
#ifdef CONFIG_AMD_PMF_DEBUG
static const char *slider_v2_as_str(unsigned int state)
@@ -97,6 +102,27 @@ static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v
pr_debug("Static Slider APTS state index data - END\n");
}
+static void amd_pmf_dump_apts_sps_defaults_v2(struct amd_pmf_apts_granular_v2 *info)
+{
+ int i;
+
+ pr_debug("Static Slider APTS index default v2 values data - BEGIN\n");
+
+ for (i = 0; i < APTS_MAX_STATES; i++) {
+ pr_debug("Table Version[%d] = %u\n", i, info->val[i].table_version);
+ pr_debug("Fan Index[%d] = %u\n", i, info->val[i].fan_table_idx);
+ pr_debug("PMF Slow PPT[%d] = %u\n", i, info->val[i].pmf_slow_ppt);
+ pr_debug("PPT PMF APU[%d] = %u\n", i, info->val[i].ppt_pmf_apu_only);
+ pr_debug("STT Min[%d] = %u\n", i, info->val[i].stt_min_limit);
+ pr_debug("STT APU[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_apu);
+ pr_debug("STT HS2[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_hs2);
+ pr_debug("PMF Fast PPT[%d] = %u\n", i, info->val[i].pmf_fast_ppt);
+ pr_debug("PPT Fast PMF APU[%d] = %u\n", i, info->val[i].ppt_fast_pmf_apu_only);
+ }
+
+ pr_debug("Static Slider APTS index default v2 values data - END\n");
+}
+
static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info)
{
int i;
@@ -119,8 +145,31 @@ static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info)
static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {}
static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2 *data) {}
static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info) {}
+static void amd_pmf_dump_apts_sps_defaults_v2(struct amd_pmf_apts_granular_v2 *info) {}
#endif
+static int amd_pmf_load_apts_defaults_sps_v3(struct amd_pmf_dev *pdev)
+{
+ struct amd_pmf_apts_granular_output_v2 output;
+ int i, ret;
+
+ memset(&apts_config_store_v2, 0, sizeof(apts_config_store_v2));
+
+ for (i = 0; i < APTS_MAX_STATES; i++) {
+ ret = apts_get_static_slider_granular_v3(pdev, &output, i);
+ if (ret) {
+ dev_err(pdev->dev, "Failed to read APTS v2 defaults: %d\n", ret);
+ return ret;
+ }
+
+ apts_config_store_v2.val[i] = output.val;
+ }
+
+ amd_pmf_dump_apts_sps_defaults_v2(&apts_config_store_v2);
+
+ return 0;
+}
+
static void amd_pmf_load_apts_defaults_sps_v2(struct amd_pmf_dev *pdev)
{
struct amd_pmf_apts_granular_output output;
@@ -190,6 +239,30 @@ static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
amd_pmf_dump_sps_defaults(&config_store);
}
+static void amd_pmf_update_slider_v3(struct amd_pmf_dev *dev, int idx)
+{
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_SPM, SET_CMD,
+ apts_config_store_v2.val[idx].pmf_slow_ppt, NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_APU_ONLY, SET_CMD,
+ apts_config_store_v2.val[idx].ppt_pmf_apu_only, NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_MIN_LIMIT, SET_CMD,
+ apts_config_store_v2.val[idx].stt_min_limit, NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_APU, SET_CMD,
+ fixp_q88_fromint(apts_config_store_v2.val[idx].stt_skin_temp_limit_apu),
+ NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_HS2, SET_CMD,
+ fixp_q88_fromint(apts_config_store_v2.val[idx].stt_skin_temp_limit_hs2),
+ NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_FPPT_SPM, SET_CMD,
+ apts_config_store_v2.val[idx].pmf_fast_ppt, NULL);
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_FPPT_APU_ONLY, SET_CMD,
+ apts_config_store_v2.val[idx].ppt_fast_pmf_apu_only, NULL);
+
+ if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX) &&
+ apts_config_store_v2.val[idx].fan_table_idx != FAN_INDEX_AUTO)
+ apmf_update_fan_idx(dev, true, apts_config_store_v2.val[idx].fan_table_idx);
+}
+
static void amd_pmf_update_slider_v2(struct amd_pmf_dev *dev, int idx)
{
amd_pmf_send_cmd(dev, SET_PMF_PPT, SET_CMD, apts_config_store.val[idx].pmf_ppt, NULL);
@@ -264,7 +337,10 @@ static int amd_pmf_update_sps_power_limits_v2(struct amd_pmf_dev *pdev, int pwr_
return -EINVAL;
}
- amd_pmf_update_slider_v2(pdev, index);
+ if (is_amd_pmf_1ah_m80h(pdev))
+ amd_pmf_update_slider_v3(pdev, index);
+ else
+ amd_pmf_update_slider_v2(pdev, index);
return 0;
}
@@ -418,12 +494,20 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {
int amd_pmf_init_sps(struct amd_pmf_dev *dev)
{
+ int ret;
+
dev->current_profile = PLATFORM_PROFILE_BALANCED;
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
if (dev->pmf_if_version == PMF_IF_V2) {
amd_pmf_load_defaults_sps_v2(dev);
- amd_pmf_load_apts_defaults_sps_v2(dev);
+ if (is_amd_pmf_1ah_m80h(dev)) {
+ ret = amd_pmf_load_apts_defaults_sps_v3(dev);
+ if (ret)
+ return ret;
+ } else {
+ amd_pmf_load_apts_defaults_sps_v2(dev);
+ }
} else {
amd_pmf_load_defaults_sps(dev);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 1/8] platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 2/8] platform/x86/amd/pmf: Add 1AH_M80H static slider support Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 4/8] platform/x86/amd/pmf: Get policy binary signature size from PSP header Shyam Sundar S K
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
The UUID list, the shared memory size and the init/enact calls of the
PMF Trusted Application (TA) are hardcoded in the driver. Upcoming
platforms use a different TA with its own shared memory layout, so
these need to be selected per platform.
Add struct amd_pmf_ta_ops to hold the per-platform TA details and use
it in place of the direct calls. All existing platforms use the
default ops, which point to the current functions.
No functional changes.
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/acpi.c | 2 +-
drivers/platform/x86/amd/pmf/core.c | 4 ++--
drivers/platform/x86/amd/pmf/pmf.h | 11 +++++++++++
drivers/platform/x86/amd/pmf/tee-if.c | 27 +++++++++++++++++++++------
4 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index 4392bf0bc0bf..24e6dffc608f 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -310,7 +310,7 @@ static void amd_pmf_handle_early_preq(struct amd_pmf_dev *pdev)
if (!pdev->cb_flag)
return;
- amd_pmf_invoke_cmd_enact(pdev);
+ pdev->ta_ops->invoke_enact(pdev);
pdev->cb_flag = false;
}
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index f7df72d3076b..06b7f9f2cda5 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -259,8 +259,8 @@ static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev)
bool status;
int ret, i;
- for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) {
- ret = amd_pmf_tee_init(pdev, &amd_pmf_ta_uuid[i]);
+ for (i = 0; i < pdev->ta_ops->num_uuids; i++) {
+ ret = amd_pmf_tee_init(pdev, &pdev->ta_ops->uuids[i]);
if (ret) {
dev_err(pdev->dev, "TEE init failed for UUID[%d] ret: %d\n", i, ret);
return ret;
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 73d981b25b38..d9fa99c2750f 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -650,6 +650,16 @@ struct amd_pmf_arg_data {
u32 size;
};
+struct amd_pmf_dev;
+
+struct amd_pmf_ta_ops {
+ const uuid_t *uuids;
+ int num_uuids;
+ size_t shm_size;
+ int (*invoke_init)(struct amd_pmf_dev *dev);
+ int (*invoke_enact)(struct amd_pmf_dev *dev);
+};
+
struct amd_pmf_dev {
void __iomem *regbase;
void __iomem *smu_virt_addr;
@@ -709,6 +719,7 @@ struct amd_pmf_dev {
struct amd_pmf_arg_data dram_addr;
struct amd_pmf_metrics_v3 prev_metrics; /* Previous metrics for delta calculation */
bool npu_metrics_have_prev;
+ const struct amd_pmf_ta_ops *ta_ops;
};
struct apmf_sps_prop_granular_v2 {
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 3fe79f0f37c5..e145eb7b03cd 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -55,7 +55,7 @@ static void amd_pmf_prepare_args(struct amd_pmf_dev *dev, int cmd,
arg->num_params = MAX_TEE_PARAM;
/* Fill invoke cmd params */
- param[0].u.memref.size = sizeof(struct ta_pmf_shared_memory);
+ param[0].u.memref.size = dev->ta_ops->shm_size;
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
param[0].u.memref.shm = dev->fw_shm_pool;
param[0].u.memref.shm_offs = 0;
@@ -323,7 +323,7 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
{
struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, pb_work.work);
- amd_pmf_invoke_cmd_enact(dev);
+ dev->ta_ops->invoke_enact(dev);
schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
}
@@ -347,7 +347,7 @@ int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
/* Update the actual length */
dev->policy_sz = header->length + 512;
- res = amd_pmf_invoke_cmd_init(dev);
+ res = dev->ta_ops->invoke_init(dev);
if (res == TA_PMF_TYPE_SUCCESS) {
/* Now its safe to announce that smart pc is enabled */
dev->smart_pc_enabled = true;
@@ -503,7 +503,7 @@ int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
goto out_ctx;
}
- size = sizeof(struct ta_pmf_shared_memory) + dev->policy_sz;
+ size = dev->ta_ops->shm_size + dev->policy_sz;
dev->fw_shm_pool = tee_shm_alloc_kernel_buf(dev->tee_ctx, size);
if (IS_ERR(dev->fw_shm_pool)) {
dev_err(dev->dev, "Failed to alloc TEE shared memory\n");
@@ -541,6 +541,19 @@ void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
dev->tee_ctx = NULL;
}
+static const struct amd_pmf_ta_ops amd_pmf_ta_default_ops = {
+ .uuids = amd_pmf_ta_uuid,
+ .num_uuids = ARRAY_SIZE(amd_pmf_ta_uuid),
+ .shm_size = sizeof(struct ta_pmf_shared_memory),
+ .invoke_init = amd_pmf_invoke_cmd_init,
+ .invoke_enact = amd_pmf_invoke_cmd_enact,
+};
+
+static void amd_pmf_select_ta_ops(struct amd_pmf_dev *dev)
+{
+ dev->ta_ops = &amd_pmf_ta_default_ops;
+}
+
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
{
bool status;
@@ -584,8 +597,10 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
if (!dev->prev_data)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) {
- ret = amd_pmf_tee_init(dev, &amd_pmf_ta_uuid[i]);
+ amd_pmf_select_ta_ops(dev);
+
+ for (i = 0; i < dev->ta_ops->num_uuids; i++) {
+ ret = amd_pmf_tee_init(dev, &dev->ta_ops->uuids[i]);
if (ret)
return ret;
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] platform/x86/amd/pmf: Get policy binary signature size from PSP header
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (2 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 3/8] platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 5/8] platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H Shyam Sundar S K
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
The policy binary size is calculated as the payload length plus a fixed
512 bytes, which assumes a 256 byte PSP header and a 256 byte RSA2K
signature. Newer policy binaries can be signed with RSA4K, which has a
512 byte signature.
Read the signature algorithm from the PSP header and use it to get the
signature size. Check that the buffer is large enough before reading
the header field, and that the size calculation does not overflow.
Policy binaries with an unknown signature algorithm are now rejected.
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/pmf.h | 8 +++++++
drivers/platform/x86/amd/pmf/tee-if.c | 34 +++++++++++++++++++++++++--
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index d9fa99c2750f..86999802602c 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -29,6 +29,14 @@
#define POLICY_SIGN_COOKIE 0x31535024
#define POLICY_COOKIE_OFFSET 0x10
+/* Policy binary PSP header */
+#define POLICY_PSP_HEADER_SIZE 256
+#define POLICY_PSP_SIG_ALG_OFFSET 0x34
+#define POLICY_PSP_SIG_ALG_RSA2K 0
+#define POLICY_PSP_SIG_ALG_RSA4K 2
+#define POLICY_PSP_SIG_SIZE_RSA2K 256
+#define POLICY_PSP_SIG_SIZE_RSA4K 512
+
/* List of supported CPU ids */
#define AMD_CPU_ID_RMB 0x14b5
#define AMD_CPU_ID_PS 0x14e8
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index e145eb7b03cd..9b328be1e8f4 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -11,7 +11,9 @@
#include <linux/array_size.h>
#include <linux/debugfs.h>
#include <linux/dev_printk.h>
+#include <linux/overflow.h>
#include <linux/tee_drv.h>
+#include <linux/unaligned.h>
#include <linux/uuid.h>
#include "pmf.h"
@@ -327,9 +329,32 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
}
+static int amd_pmf_get_pb_sig_size(struct amd_pmf_dev *dev, u32 *sig_size)
+{
+ u32 sig_alg;
+
+ if (dev->policy_sz < POLICY_PSP_SIG_ALG_OFFSET + sizeof(sig_alg))
+ return -EINVAL;
+
+ sig_alg = get_unaligned_le32(dev->policy_buf + POLICY_PSP_SIG_ALG_OFFSET);
+
+ switch (sig_alg) {
+ case POLICY_PSP_SIG_ALG_RSA2K:
+ *sig_size = POLICY_PSP_SIG_SIZE_RSA2K;
+ return 0;
+ case POLICY_PSP_SIG_ALG_RSA4K:
+ *sig_size = POLICY_PSP_SIG_SIZE_RSA4K;
+ return 0;
+ default:
+ dev_dbg(dev->dev, "Unknown PSP signature algorithm: %u\n", sig_alg);
+ return -EINVAL;
+ }
+}
+
int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
{
struct cookie_header *header;
+ u32 sig_size, total_sz;
int res;
if (dev->policy_sz < POLICY_COOKIE_OFFSET + sizeof(*header))
@@ -342,11 +367,16 @@ int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
return -EINVAL;
}
- if (dev->policy_sz < header->length + 512)
+ res = amd_pmf_get_pb_sig_size(dev, &sig_size);
+ if (res)
+ return res;
+
+ if (check_add_overflow(header->length, POLICY_PSP_HEADER_SIZE + sig_size, &total_sz) ||
+ dev->policy_sz < total_sz)
return -EINVAL;
/* Update the actual length */
- dev->policy_sz = header->length + 512;
+ dev->policy_sz = total_sz;
res = dev->ta_ops->invoke_init(dev);
if (res == TA_PMF_TYPE_SUCCESS) {
/* Now its safe to announce that smart pc is enabled */
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (3 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 4/8] platform/x86/amd/pmf: Get policy binary signature size from PSP header Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 6/8] platform/x86/amd/pmf: Remap metrics table on resume " Shyam Sundar S K
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
1AH_M80H uses a new PMF Trusted Application (TA) with its own UUID, a
larger shared memory layout and an extended set of policy conditions.
Add the v2 TA structures and the init/enact callbacks for this TA, and
select them through ta_ops on 1AH_M80H.
Battery, slider and sensor inputs reuse the existing helpers. SMU inputs
(socket power, skin temperature, GFX busy and C0 residency) are taken
from the accumulator based metrics table. Smart PC keeps its own
previous sample, so that it does not disturb the delta calculation of
the NPU metrics interface which reads the same table.
Key changes include:
- Add the v2 TA shared memory, condition and result structures
- Add amd_pmf_invoke_cmd_init_v2() and amd_pmf_invoke_cmd_enact_v2()
- Add amd_pmf_get_smu_info_v2() to read the accumulator metrics
- Apply the TA actions with the 1AH_M80H SMU message IDs
- Make the Q10 accumulator helpers and
amd_pmf_get_metrics_table_log_sample() available to spc.c
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/metrics.c | 9 +-
drivers/platform/x86/amd/pmf/pmf.h | 157 +++++++++++++++++++
drivers/platform/x86/amd/pmf/spc.c | 145 ++++++++++++++++++
drivers/platform/x86/amd/pmf/tee-if.c | 200 ++++++++++++++++++++++++-
4 files changed, 505 insertions(+), 6 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/metrics.c b/drivers/platform/x86/amd/pmf/metrics.c
index 5510dba95ce5..8c257ed1b455 100644
--- a/drivers/platform/x86/amd/pmf/metrics.c
+++ b/drivers/platform/x86/amd/pmf/metrics.c
@@ -28,22 +28,21 @@
static struct device *pmf_device;
-static u16 amd_pmf_q10_acc_to_mW(u64 avg_acc)
+u16 amd_pmf_q10_acc_to_mW(u64 avg_acc)
{
u64 val = DIV_U64_ROUND_CLOSEST(avg_acc, 1024) * MILLIWATT_PER_WATT;
return min_t(u16, val, U16_MAX);
}
-static u16 amd_pmf_q10_acc_to_int(u64 avg_acc)
+u16 amd_pmf_q10_acc_to_int(u64 avg_acc)
{
u64 val = DIV_U64_ROUND_CLOSEST(avg_acc, 1024);
return min_t(u16, val, U16_MAX);
}
-static u64 amd_pmf_avg_acc_metric(u32 curr_counter, u32 prev_counter,
- u64 curr_value, u64 prev_value)
+u64 amd_pmf_avg_acc_metric(u32 curr_counter, u32 prev_counter, u64 curr_value, u64 prev_value)
{
u32 counter_diff;
u64 val_diff;
@@ -92,7 +91,7 @@ int amd_pmf_get_tbl_dram_addr(struct amd_pmf_dev *dev)
return 0;
}
-static int amd_pmf_get_metrics_table_log_sample(struct amd_pmf_dev *dev)
+int amd_pmf_get_metrics_table_log_sample(struct amd_pmf_dev *dev)
{
int ret;
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 86999802602c..fff6fb3bf4e6 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -147,6 +147,15 @@ struct cookie_header {
#define TA_ERROR_CRYPTO_INVALID_PARAM 0x20002
#define TA_ERROR_CRYPTO_BIN_TOO_LARGE 0x2000d
+/* TA version-2 array sizes */
+#define TA_PMF_NUM_ACPI_SENSOR_DATA 3
+#define TA_PMF_ACPI_SENSOR_MAX 4
+#define TA_PMF_ACTION_MAX_V2 100
+#define TA_PMF_UNDO_MAX_V2 100
+#define TA_PMF_NAME_TRACKING_MAX 100
+#define TA_PMF_NAME_LENGTH_MAX 256
+#define SIDELOAD_POLICY_MAX 400
+
#define PMF_IF_V1 1
#define PMF_IF_V2 2
@@ -177,6 +186,11 @@ static const uuid_t amd_pmf_ta_uuid[] __used = { UUID_INIT(0xd9b39bf2, 0x66bd, 0
0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43),
};
+static const uuid_t amd_pmf_ta_uuid_v2[] __used = { UUID_INIT(0xf51cad64, 0xea14, 0x4789, 0xb6,
+ 0xae, 0x89, 0xec, 0x7a, 0x1b, 0x8b,
+ 0x94),
+ };
+
/* APTS PMF BIOS Interface */
struct amd_pmf_apts_output {
u16 table_version;
@@ -728,6 +742,8 @@ struct amd_pmf_dev {
struct amd_pmf_metrics_v3 prev_metrics; /* Previous metrics for delta calculation */
bool npu_metrics_have_prev;
const struct amd_pmf_ta_ops *ta_ops;
+ struct amd_pmf_metrics_v3 smartpc_prev_metrics; /* Smart PC delta baseline */
+ bool smartpc_metrics_have_prev;
};
struct apmf_sps_prop_granular_v2 {
@@ -1122,6 +1138,138 @@ struct ta_pmf_shared_memory {
union ta_pmf_input pmf_input;
};
+struct ta_pmf_name_eval_info {
+ u32 value1;
+ u32 value2;
+ u32 value3;
+};
+
+struct ta_pmf_name_eval_table {
+ s32 result_count;
+ struct ta_pmf_name_eval_info eval_results[TA_PMF_NAME_TRACKING_MAX];
+};
+
+struct ta_pmf_condition_info_v2 {
+ u32 power_source;
+ u32 bat_percentage;
+ u32 power_slider;
+ u32 lid_state;
+ u32 user_present;
+ u32 bios_input_1[2];
+ u32 monitor_count;
+ u32 mouse_count;
+ u32 keyboard_count;
+ u32 bat_design;
+ u32 full_charge_capacity;
+ s32 drain_rate;
+ u32 user_engaged;
+ u32 device_state;
+ u32 socket_power;
+ u32 skin_temperature;
+ u32 day_of_week;
+ u32 sys_time_minutes;
+ u32 platform_type;
+ u32 app_input1;
+ u32 app_input2;
+ u32 ambient_light;
+ u32 proc_queue_len;
+ u32 avg_c0residency;
+ u32 max_c0residency;
+ u32 s0i3_entry;
+ u32 gfx_busy;
+ u32 proc_time_avg;
+ u32 proc_time_max;
+ u32 irq_per_sec_avg;
+ u32 irq_per_sec_max;
+ u32 gpu_engine_time;
+ u32 gpu_engine_util;
+ u32 user_input_delay;
+ u32 camera_state;
+ u32 workload_type;
+ u32 display_type;
+ u32 display_state;
+ u32 asm_state;
+ u32 sensor_data[TA_PMF_ACPI_SENSOR_MAX * TA_PMF_NUM_ACPI_SENSOR_DATA];
+ u32 sensor_status[TA_PMF_ACPI_SENSOR_MAX];
+ u32 combined_socket_pwr;
+ u32 bios_input_2[8];
+ u32 hetero_state;
+ u32 game_mode;
+ u32 activity_balance;
+ u32 pepl_level;
+ u32 transport_mode;
+ u32 asm_supported;
+ u32 workload_class;
+ u32 video_enc_sessions;
+ u32 video_dec_sessions;
+ u32 rsvd[10];
+};
+
+struct ta_pmf_enact_table_v2 {
+ struct ta_pmf_condition_info_v2 ev_info;
+ struct ta_pmf_name_eval_table name_ev_info;
+};
+
+union ta_pmf_input_v2 {
+ struct ta_pmf_enact_table_v2 enact_table;
+ struct ta_pmf_init_table init_table;
+};
+
+struct ta_pmf_sideload_policy_info {
+ u16 num_policies;
+ u32 priorities[SIDELOAD_POLICY_MAX];
+ bool expression_result[SIDELOAD_POLICY_MAX];
+ bool policy_applied[SIDELOAD_POLICY_MAX];
+};
+
+struct ta_pmf_agm_log_table {
+ s32 policies_applied_count;
+ u32 policy_priority_list[TA_PMF_ACTION_MAX_V2];
+};
+
+struct ta_pmf_enact_result_v2 {
+ u32 actions_count;
+ struct ta_pmf_action actions_list[TA_PMF_ACTION_MAX_V2];
+ u32 undo_count;
+ struct ta_pmf_action undo_list[TA_PMF_UNDO_MAX_V2];
+ struct ta_pmf_agm_log_table agm_log_table;
+ struct ta_pmf_sideload_policy_info sideload_policy_info;
+};
+
+struct ta_pmf_name_info {
+ u32 type;
+ u16 name[TA_PMF_NAME_LENGTH_MAX];
+};
+
+struct ta_pmf_oem_debug_table {
+ u16 oem_major_version;
+ u16 oem_minor_version;
+};
+
+struct ta_pmf_load_policy_result {
+ bool add_policy_success;
+ bool sideload_enabled;
+ struct ta_pmf_oem_debug_table oem_table;
+ u64 conditions_to_track[8];
+ u32 max_policy_sppt_limit;
+ s32 name_count;
+ struct ta_pmf_name_info name_table;
+};
+
+union ta_pmf_output_v2 {
+ struct ta_pmf_load_policy_result load_policy_result;
+ struct ta_pmf_enact_result_v2 policy_apply_table;
+};
+
+struct ta_pmf_shared_memory_v2 {
+ int command_id;
+ int resp_id;
+ u32 pmf_result;
+ u32 if_version;
+ union ta_pmf_output_v2 pmf_output;
+ union ta_pmf_input_v2 pmf_input;
+};
+
/* Core Layer */
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
@@ -1185,6 +1333,10 @@ static inline u32 fixp_q88_fromint(u32 val)
/* Metrics layer */
int amd_pmf_get_tbl_dram_addr(struct amd_pmf_dev *dev);
+int amd_pmf_get_metrics_table_log_sample(struct amd_pmf_dev *dev);
+u64 amd_pmf_avg_acc_metric(u32 curr_counter, u32 prev_counter, u64 curr_value, u64 prev_value);
+u16 amd_pmf_q10_acc_to_mW(u64 avg_acc);
+u16 amd_pmf_q10_acc_to_int(u64 avg_acc);
/* SPS Layer */
int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
@@ -1304,6 +1456,8 @@ int amd_pmf_smartpc_apply_bios_output(struct amd_pmf_dev *dev, u32 val, u32 preq
/* Smart PC - TA interfaces */
void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev);
+void amd_pmf_populate_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in);
+int amd_pmf_invoke_cmd_enact_v2(struct amd_pmf_dev *dev);
static inline u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *in, int index)
{
@@ -1319,8 +1473,11 @@ static inline u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *i
#ifdef CONFIG_AMD_PMF_DEBUG
void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
+void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in);
#else
static inline void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in) {}
+static inline void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev,
+ struct ta_pmf_enact_table_v2 *in) {}
#endif
int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index a12b4ee965a2..e1f2ea268d4e 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -13,11 +13,45 @@
#include <linux/amd-pmf.h>
#include <linux/amd-pmf-io.h>
#include <linux/cleanup.h>
+#include <linux/io.h>
+#include <linux/math64.h>
#include <linux/power_supply.h>
#include <linux/units.h>
#include "pmf.h"
+/*
+ * The metrics table reports C0 residency per CCX, while the enabled cores
+ * are reported per core type. Core types 0-2 belong to CCX0 and type 3
+ * to CCX1.
+ */
+static const u8 core_type_to_ccx[AMD_PMF_METRIC_CORE_TYPE_MAX] = { 0, 0, 0, 1 };
+
#ifdef CONFIG_AMD_PMF_DEBUG
+void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in)
+{
+ dev_dbg(dev->dev, "==== TA v2 inputs START ====\n");
+ dev_dbg(dev->dev, "Slider State: %s\n",
+ amd_pmf_get_slider_position(in->ev_info.power_slider));
+ dev_dbg(dev->dev, "Power Source: %s\n", amd_pmf_source_as_str(in->ev_info.power_source));
+ dev_dbg(dev->dev, "Battery Percentage: %u\n", in->ev_info.bat_percentage);
+ dev_dbg(dev->dev, "Designed Battery Capacity: %u\n", in->ev_info.bat_design);
+ dev_dbg(dev->dev, "Fully Charged Capacity: %u\n", in->ev_info.full_charge_capacity);
+ dev_dbg(dev->dev, "Drain Rate: %d\n", in->ev_info.drain_rate);
+ dev_dbg(dev->dev, "Socket Power: %u\n", in->ev_info.socket_power);
+ dev_dbg(dev->dev, "Skin Temperature: %u\n", in->ev_info.skin_temperature);
+ dev_dbg(dev->dev, "Avg C0 Residency: %u\n", in->ev_info.avg_c0residency);
+ dev_dbg(dev->dev, "Max C0 Residency: %u\n", in->ev_info.max_c0residency);
+ dev_dbg(dev->dev, "GFX Busy: %u\n", in->ev_info.gfx_busy);
+ dev_dbg(dev->dev, "LID State: %s\n", in->ev_info.lid_state ? "close" : "open");
+ dev_dbg(dev->dev, "User Presence: %s\n", in->ev_info.user_present ? "Present" : "Away");
+ dev_dbg(dev->dev, "Ambient Light: %u\n", in->ev_info.ambient_light);
+ dev_dbg(dev->dev, "Platform type: %s\n",
+ amd_pmf_get_platform_type(in->ev_info.platform_type));
+ dev_dbg(dev->dev, "Laptop placement: %s\n",
+ amd_pmf_get_laptop_placement(in->ev_info.device_state));
+ dev_dbg(dev->dev, "==== TA v2 inputs END ====\n");
+}
+
void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
{
int i;
@@ -121,6 +155,49 @@ static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev,
rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1);
}
+static void amd_pmf_get_c0_residency_v2(struct amd_pmf_metrics_v3 *curr,
+ struct amd_pmf_metrics_v3 *prev,
+ struct ta_pmf_enact_table_v2 *in)
+{
+ u32 curr_counter = curr->iod.counter_acc;
+ u32 prev_counter = prev->iod.counter_acc;
+ int active_cores = 0, core, type;
+ u64 sum_of_avgs = 0;
+ u32 local_max = 0;
+
+ if (!curr_counter) {
+ in->ev_info.avg_c0residency = 0;
+ in->ev_info.max_c0residency = 0;
+ return;
+ }
+
+ for (type = 0; type < ARRAY_SIZE(core_type_to_ccx); type++) {
+ u8 ccx = core_type_to_ccx[type];
+
+ for (core = 0; core < AMD_PMF_NUM_MAX_CORES; core++) {
+ u32 core_avg;
+ u64 avg_acc;
+
+ /* Skip cores which are not enabled */
+ if (!curr->iod.cclk_core_enabled[type][core])
+ continue;
+
+ avg_acc = amd_pmf_avg_acc_metric(curr_counter, prev_counter,
+ curr->ccx[ccx].core_c0[core],
+ prev->ccx[ccx].core_c0[core]);
+ core_avg = amd_pmf_q10_acc_to_int(avg_acc);
+ sum_of_avgs += core_avg;
+ active_cores++;
+
+ if (core_avg > local_max)
+ local_max = core_avg;
+ }
+ }
+
+ in->ev_info.avg_c0residency = active_cores ? div_u64(sum_of_avgs, active_cores) : 0;
+ in->ev_info.max_c0residency = local_max;
+}
+
static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in)
{
u16 max, avg = 0;
@@ -138,6 +215,50 @@ static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_e
in->ev_info.max_c0residency = max;
}
+static void amd_pmf_get_smu_info_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in)
+{
+ struct amd_pmf_metrics_iod *curr, *prev;
+ u64 val;
+ int ret;
+
+ guard(mutex)(&dev->metrics_mutex);
+
+ ret = amd_pmf_get_metrics_table_log_sample(dev);
+ if (ret)
+ return;
+
+ memcpy_fromio(&dev->mtable_v3, dev->metrics_table_virt, sizeof(dev->mtable_v3));
+
+ if (!dev->smartpc_metrics_have_prev) {
+ memcpy(&dev->smartpc_prev_metrics, &dev->mtable_v3, sizeof(dev->mtable_v3));
+ dev->smartpc_metrics_have_prev = true;
+ return;
+ }
+
+ curr = &dev->mtable_v3.iod;
+ prev = &dev->smartpc_prev_metrics.iod;
+
+ val = amd_pmf_avg_acc_metric(curr->counter_acc, prev->counter_acc,
+ curr->apu_power_acc, prev->apu_power_acc);
+ in->ev_info.socket_power = amd_pmf_q10_acc_to_mW(val);
+
+ val = amd_pmf_avg_acc_metric(curr->counter_acc, prev->counter_acc,
+ curr->dgpu_power_acc, prev->dgpu_power_acc);
+ in->ev_info.socket_power += amd_pmf_q10_acc_to_mW(val);
+
+ val = amd_pmf_avg_acc_metric(curr->counter_acc, prev->counter_acc,
+ curr->stt_apu_skin_temp_acc, prev->stt_apu_skin_temp_acc);
+ in->ev_info.skin_temperature = amd_pmf_q10_acc_to_int(val);
+
+ val = amd_pmf_avg_acc_metric(curr->counter_acc, prev->counter_acc,
+ curr->gfx_busy_acc, prev->gfx_busy_acc);
+ in->ev_info.gfx_busy = amd_pmf_q10_acc_to_int(val);
+
+ amd_pmf_get_c0_residency_v2(&dev->mtable_v3, &dev->smartpc_prev_metrics, in);
+
+ memcpy(&dev->smartpc_prev_metrics, &dev->mtable_v3, sizeof(dev->mtable_v3));
+}
+
static void amd_pmf_get_smu_info(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
{
/* Get the updated metrics table data */
@@ -268,6 +389,30 @@ static void amd_pmf_get_sensor_info(struct amd_pmf_dev *dev, struct ta_pmf_enact
}
}
+void amd_pmf_populate_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in)
+{
+ struct ta_pmf_enact_table tmp = { };
+
+ in->ev_info.lid_state = !acpi_lid_open();
+ in->ev_info.power_source = amd_pmf_get_power_source();
+
+ amd_pmf_get_battery_info(dev, &tmp);
+ amd_pmf_get_slider_info(dev, &tmp);
+ amd_pmf_get_sensor_info(dev, &tmp);
+
+ in->ev_info.bat_percentage = tmp.ev_info.bat_percentage;
+ in->ev_info.bat_design = tmp.ev_info.bat_design;
+ in->ev_info.full_charge_capacity = tmp.ev_info.full_charge_capacity;
+ in->ev_info.drain_rate = tmp.ev_info.drain_rate;
+ in->ev_info.power_slider = tmp.ev_info.power_slider;
+ in->ev_info.user_present = tmp.ev_info.user_present;
+ in->ev_info.ambient_light = tmp.ev_info.ambient_light;
+ in->ev_info.platform_type = tmp.ev_info.platform_type;
+ in->ev_info.device_state = tmp.ev_info.device_state;
+
+ amd_pmf_get_smu_info_v2(dev, in);
+}
+
void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
{
/* TA side lid open is 1 and close is 0, hence the ! here */
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 9b328be1e8f4..2ed9014cb7c4 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -115,6 +115,110 @@ static void amd_pmf_update_bios_output(struct amd_pmf_dev *pdev, struct ta_pmf_a
pdev->bios_output[bios_idx] = action->value;
}
+static void amd_pmf_apply_policies_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_result_v2 *out)
+{
+ struct ta_pmf_action *action;
+ u32 val;
+ int idx;
+
+ if (out->actions_count > TA_PMF_ACTION_MAX_V2) {
+ dev_err(dev->dev, "TA actions count %u exceeds max %u\n",
+ out->actions_count, TA_PMF_ACTION_MAX_V2);
+ return;
+ }
+
+ for (idx = 0; idx < out->actions_count; idx++) {
+ action = &out->actions_list[idx];
+ val = action->value;
+ switch (action->action_index) {
+ case PMF_POLICY_SPPT:
+ if (dev->prev_data->sppt != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_SPM,
+ SET_CMD, val, NULL);
+ dev_dbg(dev->dev, "update SPPT: %u\n", val);
+ dev->prev_data->sppt = val;
+ }
+ break;
+
+ case PMF_POLICY_FPPT:
+ if (dev->prev_data->fppt != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_FPPT_SPM,
+ SET_CMD, val, NULL);
+ dev_dbg(dev->dev, "update FPPT: %u\n", val);
+ dev->prev_data->fppt = val;
+ }
+ break;
+
+ case PMF_POLICY_SPPT_APU_ONLY:
+ if (dev->prev_data->sppt_apuonly != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_APU_ONLY,
+ SET_CMD, val, NULL);
+ dev_dbg(dev->dev, "update SPPT_APU_ONLY: %u\n", val);
+ dev->prev_data->sppt_apuonly = val;
+ }
+ break;
+
+ case PMF_POLICY_STT_MIN:
+ if (dev->prev_data->stt_minlimit != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_MIN_LIMIT,
+ SET_CMD, val, NULL);
+ dev_dbg(dev->dev, "update STT_MIN: %u\n", val);
+ dev->prev_data->stt_minlimit = val;
+ }
+ break;
+
+ case PMF_POLICY_STT_SKINTEMP_APU:
+ if (dev->prev_data->stt_skintemp_apu != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_APU, SET_CMD,
+ fixp_q88_fromint(val), NULL);
+ dev_dbg(dev->dev, "update STT_LIMIT_APU: %u\n", val);
+ dev->prev_data->stt_skintemp_apu = val;
+ }
+ break;
+
+ case PMF_POLICY_STT_SKINTEMP_HS2:
+ if (dev->prev_data->stt_skintemp_hs2 != val) {
+ amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_HS2, SET_CMD,
+ fixp_q88_fromint(val), NULL);
+ dev_dbg(dev->dev, "update STT_LIMIT_HS2: %u\n", val);
+ dev->prev_data->stt_skintemp_hs2 = val;
+ }
+ break;
+
+ case PMF_POLICY_SYSTEM_STATE:
+ switch (val) {
+ case 0:
+ amd_pmf_update_uevents(dev, KEY_SLEEP);
+ break;
+ case 1:
+ amd_pmf_update_uevents(dev, KEY_SUSPEND);
+ break;
+ case 2:
+ amd_pmf_update_uevents(dev, KEY_SCREENLOCK);
+ break;
+ default:
+ dev_err(dev->dev, "Invalid PMF policy system state: %u\n", val);
+ }
+
+ dev_dbg(dev->dev, "update SYSTEM_STATE: %s\n", amd_pmf_uevent_as_str(val));
+ break;
+
+ case PMF_POLICY_BIOS_OUTPUT_1:
+ case PMF_POLICY_BIOS_OUTPUT_2:
+ case PMF_POLICY_BIOS_OUTPUT_3:
+ case PMF_POLICY_BIOS_OUTPUT_4:
+ case PMF_POLICY_BIOS_OUTPUT_5:
+ case PMF_POLICY_BIOS_OUTPUT_6:
+ case PMF_POLICY_BIOS_OUTPUT_7:
+ case PMF_POLICY_BIOS_OUTPUT_8:
+ case PMF_POLICY_BIOS_OUTPUT_9:
+ case PMF_POLICY_BIOS_OUTPUT_10:
+ amd_pmf_update_bios_output(dev, action);
+ break;
+ }
+ }
+}
+
static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
{
struct ta_pmf_action *action;
@@ -242,6 +346,46 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
}
}
+int amd_pmf_invoke_cmd_enact_v2(struct amd_pmf_dev *dev)
+{
+ struct ta_pmf_shared_memory_v2 *ta_sm = NULL;
+ struct ta_pmf_enact_result_v2 *out = NULL;
+ struct ta_pmf_enact_table_v2 *in = NULL;
+ struct tee_param param[MAX_TEE_PARAM];
+ struct tee_ioctl_invoke_arg arg;
+ int ret = 0;
+
+ if (!dev->tee_ctx)
+ return -ENODEV;
+
+ memset(dev->shbuf, 0, dev->policy_sz);
+ ta_sm = dev->shbuf;
+ in = &ta_sm->pmf_input.enact_table;
+ out = &ta_sm->pmf_output.policy_apply_table;
+
+ memset(ta_sm, 0, sizeof(*ta_sm));
+ ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES;
+ ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
+
+ amd_pmf_populate_ta_inputs_v2(dev, in);
+ amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER_ENACT_POLICIES, &arg, param);
+
+ ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ dev_err(dev->dev, "TEE enact cmd failed. err: %x, ret:%d\n", arg.ret, ret);
+ return ret;
+ }
+
+ if (ta_sm->pmf_result == TA_PMF_TYPE_SUCCESS && out->actions_count) {
+ amd_pmf_dump_ta_inputs_v2(dev, in);
+ dev_dbg(dev->dev, "TA v2 action count:%u result:%x\n", out->actions_count,
+ ta_sm->pmf_result);
+ amd_pmf_apply_policies_v2(dev, out);
+ }
+
+ return 0;
+}
+
int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
{
struct ta_pmf_shared_memory *ta_sm = NULL;
@@ -282,6 +426,45 @@ int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
return 0;
}
+static int amd_pmf_invoke_cmd_init_v2(struct amd_pmf_dev *dev)
+{
+ struct ta_pmf_shared_memory_v2 *ta_sm = NULL;
+ struct tee_param param[MAX_TEE_PARAM];
+ struct ta_pmf_init_table *in = NULL;
+ struct tee_ioctl_invoke_arg arg;
+ int ret = 0;
+
+ if (!dev->tee_ctx) {
+ dev_err(dev->dev, "Failed to get TEE context\n");
+ return -ENODEV;
+ }
+
+ dev_dbg(dev->dev, "Policy Binary size: %llu bytes\n", (unsigned long long)dev->policy_sz);
+ memset(dev->shbuf, 0, dev->policy_sz);
+ ta_sm = dev->shbuf;
+
+ ta_sm->command_id = TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE;
+ ta_sm->if_version = PMF_TA_IF_VERSION_MAJOR;
+ in = &ta_sm->pmf_input.init_table;
+
+ in->metadata_macrocheck = false;
+ in->sku_check = false;
+ in->validate = true;
+ in->frequency = pb_actions_ms;
+ in->policies_table.table_size = dev->policy_sz;
+
+ memcpy(in->policies_table.table, dev->policy_buf, dev->policy_sz);
+ amd_pmf_prepare_args(dev, TA_PMF_COMMAND_POLICY_BUILDER_INITIALIZE, &arg, param);
+
+ ret = tee_client_invoke_func(dev->tee_ctx, &arg, param);
+ if (ret < 0 || arg.ret != 0) {
+ dev_err(dev->dev, "Failed to invoke TEE init cmd. err: %x, ret:%d\n", arg.ret, ret);
+ return ret;
+ }
+
+ return ta_sm->pmf_result;
+}
+
static int amd_pmf_invoke_cmd_init(struct amd_pmf_dev *dev)
{
struct ta_pmf_shared_memory *ta_sm = NULL;
@@ -579,9 +762,24 @@ static const struct amd_pmf_ta_ops amd_pmf_ta_default_ops = {
.invoke_enact = amd_pmf_invoke_cmd_enact,
};
+static const struct amd_pmf_ta_ops amd_pmf_ta_ops_v2 = {
+ .uuids = amd_pmf_ta_uuid_v2,
+ .num_uuids = ARRAY_SIZE(amd_pmf_ta_uuid_v2),
+ .shm_size = sizeof(struct ta_pmf_shared_memory_v2),
+ .invoke_enact = amd_pmf_invoke_cmd_enact_v2,
+ .invoke_init = amd_pmf_invoke_cmd_init_v2,
+};
+
static void amd_pmf_select_ta_ops(struct amd_pmf_dev *dev)
{
- dev->ta_ops = &amd_pmf_ta_default_ops;
+ switch (dev->cpu_id) {
+ case PCI_DEVICE_ID_AMD_1AH_M80H_ROOT:
+ dev->ta_ops = &amd_pmf_ta_ops_v2;
+ break;
+ default:
+ dev->ta_ops = &amd_pmf_ta_default_ops;
+ break;
+ }
}
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] platform/x86/amd/pmf: Remap metrics table on resume for 1AH_M80H
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (4 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 5/8] platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 7/8] platform/x86/amd/pmf: Add custom BIOS input support " Shyam Sundar S K
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
On 1AH_M80H the metrics table address is provided by PMFW, and PMFW may
place the table at a different address after a suspend/resume or
hibernate cycle. Reading through the old mapping then returns wrong
accumulator values, which end up as wrong inputs to the TA and the NPU
metrics interface.
Add amd_pmf_remap_metrics_table() and call it from the resume and
restore handlers. It gets the table address from PMFW again and maps
it under metrics_mutex. The previous samples of Smart PC and NPU
metrics are dropped, so that the first sample after resume starts a
new baseline.
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/core.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 06b7f9f2cda5..3d9029351041 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -277,6 +277,24 @@ static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev)
return 0;
}
+static int amd_pmf_remap_metrics_table(struct amd_pmf_dev *pdev)
+{
+ if (!amd_pmf_supports_accumulator_metrics(pdev))
+ return 0;
+
+ guard(mutex)(&pdev->metrics_mutex);
+
+ if (pdev->metrics_table_virt) {
+ devm_iounmap(pdev->dev, pdev->metrics_table_virt);
+ pdev->metrics_table_virt = NULL;
+ }
+
+ pdev->smartpc_metrics_have_prev = false;
+ pdev->npu_metrics_have_prev = false;
+
+ return amd_pmf_get_tbl_dram_addr(pdev);
+}
+
static int amd_pmf_restore_handler(struct device *dev)
{
struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
@@ -288,6 +306,10 @@ static int amd_pmf_restore_handler(struct device *dev)
return ret;
}
+ ret = amd_pmf_remap_metrics_table(pdev);
+ if (ret)
+ return ret;
+
if (pdev->smart_pc_enabled)
amd_pmf_reinit_ta(pdev);
@@ -336,6 +358,10 @@ static int amd_pmf_resume_handler(struct device *dev)
if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_RESUME);
+ ret = amd_pmf_remap_metrics_table(pdev);
+ if (ret)
+ return ret;
+
if (pdev->smart_pc_enabled)
schedule_delayed_work(&pdev->pb_work, msecs_to_jiffies(2000));
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] platform/x86/amd/pmf: Add custom BIOS input support for 1AH_M80H
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (5 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 6/8] platform/x86/amd/pmf: Remap metrics table on resume " Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 8/8] platform/x86/amd/pmf: Share TA policy apply code between TA versions Shyam Sundar S K
2026-10-12 16:36 ` [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Mario Limonciello
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
Custom BIOS inputs 1-10 are reported through the APMF SBIOS requests
function in the same way as on 1AH_M20H and 1AH_M60H, but on 1AH_M80H
they are not passed to the TA yet.
Store the inputs in the existing ring buffer on 1AH_M80H and fill them
into the v2 TA condition table. The SBIOS request layout up to the
custom inputs is the same, so the existing structure is used.
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/acpi.c | 1 +
drivers/platform/x86/amd/pmf/pmf.h | 12 ++++++
drivers/platform/x86/amd/pmf/spc.c | 61 +++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index 24e6dffc608f..20e9603d5c08 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -288,6 +288,7 @@ static void amd_pmf_custom_bios_inputs_rb(struct amd_pmf_dev *pmf_dev)
break;
case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT:
case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
+ case PCI_DEVICE_ID_AMD_1AH_M80H_ROOT:
for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
rb->data[rb->head].val[i] = pmf_dev->req.custom_policy[i];
rb->data[rb->head].preq = pmf_dev->req.pending_req;
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index fff6fb3bf4e6..70ed0b07faae 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -1471,6 +1471,18 @@ static inline u32 amd_pmf_get_ta_custom_bios_inputs(struct ta_pmf_enact_table *i
}
}
+static inline u32 amd_pmf_get_ta_custom_bios_inputs_v2(struct ta_pmf_enact_table_v2 *in, int index)
+{
+ switch (index) {
+ case 0 ... 1:
+ return in->ev_info.bios_input_1[index];
+ case 2 ... 9:
+ return in->ev_info.bios_input_2[index - 2];
+ default:
+ return 0;
+ }
+}
+
#ifdef CONFIG_AMD_PMF_DEBUG
void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in);
diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c
index e1f2ea268d4e..4c6e32a50ab2 100644
--- a/drivers/platform/x86/amd/pmf/spc.c
+++ b/drivers/platform/x86/amd/pmf/spc.c
@@ -29,6 +29,8 @@ static const u8 core_type_to_ccx[AMD_PMF_METRIC_CORE_TYPE_MAX] = { 0, 0, 0, 1 };
#ifdef CONFIG_AMD_PMF_DEBUG
void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_table_v2 *in)
{
+ int i;
+
dev_dbg(dev->dev, "==== TA v2 inputs START ====\n");
dev_dbg(dev->dev, "Slider State: %s\n",
amd_pmf_get_slider_position(in->ev_info.power_slider));
@@ -49,6 +51,9 @@ void amd_pmf_dump_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_tabl
amd_pmf_get_platform_type(in->ev_info.platform_type));
dev_dbg(dev->dev, "Laptop placement: %s\n",
amd_pmf_get_laptop_placement(in->ev_info.device_state));
+ for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
+ dev_dbg(dev->dev, "Custom BIOS input%d: %u\n", i + 1,
+ amd_pmf_get_ta_custom_bios_inputs_v2(in, i));
dev_dbg(dev->dev, "==== TA v2 inputs END ====\n");
}
@@ -83,6 +88,19 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
}
#endif
+static void amd_pmf_set_ta_custom_bios_input_v2(struct ta_pmf_enact_table_v2 *in,
+ int index, u32 value)
+{
+ switch (index) {
+ case 0 ... 1:
+ in->ev_info.bios_input_1[index] = value;
+ break;
+ case 2 ... 9:
+ in->ev_info.bios_input_2[index - 2] = value;
+ break;
+ }
+}
+
/*
* This helper function sets the appropriate BIOS input value in the TA enact
* table based on the provided index. We need this approach because the custom
@@ -102,6 +120,21 @@ static void amd_pmf_set_ta_custom_bios_input(struct ta_pmf_enact_table *in, int
}
}
+static void amd_pmf_update_bios_inputs_v2(struct amd_pmf_dev *pdev,
+ struct pmf_bios_input_entry *data,
+ struct ta_pmf_enact_table_v2 *in)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) {
+ if (!(data->preq & custom_bios_inputs[i].bit_mask))
+ continue;
+ amd_pmf_set_ta_custom_bios_input_v2(in, i, data->val[i]);
+ pdev->cb_prev.custom_bios_inputs[i] = data->val[i];
+ dev_dbg(pdev->dev, "Custom BIOS Input[%d]: %u\n", i, data->val[i]);
+ }
+}
+
static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, struct pmf_bios_input_entry *data,
const struct amd_pmf_pb_bitmap *inputs,
struct ta_pmf_enact_table *in)
@@ -117,6 +150,33 @@ static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, struct pmf_bios
}
}
+static void amd_pmf_get_custom_bios_inputs_v2(struct amd_pmf_dev *pdev,
+ struct ta_pmf_enact_table_v2 *in)
+{
+ struct pmf_cbi_ring_buffer *rb = &pdev->cbi_buf;
+ unsigned int i;
+
+ guard(mutex)(&pdev->cbi_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++)
+ amd_pmf_set_ta_custom_bios_input_v2(in, i, pdev->cb_prev.custom_bios_inputs[i]);
+
+ if (CIRC_CNT(rb->head, rb->tail, CUSTOM_BIOS_INPUT_RING_ENTRIES) == 0)
+ return;
+
+ /* If no active custom BIOS input pending request, do not consume further work */
+ if (!rb->data[rb->tail].preq)
+ goto out_rbadvance;
+
+ if (!pdev->smart_pc_enabled)
+ return;
+
+ amd_pmf_update_bios_inputs_v2(pdev, &rb->data[rb->tail], in);
+
+out_rbadvance:
+ rb->tail = (rb->tail + 1) & (CUSTOM_BIOS_INPUT_RING_ENTRIES - 1);
+}
+
static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev,
struct ta_pmf_enact_table *in)
{
@@ -411,6 +471,7 @@ void amd_pmf_populate_ta_inputs_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_
in->ev_info.device_state = tmp.ev_info.device_state;
amd_pmf_get_smu_info_v2(dev, in);
+ amd_pmf_get_custom_bios_inputs_v2(dev, in);
}
void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in)
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] platform/x86/amd/pmf: Share TA policy apply code between TA versions
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (6 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 7/8] platform/x86/amd/pmf: Add custom BIOS input support " Shyam Sundar S K
@ 2026-10-11 10:05 ` Shyam Sundar S K
2026-10-12 16:36 ` [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Mario Limonciello
8 siblings, 0 replies; 10+ messages in thread
From: Shyam Sundar S K @ 2026-10-11 10:05 UTC (permalink / raw)
To: hansg, ilpo.jarvinen
Cc: platform-driver-x86, Patil.Reddy, mario.limonciello,
Shyam Sundar S K
amd_pmf_apply_policies() and amd_pmf_apply_policies_v2() handle the
same TA actions and differ only in the SMU message IDs used to program
the limits.
Add a table of SMU message IDs to ta_ops and use a single function for
both TA versions. Actions without a message ID on a platform are
ignored, as before. The check on the number of actions returned by
the TA now applies to all platforms.
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
drivers/platform/x86/amd/pmf/pmf.h | 3 +
drivers/platform/x86/amd/pmf/tee-if.c | 197 +++++++++-----------------
2 files changed, 73 insertions(+), 127 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 70ed0b07faae..ac9a99fd9449 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -674,10 +674,13 @@ struct amd_pmf_arg_data {
struct amd_pmf_dev;
+struct amd_pmf_policy_msg_ids;
+
struct amd_pmf_ta_ops {
const uuid_t *uuids;
int num_uuids;
size_t shm_size;
+ const struct amd_pmf_policy_msg_ids *msg_ids;
int (*invoke_init)(struct amd_pmf_dev *dev);
int (*invoke_enact)(struct amd_pmf_dev *dev);
};
diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
index 2ed9014cb7c4..1e9262764395 100644
--- a/drivers/platform/x86/amd/pmf/tee-if.c
+++ b/drivers/platform/x86/amd/pmf/tee-if.c
@@ -115,163 +115,102 @@ static void amd_pmf_update_bios_output(struct amd_pmf_dev *pdev, struct ta_pmf_a
pdev->bios_output[bios_idx] = action->value;
}
-static void amd_pmf_apply_policies_v2(struct amd_pmf_dev *dev, struct ta_pmf_enact_result_v2 *out)
-{
- struct ta_pmf_action *action;
- u32 val;
- int idx;
-
- if (out->actions_count > TA_PMF_ACTION_MAX_V2) {
- dev_err(dev->dev, "TA actions count %u exceeds max %u\n",
- out->actions_count, TA_PMF_ACTION_MAX_V2);
- return;
- }
-
- for (idx = 0; idx < out->actions_count; idx++) {
- action = &out->actions_list[idx];
- val = action->value;
- switch (action->action_index) {
- case PMF_POLICY_SPPT:
- if (dev->prev_data->sppt != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_SPM,
- SET_CMD, val, NULL);
- dev_dbg(dev->dev, "update SPPT: %u\n", val);
- dev->prev_data->sppt = val;
- }
- break;
-
- case PMF_POLICY_FPPT:
- if (dev->prev_data->fppt != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_FPPT_SPM,
- SET_CMD, val, NULL);
- dev_dbg(dev->dev, "update FPPT: %u\n", val);
- dev->prev_data->fppt = val;
- }
- break;
-
- case PMF_POLICY_SPPT_APU_ONLY:
- if (dev->prev_data->sppt_apuonly != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_PMF_SPPT_APU_ONLY,
- SET_CMD, val, NULL);
- dev_dbg(dev->dev, "update SPPT_APU_ONLY: %u\n", val);
- dev->prev_data->sppt_apuonly = val;
- }
- break;
-
- case PMF_POLICY_STT_MIN:
- if (dev->prev_data->stt_minlimit != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_MIN_LIMIT,
- SET_CMD, val, NULL);
- dev_dbg(dev->dev, "update STT_MIN: %u\n", val);
- dev->prev_data->stt_minlimit = val;
- }
- break;
-
- case PMF_POLICY_STT_SKINTEMP_APU:
- if (dev->prev_data->stt_skintemp_apu != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_APU, SET_CMD,
- fixp_q88_fromint(val), NULL);
- dev_dbg(dev->dev, "update STT_LIMIT_APU: %u\n", val);
- dev->prev_data->stt_skintemp_apu = val;
- }
- break;
-
- case PMF_POLICY_STT_SKINTEMP_HS2:
- if (dev->prev_data->stt_skintemp_hs2 != val) {
- amd_pmf_send_cmd(dev, SET_1AH_M80H_STT_LIMIT_HS2, SET_CMD,
- fixp_q88_fromint(val), NULL);
- dev_dbg(dev->dev, "update STT_LIMIT_HS2: %u\n", val);
- dev->prev_data->stt_skintemp_hs2 = val;
- }
- break;
-
- case PMF_POLICY_SYSTEM_STATE:
- switch (val) {
- case 0:
- amd_pmf_update_uevents(dev, KEY_SLEEP);
- break;
- case 1:
- amd_pmf_update_uevents(dev, KEY_SUSPEND);
- break;
- case 2:
- amd_pmf_update_uevents(dev, KEY_SCREENLOCK);
- break;
- default:
- dev_err(dev->dev, "Invalid PMF policy system state: %u\n", val);
- }
+/* SMU message IDs used to apply the TA policy actions, 0 if not supported */
+struct amd_pmf_policy_msg_ids {
+ u8 spl;
+ u8 sppt;
+ u8 fppt;
+ u8 sppt_apu_only;
+ u8 stt_min;
+ u8 stt_skintemp_apu;
+ u8 stt_skintemp_hs2;
+ u8 p3t;
+ u8 pmf_ppt;
+ u8 pmf_ppt_apu_only;
+};
- dev_dbg(dev->dev, "update SYSTEM_STATE: %s\n", amd_pmf_uevent_as_str(val));
- break;
+static const struct amd_pmf_policy_msg_ids amd_pmf_policy_default_msg_ids = {
+ .spl = SET_SPL,
+ .sppt = SET_SPPT,
+ .fppt = SET_FPPT,
+ .sppt_apu_only = SET_SPPT_APU_ONLY,
+ .stt_min = SET_STT_MIN_LIMIT,
+ .stt_skintemp_apu = SET_STT_LIMIT_APU,
+ .stt_skintemp_hs2 = SET_STT_LIMIT_HS2,
+ .p3t = SET_P3T,
+ .pmf_ppt = SET_PMF_PPT,
+ .pmf_ppt_apu_only = SET_PMF_PPT_APU_ONLY,
+};
- case PMF_POLICY_BIOS_OUTPUT_1:
- case PMF_POLICY_BIOS_OUTPUT_2:
- case PMF_POLICY_BIOS_OUTPUT_3:
- case PMF_POLICY_BIOS_OUTPUT_4:
- case PMF_POLICY_BIOS_OUTPUT_5:
- case PMF_POLICY_BIOS_OUTPUT_6:
- case PMF_POLICY_BIOS_OUTPUT_7:
- case PMF_POLICY_BIOS_OUTPUT_8:
- case PMF_POLICY_BIOS_OUTPUT_9:
- case PMF_POLICY_BIOS_OUTPUT_10:
- amd_pmf_update_bios_output(dev, action);
- break;
- }
- }
-}
+static const struct amd_pmf_policy_msg_ids amd_pmf_policy_msg_ids_v2 = {
+ .sppt = SET_1AH_M80H_PMF_SPPT_SPM,
+ .fppt = SET_1AH_M80H_PMF_FPPT_SPM,
+ .sppt_apu_only = SET_1AH_M80H_PMF_SPPT_APU_ONLY,
+ .stt_min = SET_1AH_M80H_STT_MIN_LIMIT,
+ .stt_skintemp_apu = SET_1AH_M80H_STT_LIMIT_APU,
+ .stt_skintemp_hs2 = SET_1AH_M80H_STT_LIMIT_HS2,
+};
-static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_result *out)
+static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_action *actions,
+ u32 count, u32 max)
{
+ const struct amd_pmf_policy_msg_ids *ids = dev->ta_ops->msg_ids;
struct ta_pmf_action *action;
u32 val;
int idx;
- for (idx = 0; idx < out->actions_count; idx++) {
- action = &out->actions_list[idx];
+ if (count > max) {
+ dev_err(dev->dev, "TA actions count %u exceeds max %u\n", count, max);
+ return;
+ }
+
+ for (idx = 0; idx < count; idx++) {
+ action = &actions[idx];
val = action->value;
switch (action->action_index) {
case PMF_POLICY_SPL:
- if (dev->prev_data->spl != val) {
- amd_pmf_send_cmd(dev, SET_SPL, SET_CMD, val, NULL);
+ if (ids->spl && dev->prev_data->spl != val) {
+ amd_pmf_send_cmd(dev, ids->spl, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update SPL: %u\n", val);
dev->prev_data->spl = val;
}
break;
case PMF_POLICY_SPPT:
- if (dev->prev_data->sppt != val) {
- amd_pmf_send_cmd(dev, SET_SPPT, SET_CMD, val, NULL);
+ if (ids->sppt && dev->prev_data->sppt != val) {
+ amd_pmf_send_cmd(dev, ids->sppt, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update SPPT: %u\n", val);
dev->prev_data->sppt = val;
}
break;
case PMF_POLICY_FPPT:
- if (dev->prev_data->fppt != val) {
- amd_pmf_send_cmd(dev, SET_FPPT, SET_CMD, val, NULL);
+ if (ids->fppt && dev->prev_data->fppt != val) {
+ amd_pmf_send_cmd(dev, ids->fppt, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update FPPT: %u\n", val);
dev->prev_data->fppt = val;
}
break;
case PMF_POLICY_SPPT_APU_ONLY:
- if (dev->prev_data->sppt_apuonly != val) {
- amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, SET_CMD, val, NULL);
+ if (ids->sppt_apu_only && dev->prev_data->sppt_apuonly != val) {
+ amd_pmf_send_cmd(dev, ids->sppt_apu_only, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update SPPT_APU_ONLY: %u\n", val);
dev->prev_data->sppt_apuonly = val;
}
break;
case PMF_POLICY_STT_MIN:
- if (dev->prev_data->stt_minlimit != val) {
- amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, SET_CMD, val, NULL);
+ if (ids->stt_min && dev->prev_data->stt_minlimit != val) {
+ amd_pmf_send_cmd(dev, ids->stt_min, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update STT_MIN: %u\n", val);
dev->prev_data->stt_minlimit = val;
}
break;
case PMF_POLICY_STT_SKINTEMP_APU:
- if (dev->prev_data->stt_skintemp_apu != val) {
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, SET_CMD,
+ if (ids->stt_skintemp_apu && dev->prev_data->stt_skintemp_apu != val) {
+ amd_pmf_send_cmd(dev, ids->stt_skintemp_apu, SET_CMD,
fixp_q88_fromint(val), NULL);
dev_dbg(dev->dev, "update STT_SKINTEMP_APU: %u\n", val);
dev->prev_data->stt_skintemp_apu = val;
@@ -279,8 +218,8 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
break;
case PMF_POLICY_STT_SKINTEMP_HS2:
- if (dev->prev_data->stt_skintemp_hs2 != val) {
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, SET_CMD,
+ if (ids->stt_skintemp_hs2 && dev->prev_data->stt_skintemp_hs2 != val) {
+ amd_pmf_send_cmd(dev, ids->stt_skintemp_hs2, SET_CMD,
fixp_q88_fromint(val), NULL);
dev_dbg(dev->dev, "update STT_SKINTEMP_HS2: %u\n", val);
dev->prev_data->stt_skintemp_hs2 = val;
@@ -288,24 +227,24 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
break;
case PMF_POLICY_P3T:
- if (dev->prev_data->p3t_limit != val) {
- amd_pmf_send_cmd(dev, SET_P3T, SET_CMD, val, NULL);
+ if (ids->p3t && dev->prev_data->p3t_limit != val) {
+ amd_pmf_send_cmd(dev, ids->p3t, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update P3T: %u\n", val);
dev->prev_data->p3t_limit = val;
}
break;
case PMF_POLICY_PMF_PPT:
- if (dev->prev_data->pmf_ppt != val) {
- amd_pmf_send_cmd(dev, SET_PMF_PPT, SET_CMD, val, NULL);
+ if (ids->pmf_ppt && dev->prev_data->pmf_ppt != val) {
+ amd_pmf_send_cmd(dev, ids->pmf_ppt, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update PMF PPT: %u\n", val);
dev->prev_data->pmf_ppt = val;
}
break;
case PMF_POLICY_PMF_PPT_APU_ONLY:
- if (dev->prev_data->pmf_ppt_apu_only != val) {
- amd_pmf_send_cmd(dev, SET_PMF_PPT_APU_ONLY, SET_CMD, val, NULL);
+ if (ids->pmf_ppt_apu_only && dev->prev_data->pmf_ppt_apu_only != val) {
+ amd_pmf_send_cmd(dev, ids->pmf_ppt_apu_only, SET_CMD, val, NULL);
dev_dbg(dev->dev, "update PMF PPT APU ONLY: %u\n", val);
dev->prev_data->pmf_ppt_apu_only = val;
}
@@ -323,7 +262,7 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
amd_pmf_update_uevents(dev, KEY_SCREENLOCK);
break;
default:
- dev_err(dev->dev, "Invalid PMF policy system state: %d\n", val);
+ dev_err(dev->dev, "Invalid PMF policy system state: %u\n", val);
}
dev_dbg(dev->dev, "update SYSTEM_STATE: %s\n",
@@ -380,7 +319,8 @@ int amd_pmf_invoke_cmd_enact_v2(struct amd_pmf_dev *dev)
amd_pmf_dump_ta_inputs_v2(dev, in);
dev_dbg(dev->dev, "TA v2 action count:%u result:%x\n", out->actions_count,
ta_sm->pmf_result);
- amd_pmf_apply_policies_v2(dev, out);
+ amd_pmf_apply_policies(dev, out->actions_list, out->actions_count,
+ ARRAY_SIZE(out->actions_list));
}
return 0;
@@ -420,7 +360,8 @@ int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev)
amd_pmf_dump_ta_inputs(dev, in);
dev_dbg(dev->dev, "action count:%u result:%x\n", out->actions_count,
ta_sm->pmf_result);
- amd_pmf_apply_policies(dev, out);
+ amd_pmf_apply_policies(dev, out->actions_list, out->actions_count,
+ ARRAY_SIZE(out->actions_list));
}
return 0;
@@ -758,6 +699,7 @@ static const struct amd_pmf_ta_ops amd_pmf_ta_default_ops = {
.uuids = amd_pmf_ta_uuid,
.num_uuids = ARRAY_SIZE(amd_pmf_ta_uuid),
.shm_size = sizeof(struct ta_pmf_shared_memory),
+ .msg_ids = &amd_pmf_policy_default_msg_ids,
.invoke_init = amd_pmf_invoke_cmd_init,
.invoke_enact = amd_pmf_invoke_cmd_enact,
};
@@ -766,6 +708,7 @@ static const struct amd_pmf_ta_ops amd_pmf_ta_ops_v2 = {
.uuids = amd_pmf_ta_uuid_v2,
.num_uuids = ARRAY_SIZE(amd_pmf_ta_uuid_v2),
.shm_size = sizeof(struct ta_pmf_shared_memory_v2),
+ .msg_ids = &amd_pmf_policy_msg_ids_v2,
.invoke_enact = amd_pmf_invoke_cmd_enact_v2,
.invoke_init = amd_pmf_invoke_cmd_init_v2,
};
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
` (7 preceding siblings ...)
2026-10-11 10:05 ` [PATCH 8/8] platform/x86/amd/pmf: Share TA policy apply code between TA versions Shyam Sundar S K
@ 2026-10-12 16:36 ` Mario Limonciello
8 siblings, 0 replies; 10+ messages in thread
From: Mario Limonciello @ 2026-10-12 16:36 UTC (permalink / raw)
To: Shyam Sundar S K, hansg, ilpo.jarvinen; +Cc: platform-driver-x86, Patil.Reddy
On 10/11/26 05:05, Shyam Sundar S K wrote:
> This series enables the PMF driver features on the 1AH_M80H platform.
>
> Patch 1 stops sending the legacy DRAM address commands on 1AH_M80H.
> Patch 2 adds the static slider support as per APMF 2.03.
> Patches 3-5 add per-platform TA ops, the signature size handling for
> RSA4K signed policy binaries and the Smart PC builder support for the
> new TA.
> Patch 6 remaps the metrics table on resume.
> Patch 7 passes the custom BIOS inputs to the TA on 1AH_M80H.
> Patch 8 shares the TA policy apply code between the TA versions.
>
> Shyam Sundar S K (8):
> platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H
> platform/x86/amd/pmf: Add 1AH_M80H static slider support
> platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table
> platform/x86/amd/pmf: Get policy binary signature size from PSP header
> platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H
> platform/x86/amd/pmf: Remap metrics table on resume for 1AH_M80H
> platform/x86/amd/pmf: Add custom BIOS input support for 1AH_M80H
> platform/x86/amd/pmf: Share TA policy apply code between TA versions
>
> drivers/platform/x86/amd/pmf/acpi.c | 3 +-
> drivers/platform/x86/amd/pmf/core.c | 50 +++--
> drivers/platform/x86/amd/pmf/metrics.c | 13 +-
> drivers/platform/x86/amd/pmf/pmf.h | 246 ++++++++++++++++++++++++
> drivers/platform/x86/amd/pmf/spc.c | 206 ++++++++++++++++++++
> drivers/platform/x86/amd/pmf/sps.c | 88 ++++++++-
> drivers/platform/x86/amd/pmf/tee-if.c | 252 +++++++++++++++++++++----
> 7 files changed, 801 insertions(+), 57 deletions(-)
>
>
> base-commit: 9cdc0dcc1e3677fca59bb314f2ec9e33383136d9
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-10-12 16:36 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-11 10:05 [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 1/8] platform/x86/amd/pmf: Skip legacy DRAM address commands on 1AH_M80H Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 2/8] platform/x86/amd/pmf: Add 1AH_M80H static slider support Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 3/8] platform/x86/amd/pmf: Abstract TA dispatch through ta_ops table Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 4/8] platform/x86/amd/pmf: Get policy binary signature size from PSP header Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 5/8] platform/x86/amd/pmf: Add Smart PC builder support for 1AH_M80H Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 6/8] platform/x86/amd/pmf: Remap metrics table on resume " Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 7/8] platform/x86/amd/pmf: Add custom BIOS input support " Shyam Sundar S K
2026-10-11 10:05 ` [PATCH 8/8] platform/x86/amd/pmf: Share TA policy apply code between TA versions Shyam Sundar S K
2026-10-12 16:36 ` [PATCH 0/8] platform/x86/amd/pmf: Add 1AH_M80H support Mario Limonciello
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.