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