// SPDX-License-Identifier: GPL-2.0-only /* * SolidRun DPU driver for control plane * * Copyright (C) 2022-2023 SolidRun * * Author: Alvaro Karsz * */ #include #include "snet_vdpa.h" /* Monitor offsets */ #define SNET_MON_TMP0_IN_OFF 0x00 #define SNET_MON_TMP0_MAX_OFF 0x08 #define SNET_MON_TMP0_CRIT_OFF 0x10 #define SNET_MON_TMP1_IN_OFF 0x18 #define SNET_MON_TMP1_CRIT_OFF 0x20 #define SNET_MON_CURR_IN_OFF 0x28 #define SNET_MON_CURR_MAX_OFF 0x30 #define SNET_MON_CURR_CRIT_OFF 0x38 #define SNET_MON_PWR_IN_OFF 0x40 #define SNET_MON_VOLT_IN_OFF 0x48 #define SNET_MON_VOLT_CRIT_OFF 0x50 #define SNET_MON_VOLT_LCRIT_OFF 0x58 static void snet_hwmon_read_reg(struct psnet *psnet, u32 reg, long *out) { *out = psnet_read64(psnet, psnet->cfg.hwmon_off + reg); } static umode_t snet_howmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { return 0444; } static int snet_howmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct psnet *psnet = dev_get_drvdata(dev); int ret = 0; switch (type) { case hwmon_in: switch (attr) { case hwmon_in_lcrit: snet_hwmon_read_reg(psnet, SNET_MON_VOLT_LCRIT_OFF, val); break; case hwmon_in_crit: snet_hwmon_read_reg(psnet, SNET_MON_VOLT_CRIT_OFF, val); break; case hwmon_in_input: snet_hwmon_read_reg(psnet, SNET_MON_VOLT_IN_OFF, val); break; default: ret = -EOPNOTSUPP; break; } break; case hwmon_power: switch (attr) { case hwmon_power_input: snet_hwmon_read_reg(psnet, SNET_MON_PWR_IN_OFF, val); break; default: ret = -EOPNOTSUPP; break; } break; case hwmon_curr: switch (attr) { case hwmon_curr_input: snet_hwmon_read_reg(psnet, SNET_MON_CURR_IN_OFF, val); break; case hwmon_curr_max: snet_hwmon_read_reg(psnet, SNET_MON_CURR_MAX_OFF, val); break; case hwmon_curr_crit: snet_hwmon_read_reg(psnet, SNET_MON_CURR_CRIT_OFF, val); break; default: ret = -EOPNOTSUPP; break; } break; case hwmon_temp: switch (attr) { case hwmon_temp_input: if (channel == 0) snet_hwmon_read_reg(psnet, SNET_MON_TMP0_IN_OFF, val); else snet_hwmon_read_reg(psnet, SNET_MON_TMP1_IN_OFF, val); break; case hwmon_temp_max: if (channel == 0) snet_hwmon_read_reg(psnet, SNET_MON_TMP0_MAX_OFF, val); else ret = -EOPNOTSUPP; break; case hwmon_temp_crit: if (channel == 0) snet_hwmon_read_reg(psnet, SNET_MON_TMP0_CRIT_OFF, val); else snet_hwmon_read_reg(psnet, SNET_MON_TMP1_CRIT_OFF, val); break; default: ret = -EOPNOTSUPP; break; } break; default: ret = -EOPNOTSUPP; break; } return ret; } static int snet_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, const char **str) { int ret = 0; switch (type) { case hwmon_in: *str = "main_vin"; break; case hwmon_power: *str = "soc_pin"; break; case hwmon_curr: *str = "soc_iin"; break; case hwmon_temp: if (channel == 0) *str = "power_stage_temp"; else *str = "ic_junction_temp"; break; default: ret = -EOPNOTSUPP; break; } return ret; } static const struct hwmon_ops snet_hwmon_ops = { .is_visible = snet_howmon_is_visible, .read = snet_howmon_read, .read_string = snet_hwmon_read_string }; static const struct hwmon_channel_info * const snet_hwmon_info[] = { HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL), HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL), HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_CRIT | HWMON_C_LABEL), HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_LCRIT | HWMON_I_LABEL), NULL }; static const struct hwmon_chip_info snet_hwmono_info = { .ops = &snet_hwmon_ops, .info = snet_hwmon_info, }; /* Create an HW monitor device */ void psnet_create_hwmon(struct pci_dev *pdev) { struct device *hwmon; struct psnet *psnet = pci_get_drvdata(pdev); snprintf(psnet->hwmon_name, SNET_NAME_SIZE, "snet_%s", pci_name(pdev)); hwmon = devm_hwmon_device_register_with_info(&pdev->dev, psnet->hwmon_name, psnet, &snet_hwmono_info, NULL); /* The monitor is not mandatory, Just alert user in case of an error */ if (IS_ERR(hwmon)) SNET_WARN(pdev, "Failed to create SNET hwmon, error %ld\n", PTR_ERR(hwmon)); }