1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Copyright (C) 2014-2019 aQuantia Corporation. */ 3 4 /* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/ 5 6 #include <linux/init.h> 7 #include <linux/kobject.h> 8 #include <linux/module.h> 9 #include <linux/stat.h> 10 #include <linux/string.h> 11 #include <linux/hwmon.h> 12 #include <linux/uaccess.h> 13 14 #include "aq_drvinfo.h" 15 16 #if IS_REACHABLE(CONFIG_HWMON) 17 static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 18 u32 attr, int channel, long *value) 19 { 20 struct aq_nic_s *aq_nic = dev_get_drvdata(dev); 21 int temp; 22 int err; 23 24 if (!aq_nic) 25 return -EIO; 26 27 if (type != hwmon_temp) 28 return -EOPNOTSUPP; 29 30 if (!aq_nic->aq_fw_ops->get_phy_temp) 31 return -EOPNOTSUPP; 32 33 switch (attr) { 34 case hwmon_temp_input: 35 err = aq_nic->aq_fw_ops->get_phy_temp(aq_nic->aq_hw, &temp); 36 *value = temp; 37 return err; 38 default: 39 return -EOPNOTSUPP; 40 } 41 } 42 43 static int aq_hwmon_read_string(struct device *dev, 44 enum hwmon_sensor_types type, 45 u32 attr, int channel, const char **str) 46 { 47 struct aq_nic_s *aq_nic = dev_get_drvdata(dev); 48 49 if (!aq_nic) 50 return -EIO; 51 52 if (type != hwmon_temp) 53 return -EOPNOTSUPP; 54 55 if (!aq_nic->aq_fw_ops->get_phy_temp) 56 return -EOPNOTSUPP; 57 58 switch (attr) { 59 case hwmon_temp_label: 60 *str = "PHY Temperature"; 61 return 0; 62 default: 63 return -EOPNOTSUPP; 64 } 65 } 66 67 static umode_t aq_hwmon_is_visible(const void *data, 68 enum hwmon_sensor_types type, 69 u32 attr, int channel) 70 { 71 if (type != hwmon_temp) 72 return 0; 73 74 switch (attr) { 75 case hwmon_temp_input: 76 case hwmon_temp_label: 77 return 0444; 78 default: 79 return 0; 80 } 81 } 82 83 static const struct hwmon_ops aq_hwmon_ops = { 84 .is_visible = aq_hwmon_is_visible, 85 .read = aq_hwmon_read, 86 .read_string = aq_hwmon_read_string, 87 }; 88 89 static u32 aq_hwmon_temp_config[] = { 90 HWMON_T_INPUT | HWMON_T_LABEL, 91 0, 92 }; 93 94 static const struct hwmon_channel_info aq_hwmon_temp = { 95 .type = hwmon_temp, 96 .config = aq_hwmon_temp_config, 97 }; 98 99 static const struct hwmon_channel_info *aq_hwmon_info[] = { 100 &aq_hwmon_temp, 101 NULL, 102 }; 103 104 static const struct hwmon_chip_info aq_hwmon_chip_info = { 105 .ops = &aq_hwmon_ops, 106 .info = aq_hwmon_info, 107 }; 108 109 int aq_drvinfo_init(struct net_device *ndev) 110 { 111 struct aq_nic_s *aq_nic = netdev_priv(ndev); 112 struct device *dev = &aq_nic->pdev->dev; 113 struct device *hwmon_dev; 114 int err = 0; 115 116 hwmon_dev = devm_hwmon_device_register_with_info(dev, 117 ndev->name, 118 aq_nic, 119 &aq_hwmon_chip_info, 120 NULL); 121 122 if (IS_ERR(hwmon_dev)) 123 err = PTR_ERR(hwmon_dev); 124 125 return err; 126 } 127 128 #else 129 int aq_drvinfo_init(struct net_device *ndev) { return 0; } 130 #endif 131