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_MODULE_TEMP_NORM 55000 /* 55C */
23 #define MLXSW_THERMAL_MODULE_TEMP_HIGH 65000 /* 65C */
24 #define MLXSW_THERMAL_MODULE_TEMP_HOT 80000 /* 80C */
25 #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
26 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
27 #define MLXSW_THERMAL_MAX_STATE 10
28 #define MLXSW_THERMAL_MIN_STATE 2
29 #define MLXSW_THERMAL_MAX_DUTY 255
30
31 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
32 static char * const mlxsw_thermal_external_allowed_cdev[] = {
33 "mlxreg_fan",
34 "emc2305",
35 };
36
37 struct mlxsw_cooling_states {
38 int min_state;
39 int max_state;
40 };
41
42 static const struct thermal_trip default_thermal_trips[] = {
43 { /* In range - 0-40% PWM */
44 .type = THERMAL_TRIP_ACTIVE,
45 .temperature = MLXSW_THERMAL_ASIC_TEMP_NORM,
46 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
47 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
48 },
49 {
50 /* In range - 40-100% PWM */
51 .type = THERMAL_TRIP_ACTIVE,
52 .temperature = MLXSW_THERMAL_ASIC_TEMP_HIGH,
53 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
54 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
55 },
56 { /* Warning */
57 .type = THERMAL_TRIP_HOT,
58 .temperature = MLXSW_THERMAL_ASIC_TEMP_HOT,
59 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
60 },
61 };
62
63 static const struct thermal_trip default_thermal_module_trips[] = {
64 { /* In range - 0-40% PWM */
65 .type = THERMAL_TRIP_ACTIVE,
66 .temperature = MLXSW_THERMAL_MODULE_TEMP_NORM,
67 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
68 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
69 },
70 {
71 /* In range - 40-100% PWM */
72 .type = THERMAL_TRIP_ACTIVE,
73 .temperature = MLXSW_THERMAL_MODULE_TEMP_HIGH,
74 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
75 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
76 },
77 { /* Warning */
78 .type = THERMAL_TRIP_HOT,
79 .temperature = MLXSW_THERMAL_MODULE_TEMP_HOT,
80 .flags = THERMAL_TRIP_FLAG_RW_TEMP,
81 },
82 };
83
84 static const struct mlxsw_cooling_states default_cooling_states[] = {
85 {
86 .min_state = 0,
87 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
88 },
89 {
90 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
91 .max_state = MLXSW_THERMAL_MAX_STATE,
92 },
93 {
94 .min_state = MLXSW_THERMAL_MAX_STATE,
95 .max_state = MLXSW_THERMAL_MAX_STATE,
96 },
97 };
98
99 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
100
101 struct mlxsw_thermal;
102
103 struct mlxsw_thermal_cooling_device {
104 struct mlxsw_thermal *thermal;
105 struct thermal_cooling_device *cdev;
106 unsigned int idx;
107 };
108
109 struct mlxsw_thermal_module {
110 struct mlxsw_thermal *parent;
111 struct thermal_zone_device *tzdev;
112 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
113 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
114 int module; /* Module or gearbox number */
115 u8 slot_index;
116 };
117
118 struct mlxsw_thermal_area {
119 struct mlxsw_thermal_module *tz_module_arr;
120 u8 tz_module_num;
121 struct mlxsw_thermal_module *tz_gearbox_arr;
122 u8 tz_gearbox_num;
123 u8 slot_index;
124 bool active;
125 };
126
127 struct mlxsw_thermal {
128 struct mlxsw_core *core;
129 const struct mlxsw_bus_info *bus_info;
130 struct thermal_zone_device *tzdev;
131 int polling_delay;
132 struct mlxsw_thermal_cooling_device cdevs[MLXSW_MFCR_PWMS_MAX];
133 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
134 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
135 struct mlxsw_thermal_area line_cards[];
136 };
137
mlxsw_state_to_duty(int state)138 static inline u8 mlxsw_state_to_duty(int state)
139 {
140 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
141 MLXSW_THERMAL_MAX_STATE);
142 }
143
mlxsw_duty_to_state(u8 duty)144 static inline int mlxsw_duty_to_state(u8 duty)
145 {
146 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
147 MLXSW_THERMAL_MAX_DUTY);
148 }
149
mlxsw_get_cooling_device_idx(struct mlxsw_thermal * thermal,struct thermal_cooling_device * cdev)150 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
151 struct thermal_cooling_device *cdev)
152 {
153 int i;
154
155 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
156 if (thermal->cdevs[i].cdev == cdev)
157 return i;
158
159 /* Allow mlxsw thermal zone binding to an external cooling device */
160 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
161 if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
162 return 0;
163 }
164
165 return -ENODEV;
166 }
167
mlxsw_thermal_should_bind(struct thermal_zone_device * tzdev,const struct thermal_trip * trip,struct thermal_cooling_device * cdev,struct cooling_spec * c)168 static bool mlxsw_thermal_should_bind(struct thermal_zone_device *tzdev,
169 const struct thermal_trip *trip,
170 struct thermal_cooling_device *cdev,
171 struct cooling_spec *c)
172 {
173 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
174 const struct mlxsw_cooling_states *state = trip->priv;
175
176 /* If the cooling device is one of ours bind it */
177 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
178 return false;
179
180 c->upper = state->max_state;
181 c->lower = state->min_state;
182
183 return true;
184 }
185
mlxsw_thermal_get_temp(struct thermal_zone_device * tzdev,int * p_temp)186 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
187 int *p_temp)
188 {
189 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
190 struct device *dev = thermal->bus_info->dev;
191 char mtmp_pl[MLXSW_REG_MTMP_LEN];
192 int temp;
193 int err;
194
195 mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
196
197 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
198 if (err) {
199 dev_err(dev, "Failed to query temp sensor\n");
200 return err;
201 }
202 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
203
204 *p_temp = temp;
205 return 0;
206 }
207
208 static struct thermal_zone_params mlxsw_thermal_params = {
209 .no_hwmon = true,
210 };
211
212 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
213 .should_bind = mlxsw_thermal_should_bind,
214 .get_temp = mlxsw_thermal_get_temp,
215 };
216
mlxsw_thermal_module_should_bind(struct thermal_zone_device * tzdev,const struct thermal_trip * trip,struct thermal_cooling_device * cdev,struct cooling_spec * c)217 static bool mlxsw_thermal_module_should_bind(struct thermal_zone_device *tzdev,
218 const struct thermal_trip *trip,
219 struct thermal_cooling_device *cdev,
220 struct cooling_spec *c)
221 {
222 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
223 const struct mlxsw_cooling_states *state = trip->priv;
224 struct mlxsw_thermal *thermal = tz->parent;
225
226 /* If the cooling device is one of ours bind it */
227 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
228 return false;
229
230 c->upper = state->max_state;
231 c->lower = state->min_state;
232
233 return true;
234 }
235
mlxsw_thermal_module_temp_get(struct thermal_zone_device * tzdev,int * p_temp)236 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
237 int *p_temp)
238 {
239 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
240 struct mlxsw_thermal *thermal = tz->parent;
241 char mtmp_pl[MLXSW_REG_MTMP_LEN];
242 u16 sensor_index;
243 int err;
244
245 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
246 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, sensor_index,
247 false, false);
248 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
249 if (err)
250 return err;
251 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL);
252 return 0;
253 }
254
255 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
256 .should_bind = mlxsw_thermal_module_should_bind,
257 .get_temp = mlxsw_thermal_module_temp_get,
258 };
259
mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device * tzdev,int * p_temp)260 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
261 int *p_temp)
262 {
263 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
264 struct mlxsw_thermal *thermal = tz->parent;
265 char mtmp_pl[MLXSW_REG_MTMP_LEN];
266 u16 index;
267 int temp;
268 int err;
269
270 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
271 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
272
273 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
274 if (err)
275 return err;
276
277 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
278
279 *p_temp = temp;
280 return 0;
281 }
282
283 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
284 .should_bind = mlxsw_thermal_module_should_bind,
285 .get_temp = mlxsw_thermal_gearbox_temp_get,
286 };
287
mlxsw_thermal_get_max_state(struct thermal_cooling_device * cdev,unsigned long * p_state)288 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
289 unsigned long *p_state)
290 {
291 *p_state = MLXSW_THERMAL_MAX_STATE;
292 return 0;
293 }
294
mlxsw_thermal_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * p_state)295 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
296 unsigned long *p_state)
297
298 {
299 struct mlxsw_thermal_cooling_device *mlxsw_cdev = cdev->devdata;
300 struct mlxsw_thermal *thermal = mlxsw_cdev->thermal;
301 struct device *dev = thermal->bus_info->dev;
302 char mfsc_pl[MLXSW_REG_MFSC_LEN];
303 u8 duty;
304 int err;
305
306 mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_cdev->idx, 0);
307 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
308 if (err) {
309 dev_err(dev, "Failed to query PWM duty\n");
310 return err;
311 }
312
313 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
314 *p_state = mlxsw_duty_to_state(duty);
315 return 0;
316 }
317
mlxsw_thermal_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)318 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
319 unsigned long state)
320
321 {
322 struct mlxsw_thermal_cooling_device *mlxsw_cdev = cdev->devdata;
323 struct mlxsw_thermal *thermal = mlxsw_cdev->thermal;
324 struct device *dev = thermal->bus_info->dev;
325 char mfsc_pl[MLXSW_REG_MFSC_LEN];
326 int err;
327
328 if (state > MLXSW_THERMAL_MAX_STATE)
329 return -EINVAL;
330
331 /* Normalize the state to the valid speed range. */
332 state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
333 mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_cdev->idx,
334 mlxsw_state_to_duty(state));
335 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
336 if (err) {
337 dev_err(dev, "Failed to write PWM duty\n");
338 return err;
339 }
340 return 0;
341 }
342
343 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
344 .get_max_state = mlxsw_thermal_get_max_state,
345 .get_cur_state = mlxsw_thermal_get_cur_state,
346 .set_cur_state = mlxsw_thermal_set_cur_state,
347 };
348
349 static int
mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module * module_tz)350 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
351 {
352 char tz_name[40];
353 int err;
354
355 if (module_tz->slot_index)
356 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
357 module_tz->slot_index, module_tz->module + 1);
358 else
359 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
360 module_tz->module + 1);
361 module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
362 module_tz->trips,
363 MLXSW_THERMAL_NUM_TRIPS,
364 module_tz,
365 &mlxsw_thermal_module_ops,
366 &mlxsw_thermal_params,
367 0,
368 module_tz->parent->polling_delay);
369 if (IS_ERR(module_tz->tzdev)) {
370 err = PTR_ERR(module_tz->tzdev);
371 return err;
372 }
373
374 err = thermal_zone_device_enable(module_tz->tzdev);
375 if (err)
376 thermal_zone_device_unregister(module_tz->tzdev);
377
378 return err;
379 }
380
mlxsw_thermal_module_tz_fini(struct thermal_zone_device * tzdev)381 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
382 {
383 thermal_zone_device_unregister(tzdev);
384 }
385
386 static int
mlxsw_thermal_module_init(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area,u8 module)387 mlxsw_thermal_module_init(struct mlxsw_thermal *thermal,
388 struct mlxsw_thermal_area *area, u8 module)
389 {
390 struct mlxsw_thermal_module *module_tz;
391 int i;
392
393 module_tz = &area->tz_module_arr[module];
394 module_tz->module = module;
395 module_tz->slot_index = area->slot_index;
396 module_tz->parent = thermal;
397 BUILD_BUG_ON(ARRAY_SIZE(default_thermal_module_trips) !=
398 MLXSW_THERMAL_NUM_TRIPS);
399 memcpy(module_tz->trips, default_thermal_module_trips,
400 sizeof(thermal->trips));
401 memcpy(module_tz->cooling_states, default_cooling_states,
402 sizeof(thermal->cooling_states));
403 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++)
404 module_tz->trips[i].priv = &module_tz->cooling_states[i];
405
406 return mlxsw_thermal_module_tz_init(module_tz);
407 }
408
mlxsw_thermal_module_fini(struct mlxsw_thermal_module * module_tz)409 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
410 {
411 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
412 }
413
414 static int
mlxsw_thermal_modules_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)415 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
416 struct mlxsw_thermal *thermal,
417 struct mlxsw_thermal_area *area)
418 {
419 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
420 int i, err;
421
422 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
423 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
424 if (err)
425 return err;
426
427 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
428 &area->tz_module_num, NULL);
429
430 /* For modular system module counter could be zero. */
431 if (!area->tz_module_num)
432 return 0;
433
434 area->tz_module_arr = kcalloc(area->tz_module_num,
435 sizeof(*area->tz_module_arr),
436 GFP_KERNEL);
437 if (!area->tz_module_arr)
438 return -ENOMEM;
439
440 for (i = 0; i < area->tz_module_num; i++) {
441 err = mlxsw_thermal_module_init(thermal, area, i);
442 if (err)
443 goto err_thermal_module_init;
444 }
445
446 return 0;
447
448 err_thermal_module_init:
449 for (i--; i >= 0; i--)
450 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
451 kfree(area->tz_module_arr);
452 return err;
453 }
454
455 static void
mlxsw_thermal_modules_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)456 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
457 struct mlxsw_thermal_area *area)
458 {
459 int i;
460
461 for (i = area->tz_module_num - 1; i >= 0; i--)
462 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
463 kfree(area->tz_module_arr);
464 }
465
466 static int
mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module * gearbox_tz)467 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
468 {
469 char tz_name[40];
470 int ret;
471
472 if (gearbox_tz->slot_index)
473 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
474 gearbox_tz->slot_index, gearbox_tz->module + 1);
475 else
476 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
477 gearbox_tz->module + 1);
478 gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
479 gearbox_tz->trips,
480 MLXSW_THERMAL_NUM_TRIPS,
481 gearbox_tz,
482 &mlxsw_thermal_gearbox_ops,
483 &mlxsw_thermal_params, 0,
484 gearbox_tz->parent->polling_delay);
485 if (IS_ERR(gearbox_tz->tzdev))
486 return PTR_ERR(gearbox_tz->tzdev);
487
488 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
489 if (ret)
490 thermal_zone_device_unregister(gearbox_tz->tzdev);
491
492 return ret;
493 }
494
495 static void
mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module * gearbox_tz)496 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
497 {
498 thermal_zone_device_unregister(gearbox_tz->tzdev);
499 }
500
501 static int
mlxsw_thermal_gearboxes_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)502 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
503 struct mlxsw_thermal *thermal,
504 struct mlxsw_thermal_area *area)
505 {
506 enum mlxsw_reg_mgpir_device_type device_type;
507 struct mlxsw_thermal_module *gearbox_tz;
508 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
509 u8 gbox_num;
510 int i, j;
511 int err;
512
513 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
514 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
515 if (err)
516 return err;
517
518 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
519 NULL, NULL);
520 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
521 !gbox_num)
522 return 0;
523
524 area->tz_gearbox_num = gbox_num;
525 area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
526 sizeof(*area->tz_gearbox_arr),
527 GFP_KERNEL);
528 if (!area->tz_gearbox_arr)
529 return -ENOMEM;
530
531 for (i = 0; i < area->tz_gearbox_num; i++) {
532 gearbox_tz = &area->tz_gearbox_arr[i];
533 memcpy(gearbox_tz->trips, default_thermal_trips,
534 sizeof(thermal->trips));
535 memcpy(gearbox_tz->cooling_states, default_cooling_states,
536 sizeof(thermal->cooling_states));
537 for (j = 0; j < MLXSW_THERMAL_NUM_TRIPS; j++)
538 gearbox_tz->trips[j].priv = &gearbox_tz->cooling_states[j];
539
540 gearbox_tz->module = i;
541 gearbox_tz->parent = thermal;
542 gearbox_tz->slot_index = area->slot_index;
543 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
544 if (err)
545 goto err_thermal_gearbox_tz_init;
546 }
547
548 return 0;
549
550 err_thermal_gearbox_tz_init:
551 for (i--; i >= 0; i--)
552 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
553 kfree(area->tz_gearbox_arr);
554 return err;
555 }
556
557 static void
mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)558 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
559 struct mlxsw_thermal_area *area)
560 {
561 int i;
562
563 for (i = area->tz_gearbox_num - 1; i >= 0; i--)
564 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
565 kfree(area->tz_gearbox_arr);
566 }
567
568 static void
mlxsw_thermal_got_active(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)569 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
570 void *priv)
571 {
572 struct mlxsw_thermal *thermal = priv;
573 struct mlxsw_thermal_area *linecard;
574 int err;
575
576 linecard = &thermal->line_cards[slot_index];
577
578 if (linecard->active)
579 return;
580
581 linecard->slot_index = slot_index;
582 err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
583 thermal, linecard);
584 if (err) {
585 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
586 slot_index);
587 return;
588 }
589
590 err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
591 thermal->core, thermal, linecard);
592 if (err) {
593 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
594 slot_index);
595 goto err_thermal_linecard_gearboxes_init;
596 }
597
598 linecard->active = true;
599
600 return;
601
602 err_thermal_linecard_gearboxes_init:
603 mlxsw_thermal_modules_fini(thermal, linecard);
604 }
605
606 static void
mlxsw_thermal_got_inactive(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)607 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
608 void *priv)
609 {
610 struct mlxsw_thermal *thermal = priv;
611 struct mlxsw_thermal_area *linecard;
612
613 linecard = &thermal->line_cards[slot_index];
614 if (!linecard->active)
615 return;
616 linecard->active = false;
617 mlxsw_thermal_gearboxes_fini(thermal, linecard);
618 mlxsw_thermal_modules_fini(thermal, linecard);
619 }
620
621 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
622 .got_active = mlxsw_thermal_got_active,
623 .got_inactive = mlxsw_thermal_got_inactive,
624 };
625
mlxsw_thermal_init(struct mlxsw_core * core,const struct mlxsw_bus_info * bus_info,struct mlxsw_thermal ** p_thermal)626 int mlxsw_thermal_init(struct mlxsw_core *core,
627 const struct mlxsw_bus_info *bus_info,
628 struct mlxsw_thermal **p_thermal)
629 {
630 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
631 enum mlxsw_reg_mfcr_pwm_frequency freq;
632 struct device *dev = bus_info->dev;
633 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
634 struct mlxsw_thermal *thermal;
635 u8 pwm_active, num_of_slots;
636 u16 tacho_active;
637 int err, i;
638
639 mlxsw_reg_mgpir_pack(mgpir_pl, 0);
640 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
641 if (err)
642 return err;
643
644 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
645 &num_of_slots);
646
647 thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
648 GFP_KERNEL);
649 if (!thermal)
650 return -ENOMEM;
651
652 thermal->core = core;
653 thermal->bus_info = bus_info;
654 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
655 memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
656 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++)
657 thermal->trips[i].priv = &thermal->cooling_states[i];
658
659 thermal->line_cards[0].slot_index = 0;
660
661 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
662 if (err) {
663 dev_err(dev, "Failed to probe PWMs\n");
664 goto err_reg_query;
665 }
666 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
667
668 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
669 if (tacho_active & BIT(i)) {
670 char mfsl_pl[MLXSW_REG_MFSL_LEN];
671
672 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
673
674 /* We need to query the register to preserve maximum */
675 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
676 mfsl_pl);
677 if (err)
678 goto err_reg_query;
679
680 /* set the minimal RPMs to 0 */
681 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
682 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
683 mfsl_pl);
684 if (err)
685 goto err_reg_write;
686 }
687 }
688 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
689 if (pwm_active & BIT(i)) {
690 struct mlxsw_thermal_cooling_device *mlxsw_cdev;
691 struct thermal_cooling_device *cdev;
692
693 mlxsw_cdev = &thermal->cdevs[i];
694 mlxsw_cdev->thermal = thermal;
695 mlxsw_cdev->idx = i;
696 cdev = thermal_cooling_device_register("mlxsw_fan",
697 mlxsw_cdev,
698 &mlxsw_cooling_ops);
699 if (IS_ERR(cdev)) {
700 err = PTR_ERR(cdev);
701 dev_err(dev, "Failed to register cooling device\n");
702 goto err_thermal_cooling_device_register;
703 }
704 mlxsw_cdev->cdev = cdev;
705 }
706 }
707
708 thermal->polling_delay = bus_info->low_frequency ?
709 MLXSW_THERMAL_SLOW_POLL_INT :
710 MLXSW_THERMAL_POLL_INT;
711
712 thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw",
713 thermal->trips,
714 MLXSW_THERMAL_NUM_TRIPS,
715 thermal,
716 &mlxsw_thermal_ops,
717 &mlxsw_thermal_params, 0,
718 thermal->polling_delay);
719 if (IS_ERR(thermal->tzdev)) {
720 err = PTR_ERR(thermal->tzdev);
721 dev_err(dev, "Failed to register thermal zone\n");
722 goto err_thermal_zone_device_register;
723 }
724
725 err = mlxsw_thermal_modules_init(dev, core, thermal,
726 &thermal->line_cards[0]);
727 if (err)
728 goto err_thermal_modules_init;
729
730 err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
731 &thermal->line_cards[0]);
732 if (err)
733 goto err_thermal_gearboxes_init;
734
735 err = mlxsw_linecards_event_ops_register(core,
736 &mlxsw_thermal_event_ops,
737 thermal);
738 if (err)
739 goto err_linecards_event_ops_register;
740
741 err = thermal_zone_device_enable(thermal->tzdev);
742 if (err)
743 goto err_thermal_zone_device_enable;
744
745 thermal->line_cards[0].active = true;
746 *p_thermal = thermal;
747 return 0;
748
749 err_thermal_zone_device_enable:
750 mlxsw_linecards_event_ops_unregister(thermal->core,
751 &mlxsw_thermal_event_ops,
752 thermal);
753 err_linecards_event_ops_register:
754 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
755 err_thermal_gearboxes_init:
756 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
757 err_thermal_modules_init:
758 thermal_zone_device_unregister(thermal->tzdev);
759 err_thermal_zone_device_register:
760 err_thermal_cooling_device_register:
761 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
762 thermal_cooling_device_unregister(thermal->cdevs[i].cdev);
763 err_reg_write:
764 err_reg_query:
765 kfree(thermal);
766 return err;
767 }
768
mlxsw_thermal_fini(struct mlxsw_thermal * thermal)769 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
770 {
771 int i;
772
773 thermal->line_cards[0].active = false;
774 mlxsw_linecards_event_ops_unregister(thermal->core,
775 &mlxsw_thermal_event_ops,
776 thermal);
777 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
778 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
779 thermal_zone_device_unregister(thermal->tzdev);
780
781 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
782 thermal_cooling_device_unregister(thermal->cdevs[i].cdev);
783
784 kfree(thermal);
785 }
786