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_ZONE_MAX_NAME 16
25 #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0)
26 #define MLXSW_THERMAL_MAX_STATE 10
27 #define MLXSW_THERMAL_MAX_DUTY 255
28 /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
29 * MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for
30 * setting fan speed dynamic minimum. For example, if value is set to 14 (40%)
31 * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to
32 * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100.
34 #define MLXSW_THERMAL_SPEED_MIN (MLXSW_THERMAL_MAX_STATE + 2)
35 #define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2)
36 #define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */
38 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
39 static char * const mlxsw_thermal_external_allowed_cdev[] = {
43 enum mlxsw_thermal_trips {
44 MLXSW_THERMAL_TEMP_TRIP_NORM,
45 MLXSW_THERMAL_TEMP_TRIP_HIGH,
46 MLXSW_THERMAL_TEMP_TRIP_HOT,
49 struct mlxsw_thermal_trip {
57 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
58 { /* In range - 0-40% PWM */
59 .type = THERMAL_TRIP_ACTIVE,
60 .temp = MLXSW_THERMAL_ASIC_TEMP_NORM,
61 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
63 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
66 /* In range - 40-100% PWM */
67 .type = THERMAL_TRIP_ACTIVE,
68 .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH,
69 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
70 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
71 .max_state = MLXSW_THERMAL_MAX_STATE,
74 .type = THERMAL_TRIP_HOT,
75 .temp = MLXSW_THERMAL_ASIC_TEMP_HOT,
76 .min_state = MLXSW_THERMAL_MAX_STATE,
77 .max_state = MLXSW_THERMAL_MAX_STATE,
81 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
83 /* Make sure all trips are writable */
84 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
88 struct mlxsw_thermal_module {
89 struct mlxsw_thermal *parent;
90 struct thermal_zone_device *tzdev;
91 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
92 int module; /* Module or gearbox number */
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_module *tz_module_arr;
105 struct mlxsw_thermal_module *tz_gearbox_arr;
107 unsigned int tz_highest_score;
108 struct thermal_zone_device *tz_highest_dev;
111 static inline u8 mlxsw_state_to_duty(int state)
113 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
114 MLXSW_THERMAL_MAX_STATE);
117 static inline int mlxsw_duty_to_state(u8 duty)
119 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
120 MLXSW_THERMAL_MAX_DUTY);
123 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
124 struct thermal_cooling_device *cdev)
128 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
129 if (thermal->cdevs[i] == cdev)
132 /* Allow mlxsw thermal zone binding to an external cooling device */
133 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
134 if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
143 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
145 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
146 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
147 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
151 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
152 struct mlxsw_thermal_module *tz,
153 int crit_temp, int emerg_temp)
157 /* Do not try to query temperature thresholds directly from the module's
158 * EEPROM if we got valid thresholds from MTMP.
160 if (!emerg_temp || !crit_temp) {
161 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
167 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
174 if (crit_temp > emerg_temp) {
175 dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
176 tz->tzdev->type, crit_temp, emerg_temp);
180 /* According to the system thermal requirements, the thermal zones are
181 * defined with three trip points. The critical and emergency
182 * temperature thresholds, provided by QSFP module are set as "active"
183 * and "hot" trip points, "normal" trip point is derived from "active"
184 * by subtracting double hysteresis value.
186 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
187 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
188 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
190 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
191 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
192 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
197 static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
198 struct thermal_zone_device *tzdev,
199 struct mlxsw_thermal_trip *trips,
202 struct mlxsw_thermal_trip *trip = trips;
203 unsigned int score, delta, i, shift = 1;
205 /* Calculate thermal zone score, if temperature is above the hot
206 * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
208 score = MLXSW_THERMAL_TEMP_SCORE_MAX;
209 for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
211 if (temp < trip->temp) {
212 delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
213 score = delta * shift;
219 if (score > thermal->tz_highest_score) {
220 thermal->tz_highest_score = score;
221 thermal->tz_highest_dev = tzdev;
225 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
226 struct thermal_cooling_device *cdev)
228 struct mlxsw_thermal *thermal = tzdev->devdata;
229 struct device *dev = thermal->bus_info->dev;
232 /* If the cooling device is one of ours bind it */
233 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
236 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
237 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
239 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
242 THERMAL_WEIGHT_DEFAULT);
244 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
251 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
252 struct thermal_cooling_device *cdev)
254 struct mlxsw_thermal *thermal = tzdev->devdata;
255 struct device *dev = thermal->bus_info->dev;
259 /* If the cooling device is our one unbind it */
260 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
263 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
264 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
266 dev_err(dev, "Failed to unbind cooling device\n");
273 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
276 struct mlxsw_thermal *thermal = tzdev->devdata;
277 struct device *dev = thermal->bus_info->dev;
278 char mtmp_pl[MLXSW_REG_MTMP_LEN];
282 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
284 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
286 dev_err(dev, "Failed to query temp sensor\n");
289 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
291 mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
298 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
300 enum thermal_trip_type *p_type)
302 struct mlxsw_thermal *thermal = tzdev->devdata;
304 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
307 *p_type = thermal->trips[trip].type;
311 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
312 int trip, int *p_temp)
314 struct mlxsw_thermal *thermal = tzdev->devdata;
316 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
319 *p_temp = thermal->trips[trip].temp;
323 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
326 struct mlxsw_thermal *thermal = tzdev->devdata;
328 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
331 thermal->trips[trip].temp = temp;
335 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
336 int trip, int *p_hyst)
338 struct mlxsw_thermal *thermal = tzdev->devdata;
340 *p_hyst = thermal->trips[trip].hyst;
344 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
347 struct mlxsw_thermal *thermal = tzdev->devdata;
349 thermal->trips[trip].hyst = hyst;
353 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
354 int trip, enum thermal_trend *trend)
356 struct mlxsw_thermal *thermal = tzdev->devdata;
358 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
361 if (tzdev == thermal->tz_highest_dev)
364 *trend = THERMAL_TREND_STABLE;
368 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
369 .bind = mlxsw_thermal_bind,
370 .unbind = mlxsw_thermal_unbind,
371 .get_temp = mlxsw_thermal_get_temp,
372 .get_trip_type = mlxsw_thermal_get_trip_type,
373 .get_trip_temp = mlxsw_thermal_get_trip_temp,
374 .set_trip_temp = mlxsw_thermal_set_trip_temp,
375 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
376 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
377 .get_trend = mlxsw_thermal_trend_get,
380 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
381 struct thermal_cooling_device *cdev)
383 struct mlxsw_thermal_module *tz = tzdev->devdata;
384 struct mlxsw_thermal *thermal = tz->parent;
387 /* If the cooling device is one of ours bind it */
388 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
391 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
392 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
394 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
397 THERMAL_WEIGHT_DEFAULT);
399 goto err_bind_cooling_device;
403 err_bind_cooling_device:
404 for (j = i - 1; j >= 0; j--)
405 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
409 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
410 struct thermal_cooling_device *cdev)
412 struct mlxsw_thermal_module *tz = tzdev->devdata;
413 struct mlxsw_thermal *thermal = tz->parent;
417 /* If the cooling device is one of ours unbind it */
418 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
421 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
422 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
429 mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
430 u16 sensor_index, int *p_temp,
434 char mtmp_pl[MLXSW_REG_MTMP_LEN];
437 /* Read module temperature and thresholds. */
438 mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, false, false);
439 err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
441 /* Set temperature and thresholds to zero to avoid passing
442 * uninitialized data back to the caller.
450 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, p_crit_temp, p_emerg_temp,
454 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
457 struct mlxsw_thermal_module *tz = tzdev->devdata;
458 struct mlxsw_thermal *thermal = tz->parent;
459 int temp, crit_temp, emerg_temp;
464 dev = thermal->bus_info->dev;
465 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
467 /* Read module temperature and thresholds. */
468 mlxsw_thermal_module_temp_and_thresholds_get(thermal->core,
470 &crit_temp, &emerg_temp);
476 /* Update trip points. */
477 err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz,
478 crit_temp, emerg_temp);
479 if (!err && temp > 0)
480 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
486 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
487 enum thermal_trip_type *p_type)
489 struct mlxsw_thermal_module *tz = tzdev->devdata;
491 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
494 *p_type = tz->trips[trip].type;
499 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
500 int trip, int *p_temp)
502 struct mlxsw_thermal_module *tz = tzdev->devdata;
504 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
507 *p_temp = tz->trips[trip].temp;
512 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
515 struct mlxsw_thermal_module *tz = tzdev->devdata;
517 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
520 tz->trips[trip].temp = temp;
525 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
528 struct mlxsw_thermal_module *tz = tzdev->devdata;
530 *p_hyst = tz->trips[trip].hyst;
535 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
538 struct mlxsw_thermal_module *tz = tzdev->devdata;
540 tz->trips[trip].hyst = hyst;
544 static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
545 int trip, enum thermal_trend *trend)
547 struct mlxsw_thermal_module *tz = tzdev->devdata;
548 struct mlxsw_thermal *thermal = tz->parent;
550 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
553 if (tzdev == thermal->tz_highest_dev)
556 *trend = THERMAL_TREND_STABLE;
560 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
561 .bind = mlxsw_thermal_module_bind,
562 .unbind = mlxsw_thermal_module_unbind,
563 .get_temp = mlxsw_thermal_module_temp_get,
564 .get_trip_type = mlxsw_thermal_module_trip_type_get,
565 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
566 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
567 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
568 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
569 .get_trend = mlxsw_thermal_module_trend_get,
572 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
575 struct mlxsw_thermal_module *tz = tzdev->devdata;
576 struct mlxsw_thermal *thermal = tz->parent;
577 char mtmp_pl[MLXSW_REG_MTMP_LEN];
582 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
583 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
585 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
589 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
591 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
597 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
598 .bind = mlxsw_thermal_module_bind,
599 .unbind = mlxsw_thermal_module_unbind,
600 .get_temp = mlxsw_thermal_gearbox_temp_get,
601 .get_trip_type = mlxsw_thermal_module_trip_type_get,
602 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
603 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
604 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
605 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
606 .get_trend = mlxsw_thermal_module_trend_get,
609 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
610 unsigned long *p_state)
612 *p_state = MLXSW_THERMAL_MAX_STATE;
616 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
617 unsigned long *p_state)
620 struct mlxsw_thermal *thermal = cdev->devdata;
621 struct device *dev = thermal->bus_info->dev;
622 char mfsc_pl[MLXSW_REG_MFSC_LEN];
626 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
630 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
631 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
633 dev_err(dev, "Failed to query PWM duty\n");
637 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
638 *p_state = mlxsw_duty_to_state(duty);
642 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
646 struct mlxsw_thermal *thermal = cdev->devdata;
647 struct device *dev = thermal->bus_info->dev;
648 char mfsc_pl[MLXSW_REG_MFSC_LEN];
649 unsigned long cur_state, i;
654 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
658 /* Verify if this request is for changing allowed fan dynamical
659 * minimum. If it is - update cooling levels accordingly and update
660 * state, if current state is below the newly requested minimum state.
661 * For example, if current state is 5, and minimal state is to be
662 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
663 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
666 if (state >= MLXSW_THERMAL_SPEED_MIN &&
667 state <= MLXSW_THERMAL_SPEED_MAX) {
668 state -= MLXSW_THERMAL_MAX_STATE;
669 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
670 thermal->cooling_levels[i] = max(state, i);
672 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
673 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
677 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
678 cur_state = mlxsw_duty_to_state(duty);
680 /* If current fan state is lower than requested dynamical
681 * minimum, increase fan speed up to dynamical minimum.
683 if (state < cur_state)
689 if (state > MLXSW_THERMAL_MAX_STATE)
692 /* Normalize the state to the valid speed range. */
693 state = thermal->cooling_levels[state];
694 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
695 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
697 dev_err(dev, "Failed to write PWM duty\n");
703 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
704 .get_max_state = mlxsw_thermal_get_max_state,
705 .get_cur_state = mlxsw_thermal_get_cur_state,
706 .set_cur_state = mlxsw_thermal_set_cur_state,
710 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
712 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
715 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
716 module_tz->module + 1);
717 module_tz->tzdev = thermal_zone_device_register(tz_name,
718 MLXSW_THERMAL_NUM_TRIPS,
719 MLXSW_THERMAL_TRIP_MASK,
721 &mlxsw_thermal_module_ops,
723 module_tz->parent->polling_delay);
724 if (IS_ERR(module_tz->tzdev)) {
725 err = PTR_ERR(module_tz->tzdev);
729 err = thermal_zone_device_enable(module_tz->tzdev);
731 thermal_zone_device_unregister(module_tz->tzdev);
736 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
738 thermal_zone_device_unregister(tzdev);
742 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
743 struct mlxsw_thermal *thermal, u8 module)
745 struct mlxsw_thermal_module *module_tz;
746 int dummy_temp, crit_temp, emerg_temp;
749 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module;
750 module_tz = &thermal->tz_module_arr[module];
751 /* Skip if parent is already set (case of port split). */
752 if (module_tz->parent)
754 module_tz->module = module;
755 module_tz->parent = thermal;
756 memcpy(module_tz->trips, default_thermal_trips,
757 sizeof(thermal->trips));
758 /* Initialize all trip point. */
759 mlxsw_thermal_module_trips_reset(module_tz);
760 /* Read module temperature and thresholds. */
761 mlxsw_thermal_module_temp_and_thresholds_get(core, sensor_index, &dummy_temp,
762 &crit_temp, &emerg_temp);
763 /* Update trip point according to the module data. */
764 return mlxsw_thermal_module_trips_update(dev, core, module_tz,
765 crit_temp, emerg_temp);
768 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
770 if (module_tz && module_tz->tzdev) {
771 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
772 module_tz->tzdev = NULL;
773 module_tz->parent = NULL;
778 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
779 struct mlxsw_thermal *thermal)
781 struct mlxsw_thermal_module *module_tz;
782 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
785 if (!mlxsw_core_res_query_enabled(core))
788 mlxsw_reg_mgpir_pack(mgpir_pl);
789 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
793 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
794 &thermal->tz_module_num);
796 thermal->tz_module_arr = kcalloc(thermal->tz_module_num,
797 sizeof(*thermal->tz_module_arr),
799 if (!thermal->tz_module_arr)
802 for (i = 0; i < thermal->tz_module_num; i++) {
803 err = mlxsw_thermal_module_init(dev, core, thermal, i);
805 goto err_unreg_tz_module_arr;
808 for (i = 0; i < thermal->tz_module_num; i++) {
809 module_tz = &thermal->tz_module_arr[i];
810 if (!module_tz->parent)
812 err = mlxsw_thermal_module_tz_init(module_tz);
814 goto err_unreg_tz_module_arr;
819 err_unreg_tz_module_arr:
820 for (i = thermal->tz_module_num - 1; i >= 0; i--)
821 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
822 kfree(thermal->tz_module_arr);
827 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
831 if (!mlxsw_core_res_query_enabled(thermal->core))
834 for (i = thermal->tz_module_num - 1; i >= 0; i--)
835 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
836 kfree(thermal->tz_module_arr);
840 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
842 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
845 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
846 gearbox_tz->module + 1);
847 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
848 MLXSW_THERMAL_NUM_TRIPS,
849 MLXSW_THERMAL_TRIP_MASK,
851 &mlxsw_thermal_gearbox_ops,
853 gearbox_tz->parent->polling_delay);
854 if (IS_ERR(gearbox_tz->tzdev))
855 return PTR_ERR(gearbox_tz->tzdev);
857 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
859 thermal_zone_device_unregister(gearbox_tz->tzdev);
865 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
867 thermal_zone_device_unregister(gearbox_tz->tzdev);
871 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
872 struct mlxsw_thermal *thermal)
874 enum mlxsw_reg_mgpir_device_type device_type;
875 struct mlxsw_thermal_module *gearbox_tz;
876 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
881 if (!mlxsw_core_res_query_enabled(core))
884 mlxsw_reg_mgpir_pack(mgpir_pl);
885 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
889 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
891 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
895 thermal->tz_gearbox_num = gbox_num;
896 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
897 sizeof(*thermal->tz_gearbox_arr),
899 if (!thermal->tz_gearbox_arr)
902 for (i = 0; i < thermal->tz_gearbox_num; i++) {
903 gearbox_tz = &thermal->tz_gearbox_arr[i];
904 memcpy(gearbox_tz->trips, default_thermal_trips,
905 sizeof(thermal->trips));
906 gearbox_tz->module = i;
907 gearbox_tz->parent = thermal;
908 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
910 goto err_unreg_tz_gearbox;
915 err_unreg_tz_gearbox:
916 for (i--; i >= 0; i--)
917 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
918 kfree(thermal->tz_gearbox_arr);
923 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
927 if (!mlxsw_core_res_query_enabled(thermal->core))
930 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
931 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
932 kfree(thermal->tz_gearbox_arr);
935 int mlxsw_thermal_init(struct mlxsw_core *core,
936 const struct mlxsw_bus_info *bus_info,
937 struct mlxsw_thermal **p_thermal)
939 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
940 enum mlxsw_reg_mfcr_pwm_frequency freq;
941 struct device *dev = bus_info->dev;
942 struct mlxsw_thermal *thermal;
947 thermal = devm_kzalloc(dev, sizeof(*thermal),
952 thermal->core = core;
953 thermal->bus_info = bus_info;
954 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
956 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
958 dev_err(dev, "Failed to probe PWMs\n");
959 goto err_free_thermal;
961 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
963 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
964 if (tacho_active & BIT(i)) {
965 char mfsl_pl[MLXSW_REG_MFSL_LEN];
967 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
969 /* We need to query the register to preserve maximum */
970 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
973 goto err_free_thermal;
975 /* set the minimal RPMs to 0 */
976 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
977 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
980 goto err_free_thermal;
983 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
984 if (pwm_active & BIT(i)) {
985 struct thermal_cooling_device *cdev;
987 cdev = thermal_cooling_device_register("mlxsw_fan",
992 dev_err(dev, "Failed to register cooling device\n");
993 goto err_unreg_cdevs;
995 thermal->cdevs[i] = cdev;
999 /* Initialize cooling levels per PWM state. */
1000 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
1001 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
1004 thermal->polling_delay = bus_info->low_frequency ?
1005 MLXSW_THERMAL_SLOW_POLL_INT :
1006 MLXSW_THERMAL_POLL_INT;
1008 thermal->tzdev = thermal_zone_device_register("mlxsw",
1009 MLXSW_THERMAL_NUM_TRIPS,
1010 MLXSW_THERMAL_TRIP_MASK,
1014 thermal->polling_delay);
1015 if (IS_ERR(thermal->tzdev)) {
1016 err = PTR_ERR(thermal->tzdev);
1017 dev_err(dev, "Failed to register thermal zone\n");
1018 goto err_unreg_cdevs;
1021 err = mlxsw_thermal_modules_init(dev, core, thermal);
1023 goto err_unreg_tzdev;
1025 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
1027 goto err_unreg_modules_tzdev;
1029 err = thermal_zone_device_enable(thermal->tzdev);
1031 goto err_unreg_gearboxes;
1033 *p_thermal = thermal;
1036 err_unreg_gearboxes:
1037 mlxsw_thermal_gearboxes_fini(thermal);
1038 err_unreg_modules_tzdev:
1039 mlxsw_thermal_modules_fini(thermal);
1041 if (thermal->tzdev) {
1042 thermal_zone_device_unregister(thermal->tzdev);
1043 thermal->tzdev = NULL;
1046 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1047 if (thermal->cdevs[i])
1048 thermal_cooling_device_unregister(thermal->cdevs[i]);
1050 devm_kfree(dev, thermal);
1054 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1058 mlxsw_thermal_gearboxes_fini(thermal);
1059 mlxsw_thermal_modules_fini(thermal);
1060 if (thermal->tzdev) {
1061 thermal_zone_device_unregister(thermal->tzdev);
1062 thermal->tzdev = NULL;
1065 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1066 if (thermal->cdevs[i]) {
1067 thermal_cooling_device_unregister(thermal->cdevs[i]);
1068 thermal->cdevs[i] = NULL;
1072 devm_kfree(thermal->bus_info->dev, thermal);