1 /* 2 * Copyright (C) 2017 Netronome Systems, Inc. 3 * 4 * This software is dual licensed under the GNU General License Version 2, 5 * June 1991 as shown in the file COPYING in the top-level directory of this 6 * source tree or the BSD 2-Clause License provided below. You have the 7 * option to license this software under the complete terms of either license. 8 * 9 * The BSD 2-Clause License: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * 1. Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * 2. Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #include <linux/kernel.h> 35 #include <linux/bitops.h> 36 #include <linux/hwmon.h> 37 38 #include "nfpcore/nfp_cpp.h" 39 #include "nfpcore/nfp_nsp.h" 40 #include "nfp_main.h" 41 42 #define NFP_TEMP_MAX (95 * 1000) 43 #define NFP_TEMP_CRIT (105 * 1000) 44 45 #define NFP_POWER_MAX (25 * 1000 * 1000) 46 47 static int nfp_hwmon_sensor_id(enum hwmon_sensor_types type, int channel) 48 { 49 if (type == hwmon_temp) 50 return NFP_SENSOR_CHIP_TEMPERATURE; 51 if (type == hwmon_power) 52 return NFP_SENSOR_ASSEMBLY_POWER + channel; 53 return -EINVAL; 54 } 55 56 static int 57 nfp_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, 58 int channel, long *val) 59 { 60 static const struct { 61 enum hwmon_sensor_types type; 62 u32 attr; 63 long val; 64 } const_vals[] = { 65 { hwmon_temp, hwmon_temp_max, NFP_TEMP_MAX }, 66 { hwmon_temp, hwmon_temp_crit, NFP_TEMP_CRIT }, 67 { hwmon_power, hwmon_power_max, NFP_POWER_MAX }, 68 }; 69 struct nfp_pf *pf = dev_get_drvdata(dev); 70 enum nfp_nsp_sensor_id id; 71 int err, i; 72 73 for (i = 0; i < ARRAY_SIZE(const_vals); i++) 74 if (const_vals[i].type == type && const_vals[i].attr == attr) { 75 *val = const_vals[i].val; 76 return 0; 77 } 78 79 err = nfp_hwmon_sensor_id(type, channel); 80 if (err < 0) 81 return err; 82 id = err; 83 84 if (!(pf->nspi->sensor_mask & BIT(id))) 85 return -EOPNOTSUPP; 86 87 if (type == hwmon_temp && attr == hwmon_temp_input) 88 return nfp_hwmon_read_sensor(pf->cpp, id, val); 89 if (type == hwmon_power && attr == hwmon_power_input) 90 return nfp_hwmon_read_sensor(pf->cpp, id, val); 91 92 return -EINVAL; 93 } 94 95 static umode_t 96 nfp_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, 97 int channel) 98 { 99 if (type == hwmon_temp) { 100 switch (attr) { 101 case hwmon_temp_input: 102 case hwmon_temp_crit: 103 case hwmon_temp_max: 104 return 0444; 105 } 106 } else if (type == hwmon_power) { 107 switch (attr) { 108 case hwmon_power_input: 109 case hwmon_power_max: 110 return 0444; 111 } 112 } 113 return 0; 114 } 115 116 static u32 nfp_chip_config[] = { 117 HWMON_C_REGISTER_TZ, 118 0 119 }; 120 121 static const struct hwmon_channel_info nfp_chip = { 122 .type = hwmon_chip, 123 .config = nfp_chip_config, 124 }; 125 126 static u32 nfp_temp_config[] = { 127 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT, 128 0 129 }; 130 131 static const struct hwmon_channel_info nfp_temp = { 132 .type = hwmon_temp, 133 .config = nfp_temp_config, 134 }; 135 136 static u32 nfp_power_config[] = { 137 HWMON_P_INPUT | HWMON_P_MAX, 138 HWMON_P_INPUT, 139 HWMON_P_INPUT, 140 0 141 }; 142 143 static const struct hwmon_channel_info nfp_power = { 144 .type = hwmon_power, 145 .config = nfp_power_config, 146 }; 147 148 static const struct hwmon_channel_info *nfp_hwmon_info[] = { 149 &nfp_chip, 150 &nfp_temp, 151 &nfp_power, 152 NULL 153 }; 154 155 static const struct hwmon_ops nfp_hwmon_ops = { 156 .is_visible = nfp_hwmon_is_visible, 157 .read = nfp_hwmon_read, 158 }; 159 160 static const struct hwmon_chip_info nfp_chip_info = { 161 .ops = &nfp_hwmon_ops, 162 .info = nfp_hwmon_info, 163 }; 164 165 int nfp_hwmon_register(struct nfp_pf *pf) 166 { 167 if (!IS_REACHABLE(CONFIG_HWMON)) 168 return 0; 169 170 if (!pf->nspi) { 171 nfp_warn(pf->cpp, "not registering HWMON (no NSP info)\n"); 172 return 0; 173 } 174 if (!pf->nspi->sensor_mask) { 175 nfp_info(pf->cpp, 176 "not registering HWMON (NSP doesn't report sensors)\n"); 177 return 0; 178 } 179 180 pf->hwmon_dev = hwmon_device_register_with_info(&pf->pdev->dev, "nfp", 181 pf, &nfp_chip_info, 182 NULL); 183 return PTR_ERR_OR_ZERO(pf->hwmon_dev); 184 } 185 186 void nfp_hwmon_unregister(struct nfp_pf *pf) 187 { 188 if (!IS_REACHABLE(CONFIG_HWMON) || !pf->hwmon_dev) 189 return; 190 191 hwmon_device_unregister(pf->hwmon_dev); 192 } 193