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_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
19struct 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
26static 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
34struct 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_count;
45};
46
47static 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_count);
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
70static 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_count);
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
93static 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_count);
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
122static 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
141static 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
162static 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
182static 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
208static 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
231static 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
255 switch (temp) {
256 case MLXSW_REG_MTBR_BAD_SENS_INFO:
257
258
259
260 fault = 1;
261 break;
262 case MLXSW_REG_MTBR_NO_CONN:
263 case MLXSW_REG_MTBR_NO_TEMP_SENS:
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
273static ssize_t
274mlxsw_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
295static ssize_t
296mlxsw_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
318static ssize_t
319mlxsw_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
330static ssize_t
331mlxsw_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_count + 1;
340
341 return sprintf(buf, "gearbox %03u\n", index);
342}
343
344enum 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
359static 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
460static 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
492static 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
529static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
530{
531 unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core);
532 char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0};
533 int i, index;
534 u8 width;
535 int err;
536
537 if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core))
538 return 0;
539
540
541
542
543
544
545 index = mlxsw_hwmon->sensor_count;
546 for (i = 1; i < module_count; i++) {
547 mlxsw_reg_pmlp_pack(pmlp_pl, i);
548 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp),
549 pmlp_pl);
550 if (err) {
551 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n",
552 i);
553 return err;
554 }
555 width = mlxsw_reg_pmlp_width_get(pmlp_pl);
556 if (!width)
557 continue;
558 mlxsw_hwmon_attr_add(mlxsw_hwmon,
559 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index,
560 index);
561 mlxsw_hwmon_attr_add(mlxsw_hwmon,
562 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
563 index, index);
564 mlxsw_hwmon_attr_add(mlxsw_hwmon,
565 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
566 index, index);
567 mlxsw_hwmon_attr_add(mlxsw_hwmon,
568 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
569 index, index);
570 mlxsw_hwmon_attr_add(mlxsw_hwmon,
571 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
572 index, index);
573 index++;
574 }
575 mlxsw_hwmon->module_sensor_count = index;
576
577 return 0;
578}
579
580static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
581{
582 int index, max_index, sensor_index;
583 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
584 char mtmp_pl[MLXSW_REG_MTMP_LEN];
585 u8 gbox_num;
586 int err;
587
588 mlxsw_reg_mgpir_pack(mgpir_pl);
589 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
590 if (err)
591 return err;
592
593 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL);
594 if (!gbox_num)
595 return 0;
596
597 index = mlxsw_hwmon->module_sensor_count;
598 max_index = mlxsw_hwmon->module_sensor_count + gbox_num;
599 while (index < max_index) {
600 sensor_index = index % mlxsw_hwmon->module_sensor_count +
601 MLXSW_REG_MTMP_GBOX_INDEX_MIN;
602 mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true);
603 err = mlxsw_reg_write(mlxsw_hwmon->core,
604 MLXSW_REG(mtmp), mtmp_pl);
605 if (err) {
606 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
607 sensor_index);
608 return err;
609 }
610 mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
611 index, index);
612 mlxsw_hwmon_attr_add(mlxsw_hwmon,
613 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
614 index);
615 mlxsw_hwmon_attr_add(mlxsw_hwmon,
616 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
617 index);
618 mlxsw_hwmon_attr_add(mlxsw_hwmon,
619 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
620 index, index);
621 index++;
622 }
623
624 return 0;
625}
626
627int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
628 const struct mlxsw_bus_info *mlxsw_bus_info,
629 struct mlxsw_hwmon **p_hwmon)
630{
631 struct mlxsw_hwmon *mlxsw_hwmon;
632 struct device *hwmon_dev;
633 int err;
634
635 mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL);
636 if (!mlxsw_hwmon)
637 return -ENOMEM;
638 mlxsw_hwmon->core = mlxsw_core;
639 mlxsw_hwmon->bus_info = mlxsw_bus_info;
640
641 err = mlxsw_hwmon_temp_init(mlxsw_hwmon);
642 if (err)
643 goto err_temp_init;
644
645 err = mlxsw_hwmon_fans_init(mlxsw_hwmon);
646 if (err)
647 goto err_fans_init;
648
649 err = mlxsw_hwmon_module_init(mlxsw_hwmon);
650 if (err)
651 goto err_temp_module_init;
652
653 err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon);
654 if (err)
655 goto err_temp_gearbox_init;
656
657 mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
658 mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
659
660 hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
661 "mlxsw", mlxsw_hwmon,
662 mlxsw_hwmon->groups);
663 if (IS_ERR(hwmon_dev)) {
664 err = PTR_ERR(hwmon_dev);
665 goto err_hwmon_register;
666 }
667
668 mlxsw_hwmon->hwmon_dev = hwmon_dev;
669 *p_hwmon = mlxsw_hwmon;
670 return 0;
671
672err_hwmon_register:
673err_temp_gearbox_init:
674err_temp_module_init:
675err_fans_init:
676err_temp_init:
677 kfree(mlxsw_hwmon);
678 return err;
679}
680
681void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
682{
683 hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
684 kfree(mlxsw_hwmon);
685}
686