1 /* 2 * drivers/net/ethernet/mellanox/mlxsw/core_thermal.c 3 * Copyright (c) 2016 Ivan Vecera <cera@cera.cz> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the names of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <linux/kernel.h> 35 #include <linux/types.h> 36 #include <linux/device.h> 37 #include <linux/sysfs.h> 38 #include <linux/thermal.h> 39 #include <linux/err.h> 40 41 #include "core.h" 42 43 #define MLXSW_THERMAL_POLL_INT 1000 /* ms */ 44 #define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */ 45 #define MLXSW_THERMAL_MAX_STATE 10 46 #define MLXSW_THERMAL_MAX_DUTY 255 47 48 struct mlxsw_thermal_trip { 49 int type; 50 int temp; 51 int min_state; 52 int max_state; 53 }; 54 55 static const struct mlxsw_thermal_trip default_thermal_trips[] = { 56 { /* In range - 0-40% PWM */ 57 .type = THERMAL_TRIP_ACTIVE, 58 .temp = 75000, 59 .min_state = 0, 60 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 61 }, 62 { /* High - 40-100% PWM */ 63 .type = THERMAL_TRIP_ACTIVE, 64 .temp = 80000, 65 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, 66 .max_state = MLXSW_THERMAL_MAX_STATE, 67 }, 68 { 69 /* Very high - 100% PWM */ 70 .type = THERMAL_TRIP_ACTIVE, 71 .temp = 85000, 72 .min_state = MLXSW_THERMAL_MAX_STATE, 73 .max_state = MLXSW_THERMAL_MAX_STATE, 74 }, 75 { /* Warning */ 76 .type = THERMAL_TRIP_HOT, 77 .temp = 105000, 78 .min_state = MLXSW_THERMAL_MAX_STATE, 79 .max_state = MLXSW_THERMAL_MAX_STATE, 80 }, 81 { /* Critical - soft poweroff */ 82 .type = THERMAL_TRIP_CRITICAL, 83 .temp = MLXSW_THERMAL_MAX_TEMP, 84 .min_state = MLXSW_THERMAL_MAX_STATE, 85 .max_state = MLXSW_THERMAL_MAX_STATE, 86 } 87 }; 88 89 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips) 90 91 /* Make sure all trips are writable */ 92 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1) 93 94 struct mlxsw_thermal { 95 struct mlxsw_core *core; 96 const struct mlxsw_bus_info *bus_info; 97 struct thermal_zone_device *tzdev; 98 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; 99 struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; 100 enum thermal_device_mode mode; 101 }; 102 103 static inline u8 mlxsw_state_to_duty(int state) 104 { 105 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY, 106 MLXSW_THERMAL_MAX_STATE); 107 } 108 109 static inline int mlxsw_duty_to_state(u8 duty) 110 { 111 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE, 112 MLXSW_THERMAL_MAX_DUTY); 113 } 114 115 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, 116 struct thermal_cooling_device *cdev) 117 { 118 int i; 119 120 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) 121 if (thermal->cdevs[i] == cdev) 122 return i; 123 124 return -ENODEV; 125 } 126 127 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, 128 struct thermal_cooling_device *cdev) 129 { 130 struct mlxsw_thermal *thermal = tzdev->devdata; 131 struct device *dev = thermal->bus_info->dev; 132 int i, err; 133 134 /* If the cooling device is one of ours bind it */ 135 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0) 136 return 0; 137 138 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { 139 const struct mlxsw_thermal_trip *trip = &thermal->trips[i]; 140 141 err = thermal_zone_bind_cooling_device(tzdev, i, cdev, 142 trip->max_state, 143 trip->min_state, 144 THERMAL_WEIGHT_DEFAULT); 145 if (err < 0) { 146 dev_err(dev, "Failed to bind cooling device to trip %d\n", i); 147 return err; 148 } 149 } 150 return 0; 151 } 152 153 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, 154 struct thermal_cooling_device *cdev) 155 { 156 struct mlxsw_thermal *thermal = tzdev->devdata; 157 struct device *dev = thermal->bus_info->dev; 158 int i; 159 int err; 160 161 /* If the cooling device is our one unbind it */ 162 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0) 163 return 0; 164 165 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { 166 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev); 167 if (err < 0) { 168 dev_err(dev, "Failed to unbind cooling device\n"); 169 return err; 170 } 171 } 172 return 0; 173 } 174 175 static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev, 176 enum thermal_device_mode *mode) 177 { 178 struct mlxsw_thermal *thermal = tzdev->devdata; 179 180 *mode = thermal->mode; 181 182 return 0; 183 } 184 185 static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, 186 enum thermal_device_mode mode) 187 { 188 struct mlxsw_thermal *thermal = tzdev->devdata; 189 190 mutex_lock(&tzdev->lock); 191 192 if (mode == THERMAL_DEVICE_ENABLED) 193 tzdev->polling_delay = MLXSW_THERMAL_POLL_INT; 194 else 195 tzdev->polling_delay = 0; 196 197 mutex_unlock(&tzdev->lock); 198 199 thermal->mode = mode; 200 thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); 201 202 return 0; 203 } 204 205 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, 206 int *p_temp) 207 { 208 struct mlxsw_thermal *thermal = tzdev->devdata; 209 struct device *dev = thermal->bus_info->dev; 210 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 211 unsigned int temp; 212 int err; 213 214 mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false); 215 216 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); 217 if (err) { 218 dev_err(dev, "Failed to query temp sensor\n"); 219 return err; 220 } 221 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); 222 223 *p_temp = (int) temp; 224 return 0; 225 } 226 227 static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev, 228 int trip, 229 enum thermal_trip_type *p_type) 230 { 231 struct mlxsw_thermal *thermal = tzdev->devdata; 232 233 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 234 return -EINVAL; 235 236 *p_type = thermal->trips[trip].type; 237 return 0; 238 } 239 240 static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev, 241 int trip, int *p_temp) 242 { 243 struct mlxsw_thermal *thermal = tzdev->devdata; 244 245 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) 246 return -EINVAL; 247 248 *p_temp = thermal->trips[trip].temp; 249 return 0; 250 } 251 252 static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev, 253 int trip, int temp) 254 { 255 struct mlxsw_thermal *thermal = tzdev->devdata; 256 257 if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS || 258 temp > MLXSW_THERMAL_MAX_TEMP) 259 return -EINVAL; 260 261 thermal->trips[trip].temp = temp; 262 return 0; 263 } 264 265 static struct thermal_zone_device_ops mlxsw_thermal_ops = { 266 .bind = mlxsw_thermal_bind, 267 .unbind = mlxsw_thermal_unbind, 268 .get_mode = mlxsw_thermal_get_mode, 269 .set_mode = mlxsw_thermal_set_mode, 270 .get_temp = mlxsw_thermal_get_temp, 271 .get_trip_type = mlxsw_thermal_get_trip_type, 272 .get_trip_temp = mlxsw_thermal_get_trip_temp, 273 .set_trip_temp = mlxsw_thermal_set_trip_temp, 274 }; 275 276 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, 277 unsigned long *p_state) 278 { 279 *p_state = MLXSW_THERMAL_MAX_STATE; 280 return 0; 281 } 282 283 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev, 284 unsigned long *p_state) 285 286 { 287 struct mlxsw_thermal *thermal = cdev->devdata; 288 struct device *dev = thermal->bus_info->dev; 289 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 290 int err, idx; 291 u8 duty; 292 293 idx = mlxsw_get_cooling_device_idx(thermal, cdev); 294 if (idx < 0) 295 return idx; 296 297 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0); 298 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl); 299 if (err) { 300 dev_err(dev, "Failed to query PWM duty\n"); 301 return err; 302 } 303 304 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl); 305 *p_state = mlxsw_duty_to_state(duty); 306 return 0; 307 } 308 309 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev, 310 unsigned long state) 311 312 { 313 struct mlxsw_thermal *thermal = cdev->devdata; 314 struct device *dev = thermal->bus_info->dev; 315 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 316 int err, idx; 317 318 idx = mlxsw_get_cooling_device_idx(thermal, cdev); 319 if (idx < 0) 320 return idx; 321 322 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state)); 323 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl); 324 if (err) { 325 dev_err(dev, "Failed to write PWM duty\n"); 326 return err; 327 } 328 return 0; 329 } 330 331 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = { 332 .get_max_state = mlxsw_thermal_get_max_state, 333 .get_cur_state = mlxsw_thermal_get_cur_state, 334 .set_cur_state = mlxsw_thermal_set_cur_state, 335 }; 336 337 int mlxsw_thermal_init(struct mlxsw_core *core, 338 const struct mlxsw_bus_info *bus_info, 339 struct mlxsw_thermal **p_thermal) 340 { 341 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 }; 342 enum mlxsw_reg_mfcr_pwm_frequency freq; 343 struct device *dev = bus_info->dev; 344 struct mlxsw_thermal *thermal; 345 u16 tacho_active; 346 u8 pwm_active; 347 int err, i; 348 349 thermal = devm_kzalloc(dev, sizeof(*thermal), 350 GFP_KERNEL); 351 if (!thermal) 352 return -ENOMEM; 353 354 thermal->core = core; 355 thermal->bus_info = bus_info; 356 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips)); 357 358 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); 359 if (err) { 360 dev_err(dev, "Failed to probe PWMs\n"); 361 goto err_free_thermal; 362 } 363 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); 364 365 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) { 366 if (tacho_active & BIT(i)) { 367 char mfsl_pl[MLXSW_REG_MFSL_LEN]; 368 369 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0); 370 371 /* We need to query the register to preserve maximum */ 372 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl), 373 mfsl_pl); 374 if (err) 375 goto err_free_thermal; 376 377 /* set the minimal RPMs to 0 */ 378 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0); 379 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl), 380 mfsl_pl); 381 if (err) 382 goto err_free_thermal; 383 } 384 } 385 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) { 386 if (pwm_active & BIT(i)) { 387 struct thermal_cooling_device *cdev; 388 389 cdev = thermal_cooling_device_register("Fan", thermal, 390 &mlxsw_cooling_ops); 391 if (IS_ERR(cdev)) { 392 err = PTR_ERR(cdev); 393 dev_err(dev, "Failed to register cooling device\n"); 394 goto err_unreg_cdevs; 395 } 396 thermal->cdevs[i] = cdev; 397 } 398 } 399 400 thermal->tzdev = thermal_zone_device_register("mlxsw", 401 MLXSW_THERMAL_NUM_TRIPS, 402 MLXSW_THERMAL_TRIP_MASK, 403 thermal, 404 &mlxsw_thermal_ops, 405 NULL, 0, 406 MLXSW_THERMAL_POLL_INT); 407 if (IS_ERR(thermal->tzdev)) { 408 err = PTR_ERR(thermal->tzdev); 409 dev_err(dev, "Failed to register thermal zone\n"); 410 goto err_unreg_cdevs; 411 } 412 413 thermal->mode = THERMAL_DEVICE_ENABLED; 414 *p_thermal = thermal; 415 return 0; 416 err_unreg_cdevs: 417 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) 418 if (thermal->cdevs[i]) 419 thermal_cooling_device_unregister(thermal->cdevs[i]); 420 err_free_thermal: 421 devm_kfree(dev, thermal); 422 return err; 423 } 424 425 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) 426 { 427 int i; 428 429 if (thermal->tzdev) { 430 thermal_zone_device_unregister(thermal->tzdev); 431 thermal->tzdev = NULL; 432 } 433 434 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) { 435 if (thermal->cdevs[i]) { 436 thermal_cooling_device_unregister(thermal->cdevs[i]); 437 thermal->cdevs[i] = NULL; 438 } 439 } 440 441 devm_kfree(thermal->bus_info->dev, thermal); 442 } 443