mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
platform/x86/amd/hsmp: Report power via hwmon sensors
Expose power reading and power limits via hwmon power sensors. Signed-off-by: Suma Hegde <suma.hegde@amd.com> Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com> Link: https://lore.kernel.org/r/20250506101542.200811-2-suma.hegde@amd.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
parent
cf8dea42e4
commit
92c025db52
6 changed files with 146 additions and 1 deletions
|
@ -116,6 +116,14 @@ for socket with ID00 is given below::
|
|||
})
|
||||
}
|
||||
|
||||
HSMP HWMON interface
|
||||
====================
|
||||
HSMP power sensors are registered with the hwmon interface. A separate hwmon
|
||||
directory is created for each socket and the following files are generated
|
||||
within the hwmon directory.
|
||||
- power1_input (read only)
|
||||
- power1_cap_max (read only)
|
||||
- power1_cap (read, write)
|
||||
|
||||
An example
|
||||
==========
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
obj-$(CONFIG_AMD_HSMP) += hsmp_common.o
|
||||
hsmp_common-y := hsmp.o
|
||||
hsmp_common-$(CONFIG_HWMON) += hwmon.o
|
||||
obj-$(CONFIG_AMD_HSMP_PLAT) += amd_hsmp.o
|
||||
amd_hsmp-y := plat.o
|
||||
obj-$(CONFIG_AMD_HSMP_ACPI) += hsmp_acpi.o
|
||||
|
|
|
@ -281,6 +281,10 @@ static int init_acpi(struct device *dev)
|
|||
dev_err(dev, "Failed to init metric table\n");
|
||||
}
|
||||
|
||||
ret = hsmp_create_sensor(dev, sock_ind);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <linux/compiler_types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
@ -25,7 +26,7 @@
|
|||
#define HSMP_DEVNODE_NAME "hsmp"
|
||||
#define ACPI_HSMP_DEVICE_HID "AMDI0097"
|
||||
|
||||
#define DRIVER_VERSION "2.4"
|
||||
#define DRIVER_VERSION "2.5"
|
||||
|
||||
struct hsmp_mbaddr_info {
|
||||
u32 base_addr;
|
||||
|
@ -63,4 +64,9 @@ int hsmp_misc_register(struct device *dev);
|
|||
int hsmp_get_tbl_dram_base(u16 sock_ind);
|
||||
ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size);
|
||||
struct hsmp_plat_device *get_hsmp_pdev(void);
|
||||
#if IS_REACHABLE(CONFIG_HWMON)
|
||||
int hsmp_create_sensor(struct device *dev, u16 sock_ind);
|
||||
#else
|
||||
static inline int hsmp_create_sensor(struct device *dev, u16 sock_ind) { return 0; }
|
||||
#endif
|
||||
#endif /* HSMP_H */
|
||||
|
|
121
drivers/platform/x86/amd/hsmp/hwmon.c
Normal file
121
drivers/platform/x86/amd/hsmp/hwmon.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* AMD HSMP hwmon support
|
||||
* Copyright (c) 2025, AMD.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This file provides hwmon implementation for HSMP interface.
|
||||
*/
|
||||
|
||||
#include <asm/amd_hsmp.h>
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "hsmp.h"
|
||||
|
||||
#define HSMP_HWMON_NAME "amd_hsmp_hwmon"
|
||||
|
||||
static int hsmp_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long val)
|
||||
{
|
||||
u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
|
||||
struct hsmp_message msg = {};
|
||||
|
||||
if (type != hwmon_power)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (attr != hwmon_power_cap)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
msg.num_args = 1;
|
||||
msg.args[0] = val / MICROWATT_PER_MILLIWATT;
|
||||
msg.msg_id = HSMP_SET_SOCKET_POWER_LIMIT;
|
||||
msg.sock_ind = sock_ind;
|
||||
return hsmp_send_message(&msg);
|
||||
}
|
||||
|
||||
static int hsmp_hwmon_read(struct device *dev,
|
||||
enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
|
||||
struct hsmp_message msg = {};
|
||||
int ret;
|
||||
|
||||
if (type != hwmon_power)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
msg.sock_ind = sock_ind;
|
||||
msg.response_sz = 1;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_power_input:
|
||||
msg.msg_id = HSMP_GET_SOCKET_POWER;
|
||||
break;
|
||||
case hwmon_power_cap:
|
||||
msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT;
|
||||
break;
|
||||
case hwmon_power_cap_max:
|
||||
msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT_MAX;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = hsmp_send_message(&msg);
|
||||
if (!ret)
|
||||
*val = msg.args[0] * MICROWATT_PER_MILLIWATT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static umode_t hsmp_hwmon_is_visble(const void *data,
|
||||
enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
if (type != hwmon_power)
|
||||
return 0;
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_power_input:
|
||||
return 0444;
|
||||
case hwmon_power_cap:
|
||||
return 0644;
|
||||
case hwmon_power_cap_max:
|
||||
return 0444;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct hwmon_ops hsmp_hwmon_ops = {
|
||||
.read = hsmp_hwmon_read,
|
||||
.is_visible = hsmp_hwmon_is_visble,
|
||||
.write = hsmp_hwmon_write,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info * const hsmp_info[] = {
|
||||
HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info hsmp_chip_info = {
|
||||
.ops = &hsmp_hwmon_ops,
|
||||
.info = hsmp_info,
|
||||
};
|
||||
|
||||
int hsmp_create_sensor(struct device *dev, u16 sock_ind)
|
||||
{
|
||||
struct device *hwmon_dev;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, HSMP_HWMON_NAME,
|
||||
(void *)(uintptr_t)sock_ind,
|
||||
&hsmp_chip_info,
|
||||
NULL);
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(hsmp_create_sensor, "AMD_HSMP");
|
|
@ -189,6 +189,11 @@ static int init_platform_device(struct device *dev)
|
|||
if (ret)
|
||||
dev_err(dev, "Failed to init metric table\n");
|
||||
}
|
||||
|
||||
/* Register with hwmon interface for reporting power */
|
||||
ret = hsmp_create_sensor(dev, i);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue