1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2023, Intel Corporation. */ 3 4 #include "ice.h" 5 #include "ice_hwmon.h" 6 #include "ice_adminq_cmd.h" 7 8 #include <linux/hwmon.h> 9 10 #define TEMP_FROM_REG(reg) ((reg) * 1000) 11 12 static const struct hwmon_channel_info *ice_hwmon_info[] = { 13 HWMON_CHANNEL_INFO(temp, 14 HWMON_T_INPUT | HWMON_T_MAX | 15 HWMON_T_CRIT | HWMON_T_EMERGENCY), 16 NULL 17 }; 18 19 static int ice_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 20 u32 attr, int channel, long *val) 21 { 22 struct ice_aqc_get_sensor_reading_resp resp; 23 struct ice_pf *pf = dev_get_drvdata(dev); 24 int ret; 25 26 if (type != hwmon_temp) 27 return -EOPNOTSUPP; 28 29 ret = ice_aq_get_sensor_reading(&pf->hw, &resp); 30 if (ret) { 31 dev_warn_ratelimited(dev, 32 "%s HW read failure (%d)\n", 33 __func__, 34 ret); 35 return ret; 36 } 37 38 switch (attr) { 39 case hwmon_temp_input: 40 *val = TEMP_FROM_REG(resp.data.s0f0.temp); 41 break; 42 case hwmon_temp_max: 43 *val = TEMP_FROM_REG(resp.data.s0f0.temp_warning_threshold); 44 break; 45 case hwmon_temp_crit: 46 *val = TEMP_FROM_REG(resp.data.s0f0.temp_critical_threshold); 47 break; 48 case hwmon_temp_emergency: 49 *val = TEMP_FROM_REG(resp.data.s0f0.temp_fatal_threshold); 50 break; 51 default: 52 dev_dbg(dev, "%s unsupported attribute (%d)\n", 53 __func__, attr); 54 return -EOPNOTSUPP; 55 } 56 57 return 0; 58 } 59 60 static umode_t ice_hwmon_is_visible(const void *data, 61 enum hwmon_sensor_types type, u32 attr, 62 int channel) 63 { 64 if (type != hwmon_temp) 65 return 0; 66 67 switch (attr) { 68 case hwmon_temp_input: 69 case hwmon_temp_crit: 70 case hwmon_temp_max: 71 case hwmon_temp_emergency: 72 return 0444; 73 } 74 75 return 0; 76 } 77 78 static const struct hwmon_ops ice_hwmon_ops = { 79 .is_visible = ice_hwmon_is_visible, 80 .read = ice_hwmon_read 81 }; 82 83 static const struct hwmon_chip_info ice_chip_info = { 84 .ops = &ice_hwmon_ops, 85 .info = ice_hwmon_info 86 }; 87 88 static bool ice_is_internal_reading_supported(struct ice_pf *pf) 89 { 90 /* Only the first PF will report temperature for a chip. 91 * Note that internal temp reading is not supported 92 * for older FW (< v4.30). 93 */ 94 if (pf->hw.pf_id) 95 return false; 96 97 unsigned long sensors = pf->hw.dev_caps.supported_sensors; 98 99 return test_bit(ICE_SENSOR_SUPPORT_E810_INT_TEMP_BIT, &sensors); 100 }; 101 102 void ice_hwmon_init(struct ice_pf *pf) 103 { 104 struct device *dev = ice_pf_to_dev(pf); 105 struct device *hdev; 106 107 if (!ice_is_internal_reading_supported(pf)) 108 return; 109 110 hdev = hwmon_device_register_with_info(dev, "ice", pf, &ice_chip_info, 111 NULL); 112 if (IS_ERR(hdev)) { 113 dev_warn(dev, 114 "hwmon_device_register_with_info returns error (%ld)", 115 PTR_ERR(hdev)); 116 return; 117 } 118 pf->hwmon_dev = hdev; 119 } 120 121 void ice_hwmon_exit(struct ice_pf *pf) 122 { 123 if (!pf->hwmon_dev) 124 return; 125 hwmon_device_unregister(pf->hwmon_dev); 126 } 127