Merge tag 'fuse-fixes-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszer...
[linux-2.6-microblaze.git] / drivers / net / ethernet / netronome / nfp / nfp_hwmon.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017 Netronome Systems, Inc. */
3
4 #include <linux/kernel.h>
5 #include <linux/bitops.h>
6 #include <linux/hwmon.h>
7
8 #include "nfpcore/nfp_cpp.h"
9 #include "nfpcore/nfp_nsp.h"
10 #include "nfp_main.h"
11
12 #define NFP_TEMP_MAX            (95 * 1000)
13 #define NFP_TEMP_CRIT           (105 * 1000)
14
15 #define NFP_POWER_MAX           (25 * 1000 * 1000)
16
17 static int nfp_hwmon_sensor_id(enum hwmon_sensor_types type, int channel)
18 {
19         if (type == hwmon_temp)
20                 return NFP_SENSOR_CHIP_TEMPERATURE;
21         if (type == hwmon_power)
22                 return NFP_SENSOR_ASSEMBLY_POWER + channel;
23         return -EINVAL;
24 }
25
26 static int
27 nfp_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
28                int channel, long *val)
29 {
30         static const struct {
31                 enum hwmon_sensor_types type;
32                 u32 attr;
33                 long val;
34         } const_vals[] = {
35                 { hwmon_temp,   hwmon_temp_max,         NFP_TEMP_MAX },
36                 { hwmon_temp,   hwmon_temp_crit,        NFP_TEMP_CRIT },
37                 { hwmon_power,  hwmon_power_max,        NFP_POWER_MAX },
38         };
39         struct nfp_pf *pf = dev_get_drvdata(dev);
40         enum nfp_nsp_sensor_id id;
41         int err, i;
42
43         for (i = 0; i < ARRAY_SIZE(const_vals); i++)
44                 if (const_vals[i].type == type && const_vals[i].attr == attr) {
45                         *val = const_vals[i].val;
46                         return 0;
47                 }
48
49         err = nfp_hwmon_sensor_id(type, channel);
50         if (err < 0)
51                 return err;
52         id = err;
53
54         if (!(pf->nspi->sensor_mask & BIT(id)))
55                 return -EOPNOTSUPP;
56
57         if (type == hwmon_temp && attr == hwmon_temp_input)
58                 return nfp_hwmon_read_sensor(pf->cpp, id, val);
59         if (type == hwmon_power && attr == hwmon_power_input)
60                 return nfp_hwmon_read_sensor(pf->cpp, id, val);
61
62         return -EINVAL;
63 }
64
65 static umode_t
66 nfp_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
67                      int channel)
68 {
69         if (type == hwmon_temp) {
70                 switch (attr) {
71                 case hwmon_temp_input:
72                 case hwmon_temp_crit:
73                 case hwmon_temp_max:
74                         return 0444;
75                 }
76         } else if (type == hwmon_power) {
77                 switch (attr) {
78                 case hwmon_power_input:
79                 case hwmon_power_max:
80                         return 0444;
81                 }
82         }
83         return 0;
84 }
85
86 static u32 nfp_chip_config[] = {
87         HWMON_C_REGISTER_TZ,
88         0
89 };
90
91 static const struct hwmon_channel_info nfp_chip = {
92         .type = hwmon_chip,
93         .config = nfp_chip_config,
94 };
95
96 static u32 nfp_temp_config[] = {
97         HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT,
98         0
99 };
100
101 static const struct hwmon_channel_info nfp_temp = {
102         .type = hwmon_temp,
103         .config = nfp_temp_config,
104 };
105
106 static u32 nfp_power_config[] = {
107         HWMON_P_INPUT | HWMON_P_MAX,
108         HWMON_P_INPUT,
109         HWMON_P_INPUT,
110         0
111 };
112
113 static const struct hwmon_channel_info nfp_power = {
114         .type = hwmon_power,
115         .config = nfp_power_config,
116 };
117
118 static const struct hwmon_channel_info *nfp_hwmon_info[] = {
119         &nfp_chip,
120         &nfp_temp,
121         &nfp_power,
122         NULL
123 };
124
125 static const struct hwmon_ops nfp_hwmon_ops = {
126         .is_visible = nfp_hwmon_is_visible,
127         .read = nfp_hwmon_read,
128 };
129
130 static const struct hwmon_chip_info nfp_chip_info = {
131         .ops = &nfp_hwmon_ops,
132         .info = nfp_hwmon_info,
133 };
134
135 int nfp_hwmon_register(struct nfp_pf *pf)
136 {
137         if (!IS_REACHABLE(CONFIG_HWMON))
138                 return 0;
139
140         if (!pf->nspi) {
141                 nfp_warn(pf->cpp, "not registering HWMON (no NSP info)\n");
142                 return 0;
143         }
144         if (!pf->nspi->sensor_mask) {
145                 nfp_info(pf->cpp,
146                          "not registering HWMON (NSP doesn't report sensors)\n");
147                 return 0;
148         }
149
150         pf->hwmon_dev = hwmon_device_register_with_info(&pf->pdev->dev, "nfp",
151                                                         pf, &nfp_chip_info,
152                                                         NULL);
153         return PTR_ERR_OR_ZERO(pf->hwmon_dev);
154 }
155
156 void nfp_hwmon_unregister(struct nfp_pf *pf)
157 {
158         if (!IS_REACHABLE(CONFIG_HWMON) || !pf->hwmon_dev)
159                 return;
160
161         hwmon_device_unregister(pf->hwmon_dev);
162 }