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>
4 */
5
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>
13
14 #include "core.h"
15 #include "core_env.h"
16
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.
34 */
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% */
38
39 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
40 static char * const mlxsw_thermal_external_allowed_cdev[] = {
41 "mlxreg_fan",
42 };
43
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,
49 };
50
51 struct mlxsw_thermal_trip {
52 int type;
53 int temp;
54 int hyst;
55 int min_state;
56 int max_state;
57 };
58
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,
64 .min_state = 0,
65 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
66 },
67 {
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,
74 },
75 { /* Warning */
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,
81 },
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,
87 }
88 };
89
90 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
91
92 /* Make sure all trips are writable */
93 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
94
95 struct mlxsw_thermal;
96
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 */
103 };
104
105 struct mlxsw_thermal {
106 struct mlxsw_core *core;
107 const struct mlxsw_bus_info *bus_info;
108 struct thermal_zone_device *tzdev;
109 int polling_delay;
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;
115 struct mlxsw_thermal_module *tz_gearbox_arr;
116 u8 tz_gearbox_num;
117 unsigned int tz_highest_score;
118 struct thermal_zone_device *tz_highest_dev;
119 };
120
mlxsw_state_to_duty(int state)121 static inline u8 mlxsw_state_to_duty(int state)
122 {
123 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
124 MLXSW_THERMAL_MAX_STATE);
125 }
126
mlxsw_duty_to_state(u8 duty)127 static inline int mlxsw_duty_to_state(u8 duty)
128 {
129 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
130 MLXSW_THERMAL_MAX_DUTY);
131 }
132
mlxsw_get_cooling_device_idx(struct mlxsw_thermal * thermal,struct thermal_cooling_device * cdev)133 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
134 struct thermal_cooling_device *cdev)
135 {
136 int i;
137
138 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
139 if (thermal->cdevs[i] == cdev)
140 return i;
141
142 /* Allow mlxsw thermal zone binding to an external cooling device */
143 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
144 if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i],
145 sizeof(cdev->type)))
146 return 0;
147 }
148
149 return -ENODEV;
150 }
151
152 static void
mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module * tz)153 mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
154 {
155 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0;
156 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0;
157 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0;
158 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0;
159 }
160
161 static int
mlxsw_thermal_module_trips_update(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal_module * tz)162 mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
163 struct mlxsw_thermal_module *tz)
164 {
165 int crit_temp, emerg_temp;
166 int err;
167
168 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
169 SFP_TEMP_HIGH_WARN,
170 &crit_temp);
171 if (err)
172 return err;
173
174 err = mlxsw_env_module_temp_thresholds_get(core, tz->module,
175 SFP_TEMP_HIGH_ALARM,
176 &emerg_temp);
177 if (err)
178 return err;
179
180 /* According to the system thermal requirements, the thermal zones are
181 * defined with four trip points. The critical and emergency
182 * temperature thresholds, provided by QSFP module are set as "active"
183 * and "hot" trip points, "normal" and "critical" trip points are
184 * derived from "active" and "hot" by subtracting or adding double
185 * hysteresis value.
186 */
187 if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
188 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp -
189 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
190 else
191 tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
192 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
193 tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
194 if (emerg_temp > crit_temp)
195 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
196 MLXSW_THERMAL_MODULE_TEMP_SHIFT;
197 else
198 tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
199
200 return 0;
201 }
202
mlxsw_thermal_tz_score_update(struct mlxsw_thermal * thermal,struct thermal_zone_device * tzdev,struct mlxsw_thermal_trip * trips,int temp)203 static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal,
204 struct thermal_zone_device *tzdev,
205 struct mlxsw_thermal_trip *trips,
206 int temp)
207 {
208 struct mlxsw_thermal_trip *trip = trips;
209 unsigned int score, delta, i, shift = 1;
210
211 /* Calculate thermal zone score, if temperature is above the critical
212 * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
213 */
214 score = MLXSW_THERMAL_TEMP_SCORE_MAX;
215 for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
216 i++, trip++) {
217 if (temp < trip->temp) {
218 delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
219 score = delta * shift;
220 break;
221 }
222 shift *= 256;
223 }
224
225 if (score > thermal->tz_highest_score) {
226 thermal->tz_highest_score = score;
227 thermal->tz_highest_dev = tzdev;
228 }
229 }
230
mlxsw_thermal_bind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)231 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
232 struct thermal_cooling_device *cdev)
233 {
234 struct mlxsw_thermal *thermal = tzdev->devdata;
235 struct device *dev = thermal->bus_info->dev;
236 int i, err;
237
238 /* If the cooling device is one of ours bind it */
239 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
240 return 0;
241
242 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
243 const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
244
245 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
246 trip->max_state,
247 trip->min_state,
248 THERMAL_WEIGHT_DEFAULT);
249 if (err < 0) {
250 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
251 return err;
252 }
253 }
254 return 0;
255 }
256
mlxsw_thermal_unbind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)257 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
258 struct thermal_cooling_device *cdev)
259 {
260 struct mlxsw_thermal *thermal = tzdev->devdata;
261 struct device *dev = thermal->bus_info->dev;
262 int i;
263 int err;
264
265 /* If the cooling device is our one unbind it */
266 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
267 return 0;
268
269 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
270 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
271 if (err < 0) {
272 dev_err(dev, "Failed to unbind cooling device\n");
273 return err;
274 }
275 }
276 return 0;
277 }
278
mlxsw_thermal_get_mode(struct thermal_zone_device * tzdev,enum thermal_device_mode * mode)279 static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
280 enum thermal_device_mode *mode)
281 {
282 struct mlxsw_thermal *thermal = tzdev->devdata;
283
284 *mode = thermal->mode;
285
286 return 0;
287 }
288
mlxsw_thermal_set_mode(struct thermal_zone_device * tzdev,enum thermal_device_mode mode)289 static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
290 enum thermal_device_mode mode)
291 {
292 struct mlxsw_thermal *thermal = tzdev->devdata;
293
294 mutex_lock(&tzdev->lock);
295
296 if (mode == THERMAL_DEVICE_ENABLED)
297 tzdev->polling_delay = thermal->polling_delay;
298 else
299 tzdev->polling_delay = 0;
300
301 mutex_unlock(&tzdev->lock);
302
303 thermal->mode = mode;
304 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
305
306 return 0;
307 }
308
mlxsw_thermal_get_temp(struct thermal_zone_device * tzdev,int * p_temp)309 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
310 int *p_temp)
311 {
312 struct mlxsw_thermal *thermal = tzdev->devdata;
313 struct device *dev = thermal->bus_info->dev;
314 char mtmp_pl[MLXSW_REG_MTMP_LEN];
315 int temp;
316 int err;
317
318 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
319
320 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
321 if (err) {
322 dev_err(dev, "Failed to query temp sensor\n");
323 return err;
324 }
325 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
326 if (temp > 0)
327 mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips,
328 temp);
329
330 *p_temp = temp;
331 return 0;
332 }
333
mlxsw_thermal_get_trip_type(struct thermal_zone_device * tzdev,int trip,enum thermal_trip_type * p_type)334 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
335 int trip,
336 enum thermal_trip_type *p_type)
337 {
338 struct mlxsw_thermal *thermal = tzdev->devdata;
339
340 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
341 return -EINVAL;
342
343 *p_type = thermal->trips[trip].type;
344 return 0;
345 }
346
mlxsw_thermal_get_trip_temp(struct thermal_zone_device * tzdev,int trip,int * p_temp)347 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
348 int trip, int *p_temp)
349 {
350 struct mlxsw_thermal *thermal = tzdev->devdata;
351
352 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
353 return -EINVAL;
354
355 *p_temp = thermal->trips[trip].temp;
356 return 0;
357 }
358
mlxsw_thermal_set_trip_temp(struct thermal_zone_device * tzdev,int trip,int temp)359 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
360 int trip, int temp)
361 {
362 struct mlxsw_thermal *thermal = tzdev->devdata;
363
364 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
365 temp > MLXSW_THERMAL_ASIC_TEMP_CRIT)
366 return -EINVAL;
367
368 thermal->trips[trip].temp = temp;
369 return 0;
370 }
371
mlxsw_thermal_get_trip_hyst(struct thermal_zone_device * tzdev,int trip,int * p_hyst)372 static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev,
373 int trip, int *p_hyst)
374 {
375 struct mlxsw_thermal *thermal = tzdev->devdata;
376
377 *p_hyst = thermal->trips[trip].hyst;
378 return 0;
379 }
380
mlxsw_thermal_set_trip_hyst(struct thermal_zone_device * tzdev,int trip,int hyst)381 static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
382 int trip, int hyst)
383 {
384 struct mlxsw_thermal *thermal = tzdev->devdata;
385
386 thermal->trips[trip].hyst = hyst;
387 return 0;
388 }
389
mlxsw_thermal_trend_get(struct thermal_zone_device * tzdev,int trip,enum thermal_trend * trend)390 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
391 int trip, enum thermal_trend *trend)
392 {
393 struct mlxsw_thermal_module *tz = tzdev->devdata;
394 struct mlxsw_thermal *thermal = tz->parent;
395
396 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
397 return -EINVAL;
398
399 if (tzdev == thermal->tz_highest_dev)
400 return 1;
401
402 *trend = THERMAL_TREND_STABLE;
403 return 0;
404 }
405
406 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
407 .bind = mlxsw_thermal_bind,
408 .unbind = mlxsw_thermal_unbind,
409 .get_mode = mlxsw_thermal_get_mode,
410 .set_mode = mlxsw_thermal_set_mode,
411 .get_temp = mlxsw_thermal_get_temp,
412 .get_trip_type = mlxsw_thermal_get_trip_type,
413 .get_trip_temp = mlxsw_thermal_get_trip_temp,
414 .set_trip_temp = mlxsw_thermal_set_trip_temp,
415 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
416 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
417 .get_trend = mlxsw_thermal_trend_get,
418 };
419
mlxsw_thermal_module_bind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)420 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
421 struct thermal_cooling_device *cdev)
422 {
423 struct mlxsw_thermal_module *tz = tzdev->devdata;
424 struct mlxsw_thermal *thermal = tz->parent;
425 int i, j, err;
426
427 /* If the cooling device is one of ours bind it */
428 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
429 return 0;
430
431 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
432 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
433
434 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
435 trip->max_state,
436 trip->min_state,
437 THERMAL_WEIGHT_DEFAULT);
438 if (err < 0)
439 goto err_bind_cooling_device;
440 }
441 return 0;
442
443 err_bind_cooling_device:
444 for (j = i - 1; j >= 0; j--)
445 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
446 return err;
447 }
448
mlxsw_thermal_module_unbind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)449 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
450 struct thermal_cooling_device *cdev)
451 {
452 struct mlxsw_thermal_module *tz = tzdev->devdata;
453 struct mlxsw_thermal *thermal = tz->parent;
454 int i;
455 int err;
456
457 /* If the cooling device is one of ours unbind it */
458 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
459 return 0;
460
461 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
462 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
463 WARN_ON(err);
464 }
465 return err;
466 }
467
mlxsw_thermal_module_mode_get(struct thermal_zone_device * tzdev,enum thermal_device_mode * mode)468 static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
469 enum thermal_device_mode *mode)
470 {
471 struct mlxsw_thermal_module *tz = tzdev->devdata;
472
473 *mode = tz->mode;
474
475 return 0;
476 }
477
mlxsw_thermal_module_mode_set(struct thermal_zone_device * tzdev,enum thermal_device_mode mode)478 static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
479 enum thermal_device_mode mode)
480 {
481 struct mlxsw_thermal_module *tz = tzdev->devdata;
482 struct mlxsw_thermal *thermal = tz->parent;
483
484 mutex_lock(&tzdev->lock);
485
486 if (mode == THERMAL_DEVICE_ENABLED)
487 tzdev->polling_delay = thermal->polling_delay;
488 else
489 tzdev->polling_delay = 0;
490
491 mutex_unlock(&tzdev->lock);
492
493 tz->mode = mode;
494 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
495
496 return 0;
497 }
498
mlxsw_thermal_module_temp_get(struct thermal_zone_device * tzdev,int * p_temp)499 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
500 int *p_temp)
501 {
502 struct mlxsw_thermal_module *tz = tzdev->devdata;
503 struct mlxsw_thermal *thermal = tz->parent;
504 struct device *dev = thermal->bus_info->dev;
505 char mtmp_pl[MLXSW_REG_MTMP_LEN];
506 int temp;
507 int err;
508
509 /* Read module temperature. */
510 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN +
511 tz->module, false, false);
512 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
513 if (err) {
514 /* Do not return error - in case of broken module's sensor
515 * it will cause error message flooding.
516 */
517 temp = 0;
518 *p_temp = (int) temp;
519 return 0;
520 }
521 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
522 *p_temp = temp;
523
524 if (!temp)
525 return 0;
526
527 /* Update trip points. */
528 err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
529 if (!err && temp > 0)
530 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
531
532 return 0;
533 }
534
535 static int
mlxsw_thermal_module_trip_type_get(struct thermal_zone_device * tzdev,int trip,enum thermal_trip_type * p_type)536 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
537 enum thermal_trip_type *p_type)
538 {
539 struct mlxsw_thermal_module *tz = tzdev->devdata;
540
541 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
542 return -EINVAL;
543
544 *p_type = tz->trips[trip].type;
545 return 0;
546 }
547
548 static int
mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device * tzdev,int trip,int * p_temp)549 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
550 int trip, int *p_temp)
551 {
552 struct mlxsw_thermal_module *tz = tzdev->devdata;
553
554 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
555 return -EINVAL;
556
557 *p_temp = tz->trips[trip].temp;
558 return 0;
559 }
560
561 static int
mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device * tzdev,int trip,int temp)562 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
563 int trip, int temp)
564 {
565 struct mlxsw_thermal_module *tz = tzdev->devdata;
566
567 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
568 temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp)
569 return -EINVAL;
570
571 tz->trips[trip].temp = temp;
572 return 0;
573 }
574
575 static int
mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device * tzdev,int trip,int * p_hyst)576 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
577 int *p_hyst)
578 {
579 struct mlxsw_thermal_module *tz = tzdev->devdata;
580
581 *p_hyst = tz->trips[trip].hyst;
582 return 0;
583 }
584
585 static int
mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device * tzdev,int trip,int hyst)586 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
587 int hyst)
588 {
589 struct mlxsw_thermal_module *tz = tzdev->devdata;
590
591 tz->trips[trip].hyst = hyst;
592 return 0;
593 }
594
595 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
596 .bind = mlxsw_thermal_module_bind,
597 .unbind = mlxsw_thermal_module_unbind,
598 .get_mode = mlxsw_thermal_module_mode_get,
599 .set_mode = mlxsw_thermal_module_mode_set,
600 .get_temp = mlxsw_thermal_module_temp_get,
601 .get_trip_type = mlxsw_thermal_module_trip_type_get,
602 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
603 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
604 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
605 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
606 .get_trend = mlxsw_thermal_trend_get,
607 };
608
mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device * tzdev,int * p_temp)609 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
610 int *p_temp)
611 {
612 struct mlxsw_thermal_module *tz = tzdev->devdata;
613 struct mlxsw_thermal *thermal = tz->parent;
614 char mtmp_pl[MLXSW_REG_MTMP_LEN];
615 u16 index;
616 int temp;
617 int err;
618
619 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
620 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
621
622 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
623 if (err)
624 return err;
625
626 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
627 if (temp > 0)
628 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
629
630 *p_temp = temp;
631 return 0;
632 }
633
634 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
635 .bind = mlxsw_thermal_module_bind,
636 .unbind = mlxsw_thermal_module_unbind,
637 .get_mode = mlxsw_thermal_module_mode_get,
638 .set_mode = mlxsw_thermal_module_mode_set,
639 .get_temp = mlxsw_thermal_gearbox_temp_get,
640 .get_trip_type = mlxsw_thermal_module_trip_type_get,
641 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
642 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
643 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
644 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
645 .get_trend = mlxsw_thermal_trend_get,
646 };
647
mlxsw_thermal_get_max_state(struct thermal_cooling_device * cdev,unsigned long * p_state)648 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
649 unsigned long *p_state)
650 {
651 *p_state = MLXSW_THERMAL_MAX_STATE;
652 return 0;
653 }
654
mlxsw_thermal_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * p_state)655 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
656 unsigned long *p_state)
657
658 {
659 struct mlxsw_thermal *thermal = cdev->devdata;
660 struct device *dev = thermal->bus_info->dev;
661 char mfsc_pl[MLXSW_REG_MFSC_LEN];
662 int err, idx;
663 u8 duty;
664
665 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
666 if (idx < 0)
667 return idx;
668
669 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
670 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
671 if (err) {
672 dev_err(dev, "Failed to query PWM duty\n");
673 return err;
674 }
675
676 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
677 *p_state = mlxsw_duty_to_state(duty);
678 return 0;
679 }
680
mlxsw_thermal_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)681 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
682 unsigned long state)
683
684 {
685 struct mlxsw_thermal *thermal = cdev->devdata;
686 struct device *dev = thermal->bus_info->dev;
687 char mfsc_pl[MLXSW_REG_MFSC_LEN];
688 unsigned long cur_state, i;
689 int idx;
690 u8 duty;
691 int err;
692
693 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
694 if (idx < 0)
695 return idx;
696
697 /* Verify if this request is for changing allowed fan dynamical
698 * minimum. If it is - update cooling levels accordingly and update
699 * state, if current state is below the newly requested minimum state.
700 * For example, if current state is 5, and minimal state is to be
701 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
702 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
703 * overwritten.
704 */
705 if (state >= MLXSW_THERMAL_SPEED_MIN &&
706 state <= MLXSW_THERMAL_SPEED_MAX) {
707 state -= MLXSW_THERMAL_MAX_STATE;
708 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
709 thermal->cooling_levels[i] = max(state, i);
710
711 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
712 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
713 if (err)
714 return err;
715
716 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
717 cur_state = mlxsw_duty_to_state(duty);
718
719 /* If current fan state is lower than requested dynamical
720 * minimum, increase fan speed up to dynamical minimum.
721 */
722 if (state < cur_state)
723 return 0;
724
725 state = cur_state;
726 }
727
728 if (state > MLXSW_THERMAL_MAX_STATE)
729 return -EINVAL;
730
731 /* Normalize the state to the valid speed range. */
732 state = thermal->cooling_levels[state];
733 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
734 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
735 if (err) {
736 dev_err(dev, "Failed to write PWM duty\n");
737 return err;
738 }
739 return 0;
740 }
741
742 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
743 .get_max_state = mlxsw_thermal_get_max_state,
744 .get_cur_state = mlxsw_thermal_get_cur_state,
745 .set_cur_state = mlxsw_thermal_set_cur_state,
746 };
747
748 static int
mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module * module_tz)749 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
750 {
751 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
752 int err;
753
754 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
755 module_tz->module + 1);
756 module_tz->tzdev = thermal_zone_device_register(tz_name,
757 MLXSW_THERMAL_NUM_TRIPS,
758 MLXSW_THERMAL_TRIP_MASK,
759 module_tz,
760 &mlxsw_thermal_module_ops,
761 NULL, 0, 0);
762 if (IS_ERR(module_tz->tzdev)) {
763 err = PTR_ERR(module_tz->tzdev);
764 return err;
765 }
766
767 module_tz->mode = THERMAL_DEVICE_ENABLED;
768 return 0;
769 }
770
mlxsw_thermal_module_tz_fini(struct thermal_zone_device * tzdev)771 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
772 {
773 thermal_zone_device_unregister(tzdev);
774 }
775
776 static int
mlxsw_thermal_module_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,u8 local_port)777 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
778 struct mlxsw_thermal *thermal, u8 local_port)
779 {
780 struct mlxsw_thermal_module *module_tz;
781 char pmlp_pl[MLXSW_REG_PMLP_LEN];
782 u8 width, module;
783 int err;
784
785 mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
786 err = mlxsw_reg_query(core, MLXSW_REG(pmlp), pmlp_pl);
787 if (err)
788 return err;
789
790 width = mlxsw_reg_pmlp_width_get(pmlp_pl);
791 if (!width)
792 return 0;
793
794 module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
795 module_tz = &thermal->tz_module_arr[module];
796 /* Skip if parent is already set (case of port split). */
797 if (module_tz->parent)
798 return 0;
799 module_tz->module = module;
800 module_tz->parent = thermal;
801 memcpy(module_tz->trips, default_thermal_trips,
802 sizeof(thermal->trips));
803 /* Initialize all trip point. */
804 mlxsw_thermal_module_trips_reset(module_tz);
805 /* Update trip point according to the module data. */
806 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
807 }
808
mlxsw_thermal_module_fini(struct mlxsw_thermal_module * module_tz)809 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
810 {
811 if (module_tz && module_tz->tzdev) {
812 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
813 module_tz->tzdev = NULL;
814 module_tz->parent = NULL;
815 }
816 }
817
818 static int
mlxsw_thermal_modules_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal)819 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
820 struct mlxsw_thermal *thermal)
821 {
822 unsigned int module_count = mlxsw_core_max_ports(core);
823 struct mlxsw_thermal_module *module_tz;
824 int i, err;
825
826 if (!mlxsw_core_res_query_enabled(core))
827 return 0;
828
829 thermal->tz_module_arr = kcalloc(module_count,
830 sizeof(*thermal->tz_module_arr),
831 GFP_KERNEL);
832 if (!thermal->tz_module_arr)
833 return -ENOMEM;
834
835 for (i = 1; i < module_count; i++) {
836 err = mlxsw_thermal_module_init(dev, core, thermal, i);
837 if (err)
838 goto err_unreg_tz_module_arr;
839 }
840
841 for (i = 0; i < module_count - 1; i++) {
842 module_tz = &thermal->tz_module_arr[i];
843 if (!module_tz->parent)
844 continue;
845 err = mlxsw_thermal_module_tz_init(module_tz);
846 if (err)
847 goto err_unreg_tz_module_arr;
848 }
849
850 return 0;
851
852 err_unreg_tz_module_arr:
853 for (i = module_count - 1; i >= 0; i--)
854 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
855 kfree(thermal->tz_module_arr);
856 return err;
857 }
858
859 static void
mlxsw_thermal_modules_fini(struct mlxsw_thermal * thermal)860 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
861 {
862 unsigned int module_count = mlxsw_core_max_ports(thermal->core);
863 int i;
864
865 if (!mlxsw_core_res_query_enabled(thermal->core))
866 return;
867
868 for (i = module_count - 1; i >= 0; i--)
869 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
870 kfree(thermal->tz_module_arr);
871 }
872
873 static int
mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module * gearbox_tz)874 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
875 {
876 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
877
878 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
879 gearbox_tz->module + 1);
880 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
881 MLXSW_THERMAL_NUM_TRIPS,
882 MLXSW_THERMAL_TRIP_MASK,
883 gearbox_tz,
884 &mlxsw_thermal_gearbox_ops,
885 NULL, 0, 0);
886 if (IS_ERR(gearbox_tz->tzdev))
887 return PTR_ERR(gearbox_tz->tzdev);
888
889 gearbox_tz->mode = THERMAL_DEVICE_ENABLED;
890 return 0;
891 }
892
893 static void
mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module * gearbox_tz)894 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
895 {
896 thermal_zone_device_unregister(gearbox_tz->tzdev);
897 }
898
899 static int
mlxsw_thermal_gearboxes_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal)900 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
901 struct mlxsw_thermal *thermal)
902 {
903 struct mlxsw_thermal_module *gearbox_tz;
904 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
905 int i;
906 int err;
907
908 if (!mlxsw_core_res_query_enabled(core))
909 return 0;
910
911 mlxsw_reg_mgpir_pack(mgpir_pl);
912 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
913 if (err)
914 return err;
915
916 mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL);
917 if (!thermal->tz_gearbox_num)
918 return 0;
919
920 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
921 sizeof(*thermal->tz_gearbox_arr),
922 GFP_KERNEL);
923 if (!thermal->tz_gearbox_arr)
924 return -ENOMEM;
925
926 for (i = 0; i < thermal->tz_gearbox_num; i++) {
927 gearbox_tz = &thermal->tz_gearbox_arr[i];
928 memcpy(gearbox_tz->trips, default_thermal_trips,
929 sizeof(thermal->trips));
930 gearbox_tz->module = i;
931 gearbox_tz->parent = thermal;
932 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
933 if (err)
934 goto err_unreg_tz_gearbox;
935 }
936
937 return 0;
938
939 err_unreg_tz_gearbox:
940 for (i--; i >= 0; i--)
941 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
942 kfree(thermal->tz_gearbox_arr);
943 return err;
944 }
945
946 static void
mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal * thermal)947 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
948 {
949 int i;
950
951 if (!mlxsw_core_res_query_enabled(thermal->core))
952 return;
953
954 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
955 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
956 kfree(thermal->tz_gearbox_arr);
957 }
958
mlxsw_thermal_init(struct mlxsw_core * core,const struct mlxsw_bus_info * bus_info,struct mlxsw_thermal ** p_thermal)959 int mlxsw_thermal_init(struct mlxsw_core *core,
960 const struct mlxsw_bus_info *bus_info,
961 struct mlxsw_thermal **p_thermal)
962 {
963 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
964 enum mlxsw_reg_mfcr_pwm_frequency freq;
965 struct device *dev = bus_info->dev;
966 struct mlxsw_thermal *thermal;
967 u16 tacho_active;
968 u8 pwm_active;
969 int err, i;
970
971 thermal = devm_kzalloc(dev, sizeof(*thermal),
972 GFP_KERNEL);
973 if (!thermal)
974 return -ENOMEM;
975
976 thermal->core = core;
977 thermal->bus_info = bus_info;
978 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
979
980 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
981 if (err) {
982 dev_err(dev, "Failed to probe PWMs\n");
983 goto err_free_thermal;
984 }
985 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
986
987 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
988 if (tacho_active & BIT(i)) {
989 char mfsl_pl[MLXSW_REG_MFSL_LEN];
990
991 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
992
993 /* We need to query the register to preserve maximum */
994 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
995 mfsl_pl);
996 if (err)
997 goto err_free_thermal;
998
999 /* set the minimal RPMs to 0 */
1000 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
1001 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
1002 mfsl_pl);
1003 if (err)
1004 goto err_free_thermal;
1005 }
1006 }
1007 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1008 if (pwm_active & BIT(i)) {
1009 struct thermal_cooling_device *cdev;
1010
1011 cdev = thermal_cooling_device_register("mlxsw_fan",
1012 thermal,
1013 &mlxsw_cooling_ops);
1014 if (IS_ERR(cdev)) {
1015 err = PTR_ERR(cdev);
1016 dev_err(dev, "Failed to register cooling device\n");
1017 goto err_unreg_cdevs;
1018 }
1019 thermal->cdevs[i] = cdev;
1020 }
1021 }
1022
1023 /* Initialize cooling levels per PWM state. */
1024 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
1025 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
1026 i);
1027
1028 thermal->polling_delay = bus_info->low_frequency ?
1029 MLXSW_THERMAL_SLOW_POLL_INT :
1030 MLXSW_THERMAL_POLL_INT;
1031
1032 thermal->tzdev = thermal_zone_device_register("mlxsw",
1033 MLXSW_THERMAL_NUM_TRIPS,
1034 MLXSW_THERMAL_TRIP_MASK,
1035 thermal,
1036 &mlxsw_thermal_ops,
1037 NULL, 0,
1038 thermal->polling_delay);
1039 if (IS_ERR(thermal->tzdev)) {
1040 err = PTR_ERR(thermal->tzdev);
1041 dev_err(dev, "Failed to register thermal zone\n");
1042 goto err_unreg_cdevs;
1043 }
1044
1045 err = mlxsw_thermal_modules_init(dev, core, thermal);
1046 if (err)
1047 goto err_unreg_tzdev;
1048
1049 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
1050 if (err)
1051 goto err_unreg_modules_tzdev;
1052
1053 thermal->mode = THERMAL_DEVICE_ENABLED;
1054 *p_thermal = thermal;
1055 return 0;
1056
1057 err_unreg_modules_tzdev:
1058 mlxsw_thermal_modules_fini(thermal);
1059 err_unreg_tzdev:
1060 if (thermal->tzdev) {
1061 thermal_zone_device_unregister(thermal->tzdev);
1062 thermal->tzdev = NULL;
1063 }
1064 err_unreg_cdevs:
1065 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1066 if (thermal->cdevs[i])
1067 thermal_cooling_device_unregister(thermal->cdevs[i]);
1068 err_free_thermal:
1069 devm_kfree(dev, thermal);
1070 return err;
1071 }
1072
mlxsw_thermal_fini(struct mlxsw_thermal * thermal)1073 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1074 {
1075 int i;
1076
1077 mlxsw_thermal_gearboxes_fini(thermal);
1078 mlxsw_thermal_modules_fini(thermal);
1079 if (thermal->tzdev) {
1080 thermal_zone_device_unregister(thermal->tzdev);
1081 thermal->tzdev = NULL;
1082 }
1083
1084 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1085 if (thermal->cdevs[i]) {
1086 thermal_cooling_device_unregister(thermal->cdevs[i]);
1087 thermal->cdevs[i] = NULL;
1088 }
1089 }
1090
1091 devm_kfree(thermal->bus_info->dev, thermal);
1092 }
1093