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 
13 #include "core.h"
14 
15 #define MLXSW_THERMAL_POLL_INT	1000	/* ms */
16 #define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
17 #define MLXSW_THERMAL_MAX_STATE	10
18 #define MLXSW_THERMAL_MAX_DUTY	255
19 
20 struct mlxsw_thermal_trip {
21 	int	type;
22 	int	temp;
23 	int	min_state;
24 	int	max_state;
25 };
26 
27 static const struct mlxsw_thermal_trip default_thermal_trips[] = {
28 	{	/* In range - 0-40% PWM */
29 		.type		= THERMAL_TRIP_ACTIVE,
30 		.temp		= 75000,
31 		.min_state	= 0,
32 		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
33 	},
34 	{	/* High - 40-100% PWM */
35 		.type		= THERMAL_TRIP_ACTIVE,
36 		.temp		= 80000,
37 		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
38 		.max_state	= MLXSW_THERMAL_MAX_STATE,
39 	},
40 	{
41 		/* Very high - 100% PWM */
42 		.type		= THERMAL_TRIP_ACTIVE,
43 		.temp		= 85000,
44 		.min_state	= MLXSW_THERMAL_MAX_STATE,
45 		.max_state	= MLXSW_THERMAL_MAX_STATE,
46 	},
47 	{	/* Warning */
48 		.type		= THERMAL_TRIP_HOT,
49 		.temp		= 105000,
50 		.min_state	= MLXSW_THERMAL_MAX_STATE,
51 		.max_state	= MLXSW_THERMAL_MAX_STATE,
52 	},
53 	{	/* Critical - soft poweroff */
54 		.type		= THERMAL_TRIP_CRITICAL,
55 		.temp		= MLXSW_THERMAL_MAX_TEMP,
56 		.min_state	= MLXSW_THERMAL_MAX_STATE,
57 		.max_state	= MLXSW_THERMAL_MAX_STATE,
58 	}
59 };
60 
61 #define MLXSW_THERMAL_NUM_TRIPS	ARRAY_SIZE(default_thermal_trips)
62 
63 /* Make sure all trips are writable */
64 #define MLXSW_THERMAL_TRIP_MASK	(BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
65 
66 struct mlxsw_thermal {
67 	struct mlxsw_core *core;
68 	const struct mlxsw_bus_info *bus_info;
69 	struct thermal_zone_device *tzdev;
70 	struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
71 	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
72 	enum thermal_device_mode mode;
73 };
74 
mlxsw_state_to_duty(int state)75 static inline u8 mlxsw_state_to_duty(int state)
76 {
77 	return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
78 				 MLXSW_THERMAL_MAX_STATE);
79 }
80 
mlxsw_duty_to_state(u8 duty)81 static inline int mlxsw_duty_to_state(u8 duty)
82 {
83 	return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
84 				 MLXSW_THERMAL_MAX_DUTY);
85 }
86 
mlxsw_get_cooling_device_idx(struct mlxsw_thermal * thermal,struct thermal_cooling_device * cdev)87 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
88 					struct thermal_cooling_device *cdev)
89 {
90 	int i;
91 
92 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
93 		if (thermal->cdevs[i] == cdev)
94 			return i;
95 
96 	return -ENODEV;
97 }
98 
mlxsw_thermal_bind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)99 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
100 			      struct thermal_cooling_device *cdev)
101 {
102 	struct mlxsw_thermal *thermal = tzdev->devdata;
103 	struct device *dev = thermal->bus_info->dev;
104 	int i, err;
105 
106 	/* If the cooling device is one of ours bind it */
107 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
108 		return 0;
109 
110 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
111 		const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
112 
113 		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
114 						       trip->max_state,
115 						       trip->min_state,
116 						       THERMAL_WEIGHT_DEFAULT);
117 		if (err < 0) {
118 			dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
119 			return err;
120 		}
121 	}
122 	return 0;
123 }
124 
mlxsw_thermal_unbind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)125 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
126 				struct thermal_cooling_device *cdev)
127 {
128 	struct mlxsw_thermal *thermal = tzdev->devdata;
129 	struct device *dev = thermal->bus_info->dev;
130 	int i;
131 	int err;
132 
133 	/* If the cooling device is our one unbind it */
134 	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
135 		return 0;
136 
137 	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
138 		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
139 		if (err < 0) {
140 			dev_err(dev, "Failed to unbind cooling device\n");
141 			return err;
142 		}
143 	}
144 	return 0;
145 }
146 
mlxsw_thermal_get_mode(struct thermal_zone_device * tzdev,enum thermal_device_mode * mode)147 static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
148 				  enum thermal_device_mode *mode)
149 {
150 	struct mlxsw_thermal *thermal = tzdev->devdata;
151 
152 	*mode = thermal->mode;
153 
154 	return 0;
155 }
156 
mlxsw_thermal_set_mode(struct thermal_zone_device * tzdev,enum thermal_device_mode mode)157 static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
158 				  enum thermal_device_mode mode)
159 {
160 	struct mlxsw_thermal *thermal = tzdev->devdata;
161 
162 	mutex_lock(&tzdev->lock);
163 
164 	if (mode == THERMAL_DEVICE_ENABLED)
165 		tzdev->polling_delay = MLXSW_THERMAL_POLL_INT;
166 	else
167 		tzdev->polling_delay = 0;
168 
169 	mutex_unlock(&tzdev->lock);
170 
171 	thermal->mode = mode;
172 	thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
173 
174 	return 0;
175 }
176 
mlxsw_thermal_get_temp(struct thermal_zone_device * tzdev,int * p_temp)177 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
178 				  int *p_temp)
179 {
180 	struct mlxsw_thermal *thermal = tzdev->devdata;
181 	struct device *dev = thermal->bus_info->dev;
182 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
183 	unsigned int temp;
184 	int err;
185 
186 	mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
187 
188 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
189 	if (err) {
190 		dev_err(dev, "Failed to query temp sensor\n");
191 		return err;
192 	}
193 	mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
194 
195 	*p_temp = (int) temp;
196 	return 0;
197 }
198 
mlxsw_thermal_get_trip_type(struct thermal_zone_device * tzdev,int trip,enum thermal_trip_type * p_type)199 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
200 				       int trip,
201 				       enum thermal_trip_type *p_type)
202 {
203 	struct mlxsw_thermal *thermal = tzdev->devdata;
204 
205 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
206 		return -EINVAL;
207 
208 	*p_type = thermal->trips[trip].type;
209 	return 0;
210 }
211 
mlxsw_thermal_get_trip_temp(struct thermal_zone_device * tzdev,int trip,int * p_temp)212 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
213 				       int trip, int *p_temp)
214 {
215 	struct mlxsw_thermal *thermal = tzdev->devdata;
216 
217 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
218 		return -EINVAL;
219 
220 	*p_temp = thermal->trips[trip].temp;
221 	return 0;
222 }
223 
mlxsw_thermal_set_trip_temp(struct thermal_zone_device * tzdev,int trip,int temp)224 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
225 				       int trip, int temp)
226 {
227 	struct mlxsw_thermal *thermal = tzdev->devdata;
228 
229 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
230 	    temp > MLXSW_THERMAL_MAX_TEMP)
231 		return -EINVAL;
232 
233 	thermal->trips[trip].temp = temp;
234 	return 0;
235 }
236 
237 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
238 	.bind = mlxsw_thermal_bind,
239 	.unbind = mlxsw_thermal_unbind,
240 	.get_mode = mlxsw_thermal_get_mode,
241 	.set_mode = mlxsw_thermal_set_mode,
242 	.get_temp = mlxsw_thermal_get_temp,
243 	.get_trip_type	= mlxsw_thermal_get_trip_type,
244 	.get_trip_temp	= mlxsw_thermal_get_trip_temp,
245 	.set_trip_temp	= mlxsw_thermal_set_trip_temp,
246 };
247 
mlxsw_thermal_get_max_state(struct thermal_cooling_device * cdev,unsigned long * p_state)248 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
249 				       unsigned long *p_state)
250 {
251 	*p_state = MLXSW_THERMAL_MAX_STATE;
252 	return 0;
253 }
254 
mlxsw_thermal_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * p_state)255 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
256 				       unsigned long *p_state)
257 
258 {
259 	struct mlxsw_thermal *thermal = cdev->devdata;
260 	struct device *dev = thermal->bus_info->dev;
261 	char mfsc_pl[MLXSW_REG_MFSC_LEN];
262 	int err, idx;
263 	u8 duty;
264 
265 	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
266 	if (idx < 0)
267 		return idx;
268 
269 	mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
270 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
271 	if (err) {
272 		dev_err(dev, "Failed to query PWM duty\n");
273 		return err;
274 	}
275 
276 	duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
277 	*p_state = mlxsw_duty_to_state(duty);
278 	return 0;
279 }
280 
mlxsw_thermal_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)281 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
282 				       unsigned long state)
283 
284 {
285 	struct mlxsw_thermal *thermal = cdev->devdata;
286 	struct device *dev = thermal->bus_info->dev;
287 	char mfsc_pl[MLXSW_REG_MFSC_LEN];
288 	int err, idx;
289 
290 	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
291 	if (idx < 0)
292 		return idx;
293 
294 	mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
295 	err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
296 	if (err) {
297 		dev_err(dev, "Failed to write PWM duty\n");
298 		return err;
299 	}
300 	return 0;
301 }
302 
303 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
304 	.get_max_state	= mlxsw_thermal_get_max_state,
305 	.get_cur_state	= mlxsw_thermal_get_cur_state,
306 	.set_cur_state	= mlxsw_thermal_set_cur_state,
307 };
308 
mlxsw_thermal_init(struct mlxsw_core * core,const struct mlxsw_bus_info * bus_info,struct mlxsw_thermal ** p_thermal)309 int mlxsw_thermal_init(struct mlxsw_core *core,
310 		       const struct mlxsw_bus_info *bus_info,
311 		       struct mlxsw_thermal **p_thermal)
312 {
313 	char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
314 	enum mlxsw_reg_mfcr_pwm_frequency freq;
315 	struct device *dev = bus_info->dev;
316 	struct mlxsw_thermal *thermal;
317 	u16 tacho_active;
318 	u8 pwm_active;
319 	int err, i;
320 
321 	thermal = devm_kzalloc(dev, sizeof(*thermal),
322 			       GFP_KERNEL);
323 	if (!thermal)
324 		return -ENOMEM;
325 
326 	thermal->core = core;
327 	thermal->bus_info = bus_info;
328 	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
329 
330 	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
331 	if (err) {
332 		dev_err(dev, "Failed to probe PWMs\n");
333 		goto err_free_thermal;
334 	}
335 	mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
336 
337 	for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
338 		if (tacho_active & BIT(i)) {
339 			char mfsl_pl[MLXSW_REG_MFSL_LEN];
340 
341 			mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
342 
343 			/* We need to query the register to preserve maximum */
344 			err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
345 					      mfsl_pl);
346 			if (err)
347 				goto err_free_thermal;
348 
349 			/* set the minimal RPMs to 0 */
350 			mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
351 			err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
352 					      mfsl_pl);
353 			if (err)
354 				goto err_free_thermal;
355 		}
356 	}
357 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
358 		if (pwm_active & BIT(i)) {
359 			struct thermal_cooling_device *cdev;
360 
361 			cdev = thermal_cooling_device_register("Fan", thermal,
362 							&mlxsw_cooling_ops);
363 			if (IS_ERR(cdev)) {
364 				err = PTR_ERR(cdev);
365 				dev_err(dev, "Failed to register cooling device\n");
366 				goto err_unreg_cdevs;
367 			}
368 			thermal->cdevs[i] = cdev;
369 		}
370 	}
371 
372 	thermal->tzdev = thermal_zone_device_register("mlxsw",
373 						      MLXSW_THERMAL_NUM_TRIPS,
374 						      MLXSW_THERMAL_TRIP_MASK,
375 						      thermal,
376 						      &mlxsw_thermal_ops,
377 						      NULL, 0,
378 						      MLXSW_THERMAL_POLL_INT);
379 	if (IS_ERR(thermal->tzdev)) {
380 		err = PTR_ERR(thermal->tzdev);
381 		dev_err(dev, "Failed to register thermal zone\n");
382 		goto err_unreg_cdevs;
383 	}
384 
385 	thermal->mode = THERMAL_DEVICE_ENABLED;
386 	*p_thermal = thermal;
387 	return 0;
388 err_unreg_cdevs:
389 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
390 		if (thermal->cdevs[i])
391 			thermal_cooling_device_unregister(thermal->cdevs[i]);
392 err_free_thermal:
393 	devm_kfree(dev, thermal);
394 	return err;
395 }
396 
mlxsw_thermal_fini(struct mlxsw_thermal * thermal)397 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
398 {
399 	int i;
400 
401 	if (thermal->tzdev) {
402 		thermal_zone_device_unregister(thermal->tzdev);
403 		thermal->tzdev = NULL;
404 	}
405 
406 	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
407 		if (thermal->cdevs[i]) {
408 			thermal_cooling_device_unregister(thermal->cdevs[i]);
409 			thermal->cdevs[i] = NULL;
410 		}
411 	}
412 
413 	devm_kfree(thermal->bus_info->dev, thermal);
414 }
415