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)
154 int crit_temp, emerg_temp;
157 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
163 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
169 if (crit_temp > emerg_temp) {
170 dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
171 tz->tzdev->type, crit_temp, emerg_temp);
175 /* According to the system thermal requirements, the thermal zones are
176 * defined with three trip points. The critical and emergency
177 * temperature thresholds, provided by QSFP module are set as "active"
178 * and "hot" trip points, "normal" trip point is derived from "active"
179 * by subtracting double hysteresis value.
181 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
182 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
183 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
185 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
186 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
187 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
192 static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
193 struct thermal_zone_device *tzdev,
194 struct mlxsw_thermal_trip *trips,
197 struct mlxsw_thermal_trip *trip = trips;
198 unsigned int score, delta, i, shift = 1;
200 /* Calculate thermal zone score, if temperature is above the hot
201 * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
203 score = MLXSW_THERMAL_TEMP_SCORE_MAX;
204 for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
206 if (temp < trip->temp) {
207 delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
208 score = delta * shift;
214 if (score > thermal->tz_highest_score) {
215 thermal->tz_highest_score = score;
216 thermal->tz_highest_dev = tzdev;
220 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
221 struct thermal_cooling_device *cdev)
223 struct mlxsw_thermal *thermal = tzdev->devdata;
224 struct device *dev = thermal->bus_info->dev;
227 /* If the cooling device is one of ours bind it */
228 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
231 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
232 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
234 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
237 THERMAL_WEIGHT_DEFAULT);
239 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
246 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
247 struct thermal_cooling_device *cdev)
249 struct mlxsw_thermal *thermal = tzdev->devdata;
250 struct device *dev = thermal->bus_info->dev;
254 /* If the cooling device is our one unbind it */
255 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
258 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
259 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
261 dev_err(dev, "Failed to unbind cooling device\n");
268 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
271 struct mlxsw_thermal *thermal = tzdev->devdata;
272 struct device *dev = thermal->bus_info->dev;
273 char mtmp_pl[MLXSW_REG_MTMP_LEN];
277 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
279 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
281 dev_err(dev, "Failed to query temp sensor\n");
284 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
286 mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
293 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
295 enum thermal_trip_type *p_type)
297 struct mlxsw_thermal *thermal = tzdev->devdata;
299 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
302 *p_type = thermal->trips[trip].type;
306 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
307 int trip, int *p_temp)
309 struct mlxsw_thermal *thermal = tzdev->devdata;
311 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
314 *p_temp = thermal->trips[trip].temp;
318 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
321 struct mlxsw_thermal *thermal = tzdev->devdata;
323 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
326 thermal->trips[trip].temp = temp;
330 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
331 int trip, int *p_hyst)
333 struct mlxsw_thermal *thermal = tzdev->devdata;
335 *p_hyst = thermal->trips[trip].hyst;
339 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
342 struct mlxsw_thermal *thermal = tzdev->devdata;
344 thermal->trips[trip].hyst = hyst;
348 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
349 int trip, enum thermal_trend *trend)
351 struct mlxsw_thermal *thermal = tzdev->devdata;
353 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
356 if (tzdev == thermal->tz_highest_dev)
359 *trend = THERMAL_TREND_STABLE;
363 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
364 .bind = mlxsw_thermal_bind,
365 .unbind = mlxsw_thermal_unbind,
366 .get_temp = mlxsw_thermal_get_temp,
367 .get_trip_type = mlxsw_thermal_get_trip_type,
368 .get_trip_temp = mlxsw_thermal_get_trip_temp,
369 .set_trip_temp = mlxsw_thermal_set_trip_temp,
370 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
371 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
372 .get_trend = mlxsw_thermal_trend_get,
375 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
376 struct thermal_cooling_device *cdev)
378 struct mlxsw_thermal_module *tz = tzdev->devdata;
379 struct mlxsw_thermal *thermal = tz->parent;
382 /* If the cooling device is one of ours bind it */
383 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
386 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
387 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
389 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
392 THERMAL_WEIGHT_DEFAULT);
394 goto err_bind_cooling_device;
398 err_bind_cooling_device:
399 for (j = i - 1; j >= 0; j--)
400 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
404 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
405 struct thermal_cooling_device *cdev)
407 struct mlxsw_thermal_module *tz = tzdev->devdata;
408 struct mlxsw_thermal *thermal = tz->parent;
412 /* If the cooling device is one of ours unbind it */
413 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
416 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
417 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
423 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
426 struct mlxsw_thermal_module *tz = tzdev->devdata;
427 struct mlxsw_thermal *thermal = tz->parent;
428 struct device *dev = thermal->bus_info->dev;
429 char mtmp_pl[MLXSW_REG_MTMP_LEN];
433 /* Read module temperature. */
434 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN +
435 tz->module, false, false);
436 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
438 /* Do not return error - in case of broken module's sensor
439 * it will cause error message flooding.
442 *p_temp = (int) temp;
445 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
451 /* Update trip points. */
452 err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
453 if (!err && temp > 0)
454 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
460 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
461 enum thermal_trip_type *p_type)
463 struct mlxsw_thermal_module *tz = tzdev->devdata;
465 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
468 *p_type = tz->trips[trip].type;
473 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
474 int trip, int *p_temp)
476 struct mlxsw_thermal_module *tz = tzdev->devdata;
478 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
481 *p_temp = tz->trips[trip].temp;
486 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
489 struct mlxsw_thermal_module *tz = tzdev->devdata;
491 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
494 tz->trips[trip].temp = temp;
499 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
502 struct mlxsw_thermal_module *tz = tzdev->devdata;
504 *p_hyst = tz->trips[trip].hyst;
509 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
512 struct mlxsw_thermal_module *tz = tzdev->devdata;
514 tz->trips[trip].hyst = hyst;
518 static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
519 int trip, enum thermal_trend *trend)
521 struct mlxsw_thermal_module *tz = tzdev->devdata;
522 struct mlxsw_thermal *thermal = tz->parent;
524 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
527 if (tzdev == thermal->tz_highest_dev)
530 *trend = THERMAL_TREND_STABLE;
534 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
535 .bind = mlxsw_thermal_module_bind,
536 .unbind = mlxsw_thermal_module_unbind,
537 .get_temp = mlxsw_thermal_module_temp_get,
538 .get_trip_type = mlxsw_thermal_module_trip_type_get,
539 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
540 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
541 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
542 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
543 .get_trend = mlxsw_thermal_module_trend_get,
546 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
549 struct mlxsw_thermal_module *tz = tzdev->devdata;
550 struct mlxsw_thermal *thermal = tz->parent;
551 char mtmp_pl[MLXSW_REG_MTMP_LEN];
556 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
557 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
559 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
563 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
565 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
571 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
572 .bind = mlxsw_thermal_module_bind,
573 .unbind = mlxsw_thermal_module_unbind,
574 .get_temp = mlxsw_thermal_gearbox_temp_get,
575 .get_trip_type = mlxsw_thermal_module_trip_type_get,
576 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
577 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
578 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
579 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
580 .get_trend = mlxsw_thermal_module_trend_get,
583 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
584 unsigned long *p_state)
586 *p_state = MLXSW_THERMAL_MAX_STATE;
590 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
591 unsigned long *p_state)
594 struct mlxsw_thermal *thermal = cdev->devdata;
595 struct device *dev = thermal->bus_info->dev;
596 char mfsc_pl[MLXSW_REG_MFSC_LEN];
600 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
604 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
605 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
607 dev_err(dev, "Failed to query PWM duty\n");
611 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
612 *p_state = mlxsw_duty_to_state(duty);
616 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
620 struct mlxsw_thermal *thermal = cdev->devdata;
621 struct device *dev = thermal->bus_info->dev;
622 char mfsc_pl[MLXSW_REG_MFSC_LEN];
623 unsigned long cur_state, i;
628 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
632 /* Verify if this request is for changing allowed fan dynamical
633 * minimum. If it is - update cooling levels accordingly and update
634 * state, if current state is below the newly requested minimum state.
635 * For example, if current state is 5, and minimal state is to be
636 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
637 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
640 if (state >= MLXSW_THERMAL_SPEED_MIN &&
641 state <= MLXSW_THERMAL_SPEED_MAX) {
642 state -= MLXSW_THERMAL_MAX_STATE;
643 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
644 thermal->cooling_levels[i] = max(state, i);
646 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
647 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
651 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
652 cur_state = mlxsw_duty_to_state(duty);
654 /* If current fan state is lower than requested dynamical
655 * minimum, increase fan speed up to dynamical minimum.
657 if (state < cur_state)
663 if (state > MLXSW_THERMAL_MAX_STATE)
666 /* Normalize the state to the valid speed range. */
667 state = thermal->cooling_levels[state];
668 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
669 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
671 dev_err(dev, "Failed to write PWM duty\n");
677 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
678 .get_max_state = mlxsw_thermal_get_max_state,
679 .get_cur_state = mlxsw_thermal_get_cur_state,
680 .set_cur_state = mlxsw_thermal_set_cur_state,
684 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
686 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
689 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
690 module_tz->module + 1);
691 module_tz->tzdev = thermal_zone_device_register(tz_name,
692 MLXSW_THERMAL_NUM_TRIPS,
693 MLXSW_THERMAL_TRIP_MASK,
695 &mlxsw_thermal_module_ops,
697 if (IS_ERR(module_tz->tzdev)) {
698 err = PTR_ERR(module_tz->tzdev);
702 err = thermal_zone_device_enable(module_tz->tzdev);
704 thermal_zone_device_unregister(module_tz->tzdev);
709 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
711 thermal_zone_device_unregister(tzdev);
715 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
716 struct mlxsw_thermal *thermal, u8 module)
718 struct mlxsw_thermal_module *module_tz;
720 module_tz = &thermal->tz_module_arr[module];
721 /* Skip if parent is already set (case of port split). */
722 if (module_tz->parent)
724 module_tz->module = module;
725 module_tz->parent = thermal;
726 memcpy(module_tz->trips, default_thermal_trips,
727 sizeof(thermal->trips));
728 /* Initialize all trip point. */
729 mlxsw_thermal_module_trips_reset(module_tz);
730 /* Update trip point according to the module data. */
731 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
734 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
736 if (module_tz && module_tz->tzdev) {
737 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
738 module_tz->tzdev = NULL;
739 module_tz->parent = NULL;
744 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
745 struct mlxsw_thermal *thermal)
747 struct mlxsw_thermal_module *module_tz;
748 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
751 if (!mlxsw_core_res_query_enabled(core))
754 mlxsw_reg_mgpir_pack(mgpir_pl);
755 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
759 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
760 &thermal->tz_module_num);
762 thermal->tz_module_arr = kcalloc(thermal->tz_module_num,
763 sizeof(*thermal->tz_module_arr),
765 if (!thermal->tz_module_arr)
768 for (i = 0; i < thermal->tz_module_num; i++) {
769 err = mlxsw_thermal_module_init(dev, core, thermal, i);
771 goto err_unreg_tz_module_arr;
774 for (i = 0; i < thermal->tz_module_num; i++) {
775 module_tz = &thermal->tz_module_arr[i];
776 if (!module_tz->parent)
778 err = mlxsw_thermal_module_tz_init(module_tz);
780 goto err_unreg_tz_module_arr;
785 err_unreg_tz_module_arr:
786 for (i = thermal->tz_module_num - 1; i >= 0; i--)
787 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
788 kfree(thermal->tz_module_arr);
793 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
797 if (!mlxsw_core_res_query_enabled(thermal->core))
800 for (i = thermal->tz_module_num - 1; i >= 0; i--)
801 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
802 kfree(thermal->tz_module_arr);
806 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
808 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
811 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
812 gearbox_tz->module + 1);
813 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
814 MLXSW_THERMAL_NUM_TRIPS,
815 MLXSW_THERMAL_TRIP_MASK,
817 &mlxsw_thermal_gearbox_ops,
819 if (IS_ERR(gearbox_tz->tzdev))
820 return PTR_ERR(gearbox_tz->tzdev);
822 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
824 thermal_zone_device_unregister(gearbox_tz->tzdev);
830 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
832 thermal_zone_device_unregister(gearbox_tz->tzdev);
836 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
837 struct mlxsw_thermal *thermal)
839 enum mlxsw_reg_mgpir_device_type device_type;
840 struct mlxsw_thermal_module *gearbox_tz;
841 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
846 if (!mlxsw_core_res_query_enabled(core))
849 mlxsw_reg_mgpir_pack(mgpir_pl);
850 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
854 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
856 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
860 thermal->tz_gearbox_num = gbox_num;
861 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
862 sizeof(*thermal->tz_gearbox_arr),
864 if (!thermal->tz_gearbox_arr)
867 for (i = 0; i < thermal->tz_gearbox_num; i++) {
868 gearbox_tz = &thermal->tz_gearbox_arr[i];
869 memcpy(gearbox_tz->trips, default_thermal_trips,
870 sizeof(thermal->trips));
871 gearbox_tz->module = i;
872 gearbox_tz->parent = thermal;
873 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
875 goto err_unreg_tz_gearbox;
880 err_unreg_tz_gearbox:
881 for (i--; i >= 0; i--)
882 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
883 kfree(thermal->tz_gearbox_arr);
888 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
892 if (!mlxsw_core_res_query_enabled(thermal->core))
895 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
896 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
897 kfree(thermal->tz_gearbox_arr);
900 int mlxsw_thermal_init(struct mlxsw_core *core,
901 const struct mlxsw_bus_info *bus_info,
902 struct mlxsw_thermal **p_thermal)
904 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
905 enum mlxsw_reg_mfcr_pwm_frequency freq;
906 struct device *dev = bus_info->dev;
907 struct mlxsw_thermal *thermal;
912 thermal = devm_kzalloc(dev, sizeof(*thermal),
917 thermal->core = core;
918 thermal->bus_info = bus_info;
919 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
921 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
923 dev_err(dev, "Failed to probe PWMs\n");
924 goto err_free_thermal;
926 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
928 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
929 if (tacho_active & BIT(i)) {
930 char mfsl_pl[MLXSW_REG_MFSL_LEN];
932 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
934 /* We need to query the register to preserve maximum */
935 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
938 goto err_free_thermal;
940 /* set the minimal RPMs to 0 */
941 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
942 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
945 goto err_free_thermal;
948 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
949 if (pwm_active & BIT(i)) {
950 struct thermal_cooling_device *cdev;
952 cdev = thermal_cooling_device_register("mlxsw_fan",
957 dev_err(dev, "Failed to register cooling device\n");
958 goto err_unreg_cdevs;
960 thermal->cdevs[i] = cdev;
964 /* Initialize cooling levels per PWM state. */
965 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
966 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
969 thermal->polling_delay = bus_info->low_frequency ?
970 MLXSW_THERMAL_SLOW_POLL_INT :
971 MLXSW_THERMAL_POLL_INT;
973 thermal->tzdev = thermal_zone_device_register("mlxsw",
974 MLXSW_THERMAL_NUM_TRIPS,
975 MLXSW_THERMAL_TRIP_MASK,
979 thermal->polling_delay);
980 if (IS_ERR(thermal->tzdev)) {
981 err = PTR_ERR(thermal->tzdev);
982 dev_err(dev, "Failed to register thermal zone\n");
983 goto err_unreg_cdevs;
986 err = mlxsw_thermal_modules_init(dev, core, thermal);
988 goto err_unreg_tzdev;
990 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
992 goto err_unreg_modules_tzdev;
994 err = thermal_zone_device_enable(thermal->tzdev);
996 goto err_unreg_gearboxes;
998 *p_thermal = thermal;
1001 err_unreg_gearboxes:
1002 mlxsw_thermal_gearboxes_fini(thermal);
1003 err_unreg_modules_tzdev:
1004 mlxsw_thermal_modules_fini(thermal);
1006 if (thermal->tzdev) {
1007 thermal_zone_device_unregister(thermal->tzdev);
1008 thermal->tzdev = NULL;
1011 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1012 if (thermal->cdevs[i])
1013 thermal_cooling_device_unregister(thermal->cdevs[i]);
1015 devm_kfree(dev, thermal);
1019 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1023 mlxsw_thermal_gearboxes_fini(thermal);
1024 mlxsw_thermal_modules_fini(thermal);
1025 if (thermal->tzdev) {
1026 thermal_zone_device_unregister(thermal->tzdev);
1027 thermal->tzdev = NULL;
1030 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1031 if (thermal->cdevs[i]) {
1032 thermal_cooling_device_unregister(thermal->cdevs[i]);
1033 thermal->cdevs[i] = NULL;
1037 devm_kfree(thermal->bus_info->dev, thermal);