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