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_ASIC_TEMP_CRIT 110000 /* 110C */
23 #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
24 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
25 #define MLXSW_THERMAL_ZONE_MAX_NAME 16
26 #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0)
27 #define MLXSW_THERMAL_MAX_STATE 10
28 #define MLXSW_THERMAL_MAX_DUTY 255
29 /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
30 * MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for
31 * setting fan speed dynamic minimum. For example, if value is set to 14 (40%)
32 * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to
33 * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100.
35 #define MLXSW_THERMAL_SPEED_MIN (MLXSW_THERMAL_MAX_STATE + 2)
36 #define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2)
37 #define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */
39 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
40 static char * const mlxsw_thermal_external_allowed_cdev[] = {
44 enum mlxsw_thermal_trips {
45 MLXSW_THERMAL_TEMP_TRIP_NORM,
46 MLXSW_THERMAL_TEMP_TRIP_HIGH,
47 MLXSW_THERMAL_TEMP_TRIP_HOT,
48 MLXSW_THERMAL_TEMP_TRIP_CRIT,
51 struct mlxsw_thermal_trip {
59 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
60 { /* In range - 0-40% PWM */
61 .type = THERMAL_TRIP_ACTIVE,
62 .temp = MLXSW_THERMAL_ASIC_TEMP_NORM,
63 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
65 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
68 /* In range - 40-100% PWM */
69 .type = THERMAL_TRIP_ACTIVE,
70 .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH,
71 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
72 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
73 .max_state = MLXSW_THERMAL_MAX_STATE,
76 .type = THERMAL_TRIP_HOT,
77 .temp = MLXSW_THERMAL_ASIC_TEMP_HOT,
78 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
79 .min_state = MLXSW_THERMAL_MAX_STATE,
80 .max_state = MLXSW_THERMAL_MAX_STATE,
82 { /* Critical - soft poweroff */
83 .type = THERMAL_TRIP_CRITICAL,
84 .temp = MLXSW_THERMAL_ASIC_TEMP_CRIT,
85 .min_state = MLXSW_THERMAL_MAX_STATE,
86 .max_state = MLXSW_THERMAL_MAX_STATE,
90 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
92 /* Make sure all trips are writable */
93 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
97 struct mlxsw_thermal_module {
98 struct mlxsw_thermal *parent;
99 struct thermal_zone_device *tzdev;
100 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
101 enum thermal_device_mode mode;
102 int module; /* Module or gearbox number */
105 struct mlxsw_thermal {
106 struct mlxsw_core *core;
107 const struct mlxsw_bus_info *bus_info;
108 struct thermal_zone_device *tzdev;
110 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
111 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
112 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
113 enum thermal_device_mode mode;
114 struct mlxsw_thermal_module *tz_module_arr;
116 struct mlxsw_thermal_module *tz_gearbox_arr;
118 unsigned int tz_highest_score;
119 struct thermal_zone_device *tz_highest_dev;
122 static inline u8 mlxsw_state_to_duty(int state)
124 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
125 MLXSW_THERMAL_MAX_STATE);
128 static inline int mlxsw_duty_to_state(u8 duty)
130 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
131 MLXSW_THERMAL_MAX_DUTY);
134 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
135 struct thermal_cooling_device *cdev)
139 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
140 if (thermal->cdevs[i] == cdev)
143 /* Allow mlxsw thermal zone binding to an external cooling device */
144 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
145 if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
154 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
156 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
157 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
158 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
159 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0;
163 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
164 struct mlxsw_thermal_module *tz)
166 int crit_temp, emerg_temp;
169 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
175 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
181 /* According to the system thermal requirements, the thermal zones are
182 * defined with four trip points. The critical and emergency
183 * temperature thresholds, provided by QSFP module are set as "active"
184 * and "hot" trip points, "normal" and "critical" trip points are
185 * derived from "active" and "hot" by subtracting or adding double
188 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
189 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
190 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
192 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
193 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
194 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
195 if (emerg_temp > crit_temp)
196 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
197 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
199 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
204 static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
205 struct thermal_zone_device *tzdev,
206 struct mlxsw_thermal_trip *trips,
209 struct mlxsw_thermal_trip *trip = trips;
210 unsigned int score, delta, i, shift = 1;
212 /* Calculate thermal zone score, if temperature is above the critical
213 * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
215 score = MLXSW_THERMAL_TEMP_SCORE_MAX;
216 for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
218 if (temp < trip->temp) {
219 delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
220 score = delta * shift;
226 if (score > thermal->tz_highest_score) {
227 thermal->tz_highest_score = score;
228 thermal->tz_highest_dev = tzdev;
232 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
233 struct thermal_cooling_device *cdev)
235 struct mlxsw_thermal *thermal = tzdev->devdata;
236 struct device *dev = thermal->bus_info->dev;
239 /* If the cooling device is one of ours bind it */
240 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
243 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
244 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
246 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
249 THERMAL_WEIGHT_DEFAULT);
251 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
258 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
259 struct thermal_cooling_device *cdev)
261 struct mlxsw_thermal *thermal = tzdev->devdata;
262 struct device *dev = thermal->bus_info->dev;
266 /* If the cooling device is our one unbind it */
267 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
270 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
271 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
273 dev_err(dev, "Failed to unbind cooling device\n");
280 static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
281 enum thermal_device_mode *mode)
283 struct mlxsw_thermal *thermal = tzdev->devdata;
285 *mode = thermal->mode;
290 static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
291 enum thermal_device_mode mode)
293 struct mlxsw_thermal *thermal = tzdev->devdata;
295 mutex_lock(&tzdev->lock);
297 if (mode == THERMAL_DEVICE_ENABLED)
298 tzdev->polling_delay = thermal->polling_delay;
300 tzdev->polling_delay = 0;
302 mutex_unlock(&tzdev->lock);
304 thermal->mode = mode;
305 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
310 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
313 struct mlxsw_thermal *thermal = tzdev->devdata;
314 struct device *dev = thermal->bus_info->dev;
315 char mtmp_pl[MLXSW_REG_MTMP_LEN];
319 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
321 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
323 dev_err(dev, "Failed to query temp sensor\n");
326 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
328 mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
335 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
337 enum thermal_trip_type *p_type)
339 struct mlxsw_thermal *thermal = tzdev->devdata;
341 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
344 *p_type = thermal->trips[trip].type;
348 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
349 int trip, int *p_temp)
351 struct mlxsw_thermal *thermal = tzdev->devdata;
353 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
356 *p_temp = thermal->trips[trip].temp;
360 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
363 struct mlxsw_thermal *thermal = tzdev->devdata;
365 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
366 temp > MLXSW_THERMAL_ASIC_TEMP_CRIT)
369 thermal->trips[trip].temp = temp;
373 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
374 int trip, int *p_hyst)
376 struct mlxsw_thermal *thermal = tzdev->devdata;
378 *p_hyst = thermal->trips[trip].hyst;
382 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
385 struct mlxsw_thermal *thermal = tzdev->devdata;
387 thermal->trips[trip].hyst = hyst;
391 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
392 int trip, enum thermal_trend *trend)
394 struct mlxsw_thermal *thermal = tzdev->devdata;
396 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
399 if (tzdev == thermal->tz_highest_dev)
402 *trend = THERMAL_TREND_STABLE;
406 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
407 .bind = mlxsw_thermal_bind,
408 .unbind = mlxsw_thermal_unbind,
409 .get_mode = mlxsw_thermal_get_mode,
410 .set_mode = mlxsw_thermal_set_mode,
411 .get_temp = mlxsw_thermal_get_temp,
412 .get_trip_type = mlxsw_thermal_get_trip_type,
413 .get_trip_temp = mlxsw_thermal_get_trip_temp,
414 .set_trip_temp = mlxsw_thermal_set_trip_temp,
415 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
416 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
417 .get_trend = mlxsw_thermal_trend_get,
420 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
421 struct thermal_cooling_device *cdev)
423 struct mlxsw_thermal_module *tz = tzdev->devdata;
424 struct mlxsw_thermal *thermal = tz->parent;
427 /* If the cooling device is one of ours bind it */
428 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
431 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
432 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
434 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
437 THERMAL_WEIGHT_DEFAULT);
439 goto err_bind_cooling_device;
443 err_bind_cooling_device:
444 for (j = i - 1; j >= 0; j--)
445 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
449 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
450 struct thermal_cooling_device *cdev)
452 struct mlxsw_thermal_module *tz = tzdev->devdata;
453 struct mlxsw_thermal *thermal = tz->parent;
457 /* If the cooling device is one of ours unbind it */
458 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
461 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
462 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
468 static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
469 enum thermal_device_mode *mode)
471 struct mlxsw_thermal_module *tz = tzdev->devdata;
478 static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
479 enum thermal_device_mode mode)
481 struct mlxsw_thermal_module *tz = tzdev->devdata;
482 struct mlxsw_thermal *thermal = tz->parent;
484 mutex_lock(&tzdev->lock);
486 if (mode == THERMAL_DEVICE_ENABLED)
487 tzdev->polling_delay = thermal->polling_delay;
489 tzdev->polling_delay = 0;
491 mutex_unlock(&tzdev->lock);
494 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
499 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
502 struct mlxsw_thermal_module *tz = tzdev->devdata;
503 struct mlxsw_thermal *thermal = tz->parent;
504 struct device *dev = thermal->bus_info->dev;
505 char mtmp_pl[MLXSW_REG_MTMP_LEN];
509 /* Read module temperature. */
510 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN +
511 tz->module, false, false);
512 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
514 /* Do not return error - in case of broken module's sensor
515 * it will cause error message flooding.
518 *p_temp = (int) temp;
521 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
527 /* Update trip points. */
528 err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
529 if (!err && temp > 0)
530 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
536 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
537 enum thermal_trip_type *p_type)
539 struct mlxsw_thermal_module *tz = tzdev->devdata;
541 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
544 *p_type = tz->trips[trip].type;
549 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
550 int trip, int *p_temp)
552 struct mlxsw_thermal_module *tz = tzdev->devdata;
554 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
557 *p_temp = tz->trips[trip].temp;
562 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
565 struct mlxsw_thermal_module *tz = tzdev->devdata;
567 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
568 temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp)
571 tz->trips[trip].temp = temp;
576 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
579 struct mlxsw_thermal_module *tz = tzdev->devdata;
581 *p_hyst = tz->trips[trip].hyst;
586 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
589 struct mlxsw_thermal_module *tz = tzdev->devdata;
591 tz->trips[trip].hyst = hyst;
595 static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
596 int trip, enum thermal_trend *trend)
598 struct mlxsw_thermal_module *tz = tzdev->devdata;
599 struct mlxsw_thermal *thermal = tz->parent;
601 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
604 if (tzdev == thermal->tz_highest_dev)
607 *trend = THERMAL_TREND_STABLE;
611 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
612 .bind = mlxsw_thermal_module_bind,
613 .unbind = mlxsw_thermal_module_unbind,
614 .get_mode = mlxsw_thermal_module_mode_get,
615 .set_mode = mlxsw_thermal_module_mode_set,
616 .get_temp = mlxsw_thermal_module_temp_get,
617 .get_trip_type = mlxsw_thermal_module_trip_type_get,
618 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
619 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
620 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
621 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
622 .get_trend = mlxsw_thermal_module_trend_get,
625 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
628 struct mlxsw_thermal_module *tz = tzdev->devdata;
629 struct mlxsw_thermal *thermal = tz->parent;
630 char mtmp_pl[MLXSW_REG_MTMP_LEN];
635 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
636 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
638 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
642 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
644 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
650 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
651 .bind = mlxsw_thermal_module_bind,
652 .unbind = mlxsw_thermal_module_unbind,
653 .get_mode = mlxsw_thermal_module_mode_get,
654 .set_mode = mlxsw_thermal_module_mode_set,
655 .get_temp = mlxsw_thermal_gearbox_temp_get,
656 .get_trip_type = mlxsw_thermal_module_trip_type_get,
657 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
658 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
659 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
660 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
661 .get_trend = mlxsw_thermal_module_trend_get,
664 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
665 unsigned long *p_state)
667 *p_state = MLXSW_THERMAL_MAX_STATE;
671 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
672 unsigned long *p_state)
675 struct mlxsw_thermal *thermal = cdev->devdata;
676 struct device *dev = thermal->bus_info->dev;
677 char mfsc_pl[MLXSW_REG_MFSC_LEN];
681 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
685 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
686 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
688 dev_err(dev, "Failed to query PWM duty\n");
692 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
693 *p_state = mlxsw_duty_to_state(duty);
697 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
701 struct mlxsw_thermal *thermal = cdev->devdata;
702 struct device *dev = thermal->bus_info->dev;
703 char mfsc_pl[MLXSW_REG_MFSC_LEN];
704 unsigned long cur_state, i;
709 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
713 /* Verify if this request is for changing allowed fan dynamical
714 * minimum. If it is - update cooling levels accordingly and update
715 * state, if current state is below the newly requested minimum state.
716 * For example, if current state is 5, and minimal state is to be
717 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
718 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
721 if (state >= MLXSW_THERMAL_SPEED_MIN &&
722 state <= MLXSW_THERMAL_SPEED_MAX) {
723 state -= MLXSW_THERMAL_MAX_STATE;
724 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
725 thermal->cooling_levels[i] = max(state, i);
727 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
728 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
732 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
733 cur_state = mlxsw_duty_to_state(duty);
735 /* If current fan state is lower than requested dynamical
736 * minimum, increase fan speed up to dynamical minimum.
738 if (state < cur_state)
744 if (state > MLXSW_THERMAL_MAX_STATE)
747 /* Normalize the state to the valid speed range. */
748 state = thermal->cooling_levels[state];
749 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
750 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
752 dev_err(dev, "Failed to write PWM duty\n");
758 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
759 .get_max_state = mlxsw_thermal_get_max_state,
760 .get_cur_state = mlxsw_thermal_get_cur_state,
761 .set_cur_state = mlxsw_thermal_set_cur_state,
765 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
767 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
770 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
771 module_tz->module + 1);
772 module_tz->tzdev = thermal_zone_device_register(tz_name,
773 MLXSW_THERMAL_NUM_TRIPS,
774 MLXSW_THERMAL_TRIP_MASK,
776 &mlxsw_thermal_module_ops,
778 if (IS_ERR(module_tz->tzdev)) {
779 err = PTR_ERR(module_tz->tzdev);
783 module_tz->mode = THERMAL_DEVICE_ENABLED;
787 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
789 thermal_zone_device_unregister(tzdev);
793 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
794 struct mlxsw_thermal *thermal, u8 module)
796 struct mlxsw_thermal_module *module_tz;
798 module_tz = &thermal->tz_module_arr[module];
799 /* Skip if parent is already set (case of port split). */
800 if (module_tz->parent)
802 module_tz->module = module;
803 module_tz->parent = thermal;
804 memcpy(module_tz->trips, default_thermal_trips,
805 sizeof(thermal->trips));
806 /* Initialize all trip point. */
807 mlxsw_thermal_module_trips_reset(module_tz);
808 /* Update trip point according to the module data. */
809 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
812 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
814 if (module_tz && module_tz->tzdev) {
815 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
816 module_tz->tzdev = NULL;
817 module_tz->parent = NULL;
822 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
823 struct mlxsw_thermal *thermal)
825 struct mlxsw_thermal_module *module_tz;
826 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
829 if (!mlxsw_core_res_query_enabled(core))
832 mlxsw_reg_mgpir_pack(mgpir_pl);
833 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
837 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
838 &thermal->tz_module_num);
840 thermal->tz_module_arr = kcalloc(thermal->tz_module_num,
841 sizeof(*thermal->tz_module_arr),
843 if (!thermal->tz_module_arr)
846 for (i = 0; i < thermal->tz_module_num; i++) {
847 err = mlxsw_thermal_module_init(dev, core, thermal, i);
849 goto err_unreg_tz_module_arr;
852 for (i = 0; i < thermal->tz_module_num; i++) {
853 module_tz = &thermal->tz_module_arr[i];
854 if (!module_tz->parent)
856 err = mlxsw_thermal_module_tz_init(module_tz);
858 goto err_unreg_tz_module_arr;
863 err_unreg_tz_module_arr:
864 for (i = thermal->tz_module_num - 1; i >= 0; i--)
865 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
866 kfree(thermal->tz_module_arr);
871 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
875 if (!mlxsw_core_res_query_enabled(thermal->core))
878 for (i = thermal->tz_module_num - 1; i >= 0; i--)
879 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
880 kfree(thermal->tz_module_arr);
884 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
886 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
888 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
889 gearbox_tz->module + 1);
890 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
891 MLXSW_THERMAL_NUM_TRIPS,
892 MLXSW_THERMAL_TRIP_MASK,
894 &mlxsw_thermal_gearbox_ops,
896 if (IS_ERR(gearbox_tz->tzdev))
897 return PTR_ERR(gearbox_tz->tzdev);
899 gearbox_tz->mode = THERMAL_DEVICE_ENABLED;
904 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
906 thermal_zone_device_unregister(gearbox_tz->tzdev);
910 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
911 struct mlxsw_thermal *thermal)
913 enum mlxsw_reg_mgpir_device_type device_type;
914 struct mlxsw_thermal_module *gearbox_tz;
915 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
920 if (!mlxsw_core_res_query_enabled(core))
923 mlxsw_reg_mgpir_pack(mgpir_pl);
924 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
928 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
930 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
934 thermal->tz_gearbox_num = gbox_num;
935 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
936 sizeof(*thermal->tz_gearbox_arr),
938 if (!thermal->tz_gearbox_arr)
941 for (i = 0; i < thermal->tz_gearbox_num; i++) {
942 gearbox_tz = &thermal->tz_gearbox_arr[i];
943 memcpy(gearbox_tz->trips, default_thermal_trips,
944 sizeof(thermal->trips));
945 gearbox_tz->module = i;
946 gearbox_tz->parent = thermal;
947 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
949 goto err_unreg_tz_gearbox;
954 err_unreg_tz_gearbox:
955 for (i--; i >= 0; i--)
956 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
957 kfree(thermal->tz_gearbox_arr);
962 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
966 if (!mlxsw_core_res_query_enabled(thermal->core))
969 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
970 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
971 kfree(thermal->tz_gearbox_arr);
974 int mlxsw_thermal_init(struct mlxsw_core *core,
975 const struct mlxsw_bus_info *bus_info,
976 struct mlxsw_thermal **p_thermal)
978 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
979 enum mlxsw_reg_mfcr_pwm_frequency freq;
980 struct device *dev = bus_info->dev;
981 struct mlxsw_thermal *thermal;
986 thermal = devm_kzalloc(dev, sizeof(*thermal),
991 thermal->core = core;
992 thermal->bus_info = bus_info;
993 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
995 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
997 dev_err(dev, "Failed to probe PWMs\n");
998 goto err_free_thermal;
1000 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
1002 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
1003 if (tacho_active & BIT(i)) {
1004 char mfsl_pl[MLXSW_REG_MFSL_LEN];
1006 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
1008 /* We need to query the register to preserve maximum */
1009 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
1012 goto err_free_thermal;
1014 /* set the minimal RPMs to 0 */
1015 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
1016 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
1019 goto err_free_thermal;
1022 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1023 if (pwm_active & BIT(i)) {
1024 struct thermal_cooling_device *cdev;
1026 cdev = thermal_cooling_device_register("mlxsw_fan",
1028 &mlxsw_cooling_ops);
1030 err = PTR_ERR(cdev);
1031 dev_err(dev, "Failed to register cooling device\n");
1032 goto err_unreg_cdevs;
1034 thermal->cdevs[i] = cdev;
1038 /* Initialize cooling levels per PWM state. */
1039 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
1040 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
1043 thermal->polling_delay = bus_info->low_frequency ?
1044 MLXSW_THERMAL_SLOW_POLL_INT :
1045 MLXSW_THERMAL_POLL_INT;
1047 thermal->tzdev = thermal_zone_device_register("mlxsw",
1048 MLXSW_THERMAL_NUM_TRIPS,
1049 MLXSW_THERMAL_TRIP_MASK,
1053 thermal->polling_delay);
1054 if (IS_ERR(thermal->tzdev)) {
1055 err = PTR_ERR(thermal->tzdev);
1056 dev_err(dev, "Failed to register thermal zone\n");
1057 goto err_unreg_cdevs;
1060 err = mlxsw_thermal_modules_init(dev, core, thermal);
1062 goto err_unreg_tzdev;
1064 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
1066 goto err_unreg_modules_tzdev;
1068 thermal->mode = THERMAL_DEVICE_ENABLED;
1069 *p_thermal = thermal;
1072 err_unreg_modules_tzdev:
1073 mlxsw_thermal_modules_fini(thermal);
1075 if (thermal->tzdev) {
1076 thermal_zone_device_unregister(thermal->tzdev);
1077 thermal->tzdev = NULL;
1080 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1081 if (thermal->cdevs[i])
1082 thermal_cooling_device_unregister(thermal->cdevs[i]);
1084 devm_kfree(dev, thermal);
1088 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1092 mlxsw_thermal_gearboxes_fini(thermal);
1093 mlxsw_thermal_modules_fini(thermal);
1094 if (thermal->tzdev) {
1095 thermal_zone_device_unregister(thermal->tzdev);
1096 thermal->tzdev = NULL;
1099 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1100 if (thermal->cdevs[i]) {
1101 thermal_cooling_device_unregister(thermal->cdevs[i]);
1102 thermal->cdevs[i] = NULL;
1106 devm_kfree(thermal->bus_info->dev, thermal);