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
ice_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)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
ice_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)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
ice_is_internal_reading_supported(struct ice_pf * pf)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
ice_hwmon_init(struct ice_pf * pf)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
ice_hwmon_exit(struct ice_pf * pf)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