xref: /linux/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c (revision 189f164e573e18d9f8876dbd3ad8fcbe11f93037)
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 const struct thermal_zone_params mlxsw_thermal_params = {
209 	.no_hwmon = true,
210 };
211 
212 static const 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 const 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 const 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 = kzalloc_objs(*area->tz_module_arr,
435 					   area->tz_module_num);
436 	if (!area->tz_module_arr)
437 		return -ENOMEM;
438 
439 	for (i = 0; i < area->tz_module_num; i++) {
440 		err = mlxsw_thermal_module_init(thermal, area, i);
441 		if (err)
442 			goto err_thermal_module_init;
443 	}
444 
445 	return 0;
446 
447 err_thermal_module_init:
448 	for (i--; i >= 0; i--)
449 		mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
450 	kfree(area->tz_module_arr);
451 	return err;
452 }
453 
454 static void
mlxsw_thermal_modules_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)455 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
456 			   struct mlxsw_thermal_area *area)
457 {
458 	int i;
459 
460 	for (i = area->tz_module_num - 1; i >= 0; i--)
461 		mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
462 	kfree(area->tz_module_arr);
463 }
464 
465 static int
mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module * gearbox_tz)466 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
467 {
468 	char tz_name[40];
469 	int ret;
470 
471 	if (gearbox_tz->slot_index)
472 		snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
473 			 gearbox_tz->slot_index, gearbox_tz->module + 1);
474 	else
475 		snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
476 			 gearbox_tz->module + 1);
477 	gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
478 						gearbox_tz->trips,
479 						MLXSW_THERMAL_NUM_TRIPS,
480 						gearbox_tz,
481 						&mlxsw_thermal_gearbox_ops,
482 						&mlxsw_thermal_params, 0,
483 						gearbox_tz->parent->polling_delay);
484 	if (IS_ERR(gearbox_tz->tzdev))
485 		return PTR_ERR(gearbox_tz->tzdev);
486 
487 	ret = thermal_zone_device_enable(gearbox_tz->tzdev);
488 	if (ret)
489 		thermal_zone_device_unregister(gearbox_tz->tzdev);
490 
491 	return ret;
492 }
493 
494 static void
mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module * gearbox_tz)495 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
496 {
497 	thermal_zone_device_unregister(gearbox_tz->tzdev);
498 }
499 
500 static int
mlxsw_thermal_gearboxes_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)501 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
502 			     struct mlxsw_thermal *thermal,
503 			     struct mlxsw_thermal_area *area)
504 {
505 	enum mlxsw_reg_mgpir_device_type device_type;
506 	struct mlxsw_thermal_module *gearbox_tz;
507 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
508 	u8 gbox_num;
509 	int i, j;
510 	int err;
511 
512 	mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
513 	err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
514 	if (err)
515 		return err;
516 
517 	mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
518 			       NULL, NULL);
519 	if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
520 	    !gbox_num)
521 		return 0;
522 
523 	area->tz_gearbox_num = gbox_num;
524 	area->tz_gearbox_arr = kzalloc_objs(*area->tz_gearbox_arr,
525 					    area->tz_gearbox_num);
526 	if (!area->tz_gearbox_arr)
527 		return -ENOMEM;
528 
529 	for (i = 0; i < area->tz_gearbox_num; i++) {
530 		gearbox_tz = &area->tz_gearbox_arr[i];
531 		memcpy(gearbox_tz->trips, default_thermal_trips,
532 		       sizeof(thermal->trips));
533 		memcpy(gearbox_tz->cooling_states, default_cooling_states,
534 		       sizeof(thermal->cooling_states));
535 		for (j = 0; j < MLXSW_THERMAL_NUM_TRIPS; j++)
536 			gearbox_tz->trips[j].priv = &gearbox_tz->cooling_states[j];
537 
538 		gearbox_tz->module = i;
539 		gearbox_tz->parent = thermal;
540 		gearbox_tz->slot_index = area->slot_index;
541 		err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
542 		if (err)
543 			goto err_thermal_gearbox_tz_init;
544 	}
545 
546 	return 0;
547 
548 err_thermal_gearbox_tz_init:
549 	for (i--; i >= 0; i--)
550 		mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
551 	kfree(area->tz_gearbox_arr);
552 	return err;
553 }
554 
555 static void
mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)556 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
557 			     struct mlxsw_thermal_area *area)
558 {
559 	int i;
560 
561 	for (i = area->tz_gearbox_num - 1; i >= 0; i--)
562 		mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
563 	kfree(area->tz_gearbox_arr);
564 }
565 
566 static void
mlxsw_thermal_got_active(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)567 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
568 			 void *priv)
569 {
570 	struct mlxsw_thermal *thermal = priv;
571 	struct mlxsw_thermal_area *linecard;
572 	int err;
573 
574 	linecard = &thermal->line_cards[slot_index];
575 
576 	if (linecard->active)
577 		return;
578 
579 	linecard->slot_index = slot_index;
580 	err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
581 					 thermal, linecard);
582 	if (err) {
583 		dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
584 			slot_index);
585 		return;
586 	}
587 
588 	err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
589 					   thermal->core, thermal, linecard);
590 	if (err) {
591 		dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
592 			slot_index);
593 		goto err_thermal_linecard_gearboxes_init;
594 	}
595 
596 	linecard->active = true;
597 
598 	return;
599 
600 err_thermal_linecard_gearboxes_init:
601 	mlxsw_thermal_modules_fini(thermal, linecard);
602 }
603 
604 static void
mlxsw_thermal_got_inactive(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)605 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
606 			   void *priv)
607 {
608 	struct mlxsw_thermal *thermal = priv;
609 	struct mlxsw_thermal_area *linecard;
610 
611 	linecard = &thermal->line_cards[slot_index];
612 	if (!linecard->active)
613 		return;
614 	linecard->active = false;
615 	mlxsw_thermal_gearboxes_fini(thermal, linecard);
616 	mlxsw_thermal_modules_fini(thermal, linecard);
617 }
618 
619 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
620 	.got_active = mlxsw_thermal_got_active,
621 	.got_inactive = mlxsw_thermal_got_inactive,
622 };
623 
mlxsw_thermal_init(struct mlxsw_core * core,const struct mlxsw_bus_info * bus_info,struct mlxsw_thermal ** p_thermal)624 int mlxsw_thermal_init(struct mlxsw_core *core,
625 		       const struct mlxsw_bus_info *bus_info,
626 		       struct mlxsw_thermal **p_thermal)
627 {
628 	char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
629 	enum mlxsw_reg_mfcr_pwm_frequency freq;
630 	struct device *dev = bus_info->dev;
631 	char mgpir_pl[MLXSW_REG_MGPIR_LEN];
632 	struct mlxsw_thermal *thermal;
633 	u8 pwm_active, num_of_slots;
634 	u16 tacho_active;
635 	int err, i;
636 
637 	mlxsw_reg_mgpir_pack(mgpir_pl, 0);
638 	err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
639 	if (err)
640 		return err;
641 
642 	mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
643 			       &num_of_slots);
644 
645 	thermal = kzalloc_flex(*thermal, line_cards, num_of_slots + 1);
646 	if (!thermal)
647 		return -ENOMEM;
648 
649 	thermal->core = core;
650 	thermal->bus_info = bus_info;
651 	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
652 	memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
653 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++)
654 		thermal->trips[i].priv = &thermal->cooling_states[i];
655 
656 	thermal->line_cards[0].slot_index = 0;
657 
658 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
659 	if (err) {
660 		dev_err(dev, "Failed to probe PWMs\n");
661 		goto err_reg_query;
662 	}
663 	mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
664 
665 	for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
666 		if (tacho_active & BIT(i)) {
667 			char mfsl_pl[MLXSW_REG_MFSL_LEN];
668 
669 			mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
670 
671 			/* We need to query the register to preserve maximum */
672 			err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
673 					      mfsl_pl);
674 			if (err)
675 				goto err_reg_query;
676 
677 			/* set the minimal RPMs to 0 */
678 			mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
679 			err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
680 					      mfsl_pl);
681 			if (err)
682 				goto err_reg_write;
683 		}
684 	}
685 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
686 		if (pwm_active & BIT(i)) {
687 			struct mlxsw_thermal_cooling_device *mlxsw_cdev;
688 			struct thermal_cooling_device *cdev;
689 
690 			mlxsw_cdev = &thermal->cdevs[i];
691 			mlxsw_cdev->thermal = thermal;
692 			mlxsw_cdev->idx = i;
693 			cdev = thermal_cooling_device_register("mlxsw_fan",
694 							       mlxsw_cdev,
695 							       &mlxsw_cooling_ops);
696 			if (IS_ERR(cdev)) {
697 				err = PTR_ERR(cdev);
698 				dev_err(dev, "Failed to register cooling device\n");
699 				goto err_thermal_cooling_device_register;
700 			}
701 			mlxsw_cdev->cdev = cdev;
702 		}
703 	}
704 
705 	thermal->polling_delay = bus_info->low_frequency ?
706 				 MLXSW_THERMAL_SLOW_POLL_INT :
707 				 MLXSW_THERMAL_POLL_INT;
708 
709 	thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw",
710 						      thermal->trips,
711 						      MLXSW_THERMAL_NUM_TRIPS,
712 						      thermal,
713 						      &mlxsw_thermal_ops,
714 						      &mlxsw_thermal_params, 0,
715 						      thermal->polling_delay);
716 	if (IS_ERR(thermal->tzdev)) {
717 		err = PTR_ERR(thermal->tzdev);
718 		dev_err(dev, "Failed to register thermal zone\n");
719 		goto err_thermal_zone_device_register;
720 	}
721 
722 	err = mlxsw_thermal_modules_init(dev, core, thermal,
723 					 &thermal->line_cards[0]);
724 	if (err)
725 		goto err_thermal_modules_init;
726 
727 	err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
728 					   &thermal->line_cards[0]);
729 	if (err)
730 		goto err_thermal_gearboxes_init;
731 
732 	err = mlxsw_linecards_event_ops_register(core,
733 						 &mlxsw_thermal_event_ops,
734 						 thermal);
735 	if (err)
736 		goto err_linecards_event_ops_register;
737 
738 	err = thermal_zone_device_enable(thermal->tzdev);
739 	if (err)
740 		goto err_thermal_zone_device_enable;
741 
742 	thermal->line_cards[0].active = true;
743 	*p_thermal = thermal;
744 	return 0;
745 
746 err_thermal_zone_device_enable:
747 	mlxsw_linecards_event_ops_unregister(thermal->core,
748 					     &mlxsw_thermal_event_ops,
749 					     thermal);
750 err_linecards_event_ops_register:
751 	mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
752 err_thermal_gearboxes_init:
753 	mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
754 err_thermal_modules_init:
755 	thermal_zone_device_unregister(thermal->tzdev);
756 err_thermal_zone_device_register:
757 err_thermal_cooling_device_register:
758 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
759 		thermal_cooling_device_unregister(thermal->cdevs[i].cdev);
760 err_reg_write:
761 err_reg_query:
762 	kfree(thermal);
763 	return err;
764 }
765 
mlxsw_thermal_fini(struct mlxsw_thermal * thermal)766 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
767 {
768 	int i;
769 
770 	thermal->line_cards[0].active = false;
771 	mlxsw_linecards_event_ops_unregister(thermal->core,
772 					     &mlxsw_thermal_event_ops,
773 					     thermal);
774 	mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
775 	mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
776 	thermal_zone_device_unregister(thermal->tzdev);
777 
778 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
779 		thermal_cooling_device_unregister(thermal->cdevs[i].cdev);
780 
781 	kfree(thermal);
782 }
783