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