File Index
Files and directories
Sign in
FILE

snet_hwmon.c

File preview with syntax highlighting.

linux-6.19.14/drivers/vdpa/solidrun/snet_hwmon.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * SolidRun DPU driver for control plane
  4 *
  5 * Copyright (C) 2022-2023 SolidRun
  6 *
  7 * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
  8 *
  9 */
 10#include <linux/hwmon.h>
 11
 12#include "snet_vdpa.h"
 13
 14/* Monitor offsets */
 15#define SNET_MON_TMP0_IN_OFF      0x00
 16#define SNET_MON_TMP0_MAX_OFF     0x08
 17#define SNET_MON_TMP0_CRIT_OFF    0x10
 18#define SNET_MON_TMP1_IN_OFF      0x18
 19#define SNET_MON_TMP1_CRIT_OFF    0x20
 20#define SNET_MON_CURR_IN_OFF      0x28
 21#define SNET_MON_CURR_MAX_OFF     0x30
 22#define SNET_MON_CURR_CRIT_OFF    0x38
 23#define SNET_MON_PWR_IN_OFF       0x40
 24#define SNET_MON_VOLT_IN_OFF      0x48
 25#define SNET_MON_VOLT_CRIT_OFF    0x50
 26#define SNET_MON_VOLT_LCRIT_OFF   0x58
 27
 28static void snet_hwmon_read_reg(struct psnet *psnet, u32 reg, long *out)
 29{
 30	*out = psnet_read64(psnet, psnet->cfg.hwmon_off + reg);
 31}
 32
 33static umode_t snet_howmon_is_visible(const void *data,
 34				      enum hwmon_sensor_types type,
 35				      u32 attr, int channel)
 36{
 37	return 0444;
 38}
 39
 40static int snet_howmon_read(struct device *dev, enum hwmon_sensor_types type,
 41			    u32 attr, int channel, long *val)
 42{
 43	struct psnet *psnet = dev_get_drvdata(dev);
 44	int ret = 0;
 45
 46	switch (type) {
 47	case hwmon_in:
 48		switch (attr) {
 49		case hwmon_in_lcrit:
 50			snet_hwmon_read_reg(psnet, SNET_MON_VOLT_LCRIT_OFF, val);
 51			break;
 52		case hwmon_in_crit:
 53			snet_hwmon_read_reg(psnet, SNET_MON_VOLT_CRIT_OFF, val);
 54			break;
 55		case hwmon_in_input:
 56			snet_hwmon_read_reg(psnet, SNET_MON_VOLT_IN_OFF, val);
 57			break;
 58		default:
 59			ret = -EOPNOTSUPP;
 60			break;
 61		}
 62		break;
 63
 64	case hwmon_power:
 65		switch (attr) {
 66		case hwmon_power_input:
 67			snet_hwmon_read_reg(psnet, SNET_MON_PWR_IN_OFF, val);
 68			break;
 69
 70		default:
 71			ret = -EOPNOTSUPP;
 72			break;
 73		}
 74		break;
 75
 76	case hwmon_curr:
 77		switch (attr) {
 78		case hwmon_curr_input:
 79			snet_hwmon_read_reg(psnet, SNET_MON_CURR_IN_OFF, val);
 80			break;
 81		case hwmon_curr_max:
 82			snet_hwmon_read_reg(psnet, SNET_MON_CURR_MAX_OFF, val);
 83			break;
 84		case hwmon_curr_crit:
 85			snet_hwmon_read_reg(psnet, SNET_MON_CURR_CRIT_OFF, val);
 86			break;
 87		default:
 88			ret = -EOPNOTSUPP;
 89			break;
 90		}
 91		break;
 92
 93	case hwmon_temp:
 94		switch (attr) {
 95		case hwmon_temp_input:
 96			if (channel == 0)
 97				snet_hwmon_read_reg(psnet, SNET_MON_TMP0_IN_OFF, val);
 98			else
 99				snet_hwmon_read_reg(psnet, SNET_MON_TMP1_IN_OFF, val);
100			break;
101		case hwmon_temp_max:
102			if (channel == 0)
103				snet_hwmon_read_reg(psnet, SNET_MON_TMP0_MAX_OFF, val);
104			else
105				ret = -EOPNOTSUPP;
106			break;
107		case hwmon_temp_crit:
108			if (channel == 0)
109				snet_hwmon_read_reg(psnet, SNET_MON_TMP0_CRIT_OFF, val);
110			else
111				snet_hwmon_read_reg(psnet, SNET_MON_TMP1_CRIT_OFF, val);
112			break;
113
114		default:
115			ret = -EOPNOTSUPP;
116			break;
117		}
118		break;
119
120	default:
121		ret = -EOPNOTSUPP;
122		break;
123	}
124	return ret;
125}
126
127static int snet_hwmon_read_string(struct device *dev,
128				  enum hwmon_sensor_types type, u32 attr,
129				  int channel, const char **str)
130{
131	int ret = 0;
132
133	switch (type) {
134	case hwmon_in:
135		*str = "main_vin";
136		break;
137	case hwmon_power:
138		*str = "soc_pin";
139		break;
140	case hwmon_curr:
141		*str = "soc_iin";
142		break;
143	case hwmon_temp:
144		if (channel == 0)
145			*str = "power_stage_temp";
146		else
147			*str = "ic_junction_temp";
148		break;
149	default:
150		ret = -EOPNOTSUPP;
151		break;
152	}
153	return ret;
154}
155
156static const struct hwmon_ops snet_hwmon_ops = {
157	.is_visible = snet_howmon_is_visible,
158	.read = snet_howmon_read,
159	.read_string = snet_hwmon_read_string
160};
161
162static const struct hwmon_channel_info * const snet_hwmon_info[] = {
163	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_LABEL,
164			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL),
165	HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL),
166	HWMON_CHANNEL_INFO(curr, HWMON_C_INPUT | HWMON_C_MAX | HWMON_C_CRIT | HWMON_C_LABEL),
167	HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_CRIT | HWMON_I_LCRIT | HWMON_I_LABEL),
168			   NULL
169};
170
171static const struct hwmon_chip_info snet_hwmono_info = {
172	.ops = &snet_hwmon_ops,
173	.info = snet_hwmon_info,
174};
175
176/* Create an HW monitor device */
177void psnet_create_hwmon(struct pci_dev *pdev)
178{
179	struct device *hwmon;
180	struct psnet *psnet = pci_get_drvdata(pdev);
181
182	snprintf(psnet->hwmon_name, SNET_NAME_SIZE, "snet_%s", pci_name(pdev));
183	hwmon = devm_hwmon_device_register_with_info(&pdev->dev, psnet->hwmon_name, psnet,
184						     &snet_hwmono_info, NULL);
185	/* The monitor is not mandatory, Just alert user in case of an error */
186	if (IS_ERR(hwmon))
187		SNET_WARN(pdev, "Failed to create SNET hwmon, error %ld\n", PTR_ERR(hwmon));
188}
~/ Read-only file preview.