Commit ac052d8c authored by Shyam Sundar S K's avatar Shyam Sundar S K Committed by Hans de Goede

platform/x86/amd/pmf: Add PMF TEE interface

AMD PMF driver loads the PMF TA (Trusted Application) into the AMD
ASP's (AMD Security Processor) TEE (Trusted Execution Environment).

PMF Trusted Application is a secured firmware placed under
/lib/firmware/amdtee gets loaded only when the TEE environment is
initialized. Add the initial code path to build these pipes.
Reviewed-by: default avatarMario Limonciello <mario.limonciello@amd.com>
Signed-off-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Link: https://lore.kernel.org/r/20231212014705.2017474-2-Shyam-sundar.S-k@amd.comSigned-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent ed289b98
...@@ -9,6 +9,7 @@ config AMD_PMF ...@@ -9,6 +9,7 @@ config AMD_PMF
depends on POWER_SUPPLY depends on POWER_SUPPLY
depends on AMD_NB depends on AMD_NB
select ACPI_PLATFORM_PROFILE select ACPI_PLATFORM_PROFILE
depends on TEE
help help
This driver provides support for the AMD Platform Management Framework. This driver provides support for the AMD Platform Management Framework.
The goal is to enhance end user experience by making AMD PCs smarter, The goal is to enhance end user experience by making AMD PCs smarter,
......
...@@ -6,4 +6,5 @@ ...@@ -6,4 +6,5 @@
obj-$(CONFIG_AMD_PMF) += amd-pmf.o obj-$(CONFIG_AMD_PMF) += amd-pmf.o
amd-pmf-objs := core.o acpi.o sps.o \ amd-pmf-objs := core.o acpi.o sps.o \
auto-mode.o cnqf.o auto-mode.o cnqf.o \
tee-if.o
...@@ -309,13 +309,13 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev) ...@@ -309,13 +309,13 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n"); dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
} }
/* Enable Auto Mode */ if (!amd_pmf_init_smart_pc(dev)) {
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_init_auto_mode(dev); amd_pmf_init_auto_mode(dev);
dev_dbg(dev->dev, "Auto Mode Init done\n"); dev_dbg(dev->dev, "Auto Mode Init done\n");
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) || } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) { is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
/* Enable Cool n Quiet Framework (CnQF) */
ret = amd_pmf_init_cnqf(dev); ret = amd_pmf_init_cnqf(dev);
if (ret) if (ret)
dev_warn(dev->dev, "CnQF Init failed\n"); dev_warn(dev->dev, "CnQF Init failed\n");
...@@ -330,7 +330,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev) ...@@ -330,7 +330,9 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
amd_pmf_deinit_sps(dev); amd_pmf_deinit_sps(dev);
} }
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { if (!dev->smart_pc_enabled) {
amd_pmf_deinit_smart_pc(dev);
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_deinit_auto_mode(dev); amd_pmf_deinit_auto_mode(dev);
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) || } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) { is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) {
......
...@@ -179,6 +179,12 @@ struct amd_pmf_dev { ...@@ -179,6 +179,12 @@ struct amd_pmf_dev {
bool cnqf_enabled; bool cnqf_enabled;
bool cnqf_supported; bool cnqf_supported;
struct notifier_block pwr_src_notifier; struct notifier_block pwr_src_notifier;
/* Smart PC solution builder */
struct tee_context *tee_ctx;
struct tee_shm *fw_shm_pool;
u32 session_id;
void *shbuf;
bool smart_pc_enabled;
}; };
struct apmf_sps_prop_granular { struct apmf_sps_prop_granular {
...@@ -389,6 +395,13 @@ struct apmf_dyn_slider_output { ...@@ -389,6 +395,13 @@ struct apmf_dyn_slider_output {
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX]; struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
} __packed; } __packed;
struct ta_pmf_shared_memory {
int command_id;
int resp_id;
u32 pmf_result;
u32 if_version;
};
/* Core Layer */ /* Core Layer */
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev); int apmf_acpi_init(struct amd_pmf_dev *pmf_dev);
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev); void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev);
...@@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev); ...@@ -433,4 +446,7 @@ void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev);
int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms); int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms);
extern const struct attribute_group cnqf_feature_attribute_group; extern const struct attribute_group cnqf_feature_attribute_group;
/* Smart PC builder Layer */
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev);
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev);
#endif /* PMF_H */ #endif /* PMF_H */
// SPDX-License-Identifier: GPL-2.0
/*
* AMD Platform Management Framework Driver - TEE Interface
*
* Copyright (c) 2023, Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
*/
#include <linux/tee_drv.h>
#include <linux/uuid.h>
#include "pmf.h"
#define MAX_TEE_PARAM 4
static const uuid_t amd_pmf_ta_uuid = UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d,
0xb1, 0x2d, 0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43);
static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
{
return ver->impl_id == TEE_IMPL_ID_AMDTEE;
}
static int amd_pmf_ta_open_session(struct tee_context *ctx, u32 *id)
{
struct tee_ioctl_open_session_arg sess_arg = {};
int rc;
export_uuid(sess_arg.uuid, &amd_pmf_ta_uuid);
sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
sess_arg.num_params = 0;
rc = tee_client_open_session(ctx, &sess_arg, NULL);
if (rc < 0 || sess_arg.ret != 0) {
pr_err("Failed to open TEE session err:%#x, rc:%d\n", sess_arg.ret, rc);
return rc;
}
*id = sess_arg.session;
return rc;
}
static int amd_pmf_tee_init(struct amd_pmf_dev *dev)
{
u32 size;
int ret;
dev->tee_ctx = tee_client_open_context(NULL, amd_pmf_amdtee_ta_match, NULL, NULL);
if (IS_ERR(dev->tee_ctx)) {
dev_err(dev->dev, "Failed to open TEE context\n");
return PTR_ERR(dev->tee_ctx);
}
ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id);
if (ret) {
dev_err(dev->dev, "Failed to open TA session (%d)\n", ret);
ret = -EINVAL;
goto out_ctx;
}
size = sizeof(struct ta_pmf_shared_memory);
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");
ret = PTR_ERR(dev->fw_shm_pool);
goto out_sess;
}
dev->shbuf = tee_shm_get_va(dev->fw_shm_pool, 0);
if (IS_ERR(dev->shbuf)) {
dev_err(dev->dev, "Failed to get TEE virtual address\n");
ret = PTR_ERR(dev->shbuf);
goto out_shm;
}
dev_dbg(dev->dev, "TEE init done\n");
return 0;
out_shm:
tee_shm_free(dev->fw_shm_pool);
out_sess:
tee_client_close_session(dev->tee_ctx, dev->session_id);
out_ctx:
tee_client_close_context(dev->tee_ctx);
return ret;
}
static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
{
tee_shm_free(dev->fw_shm_pool);
tee_client_close_session(dev->tee_ctx, dev->session_id);
tee_client_close_context(dev->tee_ctx);
}
int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
{
return amd_pmf_tee_init(dev);
}
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
{
amd_pmf_tee_deinit(dev);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment