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_module
*tz
= tzdev
->devdata
;
395 struct mlxsw_thermal
*thermal
= tz
->parent
;
397 if (trip
< 0 || trip
>= MLXSW_THERMAL_NUM_TRIPS
)
400 if (tzdev
== thermal
->tz_highest_dev
)
403 *trend
= THERMAL_TREND_STABLE
;
407 static struct thermal_zone_device_ops mlxsw_thermal_ops
= {
408 .bind
= mlxsw_thermal_bind
,
409 .unbind
= mlxsw_thermal_unbind
,
410 .get_mode
= mlxsw_thermal_get_mode
,
411 .set_mode
= mlxsw_thermal_set_mode
,
412 .get_temp
= mlxsw_thermal_get_temp
,
413 .get_trip_type
= mlxsw_thermal_get_trip_type
,
414 .get_trip_temp
= mlxsw_thermal_get_trip_temp
,
415 .set_trip_temp
= mlxsw_thermal_set_trip_temp
,
416 .get_trip_hyst
= mlxsw_thermal_get_trip_hyst
,
417 .set_trip_hyst
= mlxsw_thermal_set_trip_hyst
,
418 .get_trend
= mlxsw_thermal_trend_get
,
421 static int mlxsw_thermal_module_bind(struct thermal_zone_device
*tzdev
,
422 struct thermal_cooling_device
*cdev
)
424 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
425 struct mlxsw_thermal
*thermal
= tz
->parent
;
428 /* If the cooling device is one of ours bind it */
429 if (mlxsw_get_cooling_device_idx(thermal
, cdev
) < 0)
432 for (i
= 0; i
< MLXSW_THERMAL_NUM_TRIPS
; i
++) {
433 const struct mlxsw_thermal_trip
*trip
= &tz
->trips
[i
];
435 err
= thermal_zone_bind_cooling_device(tzdev
, i
, cdev
,
438 THERMAL_WEIGHT_DEFAULT
);
440 goto err_bind_cooling_device
;
444 err_bind_cooling_device
:
445 for (j
= i
- 1; j
>= 0; j
--)
446 thermal_zone_unbind_cooling_device(tzdev
, j
, cdev
);
450 static int mlxsw_thermal_module_unbind(struct thermal_zone_device
*tzdev
,
451 struct thermal_cooling_device
*cdev
)
453 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
454 struct mlxsw_thermal
*thermal
= tz
->parent
;
458 /* If the cooling device is one of ours unbind it */
459 if (mlxsw_get_cooling_device_idx(thermal
, cdev
) < 0)
462 for (i
= 0; i
< MLXSW_THERMAL_NUM_TRIPS
; i
++) {
463 err
= thermal_zone_unbind_cooling_device(tzdev
, i
, cdev
);
469 static int mlxsw_thermal_module_mode_get(struct thermal_zone_device
*tzdev
,
470 enum thermal_device_mode
*mode
)
472 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
479 static int mlxsw_thermal_module_mode_set(struct thermal_zone_device
*tzdev
,
480 enum thermal_device_mode mode
)
482 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
483 struct mlxsw_thermal
*thermal
= tz
->parent
;
485 mutex_lock(&tzdev
->lock
);
487 if (mode
== THERMAL_DEVICE_ENABLED
)
488 tzdev
->polling_delay
= thermal
->polling_delay
;
490 tzdev
->polling_delay
= 0;
492 mutex_unlock(&tzdev
->lock
);
495 thermal_zone_device_update(tzdev
, THERMAL_EVENT_UNSPECIFIED
);
500 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device
*tzdev
,
503 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
504 struct mlxsw_thermal
*thermal
= tz
->parent
;
505 struct device
*dev
= thermal
->bus_info
->dev
;
506 char mtmp_pl
[MLXSW_REG_MTMP_LEN
];
510 /* Read module temperature. */
511 mlxsw_reg_mtmp_pack(mtmp_pl
, MLXSW_REG_MTMP_MODULE_INDEX_MIN
+
512 tz
->module
, false, false);
513 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mtmp
), mtmp_pl
);
515 /* Do not return error - in case of broken module's sensor
516 * it will cause error message flooding.
519 *p_temp
= (int) temp
;
522 mlxsw_reg_mtmp_unpack(mtmp_pl
, &temp
, NULL
, NULL
);
528 /* Update trip points. */
529 err
= mlxsw_thermal_module_trips_update(dev
, thermal
->core
, tz
);
530 if (!err
&& temp
> 0)
531 mlxsw_thermal_tz_score_update(thermal
, tzdev
, tz
->trips
, temp
);
537 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device
*tzdev
, int trip
,
538 enum thermal_trip_type
*p_type
)
540 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
542 if (trip
< 0 || trip
>= MLXSW_THERMAL_NUM_TRIPS
)
545 *p_type
= tz
->trips
[trip
].type
;
550 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device
*tzdev
,
551 int trip
, int *p_temp
)
553 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
555 if (trip
< 0 || trip
>= MLXSW_THERMAL_NUM_TRIPS
)
558 *p_temp
= tz
->trips
[trip
].temp
;
563 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device
*tzdev
,
566 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
568 if (trip
< 0 || trip
>= MLXSW_THERMAL_NUM_TRIPS
||
569 temp
> tz
->trips
[MLXSW_THERMAL_TEMP_TRIP_CRIT
].temp
)
572 tz
->trips
[trip
].temp
= temp
;
577 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device
*tzdev
, int trip
,
580 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
582 *p_hyst
= tz
->trips
[trip
].hyst
;
587 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device
*tzdev
, int trip
,
590 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
592 tz
->trips
[trip
].hyst
= hyst
;
596 static struct thermal_zone_device_ops mlxsw_thermal_module_ops
= {
597 .bind
= mlxsw_thermal_module_bind
,
598 .unbind
= mlxsw_thermal_module_unbind
,
599 .get_mode
= mlxsw_thermal_module_mode_get
,
600 .set_mode
= mlxsw_thermal_module_mode_set
,
601 .get_temp
= mlxsw_thermal_module_temp_get
,
602 .get_trip_type
= mlxsw_thermal_module_trip_type_get
,
603 .get_trip_temp
= mlxsw_thermal_module_trip_temp_get
,
604 .set_trip_temp
= mlxsw_thermal_module_trip_temp_set
,
605 .get_trip_hyst
= mlxsw_thermal_module_trip_hyst_get
,
606 .set_trip_hyst
= mlxsw_thermal_module_trip_hyst_set
,
607 .get_trend
= mlxsw_thermal_trend_get
,
610 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device
*tzdev
,
613 struct mlxsw_thermal_module
*tz
= tzdev
->devdata
;
614 struct mlxsw_thermal
*thermal
= tz
->parent
;
615 char mtmp_pl
[MLXSW_REG_MTMP_LEN
];
620 index
= MLXSW_REG_MTMP_GBOX_INDEX_MIN
+ tz
->module
;
621 mlxsw_reg_mtmp_pack(mtmp_pl
, index
, false, false);
623 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mtmp
), mtmp_pl
);
627 mlxsw_reg_mtmp_unpack(mtmp_pl
, &temp
, NULL
, NULL
);
629 mlxsw_thermal_tz_score_update(thermal
, tzdev
, tz
->trips
, temp
);
635 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops
= {
636 .bind
= mlxsw_thermal_module_bind
,
637 .unbind
= mlxsw_thermal_module_unbind
,
638 .get_mode
= mlxsw_thermal_module_mode_get
,
639 .set_mode
= mlxsw_thermal_module_mode_set
,
640 .get_temp
= mlxsw_thermal_gearbox_temp_get
,
641 .get_trip_type
= mlxsw_thermal_module_trip_type_get
,
642 .get_trip_temp
= mlxsw_thermal_module_trip_temp_get
,
643 .set_trip_temp
= mlxsw_thermal_module_trip_temp_set
,
644 .get_trip_hyst
= mlxsw_thermal_module_trip_hyst_get
,
645 .set_trip_hyst
= mlxsw_thermal_module_trip_hyst_set
,
646 .get_trend
= mlxsw_thermal_trend_get
,
649 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device
*cdev
,
650 unsigned long *p_state
)
652 *p_state
= MLXSW_THERMAL_MAX_STATE
;
656 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device
*cdev
,
657 unsigned long *p_state
)
660 struct mlxsw_thermal
*thermal
= cdev
->devdata
;
661 struct device
*dev
= thermal
->bus_info
->dev
;
662 char mfsc_pl
[MLXSW_REG_MFSC_LEN
];
666 idx
= mlxsw_get_cooling_device_idx(thermal
, cdev
);
670 mlxsw_reg_mfsc_pack(mfsc_pl
, idx
, 0);
671 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mfsc
), mfsc_pl
);
673 dev_err(dev
, "Failed to query PWM duty\n");
677 duty
= mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl
);
678 *p_state
= mlxsw_duty_to_state(duty
);
682 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device
*cdev
,
686 struct mlxsw_thermal
*thermal
= cdev
->devdata
;
687 struct device
*dev
= thermal
->bus_info
->dev
;
688 char mfsc_pl
[MLXSW_REG_MFSC_LEN
];
689 unsigned long cur_state
, i
;
694 idx
= mlxsw_get_cooling_device_idx(thermal
, cdev
);
698 /* Verify if this request is for changing allowed fan dynamical
699 * minimum. If it is - update cooling levels accordingly and update
700 * state, if current state is below the newly requested minimum state.
701 * For example, if current state is 5, and minimal state is to be
702 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
703 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
706 if (state
>= MLXSW_THERMAL_SPEED_MIN
&&
707 state
<= MLXSW_THERMAL_SPEED_MAX
) {
708 state
-= MLXSW_THERMAL_MAX_STATE
;
709 for (i
= 0; i
<= MLXSW_THERMAL_MAX_STATE
; i
++)
710 thermal
->cooling_levels
[i
] = max(state
, i
);
712 mlxsw_reg_mfsc_pack(mfsc_pl
, idx
, 0);
713 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mfsc
), mfsc_pl
);
717 duty
= mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl
);
718 cur_state
= mlxsw_duty_to_state(duty
);
720 /* If current fan state is lower than requested dynamical
721 * minimum, increase fan speed up to dynamical minimum.
723 if (state
< cur_state
)
729 if (state
> MLXSW_THERMAL_MAX_STATE
)
732 /* Normalize the state to the valid speed range. */
733 state
= thermal
->cooling_levels
[state
];
734 mlxsw_reg_mfsc_pack(mfsc_pl
, idx
, mlxsw_state_to_duty(state
));
735 err
= mlxsw_reg_write(thermal
->core
, MLXSW_REG(mfsc
), mfsc_pl
);
737 dev_err(dev
, "Failed to write PWM duty\n");
743 static const struct thermal_cooling_device_ops mlxsw_cooling_ops
= {
744 .get_max_state
= mlxsw_thermal_get_max_state
,
745 .get_cur_state
= mlxsw_thermal_get_cur_state
,
746 .set_cur_state
= mlxsw_thermal_set_cur_state
,
750 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module
*module_tz
)
752 char tz_name
[MLXSW_THERMAL_ZONE_MAX_NAME
];
755 snprintf(tz_name
, sizeof(tz_name
), "mlxsw-module%d",
756 module_tz
->module
+ 1);
757 module_tz
->tzdev
= thermal_zone_device_register(tz_name
,
758 MLXSW_THERMAL_NUM_TRIPS
,
759 MLXSW_THERMAL_TRIP_MASK
,
761 &mlxsw_thermal_module_ops
,
763 if (IS_ERR(module_tz
->tzdev
)) {
764 err
= PTR_ERR(module_tz
->tzdev
);
768 module_tz
->mode
= THERMAL_DEVICE_ENABLED
;
772 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device
*tzdev
)
774 thermal_zone_device_unregister(tzdev
);
778 mlxsw_thermal_module_init(struct device
*dev
, struct mlxsw_core
*core
,
779 struct mlxsw_thermal
*thermal
, u8 module
)
781 struct mlxsw_thermal_module
*module_tz
;
783 module_tz
= &thermal
->tz_module_arr
[module
];
784 /* Skip if parent is already set (case of port split). */
785 if (module_tz
->parent
)
787 module_tz
->module
= module
;
788 module_tz
->parent
= thermal
;
789 memcpy(module_tz
->trips
, default_thermal_trips
,
790 sizeof(thermal
->trips
));
791 /* Initialize all trip point. */
792 mlxsw_thermal_module_trips_reset(module_tz
);
793 /* Update trip point according to the module data. */
794 return mlxsw_thermal_module_trips_update(dev
, core
, module_tz
);
797 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module
*module_tz
)
799 if (module_tz
&& module_tz
->tzdev
) {
800 mlxsw_thermal_module_tz_fini(module_tz
->tzdev
);
801 module_tz
->tzdev
= NULL
;
802 module_tz
->parent
= NULL
;
807 mlxsw_thermal_modules_init(struct device
*dev
, struct mlxsw_core
*core
,
808 struct mlxsw_thermal
*thermal
)
810 struct mlxsw_thermal_module
*module_tz
;
811 char mgpir_pl
[MLXSW_REG_MGPIR_LEN
];
814 if (!mlxsw_core_res_query_enabled(core
))
817 mlxsw_reg_mgpir_pack(mgpir_pl
);
818 err
= mlxsw_reg_query(core
, MLXSW_REG(mgpir
), mgpir_pl
);
822 mlxsw_reg_mgpir_unpack(mgpir_pl
, NULL
, NULL
, NULL
,
823 &thermal
->tz_module_num
);
825 thermal
->tz_module_arr
= kcalloc(thermal
->tz_module_num
,
826 sizeof(*thermal
->tz_module_arr
),
828 if (!thermal
->tz_module_arr
)
831 for (i
= 0; i
< thermal
->tz_module_num
; i
++) {
832 err
= mlxsw_thermal_module_init(dev
, core
, thermal
, i
);
834 goto err_unreg_tz_module_arr
;
837 for (i
= 0; i
< thermal
->tz_module_num
; i
++) {
838 module_tz
= &thermal
->tz_module_arr
[i
];
839 if (!module_tz
->parent
)
841 err
= mlxsw_thermal_module_tz_init(module_tz
);
843 goto err_unreg_tz_module_arr
;
848 err_unreg_tz_module_arr
:
849 for (i
= thermal
->tz_module_num
- 1; i
>= 0; i
--)
850 mlxsw_thermal_module_fini(&thermal
->tz_module_arr
[i
]);
851 kfree(thermal
->tz_module_arr
);
856 mlxsw_thermal_modules_fini(struct mlxsw_thermal
*thermal
)
860 if (!mlxsw_core_res_query_enabled(thermal
->core
))
863 for (i
= thermal
->tz_module_num
- 1; i
>= 0; i
--)
864 mlxsw_thermal_module_fini(&thermal
->tz_module_arr
[i
]);
865 kfree(thermal
->tz_module_arr
);
869 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module
*gearbox_tz
)
871 char tz_name
[MLXSW_THERMAL_ZONE_MAX_NAME
];
873 snprintf(tz_name
, sizeof(tz_name
), "mlxsw-gearbox%d",
874 gearbox_tz
->module
+ 1);
875 gearbox_tz
->tzdev
= thermal_zone_device_register(tz_name
,
876 MLXSW_THERMAL_NUM_TRIPS
,
877 MLXSW_THERMAL_TRIP_MASK
,
879 &mlxsw_thermal_gearbox_ops
,
881 if (IS_ERR(gearbox_tz
->tzdev
))
882 return PTR_ERR(gearbox_tz
->tzdev
);
884 gearbox_tz
->mode
= THERMAL_DEVICE_ENABLED
;
889 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module
*gearbox_tz
)
891 thermal_zone_device_unregister(gearbox_tz
->tzdev
);
895 mlxsw_thermal_gearboxes_init(struct device
*dev
, struct mlxsw_core
*core
,
896 struct mlxsw_thermal
*thermal
)
898 struct mlxsw_thermal_module
*gearbox_tz
;
899 char mgpir_pl
[MLXSW_REG_MGPIR_LEN
];
903 if (!mlxsw_core_res_query_enabled(core
))
906 mlxsw_reg_mgpir_pack(mgpir_pl
);
907 err
= mlxsw_reg_query(core
, MLXSW_REG(mgpir
), mgpir_pl
);
911 mlxsw_reg_mgpir_unpack(mgpir_pl
, &thermal
->tz_gearbox_num
, NULL
, NULL
,
913 if (!thermal
->tz_gearbox_num
)
916 thermal
->tz_gearbox_arr
= kcalloc(thermal
->tz_gearbox_num
,
917 sizeof(*thermal
->tz_gearbox_arr
),
919 if (!thermal
->tz_gearbox_arr
)
922 for (i
= 0; i
< thermal
->tz_gearbox_num
; i
++) {
923 gearbox_tz
= &thermal
->tz_gearbox_arr
[i
];
924 memcpy(gearbox_tz
->trips
, default_thermal_trips
,
925 sizeof(thermal
->trips
));
926 gearbox_tz
->module
= i
;
927 gearbox_tz
->parent
= thermal
;
928 err
= mlxsw_thermal_gearbox_tz_init(gearbox_tz
);
930 goto err_unreg_tz_gearbox
;
935 err_unreg_tz_gearbox
:
936 for (i
--; i
>= 0; i
--)
937 mlxsw_thermal_gearbox_tz_fini(&thermal
->tz_gearbox_arr
[i
]);
938 kfree(thermal
->tz_gearbox_arr
);
943 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal
*thermal
)
947 if (!mlxsw_core_res_query_enabled(thermal
->core
))
950 for (i
= thermal
->tz_gearbox_num
- 1; i
>= 0; i
--)
951 mlxsw_thermal_gearbox_tz_fini(&thermal
->tz_gearbox_arr
[i
]);
952 kfree(thermal
->tz_gearbox_arr
);
955 int mlxsw_thermal_init(struct mlxsw_core
*core
,
956 const struct mlxsw_bus_info
*bus_info
,
957 struct mlxsw_thermal
**p_thermal
)
959 char mfcr_pl
[MLXSW_REG_MFCR_LEN
] = { 0 };
960 enum mlxsw_reg_mfcr_pwm_frequency freq
;
961 struct device
*dev
= bus_info
->dev
;
962 struct mlxsw_thermal
*thermal
;
967 thermal
= devm_kzalloc(dev
, sizeof(*thermal
),
972 thermal
->core
= core
;
973 thermal
->bus_info
= bus_info
;
974 memcpy(thermal
->trips
, default_thermal_trips
, sizeof(thermal
->trips
));
976 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mfcr
), mfcr_pl
);
978 dev_err(dev
, "Failed to probe PWMs\n");
979 goto err_free_thermal
;
981 mlxsw_reg_mfcr_unpack(mfcr_pl
, &freq
, &tacho_active
, &pwm_active
);
983 for (i
= 0; i
< MLXSW_MFCR_TACHOS_MAX
; i
++) {
984 if (tacho_active
& BIT(i
)) {
985 char mfsl_pl
[MLXSW_REG_MFSL_LEN
];
987 mlxsw_reg_mfsl_pack(mfsl_pl
, i
, 0, 0);
989 /* We need to query the register to preserve maximum */
990 err
= mlxsw_reg_query(thermal
->core
, MLXSW_REG(mfsl
),
993 goto err_free_thermal
;
995 /* set the minimal RPMs to 0 */
996 mlxsw_reg_mfsl_tach_min_set(mfsl_pl
, 0);
997 err
= mlxsw_reg_write(thermal
->core
, MLXSW_REG(mfsl
),
1000 goto err_free_thermal
;
1003 for (i
= 0; i
< MLXSW_MFCR_PWMS_MAX
; i
++) {
1004 if (pwm_active
& BIT(i
)) {
1005 struct thermal_cooling_device
*cdev
;
1007 cdev
= thermal_cooling_device_register("mlxsw_fan",
1009 &mlxsw_cooling_ops
);
1011 err
= PTR_ERR(cdev
);
1012 dev_err(dev
, "Failed to register cooling device\n");
1013 goto err_unreg_cdevs
;
1015 thermal
->cdevs
[i
] = cdev
;
1019 /* Initialize cooling levels per PWM state. */
1020 for (i
= 0; i
< MLXSW_THERMAL_MAX_STATE
; i
++)
1021 thermal
->cooling_levels
[i
] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL
,
1024 thermal
->polling_delay
= bus_info
->low_frequency
?
1025 MLXSW_THERMAL_SLOW_POLL_INT
:
1026 MLXSW_THERMAL_POLL_INT
;
1028 thermal
->tzdev
= thermal_zone_device_register("mlxsw",
1029 MLXSW_THERMAL_NUM_TRIPS
,
1030 MLXSW_THERMAL_TRIP_MASK
,
1034 thermal
->polling_delay
);
1035 if (IS_ERR(thermal
->tzdev
)) {
1036 err
= PTR_ERR(thermal
->tzdev
);
1037 dev_err(dev
, "Failed to register thermal zone\n");
1038 goto err_unreg_cdevs
;
1041 err
= mlxsw_thermal_modules_init(dev
, core
, thermal
);
1043 goto err_unreg_tzdev
;
1045 err
= mlxsw_thermal_gearboxes_init(dev
, core
, thermal
);
1047 goto err_unreg_modules_tzdev
;
1049 thermal
->mode
= THERMAL_DEVICE_ENABLED
;
1050 *p_thermal
= thermal
;
1053 err_unreg_modules_tzdev
:
1054 mlxsw_thermal_modules_fini(thermal
);
1056 if (thermal
->tzdev
) {
1057 thermal_zone_device_unregister(thermal
->tzdev
);
1058 thermal
->tzdev
= NULL
;
1061 for (i
= 0; i
< MLXSW_MFCR_PWMS_MAX
; i
++)
1062 if (thermal
->cdevs
[i
])
1063 thermal_cooling_device_unregister(thermal
->cdevs
[i
]);
1065 devm_kfree(dev
, thermal
);
1069 void mlxsw_thermal_fini(struct mlxsw_thermal
*thermal
)
1073 mlxsw_thermal_gearboxes_fini(thermal
);
1074 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
]);
1083 thermal
->cdevs
[i
] = NULL
;
1087 devm_kfree(thermal
->bus_info
->dev
, thermal
);