nfp_hwmon.c (3519B)
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 int 27nfp_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_t 66nfp_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 0 89}; 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 0 99}; 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 0 111}; 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 *nfp_hwmon_info[] = { 119 &nfp_chip, 120 &nfp_temp, 121 &nfp_power, 122 NULL 123}; 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}