18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Atlantic Network Driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2014-2019 aQuantia Corporation 58c2ecf20Sopenharmony_ci * Copyright (C) 2019-2020 Marvell International Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/kobject.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/stat.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/hwmon.h> 168c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "aq_drvinfo.h" 198c2ecf20Sopenharmony_ci#include "aq_nic.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#if IS_REACHABLE(CONFIG_HWMON) 228c2ecf20Sopenharmony_cistatic const char * const atl_temp_label[] = { 238c2ecf20Sopenharmony_ci "PHY Temperature", 248c2ecf20Sopenharmony_ci "MAC Temperature", 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 288c2ecf20Sopenharmony_ci u32 attr, int channel, long *value) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic = dev_get_drvdata(dev); 318c2ecf20Sopenharmony_ci int err = 0; 328c2ecf20Sopenharmony_ci int temp; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (!aq_nic) 358c2ecf20Sopenharmony_ci return -EIO; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (type != hwmon_temp || attr != hwmon_temp_input) 388c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci switch (channel) { 418c2ecf20Sopenharmony_ci case 0: 428c2ecf20Sopenharmony_ci if (!aq_nic->aq_fw_ops->get_phy_temp) 438c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci err = aq_nic->aq_fw_ops->get_phy_temp(aq_nic->aq_hw, &temp); 468c2ecf20Sopenharmony_ci *value = temp; 478c2ecf20Sopenharmony_ci break; 488c2ecf20Sopenharmony_ci case 1: 498c2ecf20Sopenharmony_ci if (!aq_nic->aq_fw_ops->get_mac_temp && 508c2ecf20Sopenharmony_ci !aq_nic->aq_hw_ops->hw_get_mac_temp) 518c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci if (aq_nic->aq_fw_ops->get_mac_temp) 548c2ecf20Sopenharmony_ci err = aq_nic->aq_fw_ops->get_mac_temp(aq_nic->aq_hw, &temp); 558c2ecf20Sopenharmony_ci else 568c2ecf20Sopenharmony_ci err = aq_nic->aq_hw_ops->hw_get_mac_temp(aq_nic->aq_hw, &temp); 578c2ecf20Sopenharmony_ci *value = temp; 588c2ecf20Sopenharmony_ci break; 598c2ecf20Sopenharmony_ci default: 608c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return err; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic int aq_hwmon_read_string(struct device *dev, 678c2ecf20Sopenharmony_ci enum hwmon_sensor_types type, 688c2ecf20Sopenharmony_ci u32 attr, int channel, const char **str) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic = dev_get_drvdata(dev); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (!aq_nic) 738c2ecf20Sopenharmony_ci return -EIO; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (type != hwmon_temp || attr != hwmon_temp_label) 768c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (channel < ARRAY_SIZE(atl_temp_label)) 798c2ecf20Sopenharmony_ci *str = atl_temp_label[channel]; 808c2ecf20Sopenharmony_ci else 818c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci return 0; 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic umode_t aq_hwmon_is_visible(const void *data, 878c2ecf20Sopenharmony_ci enum hwmon_sensor_types type, 888c2ecf20Sopenharmony_ci u32 attr, int channel) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci const struct aq_nic_s *nic = data; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (type != hwmon_temp) 938c2ecf20Sopenharmony_ci return 0; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (channel == 0 && !nic->aq_fw_ops->get_phy_temp) 968c2ecf20Sopenharmony_ci return 0; 978c2ecf20Sopenharmony_ci else if (channel == 1 && !nic->aq_fw_ops->get_mac_temp && 988c2ecf20Sopenharmony_ci !nic->aq_hw_ops->hw_get_mac_temp) 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci switch (attr) { 1028c2ecf20Sopenharmony_ci case hwmon_temp_input: 1038c2ecf20Sopenharmony_ci case hwmon_temp_label: 1048c2ecf20Sopenharmony_ci return 0444; 1058c2ecf20Sopenharmony_ci default: 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic const struct hwmon_ops aq_hwmon_ops = { 1118c2ecf20Sopenharmony_ci .is_visible = aq_hwmon_is_visible, 1128c2ecf20Sopenharmony_ci .read = aq_hwmon_read, 1138c2ecf20Sopenharmony_ci .read_string = aq_hwmon_read_string, 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic u32 aq_hwmon_temp_config[] = { 1178c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL, 1188c2ecf20Sopenharmony_ci HWMON_T_INPUT | HWMON_T_LABEL, 1198c2ecf20Sopenharmony_ci 0, 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic const struct hwmon_channel_info aq_hwmon_temp = { 1238c2ecf20Sopenharmony_ci .type = hwmon_temp, 1248c2ecf20Sopenharmony_ci .config = aq_hwmon_temp_config, 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic const struct hwmon_channel_info *aq_hwmon_info[] = { 1288c2ecf20Sopenharmony_ci &aq_hwmon_temp, 1298c2ecf20Sopenharmony_ci NULL, 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic const struct hwmon_chip_info aq_hwmon_chip_info = { 1338c2ecf20Sopenharmony_ci .ops = &aq_hwmon_ops, 1348c2ecf20Sopenharmony_ci .info = aq_hwmon_info, 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciint aq_drvinfo_init(struct net_device *ndev) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic = netdev_priv(ndev); 1408c2ecf20Sopenharmony_ci struct device *dev = &aq_nic->pdev->dev; 1418c2ecf20Sopenharmony_ci struct device *hwmon_dev; 1428c2ecf20Sopenharmony_ci int err = 0; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci hwmon_dev = devm_hwmon_device_register_with_info(dev, 1458c2ecf20Sopenharmony_ci ndev->name, 1468c2ecf20Sopenharmony_ci aq_nic, 1478c2ecf20Sopenharmony_ci &aq_hwmon_chip_info, 1488c2ecf20Sopenharmony_ci NULL); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (IS_ERR(hwmon_dev)) 1518c2ecf20Sopenharmony_ci err = PTR_ERR(hwmon_dev); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return err; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#else 1578c2ecf20Sopenharmony_ciint aq_drvinfo_init(struct net_device *ndev) { return 0; } 1588c2ecf20Sopenharmony_ci#endif 159