xref: /linux/drivers/net/ethernet/intel/ice/ice_hwmon.c (revision 7a08cb9b4bb92fb86f5fe8a3aa0ac08a9b3d783b)
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