brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · 0d6c59d Raw
163 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/* Copyright (C) 2017 Netronome Systems, Inc. */3 4#include <linux/kernel.h>5#include <linux/bitops.h>6#include <linux/hwmon.h>7 8#include "nfpcore/nfp_cpp.h"9#include "nfpcore/nfp_nsp.h"10#include "nfp_main.h"11 12#define NFP_TEMP_MAX		(95 * 1000)13#define NFP_TEMP_CRIT		(105 * 1000)14 15#define NFP_POWER_MAX		(25 * 1000 * 1000)16 17static int nfp_hwmon_sensor_id(enum hwmon_sensor_types type, int channel)18{19	if (type == hwmon_temp)20		return NFP_SENSOR_CHIP_TEMPERATURE;21	if (type == hwmon_power)22		return NFP_SENSOR_ASSEMBLY_POWER + channel;23	return -EINVAL;24}25 26static int27nfp_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,28	       int channel, long *val)29{30	static const struct {31		enum hwmon_sensor_types type;32		u32 attr;33		long val;34	} const_vals[] = {35		{ hwmon_temp,	hwmon_temp_max,		NFP_TEMP_MAX },36		{ hwmon_temp,	hwmon_temp_crit,	NFP_TEMP_CRIT },37		{ hwmon_power,	hwmon_power_max,	NFP_POWER_MAX },38	};39	struct nfp_pf *pf = dev_get_drvdata(dev);40	enum nfp_nsp_sensor_id id;41	int err, i;42 43	for (i = 0; i < ARRAY_SIZE(const_vals); i++)44		if (const_vals[i].type == type && const_vals[i].attr == attr) {45			*val = const_vals[i].val;46			return 0;47		}48 49	err = nfp_hwmon_sensor_id(type, channel);50	if (err < 0)51		return err;52	id = err;53 54	if (!(pf->nspi->sensor_mask & BIT(id)))55		return -EOPNOTSUPP;56 57	if (type == hwmon_temp && attr == hwmon_temp_input)58		return nfp_hwmon_read_sensor(pf->cpp, id, val);59	if (type == hwmon_power && attr == hwmon_power_input)60		return nfp_hwmon_read_sensor(pf->cpp, id, val);61 62	return -EINVAL;63}64 65static umode_t66nfp_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,67		     int channel)68{69	if (type == hwmon_temp) {70		switch (attr) {71		case hwmon_temp_input:72		case hwmon_temp_crit:73		case hwmon_temp_max:74			return 0444;75		}76	} else if (type == hwmon_power) {77		switch (attr) {78		case hwmon_power_input:79		case hwmon_power_max:80			return 0444;81		}82	}83	return 0;84}85 86static u32 nfp_chip_config[] = {87	HWMON_C_REGISTER_TZ,88	089};90 91static const struct hwmon_channel_info nfp_chip = {92	.type = hwmon_chip,93	.config = nfp_chip_config,94};95 96static u32 nfp_temp_config[] = {97	HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT,98	099};100 101static const struct hwmon_channel_info nfp_temp = {102	.type = hwmon_temp,103	.config = nfp_temp_config,104};105 106static u32 nfp_power_config[] = {107	HWMON_P_INPUT | HWMON_P_MAX,108	HWMON_P_INPUT,109	HWMON_P_INPUT,110	0111};112 113static const struct hwmon_channel_info nfp_power = {114	.type = hwmon_power,115	.config = nfp_power_config,116};117 118static const struct hwmon_channel_info * const nfp_hwmon_info[] = {119	&nfp_chip,120	&nfp_temp,121	&nfp_power,122	NULL123};124 125static const struct hwmon_ops nfp_hwmon_ops = {126	.is_visible = nfp_hwmon_is_visible,127	.read = nfp_hwmon_read,128};129 130static const struct hwmon_chip_info nfp_chip_info = {131	.ops = &nfp_hwmon_ops,132	.info = nfp_hwmon_info,133};134 135int nfp_hwmon_register(struct nfp_pf *pf)136{137	if (!IS_REACHABLE(CONFIG_HWMON))138		return 0;139 140	if (!pf->nspi) {141		nfp_warn(pf->cpp, "not registering HWMON (no NSP info)\n");142		return 0;143	}144	if (!pf->nspi->sensor_mask) {145		nfp_info(pf->cpp,146			 "not registering HWMON (NSP doesn't report sensors)\n");147		return 0;148	}149 150	pf->hwmon_dev = hwmon_device_register_with_info(&pf->pdev->dev, "nfp",151							pf, &nfp_chip_info,152							NULL);153	return PTR_ERR_OR_ZERO(pf->hwmon_dev);154}155 156void nfp_hwmon_unregister(struct nfp_pf *pf)157{158	if (!IS_REACHABLE(CONFIG_HWMON) || !pf->hwmon_dev)159		return;160 161	hwmon_device_unregister(pf->hwmon_dev);162}163