1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * rmi-hwmon.c - hwmon sensor support for side band RMI 4 * 5 * Copyright (C) 2025 Advanced Micro Devices, Inc. 6 */ 7 #include <linux/err.h> 8 #include <linux/hwmon.h> 9 #include <uapi/misc/amd-apml.h> 10 #include "rmi-core.h" 11 12 /* Do not allow setting negative power limit */ 13 #define SBRMI_PWR_MIN 0 14 15 static int sbrmi_read(struct device *dev, enum hwmon_sensor_types type, 16 u32 attr, int channel, long *val) 17 { 18 struct sbrmi_data *data = dev_get_drvdata(dev); 19 struct apml_mbox_msg msg = { 0 }; 20 int ret; 21 22 if (!data) 23 return -ENODEV; 24 25 if (type != hwmon_power) 26 return -EINVAL; 27 28 switch (attr) { 29 case hwmon_power_input: 30 msg.cmd = SBRMI_READ_PKG_PWR_CONSUMPTION; 31 ret = rmi_mailbox_xfer(data, &msg); 32 break; 33 case hwmon_power_cap: 34 msg.cmd = SBRMI_READ_PKG_PWR_LIMIT; 35 ret = rmi_mailbox_xfer(data, &msg); 36 break; 37 case hwmon_power_cap_max: 38 msg.mb_in_out = data->pwr_limit_max; 39 ret = 0; 40 break; 41 default: 42 return -EINVAL; 43 } 44 if (ret < 0) 45 return ret; 46 /* hwmon power attributes are in microWatt */ 47 *val = (long)msg.mb_in_out * 1000; 48 return ret; 49 } 50 51 static int sbrmi_write(struct device *dev, enum hwmon_sensor_types type, 52 u32 attr, int channel, long val) 53 { 54 struct sbrmi_data *data = dev_get_drvdata(dev); 55 struct apml_mbox_msg msg = { 0 }; 56 57 if (!data) 58 return -ENODEV; 59 60 if (type != hwmon_power && attr != hwmon_power_cap) 61 return -EINVAL; 62 /* 63 * hwmon power attributes are in microWatt 64 * mailbox read/write is in mWatt 65 */ 66 val /= 1000; 67 68 val = clamp_val(val, SBRMI_PWR_MIN, data->pwr_limit_max); 69 70 msg.cmd = SBRMI_WRITE_PKG_PWR_LIMIT; 71 msg.mb_in_out = val; 72 73 return rmi_mailbox_xfer(data, &msg); 74 } 75 76 static umode_t sbrmi_is_visible(const void *data, 77 enum hwmon_sensor_types type, 78 u32 attr, int channel) 79 { 80 switch (type) { 81 case hwmon_power: 82 switch (attr) { 83 case hwmon_power_input: 84 case hwmon_power_cap_max: 85 return 0444; 86 case hwmon_power_cap: 87 return 0644; 88 } 89 break; 90 default: 91 break; 92 } 93 return 0; 94 } 95 96 static const struct hwmon_channel_info * const sbrmi_info[] = { 97 HWMON_CHANNEL_INFO(power, 98 HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX), 99 NULL 100 }; 101 102 static const struct hwmon_ops sbrmi_hwmon_ops = { 103 .is_visible = sbrmi_is_visible, 104 .read = sbrmi_read, 105 .write = sbrmi_write, 106 }; 107 108 static const struct hwmon_chip_info sbrmi_chip_info = { 109 .ops = &sbrmi_hwmon_ops, 110 .info = sbrmi_info, 111 }; 112 113 int create_hwmon_sensor_device(struct device *dev, struct sbrmi_data *data) 114 { 115 struct device *hwmon_dev; 116 117 hwmon_dev = devm_hwmon_device_register_with_info(dev, "sbrmi", data, 118 &sbrmi_chip_info, NULL); 119 return PTR_ERR_OR_ZERO(hwmon_dev); 120 } 121