1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 4 #include <linux/hwmon.h> 5 6 #include "fbnic.h" 7 #include "fbnic_mac.h" 8 9 static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type) 10 { 11 if (type == hwmon_temp) 12 return FBNIC_SENSOR_TEMP; 13 if (type == hwmon_in) 14 return FBNIC_SENSOR_VOLTAGE; 15 16 return -EOPNOTSUPP; 17 } 18 19 static umode_t fbnic_hwmon_is_visible(const void *drvdata, 20 enum hwmon_sensor_types type, 21 u32 attr, int channel) 22 { 23 if (type == hwmon_temp && attr == hwmon_temp_input) 24 return 0444; 25 if (type == hwmon_in && attr == hwmon_in_input) 26 return 0444; 27 28 return 0; 29 } 30 31 static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 32 u32 attr, int channel, long *val) 33 { 34 struct fbnic_dev *fbd = dev_get_drvdata(dev); 35 const struct fbnic_mac *mac = fbd->mac; 36 int id; 37 38 id = fbnic_hwmon_sensor_id(type); 39 return id < 0 ? id : mac->get_sensor(fbd, id, val); 40 } 41 42 static const struct hwmon_ops fbnic_hwmon_ops = { 43 .is_visible = fbnic_hwmon_is_visible, 44 .read = fbnic_hwmon_read, 45 }; 46 47 static const struct hwmon_channel_info *fbnic_hwmon_info[] = { 48 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 49 HWMON_CHANNEL_INFO(in, HWMON_I_INPUT), 50 NULL 51 }; 52 53 static const struct hwmon_chip_info fbnic_chip_info = { 54 .ops = &fbnic_hwmon_ops, 55 .info = fbnic_hwmon_info, 56 }; 57 58 void fbnic_hwmon_register(struct fbnic_dev *fbd) 59 { 60 if (!IS_REACHABLE(CONFIG_HWMON)) 61 return; 62 63 fbd->hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic", 64 fbd, &fbnic_chip_info, 65 NULL); 66 if (IS_ERR(fbd->hwmon)) { 67 dev_notice(fbd->dev, 68 "Failed to register hwmon device %pe\n", 69 fbd->hwmon); 70 fbd->hwmon = NULL; 71 } 72 } 73 74 void fbnic_hwmon_unregister(struct fbnic_dev *fbd) 75 { 76 if (!IS_REACHABLE(CONFIG_HWMON) || !fbd->hwmon) 77 return; 78 79 hwmon_device_unregister(fbd->hwmon); 80 fbd->hwmon = NULL; 81 } 82