Loading...
Note: File does not exist in v5.4.
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
12static 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
19static 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
60static 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
78static const struct hwmon_ops ice_hwmon_ops = {
79 .is_visible = ice_hwmon_is_visible,
80 .read = ice_hwmon_read
81};
82
83static const struct hwmon_chip_info ice_chip_info = {
84 .ops = &ice_hwmon_ops,
85 .info = ice_hwmon_info
86};
87
88static 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
102void 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
121void ice_hwmon_exit(struct ice_pf *pf)
122{
123 if (!pf->hwmon_dev)
124 return;
125 hwmon_device_unregister(pf->hwmon_dev);
126}