// SPDX-License-Identifier: GPL-2.0-only /* Atlantic Network Driver * * Copyright (C) 2014-2019 aQuantia Corporation * Copyright (C) 2019-2020 Marvell International Ltd. */ /* File aq_drvinfo.c: Definition of common code for firmware info in sys.*/ #include #include #include #include #include #include #include #include "aq_drvinfo.h" #include "aq_nic.h" #if IS_REACHABLE(CONFIG_HWMON) static const char * const atl_temp_label[] = { "PHY Temperature", "MAC Temperature", }; static int aq_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *value) { struct aq_nic_s *aq_nic = dev_get_drvdata(dev); int err = 0; int temp; if (!aq_nic) return -EIO; if (type != hwmon_temp || attr != hwmon_temp_input) return -EOPNOTSUPP; switch (channel) { case 0: if (!aq_nic->aq_fw_ops->get_phy_temp) return -EOPNOTSUPP; err = aq_nic->aq_fw_ops->get_phy_temp(aq_nic->aq_hw, &temp); *value = temp; break; case 1: if (!aq_nic->aq_fw_ops->get_mac_temp && !aq_nic->aq_hw_ops->hw_get_mac_temp) return -EOPNOTSUPP; if (aq_nic->aq_fw_ops->get_mac_temp) err = aq_nic->aq_fw_ops->get_mac_temp(aq_nic->aq_hw, &temp); else err = aq_nic->aq_hw_ops->hw_get_mac_temp(aq_nic->aq_hw, &temp); *value = temp; break; default: return -EOPNOTSUPP; } return err; } static int aq_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, const char **str) { struct aq_nic_s *aq_nic = dev_get_drvdata(dev); if (!aq_nic) return -EIO; if (type != hwmon_temp || attr != hwmon_temp_label) return -EOPNOTSUPP; if (channel < ARRAY_SIZE(atl_temp_label)) *str = atl_temp_label[channel]; else return -EOPNOTSUPP; return 0; } static umode_t aq_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { const struct aq_nic_s *nic = data; if (type != hwmon_temp) return 0; if (channel == 0 && !nic->aq_fw_ops->get_phy_temp) return 0; else if (channel == 1 && !nic->aq_fw_ops->get_mac_temp && !nic->aq_hw_ops->hw_get_mac_temp) return 0; switch (attr) { case hwmon_temp_input: case hwmon_temp_label: return 0444; default: return 0; } } static const struct hwmon_ops aq_hwmon_ops = { .is_visible = aq_hwmon_is_visible, .read = aq_hwmon_read, .read_string = aq_hwmon_read_string, }; static u32 aq_hwmon_temp_config[] = { HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL, 0, }; static const struct hwmon_channel_info aq_hwmon_temp = { .type = hwmon_temp, .config = aq_hwmon_temp_config, }; static const struct hwmon_channel_info *aq_hwmon_info[] = { &aq_hwmon_temp, NULL, }; static const struct hwmon_chip_info aq_hwmon_chip_info = { .ops = &aq_hwmon_ops, .info = aq_hwmon_info, }; int aq_drvinfo_init(struct net_device *ndev) { struct aq_nic_s *aq_nic = netdev_priv(ndev); struct device *dev = &aq_nic->pdev->dev; struct device *hwmon_dev; int err = 0; hwmon_dev = devm_hwmon_device_register_with_info(dev, ndev->name, aq_nic, &aq_hwmon_chip_info, NULL); if (IS_ERR(hwmon_dev)) err = PTR_ERR(hwmon_dev); return err; } #else int aq_drvinfo_init(struct net_device *ndev) { return 0; } #endif