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 module_tz->parent->polling_delay);
698 if (IS_ERR(module_tz->tzdev)) {
699 err = PTR_ERR(module_tz->tzdev);
703 err = thermal_zone_device_enable(module_tz->tzdev);
705 thermal_zone_device_unregister(module_tz->tzdev);
710 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
712 thermal_zone_device_unregister(tzdev);
716 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
717 struct mlxsw_thermal *thermal, u8 module)
719 struct mlxsw_thermal_module *module_tz;
721 module_tz = &thermal->tz_module_arr[module];
722 /* Skip if parent is already set (case of port split). */
723 if (module_tz->parent)
725 module_tz->module = module;
726 module_tz->parent = thermal;
727 memcpy(module_tz->trips, default_thermal_trips,
728 sizeof(thermal->trips));
729 /* Initialize all trip point. */
730 mlxsw_thermal_module_trips_reset(module_tz);
731 /* Update trip point according to the module data. */
732 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
735 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
737 if (module_tz && module_tz->tzdev) {
738 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
739 module_tz->tzdev = NULL;
740 module_tz->parent = NULL;
745 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
746 struct mlxsw_thermal *thermal)
748 struct mlxsw_thermal_module *module_tz;
749 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
752 if (!mlxsw_core_res_query_enabled(core))
755 mlxsw_reg_mgpir_pack(mgpir_pl);
756 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
760 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
761 &thermal->tz_module_num);
763 thermal->tz_module_arr = kcalloc(thermal->tz_module_num,
764 sizeof(*thermal->tz_module_arr),
766 if (!thermal->tz_module_arr)
769 for (i = 0; i < thermal->tz_module_num; i++) {
770 err = mlxsw_thermal_module_init(dev, core, thermal, i);
772 goto err_unreg_tz_module_arr;
775 for (i = 0; i < thermal->tz_module_num; i++) {
776 module_tz = &thermal->tz_module_arr[i];
777 if (!module_tz->parent)
779 err = mlxsw_thermal_module_tz_init(module_tz);
781 goto err_unreg_tz_module_arr;
786 err_unreg_tz_module_arr:
787 for (i = thermal->tz_module_num - 1; i >= 0; i--)
788 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
789 kfree(thermal->tz_module_arr);
794 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
798 if (!mlxsw_core_res_query_enabled(thermal->core))
801 for (i = thermal->tz_module_num - 1; i >= 0; i--)
802 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
803 kfree(thermal->tz_module_arr);
807 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
809 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
812 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
813 gearbox_tz->module + 1);
814 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
815 MLXSW_THERMAL_NUM_TRIPS,
816 MLXSW_THERMAL_TRIP_MASK,
818 &mlxsw_thermal_gearbox_ops,
820 gearbox_tz->parent->polling_delay);
821 if (IS_ERR(gearbox_tz->tzdev))
822 return PTR_ERR(gearbox_tz->tzdev);
824 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
826 thermal_zone_device_unregister(gearbox_tz->tzdev);
832 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
834 thermal_zone_device_unregister(gearbox_tz->tzdev);
838 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
839 struct mlxsw_thermal *thermal)
841 enum mlxsw_reg_mgpir_device_type device_type;
842 struct mlxsw_thermal_module *gearbox_tz;
843 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
848 if (!mlxsw_core_res_query_enabled(core))
851 mlxsw_reg_mgpir_pack(mgpir_pl);
852 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
856 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
858 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
862 thermal->tz_gearbox_num = gbox_num;
863 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
864 sizeof(*thermal->tz_gearbox_arr),
866 if (!thermal->tz_gearbox_arr)
869 for (i = 0; i < thermal->tz_gearbox_num; i++) {
870 gearbox_tz = &thermal->tz_gearbox_arr[i];
871 memcpy(gearbox_tz->trips, default_thermal_trips,
872 sizeof(thermal->trips));
873 gearbox_tz->module = i;
874 gearbox_tz->parent = thermal;
875 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
877 goto err_unreg_tz_gearbox;
882 err_unreg_tz_gearbox:
883 for (i--; i >= 0; i--)
884 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
885 kfree(thermal->tz_gearbox_arr);
890 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
894 if (!mlxsw_core_res_query_enabled(thermal->core))
897 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
898 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
899 kfree(thermal->tz_gearbox_arr);
902 int mlxsw_thermal_init(struct mlxsw_core *core,
903 const struct mlxsw_bus_info *bus_info,
904 struct mlxsw_thermal **p_thermal)
906 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
907 enum mlxsw_reg_mfcr_pwm_frequency freq;
908 struct device *dev = bus_info->dev;
909 struct mlxsw_thermal *thermal;
914 thermal = devm_kzalloc(dev, sizeof(*thermal),
919 thermal->core = core;
920 thermal->bus_info = bus_info;
921 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
923 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
925 dev_err(dev, "Failed to probe PWMs\n");
926 goto err_free_thermal;
928 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
930 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
931 if (tacho_active & BIT(i)) {
932 char mfsl_pl[MLXSW_REG_MFSL_LEN];
934 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
936 /* We need to query the register to preserve maximum */
937 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
940 goto err_free_thermal;
942 /* set the minimal RPMs to 0 */
943 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
944 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
947 goto err_free_thermal;
950 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
951 if (pwm_active & BIT(i)) {
952 struct thermal_cooling_device *cdev;
954 cdev = thermal_cooling_device_register("mlxsw_fan",
959 dev_err(dev, "Failed to register cooling device\n");
960 goto err_unreg_cdevs;
962 thermal->cdevs[i] = cdev;
966 /* Initialize cooling levels per PWM state. */
967 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
968 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
971 thermal->polling_delay = bus_info->low_frequency ?
972 MLXSW_THERMAL_SLOW_POLL_INT :
973 MLXSW_THERMAL_POLL_INT;
975 thermal->tzdev = thermal_zone_device_register("mlxsw",
976 MLXSW_THERMAL_NUM_TRIPS,
977 MLXSW_THERMAL_TRIP_MASK,
981 thermal->polling_delay);
982 if (IS_ERR(thermal->tzdev)) {
983 err = PTR_ERR(thermal->tzdev);
984 dev_err(dev, "Failed to register thermal zone\n");
985 goto err_unreg_cdevs;
988 err = mlxsw_thermal_modules_init(dev, core, thermal);
990 goto err_unreg_tzdev;
992 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
994 goto err_unreg_modules_tzdev;
996 err = thermal_zone_device_enable(thermal->tzdev);
998 goto err_unreg_gearboxes;
1000 *p_thermal = thermal;
1003 err_unreg_gearboxes:
1004 mlxsw_thermal_gearboxes_fini(thermal);
1005 err_unreg_modules_tzdev:
1006 mlxsw_thermal_modules_fini(thermal);
1008 if (thermal->tzdev) {
1009 thermal_zone_device_unregister(thermal->tzdev);
1010 thermal->tzdev = NULL;
1013 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1014 if (thermal->cdevs[i])
1015 thermal_cooling_device_unregister(thermal->cdevs[i]);
1017 devm_kfree(dev, thermal);
1021 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1025 mlxsw_thermal_gearboxes_fini(thermal);
1026 mlxsw_thermal_modules_fini(thermal);
1027 if (thermal->tzdev) {
1028 thermal_zone_device_unregister(thermal->tzdev);
1029 thermal->tzdev = NULL;
1032 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1033 if (thermal->cdevs[i]) {
1034 thermal_cooling_device_unregister(thermal->cdevs[i]);
1035 thermal->cdevs[i] = NULL;
1039 devm_kfree(thermal->bus_info->dev, thermal);