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 
mlxsw_hwmon_get_attr_index(int index,int count)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 
mlxsw_hwmon_temp_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_temp_max_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_temp_rst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)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 
mlxsw_hwmon_fan_rpm_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_fan_fault_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_pwm_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_pwm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)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 
mlxsw_hwmon_module_temp_get(struct device * dev,struct device_attribute * attr,int * p_temp)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 
mlxsw_hwmon_module_temp_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_module_temp_fault_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_module_temp_critical_get(struct device * dev,struct device_attribute * attr,int * p_temp)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
mlxsw_hwmon_module_temp_critical_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_module_temp_emergency_get(struct device * dev,struct device_attribute * attr,int * p_temp)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
mlxsw_hwmon_module_temp_emergency_show(struct device * dev,struct device_attribute * attr,char * buf)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
mlxsw_hwmon_module_temp_label_show(struct device * dev,struct device_attribute * attr,char * buf)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
mlxsw_hwmon_gbox_temp_label_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_temp_critical_alarm_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_temp_emergency_alarm_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mlxsw_hwmon_attr_add(struct mlxsw_hwmon * mlxsw_hwmon,enum mlxsw_hwmon_attr_type attr_type,unsigned int type_index,unsigned int num)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 
mlxsw_hwmon_temp_init(struct mlxsw_hwmon * mlxsw_hwmon)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 
mlxsw_hwmon_fans_init(struct mlxsw_hwmon * mlxsw_hwmon)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 
mlxsw_hwmon_module_init(struct mlxsw_hwmon * mlxsw_hwmon)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 
mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon * mlxsw_hwmon)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 
mlxsw_hwmon_init(struct mlxsw_core * mlxsw_core,const struct mlxsw_bus_info * mlxsw_bus_info,struct mlxsw_hwmon ** p_hwmon)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 
mlxsw_hwmon_fini(struct mlxsw_hwmon * mlxsw_hwmon)806 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
807 {
808 	hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
809 	kfree(mlxsw_hwmon);
810 }
811