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 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 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 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 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