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_HYSTERESIS_TEMP 5000 /* 5C */
23 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
24 #define MLXSW_THERMAL_MAX_STATE 10
25 #define MLXSW_THERMAL_MIN_STATE 2
26 #define MLXSW_THERMAL_MAX_DUTY 255
28 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
29 static char * const mlxsw_thermal_external_allowed_cdev[] = {
33 enum mlxsw_thermal_trips {
34 MLXSW_THERMAL_TEMP_TRIP_NORM,
35 MLXSW_THERMAL_TEMP_TRIP_HIGH,
36 MLXSW_THERMAL_TEMP_TRIP_HOT,
39 struct mlxsw_thermal_trip {
47 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
48 { /* In range - 0-40% PWM */
49 .type = THERMAL_TRIP_ACTIVE,
50 .temp = MLXSW_THERMAL_ASIC_TEMP_NORM,
51 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
53 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
56 /* In range - 40-100% PWM */
57 .type = THERMAL_TRIP_ACTIVE,
58 .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH,
59 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
60 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
61 .max_state = MLXSW_THERMAL_MAX_STATE,
64 .type = THERMAL_TRIP_HOT,
65 .temp = MLXSW_THERMAL_ASIC_TEMP_HOT,
66 .min_state = MLXSW_THERMAL_MAX_STATE,
67 .max_state = MLXSW_THERMAL_MAX_STATE,
71 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
73 /* Make sure all trips are writable */
74 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
78 struct mlxsw_thermal_module {
79 struct mlxsw_thermal *parent;
80 struct thermal_zone_device *tzdev;
81 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
82 int module; /* Module or gearbox number */
86 struct mlxsw_thermal_area {
87 struct mlxsw_thermal_module *tz_module_arr;
89 struct mlxsw_thermal_module *tz_gearbox_arr;
95 struct mlxsw_thermal {
96 struct mlxsw_core *core;
97 const struct mlxsw_bus_info *bus_info;
98 struct thermal_zone_device *tzdev;
100 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
101 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
102 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
103 struct mlxsw_thermal_area line_cards[];
106 static inline u8 mlxsw_state_to_duty(int state)
108 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
109 MLXSW_THERMAL_MAX_STATE);
112 static inline int mlxsw_duty_to_state(u8 duty)
114 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
115 MLXSW_THERMAL_MAX_DUTY);
118 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
119 struct thermal_cooling_device *cdev)
123 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
124 if (thermal->cdevs[i] == cdev)
127 /* Allow mlxsw thermal zone binding to an external cooling device */
128 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
129 if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
137 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
139 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
140 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
141 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
145 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
146 struct mlxsw_thermal_module *tz,
147 int crit_temp, int emerg_temp)
151 /* Do not try to query temperature thresholds directly from the module's
152 * EEPROM if we got valid thresholds from MTMP.
154 if (!emerg_temp || !crit_temp) {
155 err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
162 err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
170 if (crit_temp > emerg_temp) {
171 dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
172 tz->tzdev->type, crit_temp, emerg_temp);
176 /* According to the system thermal requirements, the thermal zones are
177 * defined with three trip points. The critical and emergency
178 * temperature thresholds, provided by QSFP module are set as "active"
179 * and "hot" trip points, "normal" trip point is derived from "active"
180 * by subtracting double hysteresis value.
182 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
183 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
184 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
186 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
187 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
188 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
193 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
194 struct thermal_cooling_device *cdev)
196 struct mlxsw_thermal *thermal = tzdev->devdata;
197 struct device *dev = thermal->bus_info->dev;
200 /* If the cooling device is one of ours bind it */
201 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
204 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
205 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
207 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
210 THERMAL_WEIGHT_DEFAULT);
212 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
219 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
220 struct thermal_cooling_device *cdev)
222 struct mlxsw_thermal *thermal = tzdev->devdata;
223 struct device *dev = thermal->bus_info->dev;
227 /* If the cooling device is our one unbind it */
228 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
231 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
232 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
234 dev_err(dev, "Failed to unbind cooling device\n");
241 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
244 struct mlxsw_thermal *thermal = tzdev->devdata;
245 struct device *dev = thermal->bus_info->dev;
246 char mtmp_pl[MLXSW_REG_MTMP_LEN];
250 mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
252 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
254 dev_err(dev, "Failed to query temp sensor\n");
257 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
263 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
265 enum thermal_trip_type *p_type)
267 struct mlxsw_thermal *thermal = tzdev->devdata;
269 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
272 *p_type = thermal->trips[trip].type;
276 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
277 int trip, int *p_temp)
279 struct mlxsw_thermal *thermal = tzdev->devdata;
281 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
284 *p_temp = thermal->trips[trip].temp;
288 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
291 struct mlxsw_thermal *thermal = tzdev->devdata;
293 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
296 thermal->trips[trip].temp = temp;
300 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
301 int trip, int *p_hyst)
303 struct mlxsw_thermal *thermal = tzdev->devdata;
305 *p_hyst = thermal->trips[trip].hyst;
309 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
312 struct mlxsw_thermal *thermal = tzdev->devdata;
314 thermal->trips[trip].hyst = hyst;
318 static struct thermal_zone_params mlxsw_thermal_params = {
322 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
323 .bind = mlxsw_thermal_bind,
324 .unbind = mlxsw_thermal_unbind,
325 .get_temp = mlxsw_thermal_get_temp,
326 .get_trip_type = mlxsw_thermal_get_trip_type,
327 .get_trip_temp = mlxsw_thermal_get_trip_temp,
328 .set_trip_temp = mlxsw_thermal_set_trip_temp,
329 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
330 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
333 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
334 struct thermal_cooling_device *cdev)
336 struct mlxsw_thermal_module *tz = tzdev->devdata;
337 struct mlxsw_thermal *thermal = tz->parent;
340 /* If the cooling device is one of ours bind it */
341 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
344 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
345 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
347 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
350 THERMAL_WEIGHT_DEFAULT);
352 goto err_thermal_zone_bind_cooling_device;
356 err_thermal_zone_bind_cooling_device:
357 for (j = i - 1; j >= 0; j--)
358 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
362 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
363 struct thermal_cooling_device *cdev)
365 struct mlxsw_thermal_module *tz = tzdev->devdata;
366 struct mlxsw_thermal *thermal = tz->parent;
370 /* If the cooling device is one of ours unbind it */
371 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
374 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
375 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
382 mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
383 u8 slot_index, u16 sensor_index,
384 int *p_temp, int *p_crit_temp,
387 char mtmp_pl[MLXSW_REG_MTMP_LEN];
390 /* Read module temperature and thresholds. */
391 mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, sensor_index,
393 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
395 /* Set temperature and thresholds to zero to avoid passing
396 * uninitialized data back to the caller.
404 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, p_crit_temp, p_emerg_temp,
408 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
411 struct mlxsw_thermal_module *tz = tzdev->devdata;
412 struct mlxsw_thermal *thermal = tz->parent;
413 int temp, crit_temp, emerg_temp;
417 dev = thermal->bus_info->dev;
418 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
420 /* Read module temperature and thresholds. */
421 mlxsw_thermal_module_temp_and_thresholds_get(thermal->core,
424 &crit_temp, &emerg_temp);
430 /* Update trip points. */
431 mlxsw_thermal_module_trips_update(dev, thermal->core, tz,
432 crit_temp, emerg_temp);
438 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
439 enum thermal_trip_type *p_type)
441 struct mlxsw_thermal_module *tz = tzdev->devdata;
443 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
446 *p_type = tz->trips[trip].type;
451 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
452 int trip, int *p_temp)
454 struct mlxsw_thermal_module *tz = tzdev->devdata;
456 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
459 *p_temp = tz->trips[trip].temp;
464 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
467 struct mlxsw_thermal_module *tz = tzdev->devdata;
469 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
472 tz->trips[trip].temp = temp;
477 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
480 struct mlxsw_thermal_module *tz = tzdev->devdata;
482 *p_hyst = tz->trips[trip].hyst;
487 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
490 struct mlxsw_thermal_module *tz = tzdev->devdata;
492 tz->trips[trip].hyst = hyst;
496 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
497 .bind = mlxsw_thermal_module_bind,
498 .unbind = mlxsw_thermal_module_unbind,
499 .get_temp = mlxsw_thermal_module_temp_get,
500 .get_trip_type = mlxsw_thermal_module_trip_type_get,
501 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
502 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
503 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
504 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
507 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
510 struct mlxsw_thermal_module *tz = tzdev->devdata;
511 struct mlxsw_thermal *thermal = tz->parent;
512 char mtmp_pl[MLXSW_REG_MTMP_LEN];
517 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
518 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
520 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
524 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
530 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
531 .bind = mlxsw_thermal_module_bind,
532 .unbind = mlxsw_thermal_module_unbind,
533 .get_temp = mlxsw_thermal_gearbox_temp_get,
534 .get_trip_type = mlxsw_thermal_module_trip_type_get,
535 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
536 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
537 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
538 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
541 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
542 unsigned long *p_state)
544 *p_state = MLXSW_THERMAL_MAX_STATE;
548 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
549 unsigned long *p_state)
552 struct mlxsw_thermal *thermal = cdev->devdata;
553 struct device *dev = thermal->bus_info->dev;
554 char mfsc_pl[MLXSW_REG_MFSC_LEN];
558 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
562 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
563 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
565 dev_err(dev, "Failed to query PWM duty\n");
569 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
570 *p_state = mlxsw_duty_to_state(duty);
574 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
578 struct mlxsw_thermal *thermal = cdev->devdata;
579 struct device *dev = thermal->bus_info->dev;
580 char mfsc_pl[MLXSW_REG_MFSC_LEN];
584 if (state > MLXSW_THERMAL_MAX_STATE)
587 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
591 /* Normalize the state to the valid speed range. */
592 state = thermal->cooling_levels[state];
593 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
594 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
596 dev_err(dev, "Failed to write PWM duty\n");
602 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
603 .get_max_state = mlxsw_thermal_get_max_state,
604 .get_cur_state = mlxsw_thermal_get_cur_state,
605 .set_cur_state = mlxsw_thermal_set_cur_state,
609 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
611 char tz_name[THERMAL_NAME_LENGTH];
614 if (module_tz->slot_index)
615 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
616 module_tz->slot_index, module_tz->module + 1);
618 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
619 module_tz->module + 1);
620 module_tz->tzdev = thermal_zone_device_register(tz_name,
621 MLXSW_THERMAL_NUM_TRIPS,
622 MLXSW_THERMAL_TRIP_MASK,
624 &mlxsw_thermal_module_ops,
625 &mlxsw_thermal_params,
627 module_tz->parent->polling_delay);
628 if (IS_ERR(module_tz->tzdev)) {
629 err = PTR_ERR(module_tz->tzdev);
633 err = thermal_zone_device_enable(module_tz->tzdev);
635 thermal_zone_device_unregister(module_tz->tzdev);
640 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
642 thermal_zone_device_unregister(tzdev);
646 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
647 struct mlxsw_thermal *thermal,
648 struct mlxsw_thermal_area *area, u8 module)
650 struct mlxsw_thermal_module *module_tz;
651 int dummy_temp, crit_temp, emerg_temp;
654 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module;
655 module_tz = &area->tz_module_arr[module];
656 /* Skip if parent is already set (case of port split). */
657 if (module_tz->parent)
659 module_tz->module = module;
660 module_tz->slot_index = area->slot_index;
661 module_tz->parent = thermal;
662 memcpy(module_tz->trips, default_thermal_trips,
663 sizeof(thermal->trips));
664 /* Initialize all trip point. */
665 mlxsw_thermal_module_trips_reset(module_tz);
666 /* Read module temperature and thresholds. */
667 mlxsw_thermal_module_temp_and_thresholds_get(core, area->slot_index,
668 sensor_index, &dummy_temp,
669 &crit_temp, &emerg_temp);
670 /* Update trip point according to the module data. */
671 return mlxsw_thermal_module_trips_update(dev, core, module_tz,
672 crit_temp, emerg_temp);
675 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
677 if (module_tz && module_tz->tzdev) {
678 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
679 module_tz->tzdev = NULL;
680 module_tz->parent = NULL;
685 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
686 struct mlxsw_thermal *thermal,
687 struct mlxsw_thermal_area *area)
689 struct mlxsw_thermal_module *module_tz;
690 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
693 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
694 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
698 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
699 &area->tz_module_num, NULL);
701 /* For modular system module counter could be zero. */
702 if (!area->tz_module_num)
705 area->tz_module_arr = kcalloc(area->tz_module_num,
706 sizeof(*area->tz_module_arr),
708 if (!area->tz_module_arr)
711 for (i = 0; i < area->tz_module_num; i++) {
712 err = mlxsw_thermal_module_init(dev, core, thermal, area, i);
714 goto err_thermal_module_init;
717 for (i = 0; i < area->tz_module_num; i++) {
718 module_tz = &area->tz_module_arr[i];
719 if (!module_tz->parent)
721 err = mlxsw_thermal_module_tz_init(module_tz);
723 goto err_thermal_module_tz_init;
728 err_thermal_module_tz_init:
729 err_thermal_module_init:
730 for (i = area->tz_module_num - 1; i >= 0; i--)
731 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
732 kfree(area->tz_module_arr);
737 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
738 struct mlxsw_thermal_area *area)
742 for (i = area->tz_module_num - 1; i >= 0; i--)
743 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
744 kfree(area->tz_module_arr);
748 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
750 char tz_name[THERMAL_NAME_LENGTH];
753 if (gearbox_tz->slot_index)
754 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
755 gearbox_tz->slot_index, gearbox_tz->module + 1);
757 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
758 gearbox_tz->module + 1);
759 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
760 MLXSW_THERMAL_NUM_TRIPS,
761 MLXSW_THERMAL_TRIP_MASK,
763 &mlxsw_thermal_gearbox_ops,
764 &mlxsw_thermal_params, 0,
765 gearbox_tz->parent->polling_delay);
766 if (IS_ERR(gearbox_tz->tzdev))
767 return PTR_ERR(gearbox_tz->tzdev);
769 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
771 thermal_zone_device_unregister(gearbox_tz->tzdev);
777 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
779 thermal_zone_device_unregister(gearbox_tz->tzdev);
783 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
784 struct mlxsw_thermal *thermal,
785 struct mlxsw_thermal_area *area)
787 enum mlxsw_reg_mgpir_device_type device_type;
788 struct mlxsw_thermal_module *gearbox_tz;
789 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
794 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
795 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
799 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
801 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
805 area->tz_gearbox_num = gbox_num;
806 area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
807 sizeof(*area->tz_gearbox_arr),
809 if (!area->tz_gearbox_arr)
812 for (i = 0; i < area->tz_gearbox_num; i++) {
813 gearbox_tz = &area->tz_gearbox_arr[i];
814 memcpy(gearbox_tz->trips, default_thermal_trips,
815 sizeof(thermal->trips));
816 gearbox_tz->module = i;
817 gearbox_tz->parent = thermal;
818 gearbox_tz->slot_index = area->slot_index;
819 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
821 goto err_thermal_gearbox_tz_init;
826 err_thermal_gearbox_tz_init:
827 for (i--; i >= 0; i--)
828 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
829 kfree(area->tz_gearbox_arr);
834 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
835 struct mlxsw_thermal_area *area)
839 for (i = area->tz_gearbox_num - 1; i >= 0; i--)
840 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
841 kfree(area->tz_gearbox_arr);
845 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
848 struct mlxsw_thermal *thermal = priv;
849 struct mlxsw_thermal_area *linecard;
852 linecard = &thermal->line_cards[slot_index];
854 if (linecard->active)
857 linecard->slot_index = slot_index;
858 err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
861 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
866 err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
867 thermal->core, thermal, linecard);
869 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
871 goto err_thermal_linecard_gearboxes_init;
874 linecard->active = true;
878 err_thermal_linecard_gearboxes_init:
879 mlxsw_thermal_modules_fini(thermal, linecard);
883 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
886 struct mlxsw_thermal *thermal = priv;
887 struct mlxsw_thermal_area *linecard;
889 linecard = &thermal->line_cards[slot_index];
890 if (!linecard->active)
892 linecard->active = false;
893 mlxsw_thermal_gearboxes_fini(thermal, linecard);
894 mlxsw_thermal_modules_fini(thermal, linecard);
897 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
898 .got_active = mlxsw_thermal_got_active,
899 .got_inactive = mlxsw_thermal_got_inactive,
902 int mlxsw_thermal_init(struct mlxsw_core *core,
903 const struct mlxsw_bus_info *bus_info,
904 struct mlxsw_thermal **p_thermal)
906 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
907 enum mlxsw_reg_mfcr_pwm_frequency freq;
908 struct device *dev = bus_info->dev;
909 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
910 struct mlxsw_thermal *thermal;
911 u8 pwm_active, num_of_slots;
915 mlxsw_reg_mgpir_pack(mgpir_pl, 0);
916 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
920 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
923 thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
928 thermal->core = core;
929 thermal->bus_info = bus_info;
930 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
931 thermal->line_cards[0].slot_index = 0;
933 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
935 dev_err(dev, "Failed to probe PWMs\n");
938 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
940 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
941 if (tacho_active & BIT(i)) {
942 char mfsl_pl[MLXSW_REG_MFSL_LEN];
944 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
946 /* We need to query the register to preserve maximum */
947 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
952 /* set the minimal RPMs to 0 */
953 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
954 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
960 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
961 if (pwm_active & BIT(i)) {
962 struct thermal_cooling_device *cdev;
964 cdev = thermal_cooling_device_register("mlxsw_fan",
969 dev_err(dev, "Failed to register cooling device\n");
970 goto err_thermal_cooling_device_register;
972 thermal->cdevs[i] = cdev;
976 /* Initialize cooling levels per PWM state. */
977 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
978 thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
980 thermal->polling_delay = bus_info->low_frequency ?
981 MLXSW_THERMAL_SLOW_POLL_INT :
982 MLXSW_THERMAL_POLL_INT;
984 thermal->tzdev = thermal_zone_device_register("mlxsw",
985 MLXSW_THERMAL_NUM_TRIPS,
986 MLXSW_THERMAL_TRIP_MASK,
989 &mlxsw_thermal_params, 0,
990 thermal->polling_delay);
991 if (IS_ERR(thermal->tzdev)) {
992 err = PTR_ERR(thermal->tzdev);
993 dev_err(dev, "Failed to register thermal zone\n");
994 goto err_thermal_zone_device_register;
997 err = mlxsw_thermal_modules_init(dev, core, thermal,
998 &thermal->line_cards[0]);
1000 goto err_thermal_modules_init;
1002 err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
1003 &thermal->line_cards[0]);
1005 goto err_thermal_gearboxes_init;
1007 err = mlxsw_linecards_event_ops_register(core,
1008 &mlxsw_thermal_event_ops,
1011 goto err_linecards_event_ops_register;
1013 err = thermal_zone_device_enable(thermal->tzdev);
1015 goto err_thermal_zone_device_enable;
1017 thermal->line_cards[0].active = true;
1018 *p_thermal = thermal;
1021 err_thermal_zone_device_enable:
1022 mlxsw_linecards_event_ops_unregister(thermal->core,
1023 &mlxsw_thermal_event_ops,
1025 err_linecards_event_ops_register:
1026 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1027 err_thermal_gearboxes_init:
1028 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1029 err_thermal_modules_init:
1030 if (thermal->tzdev) {
1031 thermal_zone_device_unregister(thermal->tzdev);
1032 thermal->tzdev = NULL;
1034 err_thermal_zone_device_register:
1035 err_thermal_cooling_device_register:
1036 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1037 if (thermal->cdevs[i])
1038 thermal_cooling_device_unregister(thermal->cdevs[i]);
1045 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1049 thermal->line_cards[0].active = false;
1050 mlxsw_linecards_event_ops_unregister(thermal->core,
1051 &mlxsw_thermal_event_ops,
1053 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
1054 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
1055 if (thermal->tzdev) {
1056 thermal_zone_device_unregister(thermal->tzdev);
1057 thermal->tzdev = NULL;
1060 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1061 if (thermal->cdevs[i]) {
1062 thermal_cooling_device_unregister(thermal->cdevs[i]);
1063 thermal->cdevs[i] = NULL;