1
2
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
28struct 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
35static 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
43struct 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
56static 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, NULL, NULL);
76 return sprintf(buf, "%d\n", temp);
77}
78
79static 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, NULL, NULL);
99 return sprintf(buf, "%d\n", temp_max);
100}
101
102static 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
137static 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
156static 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
177static 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
197static 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
223static 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, NULL, NULL);
243
244 return 0;
245}
246
247static 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
260static 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
284 switch (temp) {
285 case MLXSW_REG_MTBR_BAD_SENS_INFO:
286
287
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
302static 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
323static ssize_t
324mlxsw_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
336static 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
357static ssize_t
358mlxsw_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
371static ssize_t
372mlxsw_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
383static ssize_t
384mlxsw_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
397static 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
424static 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
444enum 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
461static 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
576static 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
615static 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
652static 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
670
671
672
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
703static 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
752int 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
797err_hwmon_register:
798err_temp_gearbox_init:
799err_temp_module_init:
800err_fans_init:
801err_temp_init:
802 kfree(mlxsw_hwmon);
803 return err;
804}
805
806void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
807{
808 hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
809 kfree(mlxsw_hwmon);
810}
811