xref: /linux/drivers/platform/x86/amd/hsmp/hwmon.c (revision 92c025db52bb94a032eb3d473bb81e62c19ddbd3)
1*92c025dbSSuma Hegde // SPDX-License-Identifier: GPL-2.0
2*92c025dbSSuma Hegde /*
3*92c025dbSSuma Hegde  * AMD HSMP hwmon support
4*92c025dbSSuma Hegde  * Copyright (c) 2025, AMD.
5*92c025dbSSuma Hegde  * All Rights Reserved.
6*92c025dbSSuma Hegde  *
7*92c025dbSSuma Hegde  * This file provides hwmon implementation for HSMP interface.
8*92c025dbSSuma Hegde  */
9*92c025dbSSuma Hegde 
10*92c025dbSSuma Hegde #include <asm/amd_hsmp.h>
11*92c025dbSSuma Hegde 
12*92c025dbSSuma Hegde #include <linux/device.h>
13*92c025dbSSuma Hegde #include <linux/err.h>
14*92c025dbSSuma Hegde #include <linux/hwmon.h>
15*92c025dbSSuma Hegde #include <linux/types.h>
16*92c025dbSSuma Hegde #include <linux/units.h>
17*92c025dbSSuma Hegde 
18*92c025dbSSuma Hegde #include "hsmp.h"
19*92c025dbSSuma Hegde 
20*92c025dbSSuma Hegde #define HSMP_HWMON_NAME		"amd_hsmp_hwmon"
21*92c025dbSSuma Hegde 
22*92c025dbSSuma Hegde static int hsmp_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
23*92c025dbSSuma Hegde 			    u32 attr, int channel, long val)
24*92c025dbSSuma Hegde {
25*92c025dbSSuma Hegde 	u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
26*92c025dbSSuma Hegde 	struct hsmp_message msg = {};
27*92c025dbSSuma Hegde 
28*92c025dbSSuma Hegde 	if (type != hwmon_power)
29*92c025dbSSuma Hegde 		return -EOPNOTSUPP;
30*92c025dbSSuma Hegde 
31*92c025dbSSuma Hegde 	if (attr != hwmon_power_cap)
32*92c025dbSSuma Hegde 		return -EOPNOTSUPP;
33*92c025dbSSuma Hegde 
34*92c025dbSSuma Hegde 	msg.num_args = 1;
35*92c025dbSSuma Hegde 	msg.args[0] = val / MICROWATT_PER_MILLIWATT;
36*92c025dbSSuma Hegde 	msg.msg_id = HSMP_SET_SOCKET_POWER_LIMIT;
37*92c025dbSSuma Hegde 	msg.sock_ind = sock_ind;
38*92c025dbSSuma Hegde 	return hsmp_send_message(&msg);
39*92c025dbSSuma Hegde }
40*92c025dbSSuma Hegde 
41*92c025dbSSuma Hegde static int hsmp_hwmon_read(struct device *dev,
42*92c025dbSSuma Hegde 			   enum hwmon_sensor_types type,
43*92c025dbSSuma Hegde 			   u32 attr, int channel, long *val)
44*92c025dbSSuma Hegde {
45*92c025dbSSuma Hegde 	u16 sock_ind = (uintptr_t)dev_get_drvdata(dev);
46*92c025dbSSuma Hegde 	struct hsmp_message msg = {};
47*92c025dbSSuma Hegde 	int ret;
48*92c025dbSSuma Hegde 
49*92c025dbSSuma Hegde 	if (type != hwmon_power)
50*92c025dbSSuma Hegde 		return -EOPNOTSUPP;
51*92c025dbSSuma Hegde 
52*92c025dbSSuma Hegde 	msg.sock_ind = sock_ind;
53*92c025dbSSuma Hegde 	msg.response_sz = 1;
54*92c025dbSSuma Hegde 
55*92c025dbSSuma Hegde 	switch (attr) {
56*92c025dbSSuma Hegde 	case hwmon_power_input:
57*92c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER;
58*92c025dbSSuma Hegde 		break;
59*92c025dbSSuma Hegde 	case hwmon_power_cap:
60*92c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT;
61*92c025dbSSuma Hegde 		break;
62*92c025dbSSuma Hegde 	case hwmon_power_cap_max:
63*92c025dbSSuma Hegde 		msg.msg_id = HSMP_GET_SOCKET_POWER_LIMIT_MAX;
64*92c025dbSSuma Hegde 		break;
65*92c025dbSSuma Hegde 	default:
66*92c025dbSSuma Hegde 		return -EOPNOTSUPP;
67*92c025dbSSuma Hegde 	}
68*92c025dbSSuma Hegde 
69*92c025dbSSuma Hegde 	ret = hsmp_send_message(&msg);
70*92c025dbSSuma Hegde 	if (!ret)
71*92c025dbSSuma Hegde 		*val = msg.args[0] * MICROWATT_PER_MILLIWATT;
72*92c025dbSSuma Hegde 
73*92c025dbSSuma Hegde 	return ret;
74*92c025dbSSuma Hegde }
75*92c025dbSSuma Hegde 
76*92c025dbSSuma Hegde static umode_t hsmp_hwmon_is_visble(const void *data,
77*92c025dbSSuma Hegde 				    enum hwmon_sensor_types type,
78*92c025dbSSuma Hegde 				    u32 attr, int channel)
79*92c025dbSSuma Hegde {
80*92c025dbSSuma Hegde 	if (type != hwmon_power)
81*92c025dbSSuma Hegde 		return 0;
82*92c025dbSSuma Hegde 
83*92c025dbSSuma Hegde 	switch (attr) {
84*92c025dbSSuma Hegde 	case hwmon_power_input:
85*92c025dbSSuma Hegde 		return 0444;
86*92c025dbSSuma Hegde 	case hwmon_power_cap:
87*92c025dbSSuma Hegde 		return 0644;
88*92c025dbSSuma Hegde 	case hwmon_power_cap_max:
89*92c025dbSSuma Hegde 		return 0444;
90*92c025dbSSuma Hegde 	default:
91*92c025dbSSuma Hegde 		return 0;
92*92c025dbSSuma Hegde 	}
93*92c025dbSSuma Hegde }
94*92c025dbSSuma Hegde 
95*92c025dbSSuma Hegde static const struct hwmon_ops hsmp_hwmon_ops = {
96*92c025dbSSuma Hegde 	.read = hsmp_hwmon_read,
97*92c025dbSSuma Hegde 	.is_visible = hsmp_hwmon_is_visble,
98*92c025dbSSuma Hegde 	.write	= hsmp_hwmon_write,
99*92c025dbSSuma Hegde };
100*92c025dbSSuma Hegde 
101*92c025dbSSuma Hegde static const struct hwmon_channel_info * const hsmp_info[] = {
102*92c025dbSSuma Hegde 	HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX),
103*92c025dbSSuma Hegde 	NULL
104*92c025dbSSuma Hegde };
105*92c025dbSSuma Hegde 
106*92c025dbSSuma Hegde static const struct hwmon_chip_info hsmp_chip_info = {
107*92c025dbSSuma Hegde 	.ops = &hsmp_hwmon_ops,
108*92c025dbSSuma Hegde 	.info = hsmp_info,
109*92c025dbSSuma Hegde };
110*92c025dbSSuma Hegde 
111*92c025dbSSuma Hegde int hsmp_create_sensor(struct device *dev, u16 sock_ind)
112*92c025dbSSuma Hegde {
113*92c025dbSSuma Hegde 	struct device *hwmon_dev;
114*92c025dbSSuma Hegde 
115*92c025dbSSuma Hegde 	hwmon_dev = devm_hwmon_device_register_with_info(dev, HSMP_HWMON_NAME,
116*92c025dbSSuma Hegde 							 (void *)(uintptr_t)sock_ind,
117*92c025dbSSuma Hegde 							 &hsmp_chip_info,
118*92c025dbSSuma Hegde 							 NULL);
119*92c025dbSSuma Hegde 	return PTR_ERR_OR_ZERO(hwmon_dev);
120*92c025dbSSuma Hegde }
121*92c025dbSSuma Hegde EXPORT_SYMBOL_NS(hsmp_create_sensor, "AMD_HSMP");
122