diff --git a/drivers/platform/x86/amd/pmf/Kconfig b/drivers/platform/x86/amd/pmf/Kconfig index 25b8f7ae3abd..ad4faf18de47 100644 --- a/drivers/platform/x86/amd/pmf/Kconfig +++ b/drivers/platform/x86/amd/pmf/Kconfig @@ -30,3 +30,13 @@ config AMD_PMF_DEBUG in the PMF config store. Say Y here to enable more debug logs and Say N here if you are not sure. + +config AMD_PMF_UTIL_SUPPORT + bool "AMD PMF Util layer support" + depends on AMD_PMF + help + Enabling this option provides a character device for userspace to capture + PMF features (Smart PC Builder, Auto Mode, Static Power Slider, Dynamic + Power Slider AC/DC) along with PMF metrics from the AMD PMF driver. + + Say Y here to enable it and Say N here if you are not sure. diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile index 5978464e0eb7..bf7aad80b9e9 100644 --- a/drivers/platform/x86/amd/pmf/Makefile +++ b/drivers/platform/x86/amd/pmf/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_AMD_PMF) += amd-pmf.o amd-pmf-y := core.o acpi.o sps.o \ auto-mode.o cnqf.o \ tee-if.o spc.o +# Build util.c only when AMD_PMF_UTIL_SUPPORT is enabled +amd-pmf-$(CONFIG_AMD_PMF_UTIL_SUPPORT) += util.o diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index b9e5a2cf3aae..58d86b4c2828 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -634,6 +634,10 @@ static int amd_pmf_probe(struct platform_device *pdev) pmf_device = dev->dev; + err = amd_pmf_cdev_register(dev); + if (err) + dev_warn(dev->dev, "failed to register util interface: %d\n", err); + dev_info(dev->dev, "registered PMF device successfully\n"); return 0; @@ -643,6 +647,7 @@ static void amd_pmf_remove(struct platform_device *pdev) { struct amd_pmf_dev *dev = platform_get_drvdata(pdev); + amd_pmf_cdev_unregister(); amd_pmf_deinit_features(dev); if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2)) amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_UNLOAD); diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 69fef7448744..6f61076a9386 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -928,4 +928,13 @@ int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid); void amd_pmf_tee_deinit(struct amd_pmf_dev *dev); int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev); +/* Util Layer */ +#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT) +int amd_pmf_cdev_register(struct amd_pmf_dev *dev); +void amd_pmf_cdev_unregister(void); +#else +static inline int amd_pmf_cdev_register(struct amd_pmf_dev *dev) { return 0; } +static inline void amd_pmf_cdev_unregister(void) {} +#endif + #endif /* PMF_H */ diff --git a/drivers/platform/x86/amd/pmf/util.c b/drivers/platform/x86/amd/pmf/util.c new file mode 100644 index 000000000000..f8a283192ffe --- /dev/null +++ b/drivers/platform/x86/amd/pmf/util.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Platform Management Framework Util Layer + * + * Copyright (c) 2026, Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Authors: Shyam Sundar S K + * Sanket Goswami + */ + +#include +#include +#include +#include + +#include "pmf.h" + +static struct amd_pmf_dev *pmf_dev_handle; +static DEFINE_MUTEX(pmf_util_lock); + +static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +static int amd_pmf_open(struct inode *inode, struct file *filp) +{ + guard(mutex)(&pmf_util_lock); + if (!pmf_dev_handle) + return -ENODEV; + + filp->private_data = pmf_dev_handle; + return 0; +} + +static const struct file_operations pmf_if_ops = { + .owner = THIS_MODULE, + .open = amd_pmf_open, + .unlocked_ioctl = amd_pmf_set_ioctl, +}; + +static struct miscdevice amd_pmf_util_if = { + .minor = MISC_DYNAMIC_MINOR, + .name = "amdpmf_interface", + .fops = &pmf_if_ops, +}; + +int amd_pmf_cdev_register(struct amd_pmf_dev *dev) +{ + int ret; + + guard(mutex)(&pmf_util_lock); + pmf_dev_handle = dev; + ret = misc_register(&amd_pmf_util_if); + if (ret) + pmf_dev_handle = NULL; + + return ret; +} + +void amd_pmf_cdev_unregister(void) +{ + guard(mutex)(&pmf_util_lock); + if (pmf_dev_handle) + misc_deregister(&amd_pmf_util_if); + pmf_dev_handle = NULL; +} diff --git a/include/uapi/linux/amd-pmf.h b/include/uapi/linux/amd-pmf.h new file mode 100644 index 000000000000..bbbd39b2ce15 --- /dev/null +++ b/include/uapi/linux/amd-pmf.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ +/* + * AMD Platform Management Framework (PMF) UAPI Header + * + * Copyright (c) 2026, Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * This file defines the user-space API for interacting with the AMD PMF + * driver. It provides ioctl interfaces to query platform-specific metrics + * such as power source, slider position, platform type, laptop placement, + * and various BIOS input/output parameters. + */ + +#ifndef _UAPI_LINUX_AMD_PMF_H +#define _UAPI_LINUX_AMD_PMF_H + +#include +#include +#include + +/** + * AMD_PMF_IOC_MAGIC - Magic number for AMD PMF ioctl commands + * + * This magic number uniquely identifies AMD PMF ioctl operations. + */ +#define AMD_PMF_IOC_MAGIC 'p' + +/** + * IOCTL_AMD_PMF_POPULATE_DATA - ioctl command to retrieve PMF metrics data + * + * This ioctl command is used to populate the amd_pmf_info structure + * with the requested PMF metrics information. + */ +#define IOCTL_AMD_PMF_POPULATE_DATA _IOWR(AMD_PMF_IOC_MAGIC, 0x00, __u64) + +#define AMD_PMF_BIOS_PARAMS_MAX 10 + +/* AMD PMF feature flags - bitmask indicating supported features */ +#define AMD_PMF_FEAT_AUTO_MODE BIT(0) +#define AMD_PMF_FEAT_STATIC_POWER_SLIDER BIT(1) +#define AMD_PMF_FEAT_POLICY_BUILDER BIT(2) +#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3) +#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4) + +struct amd_pmf_info { + __u64 size; + + /* Feature info */ + __u32 features_supported; + + /* Power and state info */ + __u32 platform_type; + __u32 power_source; + __u32 laptop_placement; + __u32 lid_state; + __u32 user_presence; + __u32 slider_position; + + /* Thermal and power metrics */ + __s32 skin_temp; + __u32 gfx_busy; + __s32 ambient_light; + __u32 avg_c0_residency; + __u32 max_c0_residency; + __u32 socket_power; + + /* BIOS parameters */ + __u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX]; +}; + +#endif /* _UAPI_LINUX_AMD_PMF_H */