FILE
rmi-hwmon.c
File preview with syntax highlighting.
linux-6.19.14/drivers/misc/amd-sbi/rmi-hwmon.c
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 15static 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 51static 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 76static 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 96static 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 102static const struct hwmon_ops sbrmi_hwmon_ops = { 103 .is_visible = sbrmi_is_visible, 104 .read = sbrmi_read, 105 .write = sbrmi_write, 106}; 107 108static const struct hwmon_chip_info sbrmi_chip_info = { 109 .ops = &sbrmi_hwmon_ops, 110 .info = sbrmi_info, 111}; 112 113int 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}
~/
Read-only file preview.