1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved
3  * Copyright (c) 2016 Ivan Vecera <cera@cera.cz>
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/device.h>
9 #include <linux/sysfs.h>
10 #include <linux/thermal.h>
11 #include <linux/err.h>
12 #include <linux/sfp.h>
13 
14 #include "core.h"
15 #include "core_env.h"
16 
17 #define MLXSW_THERMAL_POLL_INT	1000	/* ms */
18 #define MLXSW_THERMAL_SLOW_POLL_INT	20000	/* ms */
19 #define MLXSW_THERMAL_ASIC_TEMP_NORM	75000	/* 75C */
20 #define MLXSW_THERMAL_ASIC_TEMP_HIGH	85000	/* 85C */
21 #define MLXSW_THERMAL_ASIC_TEMP_HOT	105000	/* 105C */
22 #define MLXSW_THERMAL_HYSTERESIS_TEMP	5000	/* 5C */
23 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT	(MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
24 #define MLXSW_THERMAL_TEMP_SCORE_MAX	GENMASK(31, 0)
25 #define MLXSW_THERMAL_MAX_STATE	10
26 #define MLXSW_THERMAL_MIN_STATE	2
27 #define MLXSW_THERMAL_MAX_DUTY	255
28 
29 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
30 static char * const mlxsw_thermal_external_allowed_cdev[] = {
31 	"mlxreg_fan",
32 };
33 
34 enum mlxsw_thermal_trips {
35 	MLXSW_THERMAL_TEMP_TRIP_NORM,
36 	MLXSW_THERMAL_TEMP_TRIP_HIGH,
37 	MLXSW_THERMAL_TEMP_TRIP_HOT,
38 };
39 
40 struct mlxsw_thermal_trip {
41 	int	type;
42 	int	temp;
43 	int	hyst;
44 	int	min_state;
45 	int	max_state;
46 };
47 
48 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
49 	{	/* In range - 0-40% PWM */
50 		.type		= THERMAL_TRIP_ACTIVE,
51 		.temp		= MLXSW_THERMAL_ASIC_TEMP_NORM,
52 		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
53 		.min_state	= 0,
54 		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
55 	},
56 	{
57 		/* In range - 40-100% PWM */
58 		.type		= THERMAL_TRIP_ACTIVE,
59 		.temp		= MLXSW_THERMAL_ASIC_TEMP_HIGH,
60 		.hyst		= MLXSW_THERMAL_HYSTERESIS_TEMP,
61 		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
62 		.max_state	= MLXSW_THERMAL_MAX_STATE,
63 	},
64 	{	/* Warning */
65 		.type		= THERMAL_TRIP_HOT,
66 		.temp		= MLXSW_THERMAL_ASIC_TEMP_HOT,
67 		.min_state	= MLXSW_THERMAL_MAX_STATE,
68 		.max_state	= MLXSW_THERMAL_MAX_STATE,
69 	},
70 };
71 
72 #define MLXSW_THERMAL_NUM_TRIPS	ARRAY_SIZE(default_thermal_trips)
73 
74 /* Make sure all trips are writable */
75 #define MLXSW_THERMAL_TRIP_MASK	(BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
76 
77 struct mlxsw_thermal;
78 
79 struct mlxsw_thermal_module {
80 	struct mlxsw_thermal *parent;
81 	struct thermal_zone_device *tzdev;
82 	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
83 	int module; /* Module or gearbox number */
84 	u8 slot_index;
85 };
86 
87 struct mlxsw_thermal_area {
88 	struct mlxsw_thermal_module *tz_module_arr;
89 	u8 tz_module_num;
90 	struct mlxsw_thermal_module *tz_gearbox_arr;
91 	u8 tz_gearbox_num;
92 	u8 slot_index;
93 	bool active;
94 };
95 
96 struct mlxsw_thermal {
97 	struct mlxsw_core *core;
98 	const struct mlxsw_bus_info *bus_info;
99 	struct thermal_zone_device *tzdev;
100 	int polling_delay;
101 	struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
102 	u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
103 	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
104 	unsigned int tz_highest_score;
105 	struct thermal_zone_device *tz_highest_dev;
106 	struct mlxsw_thermal_area line_cards[];
107 };
108 
109 static inline u8 mlxsw_state_to_duty(int state)
110 {
111 	return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
112 				 MLXSW_THERMAL_MAX_STATE);
113 }
114 
115 static inline int mlxsw_duty_to_state(u8 duty)
116 {
117 	return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
118 				 MLXSW_THERMAL_MAX_DUTY);
119 }
120 
121 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
122 					struct thermal_cooling_device *cdev)
123 {
124 	int i;
125 
126 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
127 		if (thermal->cdevs[i] == cdev)
128 			return i;
129 
130 	/* Allow mlxsw thermal zone binding to an external cooling device */
131 	for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
132 		if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
133 			return 0;
134 	}
135 
136 	return -ENODEV;
137 }
138 
139 static void
140 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
141 {
142 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
143 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
144 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
145 }
146 
147 static int
148 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
149 				  struct mlxsw_thermal_module *tz,
150 				  int crit_temp, int emerg_temp)
151 {
152 	int err;
153 
154 	/* Do not try to query temperature thresholds directly from the module's
155 	 * EEPROM if we got valid thresholds from MTMP.
156 	 */
157 	if (!emerg_temp || !crit_temp) {
158 		err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
159 							   tz->module,
160 							   SFP_TEMP_HIGH_WARN,
161 							   &crit_temp);
162 		if (err)
163 			return err;
164 
165 		err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
166 							   tz->module,
167 							   SFP_TEMP_HIGH_ALARM,
168 							   &emerg_temp);
169 		if (err)
170 			return err;
171 	}
172 
173 	if (crit_temp > emerg_temp) {
174 		dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
175 			 tz->tzdev->type, crit_temp, emerg_temp);
176 		return 0;
177 	}
178 
179 	/* According to the system thermal requirements, the thermal zones are
180 	 * defined with three trip points. The critical and emergency
181 	 * temperature thresholds, provided by QSFP module are set as "active"
182 	 * and "hot" trip points, "normal" trip point is derived from "active"
183 	 * by subtracting double hysteresis value.
184 	 */
185 	if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
186 		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
187 					MLXSW_THERMAL_MODULE_TEMP_SHIFT;
188 	else
189 		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
190 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
191 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
192 
193 	return 0;
194 }
195 
196 static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
197 					  struct thermal_zone_device *tzdev,
198 					  struct mlxsw_thermal_trip *trips,
199 					  int temp)
200 {
201 	struct mlxsw_thermal_trip *trip = trips;
202 	unsigned int score, delta, i, shift = 1;
203 
204 	/* Calculate thermal zone score, if temperature is above the hot
205 	 * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
206 	 */
207 	score = MLXSW_THERMAL_TEMP_SCORE_MAX;
208 	for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
209 	     i++, trip++) {
210 		if (temp < trip->temp) {
211 			delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
212 			score = delta * shift;
213 			break;
214 		}
215 		shift *= 256;
216 	}
217 
218 	if (score > thermal->tz_highest_score) {
219 		thermal->tz_highest_score = score;
220 		thermal->tz_highest_dev = tzdev;
221 	}
222 }
223 
224 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
225 			      struct thermal_cooling_device *cdev)
226 {
227 	struct mlxsw_thermal *thermal = tzdev->devdata;
228 	struct device *dev = thermal->bus_info->dev;
229 	int i, err;
230 
231 	/* If the cooling device is one of ours bind it */
232 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
233 		return 0;
234 
235 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
236 		const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
237 
238 		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
239 						       trip->max_state,
240 						       trip->min_state,
241 						       THERMAL_WEIGHT_DEFAULT);
242 		if (err < 0) {
243 			dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
244 			return err;
245 		}
246 	}
247 	return 0;
248 }
249 
250 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
251 				struct thermal_cooling_device *cdev)
252 {
253 	struct mlxsw_thermal *thermal = tzdev->devdata;
254 	struct device *dev = thermal->bus_info->dev;
255 	int i;
256 	int err;
257 
258 	/* If the cooling device is our one unbind it */
259 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
260 		return 0;
261 
262 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
263 		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
264 		if (err < 0) {
265 			dev_err(dev, "Failed to unbind cooling device\n");
266 			return err;
267 		}
268 	}
269 	return 0;
270 }
271 
272 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
273 				  int *p_temp)
274 {
275 	struct mlxsw_thermal *thermal = tzdev->devdata;
276 	struct device *dev = thermal->bus_info->dev;
277 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
278 	int temp;
279 	int err;
280 
281 	mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
282 
283 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
284 	if (err) {
285 		dev_err(dev, "Failed to query temp sensor\n");
286 		return err;
287 	}
288 	mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
289 	if (temp > 0)
290 		mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
291 					      temp);
292 
293 	*p_temp = temp;
294 	return 0;
295 }
296 
297 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
298 				       int trip,
299 				       enum thermal_trip_type *p_type)
300 {
301 	struct mlxsw_thermal *thermal = tzdev->devdata;
302 
303 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
304 		return -EINVAL;
305 
306 	*p_type = thermal->trips[trip].type;
307 	return 0;
308 }
309 
310 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
311 				       int trip, int *p_temp)
312 {
313 	struct mlxsw_thermal *thermal = tzdev->devdata;
314 
315 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
316 		return -EINVAL;
317 
318 	*p_temp = thermal->trips[trip].temp;
319 	return 0;
320 }
321 
322 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
323 				       int trip, int temp)
324 {
325 	struct mlxsw_thermal *thermal = tzdev->devdata;
326 
327 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
328 		return -EINVAL;
329 
330 	thermal->trips[trip].temp = temp;
331 	return 0;
332 }
333 
334 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
335 				       int trip, int *p_hyst)
336 {
337 	struct mlxsw_thermal *thermal = tzdev->devdata;
338 
339 	*p_hyst = thermal->trips[trip].hyst;
340 	return 0;
341 }
342 
343 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
344 				       int trip, int hyst)
345 {
346 	struct mlxsw_thermal *thermal = tzdev->devdata;
347 
348 	thermal->trips[trip].hyst = hyst;
349 	return 0;
350 }
351 
352 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
353 				   int trip, enum thermal_trend *trend)
354 {
355 	struct mlxsw_thermal *thermal = tzdev->devdata;
356 
357 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
358 		return -EINVAL;
359 
360 	if (tzdev == thermal->tz_highest_dev)
361 		return 1;
362 
363 	*trend = THERMAL_TREND_STABLE;
364 	return 0;
365 }
366 
367 static struct thermal_zone_params mlxsw_thermal_params = {
368 	.no_hwmon = true,
369 };
370 
371 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
372 	.bind = mlxsw_thermal_bind,
373 	.unbind = mlxsw_thermal_unbind,
374 	.get_temp = mlxsw_thermal_get_temp,
375 	.get_trip_type	= mlxsw_thermal_get_trip_type,
376 	.get_trip_temp	= mlxsw_thermal_get_trip_temp,
377 	.set_trip_temp	= mlxsw_thermal_set_trip_temp,
378 	.get_trip_hyst	= mlxsw_thermal_get_trip_hyst,
379 	.set_trip_hyst	= mlxsw_thermal_set_trip_hyst,
380 	.get_trend	= mlxsw_thermal_trend_get,
381 };
382 
383 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
384 				     struct thermal_cooling_device *cdev)
385 {
386 	struct mlxsw_thermal_module *tz = tzdev->devdata;
387 	struct mlxsw_thermal *thermal = tz->parent;
388 	int i, j, err;
389 
390 	/* If the cooling device is one of ours bind it */
391 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
392 		return 0;
393 
394 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
395 		const struct mlxsw_thermal_trip *trip = &tz->trips[i];
396 
397 		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
398 						       trip->max_state,
399 						       trip->min_state,
400 						       THERMAL_WEIGHT_DEFAULT);
401 		if (err < 0)
402 			goto err_thermal_zone_bind_cooling_device;
403 	}
404 	return 0;
405 
406 err_thermal_zone_bind_cooling_device:
407 	for (j = i - 1; j >= 0; j--)
408 		thermal_zone_unbind_cooling_device(tzdev, j, cdev);
409 	return err;
410 }
411 
412 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
413 				       struct thermal_cooling_device *cdev)
414 {
415 	struct mlxsw_thermal_module *tz = tzdev->devdata;
416 	struct mlxsw_thermal *thermal = tz->parent;
417 	int i;
418 	int err;
419 
420 	/* If the cooling device is one of ours unbind it */
421 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
422 		return 0;
423 
424 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
425 		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
426 		WARN_ON(err);
427 	}
428 	return err;
429 }
430 
431 static void
432 mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
433 					     u8 slot_index, u16 sensor_index,
434 					     int *p_temp, int *p_crit_temp,
435 					     int *p_emerg_temp)
436 {
437 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
438 	int err;
439 
440 	/* Read module temperature and thresholds. */
441 	mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, sensor_index,
442 			    false, false);
443 	err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
444 	if (err) {
445 		/* Set temperature and thresholds to zero to avoid passing
446 		 * uninitialized data back to the caller.
447 		 */
448 		*p_temp = 0;
449 		*p_crit_temp = 0;
450 		*p_emerg_temp = 0;
451 
452 		return;
453 	}
454 	mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, p_crit_temp, p_emerg_temp,
455 			      NULL);
456 }
457 
458 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
459 					 int *p_temp)
460 {
461 	struct mlxsw_thermal_module *tz = tzdev->devdata;
462 	struct mlxsw_thermal *thermal = tz->parent;
463 	int temp, crit_temp, emerg_temp;
464 	struct device *dev;
465 	u16 sensor_index;
466 	int err;
467 
468 	dev = thermal->bus_info->dev;
469 	sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
470 
471 	/* Read module temperature and thresholds. */
472 	mlxsw_thermal_module_temp_and_thresholds_get(thermal->core,
473 						     tz->slot_index,
474 						     sensor_index, &temp,
475 						     &crit_temp, &emerg_temp);
476 	*p_temp = temp;
477 
478 	if (!temp)
479 		return 0;
480 
481 	/* Update trip points. */
482 	err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz,
483 						crit_temp, emerg_temp);
484 	if (!err && temp > 0)
485 		mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
486 
487 	return 0;
488 }
489 
490 static int
491 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
492 				   enum thermal_trip_type *p_type)
493 {
494 	struct mlxsw_thermal_module *tz = tzdev->devdata;
495 
496 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
497 		return -EINVAL;
498 
499 	*p_type = tz->trips[trip].type;
500 	return 0;
501 }
502 
503 static int
504 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
505 				   int trip, int *p_temp)
506 {
507 	struct mlxsw_thermal_module *tz = tzdev->devdata;
508 
509 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
510 		return -EINVAL;
511 
512 	*p_temp = tz->trips[trip].temp;
513 	return 0;
514 }
515 
516 static int
517 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
518 				   int trip, int temp)
519 {
520 	struct mlxsw_thermal_module *tz = tzdev->devdata;
521 
522 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
523 		return -EINVAL;
524 
525 	tz->trips[trip].temp = temp;
526 	return 0;
527 }
528 
529 static int
530 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
531 				   int *p_hyst)
532 {
533 	struct mlxsw_thermal_module *tz = tzdev->devdata;
534 
535 	*p_hyst = tz->trips[trip].hyst;
536 	return 0;
537 }
538 
539 static int
540 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
541 				   int hyst)
542 {
543 	struct mlxsw_thermal_module *tz = tzdev->devdata;
544 
545 	tz->trips[trip].hyst = hyst;
546 	return 0;
547 }
548 
549 static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
550 					  int trip, enum thermal_trend *trend)
551 {
552 	struct mlxsw_thermal_module *tz = tzdev->devdata;
553 	struct mlxsw_thermal *thermal = tz->parent;
554 
555 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
556 		return -EINVAL;
557 
558 	if (tzdev == thermal->tz_highest_dev)
559 		return 1;
560 
561 	*trend = THERMAL_TREND_STABLE;
562 	return 0;
563 }
564 
565 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
566 	.bind		= mlxsw_thermal_module_bind,
567 	.unbind		= mlxsw_thermal_module_unbind,
568 	.get_temp	= mlxsw_thermal_module_temp_get,
569 	.get_trip_type	= mlxsw_thermal_module_trip_type_get,
570 	.get_trip_temp	= mlxsw_thermal_module_trip_temp_get,
571 	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
572 	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
573 	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
574 	.get_trend	= mlxsw_thermal_module_trend_get,
575 };
576 
577 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
578 					  int *p_temp)
579 {
580 	struct mlxsw_thermal_module *tz = tzdev->devdata;
581 	struct mlxsw_thermal *thermal = tz->parent;
582 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
583 	u16 index;
584 	int temp;
585 	int err;
586 
587 	index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
588 	mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
589 
590 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
591 	if (err)
592 		return err;
593 
594 	mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
595 	if (temp > 0)
596 		mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
597 
598 	*p_temp = temp;
599 	return 0;
600 }
601 
602 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
603 	.bind		= mlxsw_thermal_module_bind,
604 	.unbind		= mlxsw_thermal_module_unbind,
605 	.get_temp	= mlxsw_thermal_gearbox_temp_get,
606 	.get_trip_type	= mlxsw_thermal_module_trip_type_get,
607 	.get_trip_temp	= mlxsw_thermal_module_trip_temp_get,
608 	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
609 	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
610 	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
611 	.get_trend	= mlxsw_thermal_module_trend_get,
612 };
613 
614 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
615 				       unsigned long *p_state)
616 {
617 	*p_state = MLXSW_THERMAL_MAX_STATE;
618 	return 0;
619 }
620 
621 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
622 				       unsigned long *p_state)
623 
624 {
625 	struct mlxsw_thermal *thermal = cdev->devdata;
626 	struct device *dev = thermal->bus_info->dev;
627 	char mfsc_pl[MLXSW_REG_MFSC_LEN];
628 	int err, idx;
629 	u8 duty;
630 
631 	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
632 	if (idx < 0)
633 		return idx;
634 
635 	mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
636 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
637 	if (err) {
638 		dev_err(dev, "Failed to query PWM duty\n");
639 		return err;
640 	}
641 
642 	duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
643 	*p_state = mlxsw_duty_to_state(duty);
644 	return 0;
645 }
646 
647 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
648 				       unsigned long state)
649 
650 {
651 	struct mlxsw_thermal *thermal = cdev->devdata;
652 	struct device *dev = thermal->bus_info->dev;
653 	char mfsc_pl[MLXSW_REG_MFSC_LEN];
654 	int idx;
655 	int err;
656 
657 	if (state > MLXSW_THERMAL_MAX_STATE)
658 		return -EINVAL;
659 
660 	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
661 	if (idx < 0)
662 		return idx;
663 
664 	/* Normalize the state to the valid speed range. */
665 	state = thermal->cooling_levels[state];
666 	mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
667 	err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
668 	if (err) {
669 		dev_err(dev, "Failed to write PWM duty\n");
670 		return err;
671 	}
672 	return 0;
673 }
674 
675 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
676 	.get_max_state	= mlxsw_thermal_get_max_state,
677 	.get_cur_state	= mlxsw_thermal_get_cur_state,
678 	.set_cur_state	= mlxsw_thermal_set_cur_state,
679 };
680 
681 static int
682 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
683 {
684 	char tz_name[THERMAL_NAME_LENGTH];
685 	int err;
686 
687 	if (module_tz->slot_index)
688 		snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
689 			 module_tz->slot_index, module_tz->module + 1);
690 	else
691 		snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
692 			 module_tz->module + 1);
693 	module_tz->tzdev = thermal_zone_device_register(tz_name,
694 							MLXSW_THERMAL_NUM_TRIPS,
695 							MLXSW_THERMAL_TRIP_MASK,
696 							module_tz,
697 							&mlxsw_thermal_module_ops,
698 							&mlxsw_thermal_params,
699 							0,
700 							module_tz->parent->polling_delay);
701 	if (IS_ERR(module_tz->tzdev)) {
702 		err = PTR_ERR(module_tz->tzdev);
703 		return err;
704 	}
705 
706 	err = thermal_zone_device_enable(module_tz->tzdev);
707 	if (err)
708 		thermal_zone_device_unregister(module_tz->tzdev);
709 
710 	return err;
711 }
712 
713 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
714 {
715 	thermal_zone_device_unregister(tzdev);
716 }
717 
718 static int
719 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
720 			  struct mlxsw_thermal *thermal,
721 			  struct mlxsw_thermal_area *area, u8 module)
722 {
723 	struct mlxsw_thermal_module *module_tz;
724 	int dummy_temp, crit_temp, emerg_temp;
725 	u16 sensor_index;
726 
727 	sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module;
728 	module_tz = &area->tz_module_arr[module];
729 	/* Skip if parent is already set (case of port split). */
730 	if (module_tz->parent)
731 		return 0;
732 	module_tz->module = module;
733 	module_tz->slot_index = area->slot_index;
734 	module_tz->parent = thermal;
735 	memcpy(module_tz->trips, default_thermal_trips,
736 	       sizeof(thermal->trips));
737 	/* Initialize all trip point. */
738 	mlxsw_thermal_module_trips_reset(module_tz);
739 	/* Read module temperature and thresholds. */
740 	mlxsw_thermal_module_temp_and_thresholds_get(core, area->slot_index,
741 						     sensor_index, &dummy_temp,
742 						     &crit_temp, &emerg_temp);
743 	/* Update trip point according to the module data. */
744 	return mlxsw_thermal_module_trips_update(dev, core, module_tz,
745 						 crit_temp, emerg_temp);
746 }
747 
748 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
749 {
750 	if (module_tz && module_tz->tzdev) {
751 		mlxsw_thermal_module_tz_fini(module_tz->tzdev);
752 		module_tz->tzdev = NULL;
753 		module_tz->parent = NULL;
754 	}
755 }
756 
757 static int
758 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
759 			   struct mlxsw_thermal *thermal,
760 			   struct mlxsw_thermal_area *area)
761 {
762 	struct mlxsw_thermal_module *module_tz;
763 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
764 	int i, err;
765 
766 	mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
767 	err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
768 	if (err)
769 		return err;
770 
771 	mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
772 			       &area->tz_module_num, NULL);
773 
774 	/* For modular system module counter could be zero. */
775 	if (!area->tz_module_num)
776 		return 0;
777 
778 	area->tz_module_arr = kcalloc(area->tz_module_num,
779 				      sizeof(*area->tz_module_arr),
780 				      GFP_KERNEL);
781 	if (!area->tz_module_arr)
782 		return -ENOMEM;
783 
784 	for (i = 0; i < area->tz_module_num; i++) {
785 		err = mlxsw_thermal_module_init(dev, core, thermal, area, i);
786 		if (err)
787 			goto err_thermal_module_init;
788 	}
789 
790 	for (i = 0; i < area->tz_module_num; i++) {
791 		module_tz = &area->tz_module_arr[i];
792 		if (!module_tz->parent)
793 			continue;
794 		err = mlxsw_thermal_module_tz_init(module_tz);
795 		if (err)
796 			goto err_thermal_module_tz_init;
797 	}
798 
799 	return 0;
800 
801 err_thermal_module_tz_init:
802 err_thermal_module_init:
803 	for (i = area->tz_module_num - 1; i >= 0; i--)
804 		mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
805 	kfree(area->tz_module_arr);
806 	return err;
807 }
808 
809 static void
810 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
811 			   struct mlxsw_thermal_area *area)
812 {
813 	int i;
814 
815 	for (i = area->tz_module_num - 1; i >= 0; i--)
816 		mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
817 	kfree(area->tz_module_arr);
818 }
819 
820 static int
821 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
822 {
823 	char tz_name[THERMAL_NAME_LENGTH];
824 	int ret;
825 
826 	if (gearbox_tz->slot_index)
827 		snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
828 			 gearbox_tz->slot_index, gearbox_tz->module + 1);
829 	else
830 		snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
831 			 gearbox_tz->module + 1);
832 	gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
833 						MLXSW_THERMAL_NUM_TRIPS,
834 						MLXSW_THERMAL_TRIP_MASK,
835 						gearbox_tz,
836 						&mlxsw_thermal_gearbox_ops,
837 						&mlxsw_thermal_params, 0,
838 						gearbox_tz->parent->polling_delay);
839 	if (IS_ERR(gearbox_tz->tzdev))
840 		return PTR_ERR(gearbox_tz->tzdev);
841 
842 	ret = thermal_zone_device_enable(gearbox_tz->tzdev);
843 	if (ret)
844 		thermal_zone_device_unregister(gearbox_tz->tzdev);
845 
846 	return ret;
847 }
848 
849 static void
850 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
851 {
852 	thermal_zone_device_unregister(gearbox_tz->tzdev);
853 }
854 
855 static int
856 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
857 			     struct mlxsw_thermal *thermal,
858 			     struct mlxsw_thermal_area *area)
859 {
860 	enum mlxsw_reg_mgpir_device_type device_type;
861 	struct mlxsw_thermal_module *gearbox_tz;
862 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
863 	u8 gbox_num;
864 	int i;
865 	int err;
866 
867 	mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
868 	err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
869 	if (err)
870 		return err;
871 
872 	mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
873 			       NULL, NULL);
874 	if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
875 	    !gbox_num)
876 		return 0;
877 
878 	area->tz_gearbox_num = gbox_num;
879 	area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
880 				       sizeof(*area->tz_gearbox_arr),
881 				       GFP_KERNEL);
882 	if (!area->tz_gearbox_arr)
883 		return -ENOMEM;
884 
885 	for (i = 0; i < area->tz_gearbox_num; i++) {
886 		gearbox_tz = &area->tz_gearbox_arr[i];
887 		memcpy(gearbox_tz->trips, default_thermal_trips,
888 		       sizeof(thermal->trips));
889 		gearbox_tz->module = i;
890 		gearbox_tz->parent = thermal;
891 		gearbox_tz->slot_index = area->slot_index;
892 		err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
893 		if (err)
894 			goto err_thermal_gearbox_tz_init;
895 	}
896 
897 	return 0;
898 
899 err_thermal_gearbox_tz_init:
900 	for (i--; i >= 0; i--)
901 		mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
902 	kfree(area->tz_gearbox_arr);
903 	return err;
904 }
905 
906 static void
907 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
908 			     struct mlxsw_thermal_area *area)
909 {
910 	int i;
911 
912 	for (i = area->tz_gearbox_num - 1; i >= 0; i--)
913 		mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
914 	kfree(area->tz_gearbox_arr);
915 }
916 
917 static void
918 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
919 			 void *priv)
920 {
921 	struct mlxsw_thermal *thermal = priv;
922 	struct mlxsw_thermal_area *linecard;
923 	int err;
924 
925 	linecard = &thermal->line_cards[slot_index];
926 
927 	if (linecard->active)
928 		return;
929 
930 	linecard->slot_index = slot_index;
931 	err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
932 					 thermal, linecard);
933 	if (err) {
934 		dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
935 			slot_index);
936 		return;
937 	}
938 
939 	err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
940 					   thermal->core, thermal, linecard);
941 	if (err) {
942 		dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
943 			slot_index);
944 		goto err_thermal_linecard_gearboxes_init;
945 	}
946 
947 	linecard->active = true;
948 
949 	return;
950 
951 err_thermal_linecard_gearboxes_init:
952 	mlxsw_thermal_modules_fini(thermal, linecard);
953 }
954 
955 static void
956 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
957 			   void *priv)
958 {
959 	struct mlxsw_thermal *thermal = priv;
960 	struct mlxsw_thermal_area *linecard;
961 
962 	linecard = &thermal->line_cards[slot_index];
963 	if (!linecard->active)
964 		return;
965 	linecard->active = false;
966 	mlxsw_thermal_gearboxes_fini(thermal, linecard);
967 	mlxsw_thermal_modules_fini(thermal, linecard);
968 }
969 
970 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
971 	.got_active = mlxsw_thermal_got_active,
972 	.got_inactive = mlxsw_thermal_got_inactive,
973 };
974 
975 int mlxsw_thermal_init(struct mlxsw_core *core,
976 		       const struct mlxsw_bus_info *bus_info,
977 		       struct mlxsw_thermal **p_thermal)
978 {
979 	char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
980 	enum mlxsw_reg_mfcr_pwm_frequency freq;
981 	struct device *dev = bus_info->dev;
982 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
983 	struct mlxsw_thermal *thermal;
984 	u8 pwm_active, num_of_slots;
985 	u16 tacho_active;
986 	int err, i;
987 
988 	mlxsw_reg_mgpir_pack(mgpir_pl, 0);
989 	err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
990 	if (err)
991 		return err;
992 
993 	mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
994 			       &num_of_slots);
995 
996 	thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
997 			  GFP_KERNEL);
998 	if (!thermal)
999 		return -ENOMEM;
1000 
1001 	thermal->core = core;
1002 	thermal->bus_info = bus_info;
1003 	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
1004 	thermal->line_cards[0].slot_index = 0;
1005 
1006 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
1007 	if (err) {
1008 		dev_err(dev, "Failed to probe PWMs\n");
1009 		goto err_reg_query;
1010 	}
1011 	mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
1012 
1013 	for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
1014 		if (tacho_active & BIT(i)) {
1015 			char mfsl_pl[MLXSW_REG_MFSL_LEN];
1016 
1017 			mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
1018 
1019 			/* We need to query the register to preserve maximum */
1020 			err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
1021 					      mfsl_pl);
1022 			if (err)
1023 				goto err_reg_query;
1024 
1025 			/* set the minimal RPMs to 0 */
1026 			mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
1027 			err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
1028 					      mfsl_pl);
1029 			if (err)
1030 				goto err_reg_write;
1031 		}
1032 	}
1033 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1034 		if (pwm_active & BIT(i)) {
1035 			struct thermal_cooling_device *cdev;
1036 
1037 			cdev = thermal_cooling_device_register("mlxsw_fan",
1038 							       thermal,
1039 							       &mlxsw_cooling_ops);
1040 			if (IS_ERR(cdev)) {
1041 				err = PTR_ERR(cdev);
1042 				dev_err(dev, "Failed to register cooling device\n");
1043 				goto err_thermal_cooling_device_register;
1044 			}
1045 			thermal->cdevs[i] = cdev;
1046 		}
1047 	}
1048 
1049 	/* Initialize cooling levels per PWM state. */
1050 	for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
1051 		thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
1052 
1053 	thermal->polling_delay = bus_info->low_frequency ?
1054 				 MLXSW_THERMAL_SLOW_POLL_INT :
1055 				 MLXSW_THERMAL_POLL_INT;
1056 
1057 	thermal->tzdev = thermal_zone_device_register("mlxsw",
1058 						      MLXSW_THERMAL_NUM_TRIPS,
1059 						      MLXSW_THERMAL_TRIP_MASK,
1060 						      thermal,
1061 						      &mlxsw_thermal_ops,
1062 						      &mlxsw_thermal_params, 0,
1063 						      thermal->polling_delay);
1064 	if (IS_ERR(thermal->tzdev)) {
1065 		err = PTR_ERR(thermal->tzdev);
1066 		dev_err(dev, "Failed to register thermal zone\n");
1067 		goto err_thermal_zone_device_register;
1068 	}
1069 
1070 	err = mlxsw_thermal_modules_init(dev, core, thermal,
1071 					 &thermal->line_cards[0]);
1072 	if (err)
1073 		goto err_thermal_modules_init;
1074 
1075 	err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
1076 					   &thermal->line_cards[0]);
1077 	if (err)
1078 		goto err_thermal_gearboxes_init;
1079 
1080 	err = mlxsw_linecards_event_ops_register(core,
1081 						 &mlxsw_thermal_event_ops,
1082 						 thermal);
1083 	if (err)
1084 		goto err_linecards_event_ops_register;
1085 
1086 	err = thermal_zone_device_enable(thermal->tzdev);
1087 	if (err)
1088 		goto err_thermal_zone_device_enable;
1089 
1090 	thermal->line_cards[0].active = true;
1091 	*p_thermal = thermal;
1092 	return 0;
1093 
1094 err_thermal_zone_device_enable:
1095 	mlxsw_linecards_event_ops_unregister(thermal->core,
1096 					     &mlxsw_thermal_event_ops,
1097 					     thermal);
1098 err_linecards_event_ops_register:
1099 	mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1100 err_thermal_gearboxes_init:
1101 	mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1102 err_thermal_modules_init:
1103 	if (thermal->tzdev) {
1104 		thermal_zone_device_unregister(thermal->tzdev);
1105 		thermal->tzdev = NULL;
1106 	}
1107 err_thermal_zone_device_register:
1108 err_thermal_cooling_device_register:
1109 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1110 		if (thermal->cdevs[i])
1111 			thermal_cooling_device_unregister(thermal->cdevs[i]);
1112 err_reg_write:
1113 err_reg_query:
1114 	kfree(thermal);
1115 	return err;
1116 }
1117 
1118 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1119 {
1120 	int i;
1121 
1122 	thermal->line_cards[0].active = false;
1123 	mlxsw_linecards_event_ops_unregister(thermal->core,
1124 					     &mlxsw_thermal_event_ops,
1125 					     thermal);
1126 	mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1127 	mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1128 	if (thermal->tzdev) {
1129 		thermal_zone_device_unregister(thermal->tzdev);
1130 		thermal->tzdev = NULL;
1131 	}
1132 
1133 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1134 		if (thermal->cdevs[i]) {
1135 			thermal_cooling_device_unregister(thermal->cdevs[i]);
1136 			thermal->cdevs[i] = NULL;
1137 		}
1138 	}
1139 
1140 	kfree(thermal);
1141 }
1142