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_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,
47 MLXSW_THERMAL_TEMP_TRIP_CRIT,
50 struct mlxsw_thermal_trip {
58 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
59 { /* In range - 0-40% PWM */
60 .type = THERMAL_TRIP_ACTIVE,
61 .temp = MLXSW_THERMAL_ASIC_TEMP_NORM,
62 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
64 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
67 /* In range - 40-100% PWM */
68 .type = THERMAL_TRIP_ACTIVE,
69 .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH,
70 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
71 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
72 .max_state = MLXSW_THERMAL_MAX_STATE,
75 .type = THERMAL_TRIP_HOT,
76 .temp = MLXSW_THERMAL_ASIC_TEMP_HOT,
77 .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP,
78 .min_state = MLXSW_THERMAL_MAX_STATE,
79 .max_state = MLXSW_THERMAL_MAX_STATE,
81 { /* Critical - soft poweroff */
82 .type = THERMAL_TRIP_CRITICAL,
83 .temp = MLXSW_THERMAL_ASIC_TEMP_CRIT,
84 .min_state = MLXSW_THERMAL_MAX_STATE,
85 .max_state = MLXSW_THERMAL_MAX_STATE,
89 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
91 /* Make sure all trips are writable */
92 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
96 struct mlxsw_thermal_module {
97 struct mlxsw_thermal *parent;
98 struct thermal_zone_device *tzdev;
99 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
100 enum thermal_device_mode mode;
104 struct mlxsw_thermal {
105 struct mlxsw_core *core;
106 const struct mlxsw_bus_info *bus_info;
107 struct thermal_zone_device *tzdev;
109 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
110 u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
111 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
112 enum thermal_device_mode mode;
113 struct mlxsw_thermal_module *tz_module_arr;
116 static inline u8 mlxsw_state_to_duty(int state)
118 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
119 MLXSW_THERMAL_MAX_STATE);
122 static inline int mlxsw_duty_to_state(u8 duty)
124 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
125 MLXSW_THERMAL_MAX_DUTY);
128 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
129 struct thermal_cooling_device *cdev)
133 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
134 if (thermal->cdevs[i] == cdev)
137 /* Allow mlxsw thermal zone binding to an external cooling device */
138 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
139 if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
148 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
150 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
151 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
152 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
153 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0;
157 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
158 struct mlxsw_thermal_module *tz)
160 int crit_temp, emerg_temp;
163 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
169 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
175 /* According to the system thermal requirements, the thermal zones are
176 * defined with four trip points. The critical and emergency
177 * temperature thresholds, provided by QSFP module are set as "active"
178 * and "hot" trip points, "normal" and "critical" trip points are
179 * derived from "active" and "hot" by subtracting or adding double
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;
189 if (emerg_temp > crit_temp)
190 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
191 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
193 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
198 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
199 struct thermal_cooling_device *cdev)
201 struct mlxsw_thermal *thermal = tzdev->devdata;
202 struct device *dev = thermal->bus_info->dev;
205 /* If the cooling device is one of ours bind it */
206 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
209 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
210 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
212 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
215 THERMAL_WEIGHT_DEFAULT);
217 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
224 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
225 struct thermal_cooling_device *cdev)
227 struct mlxsw_thermal *thermal = tzdev->devdata;
228 struct device *dev = thermal->bus_info->dev;
232 /* If the cooling device is our one unbind it */
233 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
236 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
237 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
239 dev_err(dev, "Failed to unbind cooling device\n");
246 static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
247 enum thermal_device_mode *mode)
249 struct mlxsw_thermal *thermal = tzdev->devdata;
251 *mode = thermal->mode;
256 static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
257 enum thermal_device_mode mode)
259 struct mlxsw_thermal *thermal = tzdev->devdata;
261 mutex_lock(&tzdev->lock);
263 if (mode == THERMAL_DEVICE_ENABLED)
264 tzdev->polling_delay = thermal->polling_delay;
266 tzdev->polling_delay = 0;
268 mutex_unlock(&tzdev->lock);
270 thermal->mode = mode;
271 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
276 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
279 struct mlxsw_thermal *thermal = tzdev->devdata;
280 struct device *dev = thermal->bus_info->dev;
281 char mtmp_pl[MLXSW_REG_MTMP_LEN];
285 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
287 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
289 dev_err(dev, "Failed to query temp sensor\n");
292 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
294 *p_temp = (int) temp;
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 ||
329 temp > MLXSW_THERMAL_ASIC_TEMP_CRIT)
332 thermal->trips[trip].temp = temp;
336 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
337 int trip, int *p_hyst)
339 struct mlxsw_thermal *thermal = tzdev->devdata;
341 *p_hyst = thermal->trips[trip].hyst;
345 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
348 struct mlxsw_thermal *thermal = tzdev->devdata;
350 thermal->trips[trip].hyst = hyst;
354 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
355 .bind = mlxsw_thermal_bind,
356 .unbind = mlxsw_thermal_unbind,
357 .get_mode = mlxsw_thermal_get_mode,
358 .set_mode = mlxsw_thermal_set_mode,
359 .get_temp = mlxsw_thermal_get_temp,
360 .get_trip_type = mlxsw_thermal_get_trip_type,
361 .get_trip_temp = mlxsw_thermal_get_trip_temp,
362 .set_trip_temp = mlxsw_thermal_set_trip_temp,
363 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
364 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
367 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
368 struct thermal_cooling_device *cdev)
370 struct mlxsw_thermal_module *tz = tzdev->devdata;
371 struct mlxsw_thermal *thermal = tz->parent;
374 /* If the cooling device is one of ours bind it */
375 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
378 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
379 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
381 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
384 THERMAL_WEIGHT_DEFAULT);
386 goto err_bind_cooling_device;
390 err_bind_cooling_device:
391 for (j = i - 1; j >= 0; j--)
392 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
396 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
397 struct thermal_cooling_device *cdev)
399 struct mlxsw_thermal_module *tz = tzdev->devdata;
400 struct mlxsw_thermal *thermal = tz->parent;
404 /* If the cooling device is one of ours unbind it */
405 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
408 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
409 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
415 static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
416 enum thermal_device_mode *mode)
418 struct mlxsw_thermal_module *tz = tzdev->devdata;
425 static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
426 enum thermal_device_mode mode)
428 struct mlxsw_thermal_module *tz = tzdev->devdata;
429 struct mlxsw_thermal *thermal = tz->parent;
431 mutex_lock(&tzdev->lock);
433 if (mode == THERMAL_DEVICE_ENABLED)
434 tzdev->polling_delay = thermal->polling_delay;
436 tzdev->polling_delay = 0;
438 mutex_unlock(&tzdev->lock);
441 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
446 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
449 struct mlxsw_thermal_module *tz = tzdev->devdata;
450 struct mlxsw_thermal *thermal = tz->parent;
451 struct device *dev = thermal->bus_info->dev;
452 char mtbr_pl[MLXSW_REG_MTBR_LEN];
456 /* Read module temperature. */
457 mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX +
459 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtbr), mtbr_pl);
463 mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
464 /* Update temperature. */
466 case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
467 case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
468 case MLXSW_REG_MTBR_INDEX_NA: /* fall-through */
469 case MLXSW_REG_MTBR_BAD_SENS_INFO:
473 temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
474 /* Reset all trip point. */
475 mlxsw_thermal_module_trips_reset(tz);
476 /* Update trip points. */
477 err = mlxsw_thermal_module_trips_update(dev, thermal->core,
484 *p_temp = (int) temp;
489 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
490 enum thermal_trip_type *p_type)
492 struct mlxsw_thermal_module *tz = tzdev->devdata;
494 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
497 *p_type = tz->trips[trip].type;
502 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
503 int trip, int *p_temp)
505 struct mlxsw_thermal_module *tz = tzdev->devdata;
507 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
510 *p_temp = tz->trips[trip].temp;
515 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
518 struct mlxsw_thermal_module *tz = tzdev->devdata;
520 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
521 temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp)
524 tz->trips[trip].temp = temp;
529 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
532 struct mlxsw_thermal_module *tz = tzdev->devdata;
534 *p_hyst = tz->trips[trip].hyst;
539 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
542 struct mlxsw_thermal_module *tz = tzdev->devdata;
544 tz->trips[trip].hyst = hyst;
548 static struct thermal_zone_params mlxsw_thermal_module_params = {
549 .governor_name = "user_space",
552 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
553 .bind = mlxsw_thermal_module_bind,
554 .unbind = mlxsw_thermal_module_unbind,
555 .get_mode = mlxsw_thermal_module_mode_get,
556 .set_mode = mlxsw_thermal_module_mode_set,
557 .get_temp = mlxsw_thermal_module_temp_get,
558 .get_trip_type = mlxsw_thermal_module_trip_type_get,
559 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
560 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
561 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
562 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
565 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
566 unsigned long *p_state)
568 *p_state = MLXSW_THERMAL_MAX_STATE;
572 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
573 unsigned long *p_state)
576 struct mlxsw_thermal *thermal = cdev->devdata;
577 struct device *dev = thermal->bus_info->dev;
578 char mfsc_pl[MLXSW_REG_MFSC_LEN];
582 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
586 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
587 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
589 dev_err(dev, "Failed to query PWM duty\n");
593 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
594 *p_state = mlxsw_duty_to_state(duty);
598 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
602 struct mlxsw_thermal *thermal = cdev->devdata;
603 struct device *dev = thermal->bus_info->dev;
604 char mfsc_pl[MLXSW_REG_MFSC_LEN];
605 unsigned long cur_state, i;
610 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
614 /* Verify if this request is for changing allowed fan dynamical
615 * minimum. If it is - update cooling levels accordingly and update
616 * state, if current state is below the newly requested minimum state.
617 * For example, if current state is 5, and minimal state is to be
618 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
619 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
622 if (state >= MLXSW_THERMAL_SPEED_MIN &&
623 state <= MLXSW_THERMAL_SPEED_MAX) {
624 state -= MLXSW_THERMAL_MAX_STATE;
625 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
626 thermal->cooling_levels[i] = max(state, i);
628 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
629 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
633 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
634 cur_state = mlxsw_duty_to_state(duty);
636 /* If current fan state is lower than requested dynamical
637 * minimum, increase fan speed up to dynamical minimum.
639 if (state < cur_state)
645 if (state > MLXSW_THERMAL_MAX_STATE)
648 /* Normalize the state to the valid speed range. */
649 state = thermal->cooling_levels[state];
650 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
651 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
653 dev_err(dev, "Failed to write PWM duty\n");
659 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
660 .get_max_state = mlxsw_thermal_get_max_state,
661 .get_cur_state = mlxsw_thermal_get_cur_state,
662 .set_cur_state = mlxsw_thermal_set_cur_state,
666 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
668 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
671 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
672 module_tz->module + 1);
673 module_tz->tzdev = thermal_zone_device_register(tz_name,
674 MLXSW_THERMAL_NUM_TRIPS,
675 MLXSW_THERMAL_TRIP_MASK,
677 &mlxsw_thermal_module_ops,
678 &mlxsw_thermal_module_params,
680 if (IS_ERR(module_tz->tzdev)) {
681 err = PTR_ERR(module_tz->tzdev);
688 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
690 thermal_zone_device_unregister(tzdev);
694 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
695 struct mlxsw_thermal *thermal, u8 local_port)
697 struct mlxsw_thermal_module *module_tz;
698 char pmlp_pl[MLXSW_REG_PMLP_LEN];
702 mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
703 err = mlxsw_reg_query(core, MLXSW_REG(pmlp), pmlp_pl);
707 width = mlxsw_reg_pmlp_width_get(pmlp_pl);
711 module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
712 module_tz = &thermal->tz_module_arr[module];
713 /* Skip if parent is already set (case of port split). */
714 if (module_tz->parent)
716 module_tz->module = module;
717 module_tz->parent = thermal;
718 memcpy(module_tz->trips, default_thermal_trips,
719 sizeof(thermal->trips));
720 /* Initialize all trip point. */
721 mlxsw_thermal_module_trips_reset(module_tz);
722 /* Update trip point according to the module data. */
723 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
726 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
728 if (module_tz && module_tz->tzdev) {
729 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
730 module_tz->tzdev = NULL;
731 module_tz->parent = NULL;
736 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
737 struct mlxsw_thermal *thermal)
739 unsigned int module_count = mlxsw_core_max_ports(core);
740 struct mlxsw_thermal_module *module_tz;
743 thermal->tz_module_arr = kcalloc(module_count,
744 sizeof(*thermal->tz_module_arr),
746 if (!thermal->tz_module_arr)
749 for (i = 1; i < module_count; i++) {
750 err = mlxsw_thermal_module_init(dev, core, thermal, i);
752 goto err_unreg_tz_module_arr;
755 for (i = 0; i < module_count - 1; i++) {
756 module_tz = &thermal->tz_module_arr[i];
757 if (!module_tz->parent)
759 err = mlxsw_thermal_module_tz_init(module_tz);
761 goto err_unreg_tz_module_arr;
766 err_unreg_tz_module_arr:
767 for (i = module_count - 1; i >= 0; i--)
768 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
769 kfree(thermal->tz_module_arr);
774 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
776 unsigned int module_count = mlxsw_core_max_ports(thermal->core);
779 for (i = module_count - 1; i >= 0; i--)
780 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
781 kfree(thermal->tz_module_arr);
784 int mlxsw_thermal_init(struct mlxsw_core *core,
785 const struct mlxsw_bus_info *bus_info,
786 struct mlxsw_thermal **p_thermal)
788 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
789 enum mlxsw_reg_mfcr_pwm_frequency freq;
790 struct device *dev = bus_info->dev;
791 struct mlxsw_thermal *thermal;
796 thermal = devm_kzalloc(dev, sizeof(*thermal),
801 thermal->core = core;
802 thermal->bus_info = bus_info;
803 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
805 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
807 dev_err(dev, "Failed to probe PWMs\n");
808 goto err_free_thermal;
810 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
812 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
813 if (tacho_active & BIT(i)) {
814 char mfsl_pl[MLXSW_REG_MFSL_LEN];
816 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
818 /* We need to query the register to preserve maximum */
819 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
822 goto err_free_thermal;
824 /* set the minimal RPMs to 0 */
825 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
826 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
829 goto err_free_thermal;
832 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
833 if (pwm_active & BIT(i)) {
834 struct thermal_cooling_device *cdev;
836 cdev = thermal_cooling_device_register("mlxsw_fan",
841 dev_err(dev, "Failed to register cooling device\n");
842 goto err_unreg_cdevs;
844 thermal->cdevs[i] = cdev;
848 /* Initialize cooling levels per PWM state. */
849 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
850 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
853 thermal->polling_delay = bus_info->low_frequency ?
854 MLXSW_THERMAL_SLOW_POLL_INT :
855 MLXSW_THERMAL_POLL_INT;
857 thermal->tzdev = thermal_zone_device_register("mlxsw",
858 MLXSW_THERMAL_NUM_TRIPS,
859 MLXSW_THERMAL_TRIP_MASK,
863 thermal->polling_delay);
864 if (IS_ERR(thermal->tzdev)) {
865 err = PTR_ERR(thermal->tzdev);
866 dev_err(dev, "Failed to register thermal zone\n");
867 goto err_unreg_cdevs;
870 err = mlxsw_thermal_modules_init(dev, core, thermal);
872 goto err_unreg_tzdev;
874 thermal->mode = THERMAL_DEVICE_ENABLED;
875 *p_thermal = thermal;
879 if (thermal->tzdev) {
880 thermal_zone_device_unregister(thermal->tzdev);
881 thermal->tzdev = NULL;
884 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
885 if (thermal->cdevs[i])
886 thermal_cooling_device_unregister(thermal->cdevs[i]);
888 devm_kfree(dev, thermal);
892 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
896 mlxsw_thermal_modules_fini(thermal);
897 if (thermal->tzdev) {
898 thermal_zone_device_unregister(thermal->tzdev);
899 thermal->tzdev = NULL;
902 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
903 if (thermal->cdevs[i]) {
904 thermal_cooling_device_unregister(thermal->cdevs[i]);
905 thermal->cdevs[i] = NULL;
909 devm_kfree(thermal->bus_info->dev, thermal);