This source file includes following definitions.
- mlxsw_state_to_duty
- mlxsw_duty_to_state
- mlxsw_get_cooling_device_idx
- mlxsw_thermal_module_trips_reset
- mlxsw_thermal_module_trips_update
- mlxsw_thermal_tz_score_update
- mlxsw_thermal_bind
- mlxsw_thermal_unbind
- mlxsw_thermal_get_mode
- mlxsw_thermal_set_mode
- mlxsw_thermal_get_temp
- mlxsw_thermal_get_trip_type
- mlxsw_thermal_get_trip_temp
- mlxsw_thermal_set_trip_temp
- mlxsw_thermal_get_trip_hyst
- mlxsw_thermal_set_trip_hyst
- mlxsw_thermal_trend_get
- mlxsw_thermal_module_bind
- mlxsw_thermal_module_unbind
- mlxsw_thermal_module_mode_get
- mlxsw_thermal_module_mode_set
- mlxsw_thermal_module_temp_get
- mlxsw_thermal_module_trip_type_get
- mlxsw_thermal_module_trip_temp_get
- mlxsw_thermal_module_trip_temp_set
- mlxsw_thermal_module_trip_hyst_get
- mlxsw_thermal_module_trip_hyst_set
- mlxsw_thermal_module_trend_get
- mlxsw_thermal_gearbox_temp_get
- mlxsw_thermal_get_max_state
- mlxsw_thermal_get_cur_state
- mlxsw_thermal_set_cur_state
- mlxsw_thermal_module_tz_init
- mlxsw_thermal_module_tz_fini
- mlxsw_thermal_module_init
- mlxsw_thermal_module_fini
- mlxsw_thermal_modules_init
- mlxsw_thermal_modules_fini
- mlxsw_thermal_gearbox_tz_init
- mlxsw_thermal_gearbox_tz_fini
- mlxsw_thermal_gearboxes_init
- mlxsw_thermal_gearboxes_fini
- mlxsw_thermal_init
- mlxsw_thermal_fini
1
2
3
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
18 #define MLXSW_THERMAL_SLOW_POLL_INT 20000
19 #define MLXSW_THERMAL_ASIC_TEMP_NORM 75000
20 #define MLXSW_THERMAL_ASIC_TEMP_HIGH 85000
21 #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000
22 #define MLXSW_THERMAL_ASIC_TEMP_CRIT 110000
23 #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000
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
30
31
32
33
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
38
39
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 {
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
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 {
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 {
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
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;
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
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
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
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
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
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
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
181
182
183
184
185
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
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
212
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
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
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
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
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
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
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
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
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
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
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
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
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
390 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
391 int trip, enum thermal_trend *trend)
392 {
393 struct mlxsw_thermal *thermal = tzdev->devdata;
394
395 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
396 return -EINVAL;
397
398 if (tzdev == thermal->tz_highest_dev)
399 return 1;
400
401 *trend = THERMAL_TREND_STABLE;
402 return 0;
403 }
404
405 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
406 .bind = mlxsw_thermal_bind,
407 .unbind = mlxsw_thermal_unbind,
408 .get_mode = mlxsw_thermal_get_mode,
409 .set_mode = mlxsw_thermal_set_mode,
410 .get_temp = mlxsw_thermal_get_temp,
411 .get_trip_type = mlxsw_thermal_get_trip_type,
412 .get_trip_temp = mlxsw_thermal_get_trip_temp,
413 .set_trip_temp = mlxsw_thermal_set_trip_temp,
414 .get_trip_hyst = mlxsw_thermal_get_trip_hyst,
415 .set_trip_hyst = mlxsw_thermal_set_trip_hyst,
416 .get_trend = mlxsw_thermal_trend_get,
417 };
418
419 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
420 struct thermal_cooling_device *cdev)
421 {
422 struct mlxsw_thermal_module *tz = tzdev->devdata;
423 struct mlxsw_thermal *thermal = tz->parent;
424 int i, j, err;
425
426
427 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
428 return 0;
429
430 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
431 const struct mlxsw_thermal_trip *trip = &tz->trips[i];
432
433 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
434 trip->max_state,
435 trip->min_state,
436 THERMAL_WEIGHT_DEFAULT);
437 if (err < 0)
438 goto err_bind_cooling_device;
439 }
440 return 0;
441
442 err_bind_cooling_device:
443 for (j = i - 1; j >= 0; j--)
444 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
445 return err;
446 }
447
448 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
449 struct thermal_cooling_device *cdev)
450 {
451 struct mlxsw_thermal_module *tz = tzdev->devdata;
452 struct mlxsw_thermal *thermal = tz->parent;
453 int i;
454 int err;
455
456
457 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
458 return 0;
459
460 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
461 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
462 WARN_ON(err);
463 }
464 return err;
465 }
466
467 static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev,
468 enum thermal_device_mode *mode)
469 {
470 struct mlxsw_thermal_module *tz = tzdev->devdata;
471
472 *mode = tz->mode;
473
474 return 0;
475 }
476
477 static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
478 enum thermal_device_mode mode)
479 {
480 struct mlxsw_thermal_module *tz = tzdev->devdata;
481 struct mlxsw_thermal *thermal = tz->parent;
482
483 mutex_lock(&tzdev->lock);
484
485 if (mode == THERMAL_DEVICE_ENABLED)
486 tzdev->polling_delay = thermal->polling_delay;
487 else
488 tzdev->polling_delay = 0;
489
490 mutex_unlock(&tzdev->lock);
491
492 tz->mode = mode;
493 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
494
495 return 0;
496 }
497
498 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
499 int *p_temp)
500 {
501 struct mlxsw_thermal_module *tz = tzdev->devdata;
502 struct mlxsw_thermal *thermal = tz->parent;
503 struct device *dev = thermal->bus_info->dev;
504 char mtmp_pl[MLXSW_REG_MTMP_LEN];
505 int temp;
506 int err;
507
508
509 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN +
510 tz->module, false, false);
511 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
512 if (err) {
513
514
515
516 temp = 0;
517 *p_temp = (int) temp;
518 return 0;
519 }
520 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
521 *p_temp = temp;
522
523 if (!temp)
524 return 0;
525
526
527 err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz);
528 if (!err && temp > 0)
529 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
530
531 return 0;
532 }
533
534 static int
535 mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip,
536 enum thermal_trip_type *p_type)
537 {
538 struct mlxsw_thermal_module *tz = tzdev->devdata;
539
540 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
541 return -EINVAL;
542
543 *p_type = tz->trips[trip].type;
544 return 0;
545 }
546
547 static int
548 mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev,
549 int trip, int *p_temp)
550 {
551 struct mlxsw_thermal_module *tz = tzdev->devdata;
552
553 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
554 return -EINVAL;
555
556 *p_temp = tz->trips[trip].temp;
557 return 0;
558 }
559
560 static int
561 mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev,
562 int trip, int temp)
563 {
564 struct mlxsw_thermal_module *tz = tzdev->devdata;
565
566 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
567 temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp)
568 return -EINVAL;
569
570 tz->trips[trip].temp = temp;
571 return 0;
572 }
573
574 static int
575 mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip,
576 int *p_hyst)
577 {
578 struct mlxsw_thermal_module *tz = tzdev->devdata;
579
580 *p_hyst = tz->trips[trip].hyst;
581 return 0;
582 }
583
584 static int
585 mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
586 int hyst)
587 {
588 struct mlxsw_thermal_module *tz = tzdev->devdata;
589
590 tz->trips[trip].hyst = hyst;
591 return 0;
592 }
593
594 static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
595 int trip, enum thermal_trend *trend)
596 {
597 struct mlxsw_thermal_module *tz = tzdev->devdata;
598 struct mlxsw_thermal *thermal = tz->parent;
599
600 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
601 return -EINVAL;
602
603 if (tzdev == thermal->tz_highest_dev)
604 return 1;
605
606 *trend = THERMAL_TREND_STABLE;
607 return 0;
608 }
609
610 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
611 .bind = mlxsw_thermal_module_bind,
612 .unbind = mlxsw_thermal_module_unbind,
613 .get_mode = mlxsw_thermal_module_mode_get,
614 .set_mode = mlxsw_thermal_module_mode_set,
615 .get_temp = mlxsw_thermal_module_temp_get,
616 .get_trip_type = mlxsw_thermal_module_trip_type_get,
617 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
618 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
619 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
620 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
621 .get_trend = mlxsw_thermal_module_trend_get,
622 };
623
624 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
625 int *p_temp)
626 {
627 struct mlxsw_thermal_module *tz = tzdev->devdata;
628 struct mlxsw_thermal *thermal = tz->parent;
629 char mtmp_pl[MLXSW_REG_MTMP_LEN];
630 u16 index;
631 int temp;
632 int err;
633
634 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
635 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
636
637 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
638 if (err)
639 return err;
640
641 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
642 if (temp > 0)
643 mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp);
644
645 *p_temp = temp;
646 return 0;
647 }
648
649 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
650 .bind = mlxsw_thermal_module_bind,
651 .unbind = mlxsw_thermal_module_unbind,
652 .get_mode = mlxsw_thermal_module_mode_get,
653 .set_mode = mlxsw_thermal_module_mode_set,
654 .get_temp = mlxsw_thermal_gearbox_temp_get,
655 .get_trip_type = mlxsw_thermal_module_trip_type_get,
656 .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
657 .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
658 .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
659 .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
660 .get_trend = mlxsw_thermal_module_trend_get,
661 };
662
663 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
664 unsigned long *p_state)
665 {
666 *p_state = MLXSW_THERMAL_MAX_STATE;
667 return 0;
668 }
669
670 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
671 unsigned long *p_state)
672
673 {
674 struct mlxsw_thermal *thermal = cdev->devdata;
675 struct device *dev = thermal->bus_info->dev;
676 char mfsc_pl[MLXSW_REG_MFSC_LEN];
677 int err, idx;
678 u8 duty;
679
680 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
681 if (idx < 0)
682 return idx;
683
684 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
685 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
686 if (err) {
687 dev_err(dev, "Failed to query PWM duty\n");
688 return err;
689 }
690
691 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
692 *p_state = mlxsw_duty_to_state(duty);
693 return 0;
694 }
695
696 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
697 unsigned long state)
698
699 {
700 struct mlxsw_thermal *thermal = cdev->devdata;
701 struct device *dev = thermal->bus_info->dev;
702 char mfsc_pl[MLXSW_REG_MFSC_LEN];
703 unsigned long cur_state, i;
704 int idx;
705 u8 duty;
706 int err;
707
708 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
709 if (idx < 0)
710 return idx;
711
712
713
714
715
716
717
718
719
720 if (state >= MLXSW_THERMAL_SPEED_MIN &&
721 state <= MLXSW_THERMAL_SPEED_MAX) {
722 state -= MLXSW_THERMAL_MAX_STATE;
723 for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
724 thermal->cooling_levels[i] = max(state, i);
725
726 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
727 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
728 if (err)
729 return err;
730
731 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
732 cur_state = mlxsw_duty_to_state(duty);
733
734
735
736
737 if (state < cur_state)
738 return 0;
739
740 state = cur_state;
741 }
742
743 if (state > MLXSW_THERMAL_MAX_STATE)
744 return -EINVAL;
745
746
747 state = thermal->cooling_levels[state];
748 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
749 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
750 if (err) {
751 dev_err(dev, "Failed to write PWM duty\n");
752 return err;
753 }
754 return 0;
755 }
756
757 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
758 .get_max_state = mlxsw_thermal_get_max_state,
759 .get_cur_state = mlxsw_thermal_get_cur_state,
760 .set_cur_state = mlxsw_thermal_set_cur_state,
761 };
762
763 static int
764 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
765 {
766 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
767 int err;
768
769 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
770 module_tz->module + 1);
771 module_tz->tzdev = thermal_zone_device_register(tz_name,
772 MLXSW_THERMAL_NUM_TRIPS,
773 MLXSW_THERMAL_TRIP_MASK,
774 module_tz,
775 &mlxsw_thermal_module_ops,
776 NULL, 0, 0);
777 if (IS_ERR(module_tz->tzdev)) {
778 err = PTR_ERR(module_tz->tzdev);
779 return err;
780 }
781
782 module_tz->mode = THERMAL_DEVICE_ENABLED;
783 return 0;
784 }
785
786 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
787 {
788 thermal_zone_device_unregister(tzdev);
789 }
790
791 static int
792 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
793 struct mlxsw_thermal *thermal, u8 local_port)
794 {
795 struct mlxsw_thermal_module *module_tz;
796 char pmlp_pl[MLXSW_REG_PMLP_LEN];
797 u8 width, module;
798 int err;
799
800 mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
801 err = mlxsw_reg_query(core, MLXSW_REG(pmlp), pmlp_pl);
802 if (err)
803 return err;
804
805 width = mlxsw_reg_pmlp_width_get(pmlp_pl);
806 if (!width)
807 return 0;
808
809 module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
810 module_tz = &thermal->tz_module_arr[module];
811
812 if (module_tz->parent)
813 return 0;
814 module_tz->module = module;
815 module_tz->parent = thermal;
816 memcpy(module_tz->trips, default_thermal_trips,
817 sizeof(thermal->trips));
818
819 mlxsw_thermal_module_trips_reset(module_tz);
820
821 return mlxsw_thermal_module_trips_update(dev, core, module_tz);
822 }
823
824 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
825 {
826 if (module_tz && module_tz->tzdev) {
827 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
828 module_tz->tzdev = NULL;
829 module_tz->parent = NULL;
830 }
831 }
832
833 static int
834 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
835 struct mlxsw_thermal *thermal)
836 {
837 unsigned int module_count = mlxsw_core_max_ports(core);
838 struct mlxsw_thermal_module *module_tz;
839 int i, err;
840
841 if (!mlxsw_core_res_query_enabled(core))
842 return 0;
843
844 thermal->tz_module_arr = kcalloc(module_count,
845 sizeof(*thermal->tz_module_arr),
846 GFP_KERNEL);
847 if (!thermal->tz_module_arr)
848 return -ENOMEM;
849
850 for (i = 1; i < module_count; i++) {
851 err = mlxsw_thermal_module_init(dev, core, thermal, i);
852 if (err)
853 goto err_unreg_tz_module_arr;
854 }
855
856 for (i = 0; i < module_count - 1; i++) {
857 module_tz = &thermal->tz_module_arr[i];
858 if (!module_tz->parent)
859 continue;
860 err = mlxsw_thermal_module_tz_init(module_tz);
861 if (err)
862 goto err_unreg_tz_module_arr;
863 }
864
865 return 0;
866
867 err_unreg_tz_module_arr:
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 return err;
872 }
873
874 static void
875 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
876 {
877 unsigned int module_count = mlxsw_core_max_ports(thermal->core);
878 int i;
879
880 if (!mlxsw_core_res_query_enabled(thermal->core))
881 return;
882
883 for (i = module_count - 1; i >= 0; i--)
884 mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
885 kfree(thermal->tz_module_arr);
886 }
887
888 static int
889 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
890 {
891 char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
892
893 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
894 gearbox_tz->module + 1);
895 gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
896 MLXSW_THERMAL_NUM_TRIPS,
897 MLXSW_THERMAL_TRIP_MASK,
898 gearbox_tz,
899 &mlxsw_thermal_gearbox_ops,
900 NULL, 0, 0);
901 if (IS_ERR(gearbox_tz->tzdev))
902 return PTR_ERR(gearbox_tz->tzdev);
903
904 gearbox_tz->mode = THERMAL_DEVICE_ENABLED;
905 return 0;
906 }
907
908 static void
909 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
910 {
911 thermal_zone_device_unregister(gearbox_tz->tzdev);
912 }
913
914 static int
915 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
916 struct mlxsw_thermal *thermal)
917 {
918 struct mlxsw_thermal_module *gearbox_tz;
919 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
920 int i;
921 int err;
922
923 if (!mlxsw_core_res_query_enabled(core))
924 return 0;
925
926 mlxsw_reg_mgpir_pack(mgpir_pl);
927 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
928 if (err)
929 return err;
930
931 mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL);
932 if (!thermal->tz_gearbox_num)
933 return 0;
934
935 thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
936 sizeof(*thermal->tz_gearbox_arr),
937 GFP_KERNEL);
938 if (!thermal->tz_gearbox_arr)
939 return -ENOMEM;
940
941 for (i = 0; i < thermal->tz_gearbox_num; i++) {
942 gearbox_tz = &thermal->tz_gearbox_arr[i];
943 memcpy(gearbox_tz->trips, default_thermal_trips,
944 sizeof(thermal->trips));
945 gearbox_tz->module = i;
946 gearbox_tz->parent = thermal;
947 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
948 if (err)
949 goto err_unreg_tz_gearbox;
950 }
951
952 return 0;
953
954 err_unreg_tz_gearbox:
955 for (i--; i >= 0; i--)
956 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
957 kfree(thermal->tz_gearbox_arr);
958 return err;
959 }
960
961 static void
962 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
963 {
964 int i;
965
966 if (!mlxsw_core_res_query_enabled(thermal->core))
967 return;
968
969 for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
970 mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
971 kfree(thermal->tz_gearbox_arr);
972 }
973
974 int mlxsw_thermal_init(struct mlxsw_core *core,
975 const struct mlxsw_bus_info *bus_info,
976 struct mlxsw_thermal **p_thermal)
977 {
978 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
979 enum mlxsw_reg_mfcr_pwm_frequency freq;
980 struct device *dev = bus_info->dev;
981 struct mlxsw_thermal *thermal;
982 u16 tacho_active;
983 u8 pwm_active;
984 int err, i;
985
986 thermal = devm_kzalloc(dev, sizeof(*thermal),
987 GFP_KERNEL);
988 if (!thermal)
989 return -ENOMEM;
990
991 thermal->core = core;
992 thermal->bus_info = bus_info;
993 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
994
995 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
996 if (err) {
997 dev_err(dev, "Failed to probe PWMs\n");
998 goto err_free_thermal;
999 }
1000 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
1001
1002 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
1003 if (tacho_active & BIT(i)) {
1004 char mfsl_pl[MLXSW_REG_MFSL_LEN];
1005
1006 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
1007
1008
1009 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
1010 mfsl_pl);
1011 if (err)
1012 goto err_free_thermal;
1013
1014
1015 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
1016 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
1017 mfsl_pl);
1018 if (err)
1019 goto err_free_thermal;
1020 }
1021 }
1022 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1023 if (pwm_active & BIT(i)) {
1024 struct thermal_cooling_device *cdev;
1025
1026 cdev = thermal_cooling_device_register("mlxsw_fan",
1027 thermal,
1028 &mlxsw_cooling_ops);
1029 if (IS_ERR(cdev)) {
1030 err = PTR_ERR(cdev);
1031 dev_err(dev, "Failed to register cooling device\n");
1032 goto err_unreg_cdevs;
1033 }
1034 thermal->cdevs[i] = cdev;
1035 }
1036 }
1037
1038
1039 for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
1040 thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
1041 i);
1042
1043 thermal->polling_delay = bus_info->low_frequency ?
1044 MLXSW_THERMAL_SLOW_POLL_INT :
1045 MLXSW_THERMAL_POLL_INT;
1046
1047 thermal->tzdev = thermal_zone_device_register("mlxsw",
1048 MLXSW_THERMAL_NUM_TRIPS,
1049 MLXSW_THERMAL_TRIP_MASK,
1050 thermal,
1051 &mlxsw_thermal_ops,
1052 NULL, 0,
1053 thermal->polling_delay);
1054 if (IS_ERR(thermal->tzdev)) {
1055 err = PTR_ERR(thermal->tzdev);
1056 dev_err(dev, "Failed to register thermal zone\n");
1057 goto err_unreg_cdevs;
1058 }
1059
1060 err = mlxsw_thermal_modules_init(dev, core, thermal);
1061 if (err)
1062 goto err_unreg_tzdev;
1063
1064 err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
1065 if (err)
1066 goto err_unreg_modules_tzdev;
1067
1068 thermal->mode = THERMAL_DEVICE_ENABLED;
1069 *p_thermal = thermal;
1070 return 0;
1071
1072 err_unreg_modules_tzdev:
1073 mlxsw_thermal_modules_fini(thermal);
1074 err_unreg_tzdev:
1075 if (thermal->tzdev) {
1076 thermal_zone_device_unregister(thermal->tzdev);
1077 thermal->tzdev = NULL;
1078 }
1079 err_unreg_cdevs:
1080 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
1081 if (thermal->cdevs[i])
1082 thermal_cooling_device_unregister(thermal->cdevs[i]);
1083 err_free_thermal:
1084 devm_kfree(dev, thermal);
1085 return err;
1086 }
1087
1088 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
1089 {
1090 int i;
1091
1092 mlxsw_thermal_gearboxes_fini(thermal);
1093 mlxsw_thermal_modules_fini(thermal);
1094 if (thermal->tzdev) {
1095 thermal_zone_device_unregister(thermal->tzdev);
1096 thermal->tzdev = NULL;
1097 }
1098
1099 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
1100 if (thermal->cdevs[i]) {
1101 thermal_cooling_device_unregister(thermal->cdevs[i]);
1102 thermal->cdevs[i] = NULL;
1103 }
1104 }
1105
1106 devm_kfree(thermal->bus_info->dev, thermal);
1107 }