xref: /linux/drivers/platform/x86/amd/hsmp/hwmon.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
192c025dbSSuma Hegde // SPDX-License-Identifier: GPL-2.0
292c025dbSSuma Hegde /*
392c025dbSSuma Hegde  * AMD HSMP hwmon support
492c025dbSSuma Hegde  * Copyright (c) 2025, AMD.
592c025dbSSuma Hegde  * All Rights Reserved.
692c025dbSSuma Hegde  *
792c025dbSSuma Hegde  * This file provides hwmon implementation for HSMP interface.
892c025dbSSuma Hegde  */
992c025dbSSuma Hegde 
10*1193e205SLinus Torvalds #include <asm/amd/hsmp.h>
1192c025dbSSuma Hegde 
1292c025dbSSuma Hegde #include <linux/device.h>
1392c025dbSSuma Hegde #include <linux/err.h>
1492c025dbSSuma Hegde #include <linux/hwmon.h>
1592c025dbSSuma Hegde #include <linux/types.h>
1692c025dbSSuma Hegde #include <linux/units.h>
1792c025dbSSuma Hegde 
1892c025dbSSuma Hegde #include "hsmp.h"
1992c025dbSSuma Hegde 
2092c025dbSSuma Hegde #define HSMP_HWMON_NAME		"amd_hsmp_hwmon"
2192c025dbSSuma Hegde 
hsmp_hwmon_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)2292c025dbSSuma Hegde static int hsmp_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
2392c025dbSSuma Hegde 			    u32 attr, int channel, long val)
2492c025dbSSuma Hegde {
2592c025dbSSuma Hegde 	u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
2692c025dbSSuma Hegde 	struct hsmp_message msg = {};
2792c025dbSSuma Hegde 
2892c025dbSSuma Hegde 	if (type != hwmon_power)
2992c025dbSSuma Hegde 		return -EOPNOTSUPP;
3092c025dbSSuma Hegde 
3192c025dbSSuma Hegde 	if (attr != hwmon_power_cap)
3292c025dbSSuma Hegde 		return -EOPNOTSUPP;
3392c025dbSSuma Hegde 
3492c025dbSSuma Hegde 	msg.num_args = 1;
3592c025dbSSuma Hegde 	msg.args[0] = val / MICROWATT_PER_MILLIWATT;
3692c025dbSSuma Hegde 	msg.msg_id = HSMP_SET_SOCKET_POWER_LIMIT;
3792c025dbSSuma Hegde 	msg.sock_ind = sock_ind;
3892c025dbSSuma Hegde 	return hsmp_send_message(&msg);
3992c025dbSSuma Hegde }
4092c025dbSSuma Hegde 
hsmp_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)4192c025dbSSuma Hegde static int hsmp_hwmon_read(struct device *dev,
4292c025dbSSuma Hegde 			   enum hwmon_sensor_types type,
4392c025dbSSuma Hegde 			   u32 attr, int channel, long *val)
4492c025dbSSuma Hegde {
4592c025dbSSuma Hegde 	u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
4692c025dbSSuma Hegde 	struct hsmp_message msg = {};
4792c025dbSSuma Hegde 	int ret;
4892c025dbSSuma Hegde 
4992c025dbSSuma Hegde 	if (type != hwmon_power)
5092c025dbSSuma Hegde 		return -EOPNOTSUPP;
5192c025dbSSuma Hegde 
5292c025dbSSuma Hegde 	msg.sock_ind = sock_ind;
5392c025dbSSuma Hegde 	msg.response_sz = 1;
5492c025dbSSuma Hegde 
5592c025dbSSuma Hegde 	switch (attr) {
5692c025dbSSuma Hegde 	case hwmon_power_input:
5792c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER;
5892c025dbSSuma Hegde 		break;
5992c025dbSSuma Hegde 	case hwmon_power_cap:
6092c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT;
6192c025dbSSuma Hegde 		break;
6292c025dbSSuma Hegde 	case hwmon_power_cap_max:
6392c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT_MAX;
6492c025dbSSuma Hegde 		break;
6592c025dbSSuma Hegde 	default:
6692c025dbSSuma Hegde 		return -EOPNOTSUPP;
6792c025dbSSuma Hegde 	}
6892c025dbSSuma Hegde 
6992c025dbSSuma Hegde 	ret = hsmp_send_message(&msg);
7092c025dbSSuma Hegde 	if (!ret)
7192c025dbSSuma Hegde 		*val = msg.args[0] * MICROWATT_PER_MILLIWATT;
7292c025dbSSuma Hegde 
7392c025dbSSuma Hegde 	return ret;
7492c025dbSSuma Hegde }
7592c025dbSSuma Hegde 
hsmp_hwmon_is_visble(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)7692c025dbSSuma Hegde static umode_t hsmp_hwmon_is_visble(const void *data,
7792c025dbSSuma Hegde 				    enum hwmon_sensor_types type,
7892c025dbSSuma Hegde 				    u32 attr, int channel)
7992c025dbSSuma Hegde {
8092c025dbSSuma Hegde 	if (type != hwmon_power)
8192c025dbSSuma Hegde 		return 0;
8292c025dbSSuma Hegde 
8392c025dbSSuma Hegde 	switch (attr) {
8492c025dbSSuma Hegde 	case hwmon_power_input:
8592c025dbSSuma Hegde 		return 0444;
8692c025dbSSuma Hegde 	case hwmon_power_cap:
8792c025dbSSuma Hegde 		return 0644;
8892c025dbSSuma Hegde 	case hwmon_power_cap_max:
8992c025dbSSuma Hegde 		return 0444;
9092c025dbSSuma Hegde 	default:
9192c025dbSSuma Hegde 		return 0;
9292c025dbSSuma Hegde 	}
9392c025dbSSuma Hegde }
9492c025dbSSuma Hegde 
9592c025dbSSuma Hegde static const struct hwmon_ops hsmp_hwmon_ops = {
9692c025dbSSuma Hegde 	.read = hsmp_hwmon_read,
9792c025dbSSuma Hegde 	.is_visible = hsmp_hwmon_is_visble,
9892c025dbSSuma Hegde 	.write	= hsmp_hwmon_write,
9992c025dbSSuma Hegde };
10092c025dbSSuma Hegde 
10192c025dbSSuma Hegde static const struct hwmon_channel_info * const hsmp_info[] = {
10292c025dbSSuma Hegde 	HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX),
10392c025dbSSuma Hegde 	NULL
10492c025dbSSuma Hegde };
10592c025dbSSuma Hegde 
10692c025dbSSuma Hegde static const struct hwmon_chip_info hsmp_chip_info = {
10792c025dbSSuma Hegde 	.ops = &hsmp_hwmon_ops,
10892c025dbSSuma Hegde 	.info = hsmp_info,
10992c025dbSSuma Hegde };
11092c025dbSSuma Hegde 
hsmp_create_sensor(struct device * dev,u16 sock_ind)11192c025dbSSuma Hegde int hsmp_create_sensor(struct device *dev, u16 sock_ind)
11292c025dbSSuma Hegde {
11392c025dbSSuma Hegde 	struct device *hwmon_dev;
11492c025dbSSuma Hegde 
11592c025dbSSuma Hegde 	hwmon_dev = devm_hwmon_device_register_with_info(dev, HSMP_HWMON_NAME,
11692c025dbSSuma Hegde 							 (void *)(uintptr_t)sock_ind,
11792c025dbSSuma Hegde 							 &hsmp_chip_info,
11892c025dbSSuma Hegde 							 NULL);
11992c025dbSSuma Hegde 	return PTR_ERR_OR_ZERO(hwmon_dev);
12092c025dbSSuma Hegde }
12192c025dbSSuma Hegde EXPORT_SYMBOL_NS(hsmp_create_sensor, "AMD_HSMP");
122