| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * SolidRun DPU driver for control plane
- *
- * Copyright (C) 2022-2023 SolidRun
- *
- * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
- *
- */
- #include <linux/hwmon.h>
- #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));
- }
|