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