Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlxsw / core_hwmon.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
3
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/device.h>
7 #include <linux/sysfs.h>
8 #include <linux/hwmon.h>
9 #include <linux/err.h>
10 #include <linux/sfp.h>
11
12 #include "core.h"
13 #include "core_env.h"
14
15 #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
16 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
17                                 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
18
19 struct mlxsw_hwmon_attr {
20         struct device_attribute dev_attr;
21         struct mlxsw_hwmon *hwmon;
22         unsigned int type_index;
23         char name[32];
24 };
25
26 static int mlxsw_hwmon_get_attr_index(int index, int count)
27 {
28         if (index >= count)
29                 return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN;
30
31         return index;
32 }
33
34 struct mlxsw_hwmon {
35         struct mlxsw_core *core;
36         const struct mlxsw_bus_info *bus_info;
37         struct device *hwmon_dev;
38         struct attribute_group group;
39         const struct attribute_group *groups[2];
40         struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
41         struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
42         unsigned int attrs_count;
43         u8 sensor_count;
44         u8 module_sensor_max;
45 };
46
47 static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
48                                      struct device_attribute *attr,
49                                      char *buf)
50 {
51         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
52                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
53         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
54         char mtmp_pl[MLXSW_REG_MTMP_LEN];
55         int temp, index;
56         int err;
57
58         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
59                                            mlxsw_hwmon->module_sensor_max);
60         mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
61         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
62         if (err) {
63                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
64                 return err;
65         }
66         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
67         return sprintf(buf, "%d\n", temp);
68 }
69
70 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
71                                          struct device_attribute *attr,
72                                          char *buf)
73 {
74         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
75                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
76         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
77         char mtmp_pl[MLXSW_REG_MTMP_LEN];
78         int temp_max, index;
79         int err;
80
81         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
82                                            mlxsw_hwmon->module_sensor_max);
83         mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
84         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
85         if (err) {
86                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
87                 return err;
88         }
89         mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL);
90         return sprintf(buf, "%d\n", temp_max);
91 }
92
93 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
94                                           struct device_attribute *attr,
95                                           const char *buf, size_t len)
96 {
97         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
98                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
99         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
100         char mtmp_pl[MLXSW_REG_MTMP_LEN];
101         unsigned long val;
102         int index;
103         int err;
104
105         err = kstrtoul(buf, 10, &val);
106         if (err)
107                 return err;
108         if (val != 1)
109                 return -EINVAL;
110
111         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
112                                            mlxsw_hwmon->module_sensor_max);
113         mlxsw_reg_mtmp_pack(mtmp_pl, index, true, true);
114         err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
115         if (err) {
116                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n");
117                 return err;
118         }
119         return len;
120 }
121
122 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
123                                         struct device_attribute *attr,
124                                         char *buf)
125 {
126         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
127                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
128         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
129         char mfsm_pl[MLXSW_REG_MFSM_LEN];
130         int err;
131
132         mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index);
133         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl);
134         if (err) {
135                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
136                 return err;
137         }
138         return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
139 }
140
141 static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev,
142                                           struct device_attribute *attr,
143                                           char *buf)
144 {
145         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
146                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
147         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
148         char fore_pl[MLXSW_REG_FORE_LEN];
149         bool fault;
150         int err;
151
152         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl);
153         if (err) {
154                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
155                 return err;
156         }
157         mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault);
158
159         return sprintf(buf, "%u\n", fault);
160 }
161
162 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
163                                     struct device_attribute *attr,
164                                     char *buf)
165 {
166         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
167                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
168         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
169         char mfsc_pl[MLXSW_REG_MFSC_LEN];
170         int err;
171
172         mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0);
173         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
174         if (err) {
175                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n");
176                 return err;
177         }
178         return sprintf(buf, "%u\n",
179                        mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl));
180 }
181
182 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
183                                      struct device_attribute *attr,
184                                      const char *buf, size_t len)
185 {
186         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
187                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
188         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
189         char mfsc_pl[MLXSW_REG_MFSC_LEN];
190         unsigned long val;
191         int err;
192
193         err = kstrtoul(buf, 10, &val);
194         if (err)
195                 return err;
196         if (val > 255)
197                 return -EINVAL;
198
199         mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val);
200         err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
201         if (err) {
202                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n");
203                 return err;
204         }
205         return len;
206 }
207
208 static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
209                                             struct device_attribute *attr,
210                                             char *buf)
211 {
212         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
213                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
214         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
215         char mtmp_pl[MLXSW_REG_MTMP_LEN];
216         u8 module;
217         int temp;
218         int err;
219
220         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
221         mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
222                             false, false);
223         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
224         if (err)
225                 return err;
226         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
227
228         return sprintf(buf, "%d\n", temp);
229 }
230
231 static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
232                                                   struct device_attribute *attr,
233                                                   char *buf)
234 {
235         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
236                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
237         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
238         char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
239         u8 module, fault;
240         u16 temp;
241         int err;
242
243         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
244         mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
245                             1);
246         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
247         if (err) {
248                 dev_err(dev, "Failed to query module temperature sensor\n");
249                 return err;
250         }
251
252         mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
253
254         /* Update status and temperature cache. */
255         switch (temp) {
256         case MLXSW_REG_MTBR_BAD_SENS_INFO:
257                 /* Untrusted cable is connected. Reading temperature from its
258                  * sensor is faulty.
259                  */
260                 fault = 1;
261                 break;
262         case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
263         case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
264         case MLXSW_REG_MTBR_INDEX_NA:
265         default:
266                 fault = 0;
267                 break;
268         }
269
270         return sprintf(buf, "%u\n", fault);
271 }
272
273 static ssize_t
274 mlxsw_hwmon_module_temp_critical_show(struct device *dev,
275                                       struct device_attribute *attr, char *buf)
276 {
277         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
278                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
279         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
280         int temp;
281         u8 module;
282         int err;
283
284         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
285         err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
286                                                    SFP_TEMP_HIGH_WARN, &temp);
287         if (err) {
288                 dev_err(dev, "Failed to query module temperature thresholds\n");
289                 return err;
290         }
291
292         return sprintf(buf, "%u\n", temp);
293 }
294
295 static ssize_t
296 mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
297                                        struct device_attribute *attr,
298                                        char *buf)
299 {
300         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
301                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
302         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
303         u8 module;
304         int temp;
305         int err;
306
307         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
308         err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
309                                                    SFP_TEMP_HIGH_ALARM, &temp);
310         if (err) {
311                 dev_err(dev, "Failed to query module temperature thresholds\n");
312                 return err;
313         }
314
315         return sprintf(buf, "%u\n", temp);
316 }
317
318 static ssize_t
319 mlxsw_hwmon_module_temp_label_show(struct device *dev,
320                                    struct device_attribute *attr,
321                                    char *buf)
322 {
323         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
324                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
325
326         return sprintf(buf, "front panel %03u\n",
327                        mlwsw_hwmon_attr->type_index);
328 }
329
330 static ssize_t
331 mlxsw_hwmon_gbox_temp_label_show(struct device *dev,
332                                  struct device_attribute *attr,
333                                  char *buf)
334 {
335         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
336                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
337         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
338         int index = mlwsw_hwmon_attr->type_index -
339                     mlxsw_hwmon->module_sensor_max + 1;
340
341         return sprintf(buf, "gearbox %03u\n", index);
342 }
343
344 enum mlxsw_hwmon_attr_type {
345         MLXSW_HWMON_ATTR_TYPE_TEMP,
346         MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
347         MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
348         MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
349         MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
350         MLXSW_HWMON_ATTR_TYPE_PWM,
351         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE,
352         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
353         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
354         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
355         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
356         MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
357 };
358
359 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
360                                  enum mlxsw_hwmon_attr_type attr_type,
361                                  unsigned int type_index, unsigned int num) {
362         struct mlxsw_hwmon_attr *mlxsw_hwmon_attr;
363         unsigned int attr_index;
364
365         attr_index = mlxsw_hwmon->attrs_count;
366         mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index];
367
368         switch (attr_type) {
369         case MLXSW_HWMON_ATTR_TYPE_TEMP:
370                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show;
371                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
372                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
373                          "temp%u_input", num + 1);
374                 break;
375         case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX:
376                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show;
377                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
378                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
379                          "temp%u_highest", num + 1);
380                 break;
381         case MLXSW_HWMON_ATTR_TYPE_TEMP_RST:
382                 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store;
383                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200;
384                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
385                          "temp%u_reset_history", num + 1);
386                 break;
387         case MLXSW_HWMON_ATTR_TYPE_FAN_RPM:
388                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show;
389                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
390                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
391                          "fan%u_input", num + 1);
392                 break;
393         case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT:
394                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show;
395                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
396                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
397                          "fan%u_fault", num + 1);
398                 break;
399         case MLXSW_HWMON_ATTR_TYPE_PWM:
400                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
401                 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
402                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644;
403                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
404                          "pwm%u", num + 1);
405                 break;
406         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE:
407                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show;
408                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
409                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
410                          "temp%u_input", num + 1);
411                 break;
412         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT:
413                 mlxsw_hwmon_attr->dev_attr.show =
414                                         mlxsw_hwmon_module_temp_fault_show;
415                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
416                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
417                          "temp%u_fault", num + 1);
418                 break;
419         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT:
420                 mlxsw_hwmon_attr->dev_attr.show =
421                         mlxsw_hwmon_module_temp_critical_show;
422                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
423                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
424                          "temp%u_crit", num + 1);
425                 break;
426         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG:
427                 mlxsw_hwmon_attr->dev_attr.show =
428                         mlxsw_hwmon_module_temp_emergency_show;
429                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
430                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
431                          "temp%u_emergency", num + 1);
432                 break;
433         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL:
434                 mlxsw_hwmon_attr->dev_attr.show =
435                         mlxsw_hwmon_module_temp_label_show;
436                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
437                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
438                          "temp%u_label", num + 1);
439                 break;
440         case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL:
441                 mlxsw_hwmon_attr->dev_attr.show =
442                         mlxsw_hwmon_gbox_temp_label_show;
443                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
444                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
445                          "temp%u_label", num + 1);
446                 break;
447         default:
448                 WARN_ON(1);
449         }
450
451         mlxsw_hwmon_attr->type_index = type_index;
452         mlxsw_hwmon_attr->hwmon = mlxsw_hwmon;
453         mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name;
454         sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr);
455
456         mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr;
457         mlxsw_hwmon->attrs_count++;
458 }
459
460 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
461 {
462         char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
463         char mtmp_pl[MLXSW_REG_MTMP_LEN];
464         int i;
465         int err;
466
467         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl);
468         if (err) {
469                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n");
470                 return err;
471         }
472         mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
473         for (i = 0; i < mlxsw_hwmon->sensor_count; i++) {
474                 mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true);
475                 err = mlxsw_reg_write(mlxsw_hwmon->core,
476                                       MLXSW_REG(mtmp), mtmp_pl);
477                 if (err) {
478                         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
479                                 i);
480                         return err;
481                 }
482                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
483                                      MLXSW_HWMON_ATTR_TYPE_TEMP, i, i);
484                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
485                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i);
486                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
487                                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i);
488         }
489         return 0;
490 }
491
492 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
493 {
494         char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
495         enum mlxsw_reg_mfcr_pwm_frequency freq;
496         unsigned int type_index;
497         unsigned int num;
498         u16 tacho_active;
499         u8 pwm_active;
500         int err;
501
502         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl);
503         if (err) {
504                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n");
505                 return err;
506         }
507         mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
508         num = 0;
509         for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
510                 if (tacho_active & BIT(type_index)) {
511                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
512                                              MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
513                                              type_index, num);
514                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
515                                              MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
516                                              type_index, num++);
517                 }
518         }
519         num = 0;
520         for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
521                 if (pwm_active & BIT(type_index))
522                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
523                                              MLXSW_HWMON_ATTR_TYPE_PWM,
524                                              type_index, num++);
525         }
526         return 0;
527 }
528
529 static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
530 {
531         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
532         u8 module_sensor_max;
533         int i, err;
534
535         if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core))
536                 return 0;
537
538         mlxsw_reg_mgpir_pack(mgpir_pl);
539         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
540         if (err)
541                 return err;
542
543         mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
544                                &module_sensor_max);
545
546         /* Add extra attributes for module temperature. Sensor index is
547          * assigned to sensor_count value, while all indexed before
548          * sensor_count are already utilized by the sensors connected through
549          * mtmp register by mlxsw_hwmon_temp_init().
550          */
551         mlxsw_hwmon->module_sensor_max = mlxsw_hwmon->sensor_count +
552                                          module_sensor_max;
553         for (i = mlxsw_hwmon->sensor_count;
554              i < mlxsw_hwmon->module_sensor_max; i++) {
555                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
556                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i);
557                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
558                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
559                                      i, i);
560                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
561                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i,
562                                      i);
563                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
564                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
565                                      i, i);
566                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
567                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
568                                      i, i);
569         }
570
571         return 0;
572 }
573
574 static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
575 {
576         int index, max_index, sensor_index;
577         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
578         char mtmp_pl[MLXSW_REG_MTMP_LEN];
579         u8 gbox_num;
580         int err;
581
582         mlxsw_reg_mgpir_pack(mgpir_pl);
583         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
584         if (err)
585                 return err;
586
587         mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL, NULL);
588         if (!gbox_num)
589                 return 0;
590
591         index = mlxsw_hwmon->module_sensor_max;
592         max_index = mlxsw_hwmon->module_sensor_max + gbox_num;
593         while (index < max_index) {
594                 sensor_index = index % mlxsw_hwmon->module_sensor_max +
595                                MLXSW_REG_MTMP_GBOX_INDEX_MIN;
596                 mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true);
597                 err = mlxsw_reg_write(mlxsw_hwmon->core,
598                                       MLXSW_REG(mtmp), mtmp_pl);
599                 if (err) {
600                         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
601                                 sensor_index);
602                         return err;
603                 }
604                 mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
605                                      index, index);
606                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
607                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
608                                      index);
609                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
610                                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
611                                      index);
612                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
613                                      MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
614                                      index, index);
615                 index++;
616         }
617
618         return 0;
619 }
620
621 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
622                      const struct mlxsw_bus_info *mlxsw_bus_info,
623                      struct mlxsw_hwmon **p_hwmon)
624 {
625         struct mlxsw_hwmon *mlxsw_hwmon;
626         struct device *hwmon_dev;
627         int err;
628
629         mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL);
630         if (!mlxsw_hwmon)
631                 return -ENOMEM;
632         mlxsw_hwmon->core = mlxsw_core;
633         mlxsw_hwmon->bus_info = mlxsw_bus_info;
634
635         err = mlxsw_hwmon_temp_init(mlxsw_hwmon);
636         if (err)
637                 goto err_temp_init;
638
639         err = mlxsw_hwmon_fans_init(mlxsw_hwmon);
640         if (err)
641                 goto err_fans_init;
642
643         err = mlxsw_hwmon_module_init(mlxsw_hwmon);
644         if (err)
645                 goto err_temp_module_init;
646
647         err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon);
648         if (err)
649                 goto err_temp_gearbox_init;
650
651         mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
652         mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
653
654         hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
655                                                       "mlxsw", mlxsw_hwmon,
656                                                       mlxsw_hwmon->groups);
657         if (IS_ERR(hwmon_dev)) {
658                 err = PTR_ERR(hwmon_dev);
659                 goto err_hwmon_register;
660         }
661
662         mlxsw_hwmon->hwmon_dev = hwmon_dev;
663         *p_hwmon = mlxsw_hwmon;
664         return 0;
665
666 err_hwmon_register:
667 err_temp_gearbox_init:
668 err_temp_module_init:
669 err_fans_init:
670 err_temp_init:
671         kfree(mlxsw_hwmon);
672         return err;
673 }
674
675 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
676 {
677         hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
678         kfree(mlxsw_hwmon);
679 }