brintos

brintos / linux-shallow public Read only

0
0
Text · 4.4 KiB · af531a3 Raw
189 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * SolidRun DPU driver for control plane4 *5 * Copyright (C) 2022-2023 SolidRun6 *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      0x0016#define SNET_MON_TMP0_MAX_OFF     0x0817#define SNET_MON_TMP0_CRIT_OFF    0x1018#define SNET_MON_TMP1_IN_OFF      0x1819#define SNET_MON_TMP1_CRIT_OFF    0x2020#define SNET_MON_CURR_IN_OFF      0x2821#define SNET_MON_CURR_MAX_OFF     0x3022#define SNET_MON_CURR_CRIT_OFF    0x3823#define SNET_MON_PWR_IN_OFF       0x4024#define SNET_MON_VOLT_IN_OFF      0x4825#define SNET_MON_VOLT_CRIT_OFF    0x5026#define SNET_MON_VOLT_LCRIT_OFF   0x5827 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			else99				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			else105				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			else111				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		else147			*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_string160};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			   NULL169};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}189