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 }
680