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>
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>
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_MODULE_TEMP_NORM 55000 /* 55C */
23 #define MLXSW_THERMAL_MODULE_TEMP_HIGH 65000 /* 65C */
24 #define MLXSW_THERMAL_MODULE_TEMP_HOT 80000 /* 80C */
25 #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
26 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
27 #define MLXSW_THERMAL_MAX_STATE 10
28 #define MLXSW_THERMAL_MIN_STATE 2
29 #define MLXSW_THERMAL_MAX_DUTY 255
31 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
32 static char * const mlxsw_thermal_external_allowed_cdev[] = {
36 struct mlxsw_cooling_states {
41 static const struct thermal_trip default_thermal_trips[] = {
42 { /* In range - 0-40% PWM */
43 .type = THERMAL_TRIP_ACTIVE,
44 .temperature = MLXSW_THERMAL_ASIC_TEMP_NORM,
45 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
48 /* In range - 40-100% PWM */
49 .type = THERMAL_TRIP_ACTIVE,
50 .temperature = MLXSW_THERMAL_ASIC_TEMP_HIGH,
51 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
54 .type = THERMAL_TRIP_HOT,
55 .temperature = MLXSW_THERMAL_ASIC_TEMP_HOT,
59 static const struct thermal_trip default_thermal_module_trips[] = {
60 { /* In range - 0-40% PWM */
61 .type = THERMAL_TRIP_ACTIVE,
62 .temperature = MLXSW_THERMAL_MODULE_TEMP_NORM,
63 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
66 /* In range - 40-100% PWM */
67 .type = THERMAL_TRIP_ACTIVE,
68 .temperature = MLXSW_THERMAL_MODULE_TEMP_HIGH,
69 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
72 .type = THERMAL_TRIP_HOT,
73 .temperature = MLXSW_THERMAL_MODULE_TEMP_HOT,
77 static const struct mlxsw_cooling_states default_cooling_states[] = {
80 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
83 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
84 .max_state = MLXSW_THERMAL_MAX_STATE,
87 .min_state = MLXSW_THERMAL_MAX_STATE,
88 .max_state = MLXSW_THERMAL_MAX_STATE,
92 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
94 /* Make sure all trips are writable */
95 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
99 struct mlxsw_thermal_module {
100 struct mlxsw_thermal *parent;
101 struct thermal_zone_device *tzdev;
102 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
103 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
104 int module; /* Module or gearbox number */
108 struct mlxsw_thermal_area {
109 struct mlxsw_thermal_module *tz_module_arr;
111 struct mlxsw_thermal_module *tz_gearbox_arr;
117 struct mlxsw_thermal {
118 struct mlxsw_core *core;
119 const struct mlxsw_bus_info *bus_info;
120 struct thermal_zone_device *tzdev;
122 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
123 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
124 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
125 struct mlxsw_thermal_area line_cards[];
128 static inline u8 mlxsw_state_to_duty(int state)
130 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
131 MLXSW_THERMAL_MAX_STATE);
134 static inline int mlxsw_duty_to_state(u8 duty)
136 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
137 MLXSW_THERMAL_MAX_DUTY);
140 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
141 struct thermal_cooling_device *cdev)
145 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
146 if (thermal->cdevs[i] == cdev)
149 /* Allow mlxsw thermal zone binding to an external cooling device */
150 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
151 if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
158 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
159 struct thermal_cooling_device *cdev)
161 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
162 struct device *dev = thermal->bus_info->dev;
165 /* If the cooling device is one of ours bind it */
166 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
169 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
170 const struct mlxsw_cooling_states *state = &thermal->cooling_states[i];
172 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
175 THERMAL_WEIGHT_DEFAULT);
177 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
184 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
185 struct thermal_cooling_device *cdev)
187 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
188 struct device *dev = thermal->bus_info->dev;
192 /* If the cooling device is our one unbind it */
193 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
196 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
197 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
199 dev_err(dev, "Failed to unbind cooling device\n");
206 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
209 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
210 struct device *dev = thermal->bus_info->dev;
211 char mtmp_pl[MLXSW_REG_MTMP_LEN];
215 mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
217 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
219 dev_err(dev, "Failed to query temp sensor\n");
222 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
228 static struct thermal_zone_params mlxsw_thermal_params = {
232 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
233 .bind = mlxsw_thermal_bind,
234 .unbind = mlxsw_thermal_unbind,
235 .get_temp = mlxsw_thermal_get_temp,
238 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
239 struct thermal_cooling_device *cdev)
241 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
242 struct mlxsw_thermal *thermal = tz->parent;
245 /* If the cooling device is one of ours bind it */
246 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
249 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
250 const struct mlxsw_cooling_states *state = &tz->cooling_states[i];
252 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
255 THERMAL_WEIGHT_DEFAULT);
257 goto err_thermal_zone_bind_cooling_device;
261 err_thermal_zone_bind_cooling_device:
262 for (j = i - 1; j >= 0; j--)
263 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
267 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
268 struct thermal_cooling_device *cdev)
270 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
271 struct mlxsw_thermal *thermal = tz->parent;
275 /* If the cooling device is one of ours unbind it */
276 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
279 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
280 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
286 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
289 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
290 struct mlxsw_thermal *thermal = tz->parent;
291 char mtmp_pl[MLXSW_REG_MTMP_LEN];
295 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
296 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, sensor_index,
298 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
301 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL);
305 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
306 .bind = mlxsw_thermal_module_bind,
307 .unbind = mlxsw_thermal_module_unbind,
308 .get_temp = mlxsw_thermal_module_temp_get,
311 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
314 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
315 struct mlxsw_thermal *thermal = tz->parent;
316 char mtmp_pl[MLXSW_REG_MTMP_LEN];
321 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
322 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
324 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
328 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
334 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
335 .bind = mlxsw_thermal_module_bind,
336 .unbind = mlxsw_thermal_module_unbind,
337 .get_temp = mlxsw_thermal_gearbox_temp_get,
340 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
341 unsigned long *p_state)
343 *p_state = MLXSW_THERMAL_MAX_STATE;
347 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
348 unsigned long *p_state)
351 struct mlxsw_thermal *thermal = cdev->devdata;
352 struct device *dev = thermal->bus_info->dev;
353 char mfsc_pl[MLXSW_REG_MFSC_LEN];
357 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
361 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
362 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
364 dev_err(dev, "Failed to query PWM duty\n");
368 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
369 *p_state = mlxsw_duty_to_state(duty);
373 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
377 struct mlxsw_thermal *thermal = cdev->devdata;
378 struct device *dev = thermal->bus_info->dev;
379 char mfsc_pl[MLXSW_REG_MFSC_LEN];
383 if (state > MLXSW_THERMAL_MAX_STATE)
386 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
390 /* Normalize the state to the valid speed range. */
391 state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
392 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
393 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
395 dev_err(dev, "Failed to write PWM duty\n");
401 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
402 .get_max_state = mlxsw_thermal_get_max_state,
403 .get_cur_state = mlxsw_thermal_get_cur_state,
404 .set_cur_state = mlxsw_thermal_set_cur_state,
408 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
410 char tz_name[THERMAL_NAME_LENGTH];
413 if (module_tz->slot_index)
414 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
415 module_tz->slot_index, module_tz->module + 1);
417 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
418 module_tz->module + 1);
419 module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
421 MLXSW_THERMAL_NUM_TRIPS,
422 MLXSW_THERMAL_TRIP_MASK,
424 &mlxsw_thermal_module_ops,
425 &mlxsw_thermal_params,
427 module_tz->parent->polling_delay);
428 if (IS_ERR(module_tz->tzdev)) {
429 err = PTR_ERR(module_tz->tzdev);
433 err = thermal_zone_device_enable(module_tz->tzdev);
435 thermal_zone_device_unregister(module_tz->tzdev);
440 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
442 thermal_zone_device_unregister(tzdev);
446 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
447 struct mlxsw_thermal *thermal,
448 struct mlxsw_thermal_area *area, u8 module)
450 struct mlxsw_thermal_module *module_tz;
452 module_tz = &area->tz_module_arr[module];
453 /* Skip if parent is already set (case of port split). */
454 if (module_tz->parent)
456 module_tz->module = module;
457 module_tz->slot_index = area->slot_index;
458 module_tz->parent = thermal;
459 BUILD_BUG_ON(ARRAY_SIZE(default_thermal_module_trips) !=
460 MLXSW_THERMAL_NUM_TRIPS);
461 memcpy(module_tz->trips, default_thermal_module_trips,
462 sizeof(thermal->trips));
463 memcpy(module_tz->cooling_states, default_cooling_states,
464 sizeof(thermal->cooling_states));
467 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
469 if (module_tz && module_tz->tzdev) {
470 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
471 module_tz->tzdev = NULL;
472 module_tz->parent = NULL;
477 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
478 struct mlxsw_thermal *thermal,
479 struct mlxsw_thermal_area *area)
481 struct mlxsw_thermal_module *module_tz;
482 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
485 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
486 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
490 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
491 &area->tz_module_num, NULL);
493 /* For modular system module counter could be zero. */
494 if (!area->tz_module_num)
497 area->tz_module_arr = kcalloc(area->tz_module_num,
498 sizeof(*area->tz_module_arr),
500 if (!area->tz_module_arr)
503 for (i = 0; i < area->tz_module_num; i++)
504 mlxsw_thermal_module_init(dev, core, thermal, area, i);
506 for (i = 0; i < area->tz_module_num; i++) {
507 module_tz = &area->tz_module_arr[i];
508 if (!module_tz->parent)
510 err = mlxsw_thermal_module_tz_init(module_tz);
512 goto err_thermal_module_tz_init;
517 err_thermal_module_tz_init:
518 for (i = area->tz_module_num - 1; i >= 0; i--)
519 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
520 kfree(area->tz_module_arr);
525 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
526 struct mlxsw_thermal_area *area)
530 for (i = area->tz_module_num - 1; i >= 0; i--)
531 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
532 kfree(area->tz_module_arr);
536 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
538 char tz_name[THERMAL_NAME_LENGTH];
541 if (gearbox_tz->slot_index)
542 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
543 gearbox_tz->slot_index, gearbox_tz->module + 1);
545 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
546 gearbox_tz->module + 1);
547 gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
549 MLXSW_THERMAL_NUM_TRIPS,
550 MLXSW_THERMAL_TRIP_MASK,
552 &mlxsw_thermal_gearbox_ops,
553 &mlxsw_thermal_params, 0,
554 gearbox_tz->parent->polling_delay);
555 if (IS_ERR(gearbox_tz->tzdev))
556 return PTR_ERR(gearbox_tz->tzdev);
558 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
560 thermal_zone_device_unregister(gearbox_tz->tzdev);
566 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
568 thermal_zone_device_unregister(gearbox_tz->tzdev);
572 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
573 struct mlxsw_thermal *thermal,
574 struct mlxsw_thermal_area *area)
576 enum mlxsw_reg_mgpir_device_type device_type;
577 struct mlxsw_thermal_module *gearbox_tz;
578 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
583 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
584 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
588 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
590 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
594 area->tz_gearbox_num = gbox_num;
595 area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
596 sizeof(*area->tz_gearbox_arr),
598 if (!area->tz_gearbox_arr)
601 for (i = 0; i < area->tz_gearbox_num; i++) {
602 gearbox_tz = &area->tz_gearbox_arr[i];
603 memcpy(gearbox_tz->trips, default_thermal_trips,
604 sizeof(thermal->trips));
605 memcpy(gearbox_tz->cooling_states, default_cooling_states,
606 sizeof(thermal->cooling_states));
607 gearbox_tz->module = i;
608 gearbox_tz->parent = thermal;
609 gearbox_tz->slot_index = area->slot_index;
610 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
612 goto err_thermal_gearbox_tz_init;
617 err_thermal_gearbox_tz_init:
618 for (i--; i >= 0; i--)
619 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
620 kfree(area->tz_gearbox_arr);
625 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
626 struct mlxsw_thermal_area *area)
630 for (i = area->tz_gearbox_num - 1; i >= 0; i--)
631 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
632 kfree(area->tz_gearbox_arr);
636 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
639 struct mlxsw_thermal *thermal = priv;
640 struct mlxsw_thermal_area *linecard;
643 linecard = &thermal->line_cards[slot_index];
645 if (linecard->active)
648 linecard->slot_index = slot_index;
649 err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
652 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
657 err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
658 thermal->core, thermal, linecard);
660 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
662 goto err_thermal_linecard_gearboxes_init;
665 linecard->active = true;
669 err_thermal_linecard_gearboxes_init:
670 mlxsw_thermal_modules_fini(thermal, linecard);
674 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
677 struct mlxsw_thermal *thermal = priv;
678 struct mlxsw_thermal_area *linecard;
680 linecard = &thermal->line_cards[slot_index];
681 if (!linecard->active)
683 linecard->active = false;
684 mlxsw_thermal_gearboxes_fini(thermal, linecard);
685 mlxsw_thermal_modules_fini(thermal, linecard);
688 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
689 .got_active = mlxsw_thermal_got_active,
690 .got_inactive = mlxsw_thermal_got_inactive,
693 int mlxsw_thermal_init(struct mlxsw_core *core,
694 const struct mlxsw_bus_info *bus_info,
695 struct mlxsw_thermal **p_thermal)
697 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
698 enum mlxsw_reg_mfcr_pwm_frequency freq;
699 struct device *dev = bus_info->dev;
700 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
701 struct mlxsw_thermal *thermal;
702 u8 pwm_active, num_of_slots;
706 mlxsw_reg_mgpir_pack(mgpir_pl, 0);
707 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
711 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
714 thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
719 thermal->core = core;
720 thermal->bus_info = bus_info;
721 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
722 memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
723 thermal->line_cards[0].slot_index = 0;
725 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
727 dev_err(dev, "Failed to probe PWMs\n");
730 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
732 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
733 if (tacho_active & BIT(i)) {
734 char mfsl_pl[MLXSW_REG_MFSL_LEN];
736 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
738 /* We need to query the register to preserve maximum */
739 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
744 /* set the minimal RPMs to 0 */
745 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
746 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
752 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
753 if (pwm_active & BIT(i)) {
754 struct thermal_cooling_device *cdev;
756 cdev = thermal_cooling_device_register("mlxsw_fan",
761 dev_err(dev, "Failed to register cooling device\n");
762 goto err_thermal_cooling_device_register;
764 thermal->cdevs[i] = cdev;
768 thermal->polling_delay = bus_info->low_frequency ?
769 MLXSW_THERMAL_SLOW_POLL_INT :
770 MLXSW_THERMAL_POLL_INT;
772 thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw",
774 MLXSW_THERMAL_NUM_TRIPS,
775 MLXSW_THERMAL_TRIP_MASK,
778 &mlxsw_thermal_params, 0,
779 thermal->polling_delay);
780 if (IS_ERR(thermal->tzdev)) {
781 err = PTR_ERR(thermal->tzdev);
782 dev_err(dev, "Failed to register thermal zone\n");
783 goto err_thermal_zone_device_register;
786 err = mlxsw_thermal_modules_init(dev, core, thermal,
787 &thermal->line_cards[0]);
789 goto err_thermal_modules_init;
791 err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
792 &thermal->line_cards[0]);
794 goto err_thermal_gearboxes_init;
796 err = mlxsw_linecards_event_ops_register(core,
797 &mlxsw_thermal_event_ops,
800 goto err_linecards_event_ops_register;
802 err = thermal_zone_device_enable(thermal->tzdev);
804 goto err_thermal_zone_device_enable;
806 thermal->line_cards[0].active = true;
807 *p_thermal = thermal;
810 err_thermal_zone_device_enable:
811 mlxsw_linecards_event_ops_unregister(thermal->core,
812 &mlxsw_thermal_event_ops,
814 err_linecards_event_ops_register:
815 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
816 err_thermal_gearboxes_init:
817 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
818 err_thermal_modules_init:
819 if (thermal->tzdev) {
820 thermal_zone_device_unregister(thermal->tzdev);
821 thermal->tzdev = NULL;
823 err_thermal_zone_device_register:
824 err_thermal_cooling_device_register:
825 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
826 if (thermal->cdevs[i])
827 thermal_cooling_device_unregister(thermal->cdevs[i]);
834 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
838 thermal->line_cards[0].active = false;
839 mlxsw_linecards_event_ops_unregister(thermal->core,
840 &mlxsw_thermal_event_ops,
842 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
843 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
844 if (thermal->tzdev) {
845 thermal_zone_device_unregister(thermal->tzdev);
846 thermal->tzdev = NULL;
849 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
850 if (thermal->cdevs[i]) {
851 thermal_cooling_device_unregister(thermal->cdevs[i]);
852 thermal->cdevs[i] = NULL;