631 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2//3// Copyright (c) 2018 Mellanox Technologies. All rights reserved.4// Copyright (c) 2018 Vadim Pasternak <vadimp@mellanox.com>5 6#include <linux/bitops.h>7#include <linux/device.h>8#include <linux/hwmon.h>9#include <linux/module.h>10#include <linux/platform_data/mlxreg.h>11#include <linux/platform_device.h>12#include <linux/regmap.h>13#include <linux/thermal.h>14 15#define MLXREG_FAN_MAX_TACHO 2416#define MLXREG_FAN_MAX_PWM 417#define MLXREG_FAN_PWM_NOT_CONNECTED 0xff18#define MLXREG_FAN_MAX_STATE 1019#define MLXREG_FAN_MIN_DUTY 51 /* 20% */20#define MLXREG_FAN_MAX_DUTY 255 /* 100% */21#define MLXREG_FAN_SPEED_MIN_LEVEL 2 /* 20 percent */22#define MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF 4423#define MLXREG_FAN_TACHO_DIV_MIN 28324#define MLXREG_FAN_TACHO_DIV_DEF (MLXREG_FAN_TACHO_DIV_MIN * 4)25#define MLXREG_FAN_TACHO_DIV_SCALE_MAX 6426/*27 * FAN datasheet defines the formula for RPM calculations as RPM = 15/t-high.28 * The logic in a programmable device measures the time t-high by sampling the29 * tachometer every t-sample (with the default value 11.32 uS) and increment30 * a counter (N) as long as the pulse has not change:31 * RPM = 15 / (t-sample * (K + Regval)), where:32 * Regval: is the value read from the programmable device register;33 * - 0xff - represents tachometer fault;34 * - 0xfe - represents tachometer minimum value , which is 4444 RPM;35 * - 0x00 - represents tachometer maximum value , which is 300000 RPM;36 * K: is 44 and it represents the minimum allowed samples per pulse;37 * N: is equal K + Regval;38 * In order to calculate RPM from the register value the following formula is39 * used: RPM = 15 / ((Regval + K) * 11.32) * 10^(-6)), which in the40 * default case is modified to:41 * RPM = 15000000 * 100 / ((Regval + 44) * 1132);42 * - for Regval 0x00, RPM will be 15000000 * 100 / (44 * 1132) = 30115;43 * - for Regval 0xfe, RPM will be 15000000 * 100 / ((254 + 44) * 1132) = 4446;44 * In common case the formula is modified to:45 * RPM = 15000000 * 100 / ((Regval + samples) * divider).46 */47#define MLXREG_FAN_GET_RPM(rval, d, s) (DIV_ROUND_CLOSEST(15000000 * 100, \48 ((rval) + (s)) * (d)))49#define MLXREG_FAN_GET_FAULT(val, mask) ((val) == (mask))50#define MLXREG_FAN_PWM_DUTY2STATE(duty) (DIV_ROUND_CLOSEST((duty) * \51 MLXREG_FAN_MAX_STATE, \52 MLXREG_FAN_MAX_DUTY))53#define MLXREG_FAN_PWM_STATE2DUTY(stat) (DIV_ROUND_CLOSEST((stat) * \54 MLXREG_FAN_MAX_DUTY, \55 MLXREG_FAN_MAX_STATE))56 57struct mlxreg_fan;58 59/*60 * struct mlxreg_fan_tacho - tachometer data (internal use):61 *62 * @connected: indicates if tachometer is connected;63 * @reg: register offset;64 * @mask: fault mask;65 * @prsnt: present register offset;66 */67struct mlxreg_fan_tacho {68 bool connected;69 u32 reg;70 u32 mask;71 u32 prsnt;72};73 74/*75 * struct mlxreg_fan_pwm - PWM data (internal use):76 *77 * @fan: private data;78 * @connected: indicates if PWM is connected;79 * @reg: register offset;80 * @cooling: cooling device levels;81 * @last_hwmon_state: last cooling state set by hwmon subsystem;82 * @last_thermal_state: last cooling state set by thermal subsystem;83 * @cdev: cooling device;84 */85struct mlxreg_fan_pwm {86 struct mlxreg_fan *fan;87 bool connected;88 u32 reg;89 unsigned long last_hwmon_state;90 unsigned long last_thermal_state;91 struct thermal_cooling_device *cdev;92};93 94/*95 * struct mlxreg_fan - private data (internal use):96 *97 * @dev: basic device;98 * @regmap: register map of parent device;99 * @tacho: tachometer data;100 * @pwm: PWM data;101 * @tachos_per_drwr - number of tachometers per drawer;102 * @samples: minimum allowed samples per pulse;103 * @divider: divider value for tachometer RPM calculation;104 */105struct mlxreg_fan {106 struct device *dev;107 void *regmap;108 struct mlxreg_core_platform_data *pdata;109 struct mlxreg_fan_tacho tacho[MLXREG_FAN_MAX_TACHO];110 struct mlxreg_fan_pwm pwm[MLXREG_FAN_MAX_PWM];111 int tachos_per_drwr;112 int samples;113 int divider;114};115 116static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,117 unsigned long state);118 119static int120mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,121 int channel, long *val)122{123 struct mlxreg_fan *fan = dev_get_drvdata(dev);124 struct mlxreg_fan_tacho *tacho;125 struct mlxreg_fan_pwm *pwm;126 u32 regval;127 int err;128 129 switch (type) {130 case hwmon_fan:131 tacho = &fan->tacho[channel];132 switch (attr) {133 case hwmon_fan_input:134 /*135 * Check FAN presence: FAN related bit in presence register is one,136 * if FAN is physically connected, zero - otherwise.137 */138 if (tacho->prsnt && fan->tachos_per_drwr) {139 err = regmap_read(fan->regmap, tacho->prsnt, ®val);140 if (err)141 return err;142 143 /*144 * Map channel to presence bit - drawer can be equipped with145 * one or few FANs, while presence is indicated per drawer.146 */147 if (BIT(channel / fan->tachos_per_drwr) & regval) {148 /* FAN is not connected - return zero for FAN speed. */149 *val = 0;150 return 0;151 }152 }153 154 err = regmap_read(fan->regmap, tacho->reg, ®val);155 if (err)156 return err;157 158 if (MLXREG_FAN_GET_FAULT(regval, tacho->mask)) {159 /* FAN is broken - return zero for FAN speed. */160 *val = 0;161 return 0;162 }163 164 *val = MLXREG_FAN_GET_RPM(regval, fan->divider,165 fan->samples);166 break;167 168 case hwmon_fan_fault:169 err = regmap_read(fan->regmap, tacho->reg, ®val);170 if (err)171 return err;172 173 *val = MLXREG_FAN_GET_FAULT(regval, tacho->mask);174 break;175 176 default:177 return -EOPNOTSUPP;178 }179 break;180 181 case hwmon_pwm:182 pwm = &fan->pwm[channel];183 switch (attr) {184 case hwmon_pwm_input:185 err = regmap_read(fan->regmap, pwm->reg, ®val);186 if (err)187 return err;188 189 *val = regval;190 break;191 192 default:193 return -EOPNOTSUPP;194 }195 break;196 197 default:198 return -EOPNOTSUPP;199 }200 201 return 0;202}203 204static int205mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,206 int channel, long val)207{208 struct mlxreg_fan *fan = dev_get_drvdata(dev);209 struct mlxreg_fan_pwm *pwm;210 211 switch (type) {212 case hwmon_pwm:213 switch (attr) {214 case hwmon_pwm_input:215 if (val < MLXREG_FAN_MIN_DUTY ||216 val > MLXREG_FAN_MAX_DUTY)217 return -EINVAL;218 pwm = &fan->pwm[channel];219 /* If thermal is configured - handle PWM limit setting. */220 if (IS_REACHABLE(CONFIG_THERMAL)) {221 pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(val);222 /*223 * Update PWM only in case requested state is not less than the224 * last thermal state.225 */226 if (pwm->last_hwmon_state >= pwm->last_thermal_state)227 return mlxreg_fan_set_cur_state(pwm->cdev,228 pwm->last_hwmon_state);229 return 0;230 }231 return regmap_write(fan->regmap, pwm->reg, val);232 default:233 return -EOPNOTSUPP;234 }235 break;236 237 default:238 return -EOPNOTSUPP;239 }240 241 return -EOPNOTSUPP;242}243 244static umode_t245mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,246 int channel)247{248 switch (type) {249 case hwmon_fan:250 if (!(((struct mlxreg_fan *)data)->tacho[channel].connected))251 return 0;252 253 switch (attr) {254 case hwmon_fan_input:255 case hwmon_fan_fault:256 return 0444;257 default:258 break;259 }260 break;261 262 case hwmon_pwm:263 if (!(((struct mlxreg_fan *)data)->pwm[channel].connected))264 return 0;265 266 switch (attr) {267 case hwmon_pwm_input:268 return 0644;269 default:270 break;271 }272 break;273 274 default:275 break;276 }277 278 return 0;279}280 281static char *mlxreg_fan_name[] = {282 "mlxreg_fan",283 "mlxreg_fan1",284 "mlxreg_fan2",285 "mlxreg_fan3",286};287 288static const struct hwmon_channel_info * const mlxreg_fan_hwmon_info[] = {289 HWMON_CHANNEL_INFO(fan,290 HWMON_F_INPUT | HWMON_F_FAULT,291 HWMON_F_INPUT | HWMON_F_FAULT,292 HWMON_F_INPUT | HWMON_F_FAULT,293 HWMON_F_INPUT | HWMON_F_FAULT,294 HWMON_F_INPUT | HWMON_F_FAULT,295 HWMON_F_INPUT | HWMON_F_FAULT,296 HWMON_F_INPUT | HWMON_F_FAULT,297 HWMON_F_INPUT | HWMON_F_FAULT,298 HWMON_F_INPUT | HWMON_F_FAULT,299 HWMON_F_INPUT | HWMON_F_FAULT,300 HWMON_F_INPUT | HWMON_F_FAULT,301 HWMON_F_INPUT | HWMON_F_FAULT,302 HWMON_F_INPUT | HWMON_F_FAULT,303 HWMON_F_INPUT | HWMON_F_FAULT,304 HWMON_F_INPUT | HWMON_F_FAULT,305 HWMON_F_INPUT | HWMON_F_FAULT,306 HWMON_F_INPUT | HWMON_F_FAULT,307 HWMON_F_INPUT | HWMON_F_FAULT,308 HWMON_F_INPUT | HWMON_F_FAULT,309 HWMON_F_INPUT | HWMON_F_FAULT,310 HWMON_F_INPUT | HWMON_F_FAULT,311 HWMON_F_INPUT | HWMON_F_FAULT,312 HWMON_F_INPUT | HWMON_F_FAULT,313 HWMON_F_INPUT | HWMON_F_FAULT),314 HWMON_CHANNEL_INFO(pwm,315 HWMON_PWM_INPUT,316 HWMON_PWM_INPUT,317 HWMON_PWM_INPUT,318 HWMON_PWM_INPUT),319 NULL320};321 322static const struct hwmon_ops mlxreg_fan_hwmon_hwmon_ops = {323 .is_visible = mlxreg_fan_is_visible,324 .read = mlxreg_fan_read,325 .write = mlxreg_fan_write,326};327 328static const struct hwmon_chip_info mlxreg_fan_hwmon_chip_info = {329 .ops = &mlxreg_fan_hwmon_hwmon_ops,330 .info = mlxreg_fan_hwmon_info,331};332 333static int mlxreg_fan_get_max_state(struct thermal_cooling_device *cdev,334 unsigned long *state)335{336 *state = MLXREG_FAN_MAX_STATE;337 return 0;338}339 340static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev,341 unsigned long *state)342 343{344 struct mlxreg_fan_pwm *pwm = cdev->devdata;345 struct mlxreg_fan *fan = pwm->fan;346 u32 regval;347 int err;348 349 err = regmap_read(fan->regmap, pwm->reg, ®val);350 if (err) {351 dev_err(fan->dev, "Failed to query PWM duty\n");352 return err;353 }354 355 *state = MLXREG_FAN_PWM_DUTY2STATE(regval);356 357 return 0;358}359 360static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,361 unsigned long state)362 363{364 struct mlxreg_fan_pwm *pwm = cdev->devdata;365 struct mlxreg_fan *fan = pwm->fan;366 int err;367 368 if (state > MLXREG_FAN_MAX_STATE)369 return -EINVAL;370 371 /* Save thermal state. */372 pwm->last_thermal_state = state;373 374 state = max_t(unsigned long, state, pwm->last_hwmon_state);375 err = regmap_write(fan->regmap, pwm->reg,376 MLXREG_FAN_PWM_STATE2DUTY(state));377 if (err) {378 dev_err(fan->dev, "Failed to write PWM duty\n");379 return err;380 }381 return 0;382}383 384static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = {385 .get_max_state = mlxreg_fan_get_max_state,386 .get_cur_state = mlxreg_fan_get_cur_state,387 .set_cur_state = mlxreg_fan_set_cur_state,388};389 390static int mlxreg_fan_connect_verify(struct mlxreg_fan *fan,391 struct mlxreg_core_data *data)392{393 u32 regval;394 int err;395 396 err = regmap_read(fan->regmap, data->capability, ®val);397 if (err) {398 dev_err(fan->dev, "Failed to query capability register 0x%08x\n",399 data->capability);400 return err;401 }402 403 return !!(regval & data->bit);404}405 406static int mlxreg_pwm_connect_verify(struct mlxreg_fan *fan,407 struct mlxreg_core_data *data)408{409 u32 regval;410 int err;411 412 err = regmap_read(fan->regmap, data->reg, ®val);413 if (err) {414 dev_err(fan->dev, "Failed to query pwm register 0x%08x\n",415 data->reg);416 return err;417 }418 419 return regval != MLXREG_FAN_PWM_NOT_CONNECTED;420}421 422static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan,423 struct mlxreg_core_data *data)424{425 u32 regval;426 int err;427 428 err = regmap_read(fan->regmap, data->capability, ®val);429 if (err) {430 dev_err(fan->dev, "Failed to query capability register 0x%08x\n",431 data->capability);432 return err;433 }434 435 /*436 * Set divider value according to the capability register, in case it437 * contains valid value. Otherwise use default value. The purpose of438 * this validation is to protect against the old hardware, in which439 * this register can return zero.440 */441 if (regval > 0 && regval <= MLXREG_FAN_TACHO_DIV_SCALE_MAX)442 fan->divider = regval * MLXREG_FAN_TACHO_DIV_MIN;443 444 return 0;445}446 447static int mlxreg_fan_config(struct mlxreg_fan *fan,448 struct mlxreg_core_platform_data *pdata)449{450 int tacho_num = 0, tacho_avail = 0, pwm_num = 0, i;451 struct mlxreg_core_data *data = pdata->data;452 bool configured = false;453 int err;454 455 fan->samples = MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF;456 fan->divider = MLXREG_FAN_TACHO_DIV_DEF;457 for (i = 0; i < pdata->counter; i++, data++) {458 if (strnstr(data->label, "tacho", sizeof(data->label))) {459 if (tacho_num == MLXREG_FAN_MAX_TACHO) {460 dev_err(fan->dev, "too many tacho entries: %s\n",461 data->label);462 return -EINVAL;463 }464 465 if (data->capability) {466 err = mlxreg_fan_connect_verify(fan, data);467 if (err < 0)468 return err;469 else if (!err) {470 tacho_num++;471 continue;472 }473 }474 475 fan->tacho[tacho_num].reg = data->reg;476 fan->tacho[tacho_num].mask = data->mask;477 fan->tacho[tacho_num].prsnt = data->reg_prsnt;478 fan->tacho[tacho_num++].connected = true;479 tacho_avail++;480 } else if (strnstr(data->label, "pwm", sizeof(data->label))) {481 if (pwm_num == MLXREG_FAN_MAX_TACHO) {482 dev_err(fan->dev, "too many pwm entries: %s\n",483 data->label);484 return -EINVAL;485 }486 487 /* Validate if more then one PWM is connected. */488 if (pwm_num) {489 err = mlxreg_pwm_connect_verify(fan, data);490 if (err < 0)491 return err;492 else if (!err)493 continue;494 }495 496 fan->pwm[pwm_num].reg = data->reg;497 fan->pwm[pwm_num].connected = true;498 pwm_num++;499 } else if (strnstr(data->label, "conf", sizeof(data->label))) {500 if (configured) {501 dev_err(fan->dev, "duplicate conf entry: %s\n",502 data->label);503 return -EINVAL;504 }505 /* Validate that conf parameters are not zeros. */506 if (!data->mask && !data->bit && !data->capability) {507 dev_err(fan->dev, "invalid conf entry params: %s\n",508 data->label);509 return -EINVAL;510 }511 if (data->capability) {512 err = mlxreg_fan_speed_divider_get(fan, data);513 if (err)514 return err;515 } else {516 if (data->mask)517 fan->samples = data->mask;518 if (data->bit)519 fan->divider = data->bit;520 }521 configured = true;522 } else {523 dev_err(fan->dev, "invalid label: %s\n", data->label);524 return -EINVAL;525 }526 }527 528 if (pdata->capability) {529 int drwr_avail;530 u32 regval;531 532 /* Obtain the number of FAN drawers, supported by system. */533 err = regmap_read(fan->regmap, pdata->capability, ®val);534 if (err) {535 dev_err(fan->dev, "Failed to query capability register 0x%08x\n",536 pdata->capability);537 return err;538 }539 540 drwr_avail = hweight32(regval);541 if (!tacho_avail || !drwr_avail || tacho_avail < drwr_avail) {542 dev_err(fan->dev, "Configuration is invalid: drawers num %d tachos num %d\n",543 drwr_avail, tacho_avail);544 return -EINVAL;545 }546 547 /* Set the number of tachometers per one drawer. */548 fan->tachos_per_drwr = tacho_avail / drwr_avail;549 }550 551 return 0;552}553 554static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan)555{556 int i;557 558 for (i = 0; i < MLXREG_FAN_MAX_PWM; i++) {559 struct mlxreg_fan_pwm *pwm = &fan->pwm[i];560 561 if (!pwm->connected)562 continue;563 pwm->fan = fan;564 pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, mlxreg_fan_name[i],565 pwm, &mlxreg_fan_cooling_ops);566 if (IS_ERR(pwm->cdev)) {567 dev_err(dev, "Failed to register cooling device\n");568 return PTR_ERR(pwm->cdev);569 }570 571 /* Set minimal PWM speed. */572 pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(MLXREG_FAN_MIN_DUTY);573 }574 575 return 0;576}577 578static int mlxreg_fan_probe(struct platform_device *pdev)579{580 struct mlxreg_core_platform_data *pdata;581 struct device *dev = &pdev->dev;582 struct mlxreg_fan *fan;583 struct device *hwm;584 int err;585 586 pdata = dev_get_platdata(dev);587 if (!pdata) {588 dev_err(dev, "Failed to get platform data.\n");589 return -EINVAL;590 }591 592 fan = devm_kzalloc(dev, sizeof(*fan), GFP_KERNEL);593 if (!fan)594 return -ENOMEM;595 596 fan->dev = dev;597 fan->regmap = pdata->regmap;598 599 err = mlxreg_fan_config(fan, pdata);600 if (err)601 return err;602 603 hwm = devm_hwmon_device_register_with_info(dev, "mlxreg_fan",604 fan,605 &mlxreg_fan_hwmon_chip_info,606 NULL);607 if (IS_ERR(hwm)) {608 dev_err(dev, "Failed to register hwmon device\n");609 return PTR_ERR(hwm);610 }611 612 if (IS_REACHABLE(CONFIG_THERMAL))613 err = mlxreg_fan_cooling_config(dev, fan);614 615 return err;616}617 618static struct platform_driver mlxreg_fan_driver = {619 .driver = {620 .name = "mlxreg-fan",621 },622 .probe = mlxreg_fan_probe,623};624 625module_platform_driver(mlxreg_fan_driver);626 627MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");628MODULE_DESCRIPTION("Mellanox FAN driver");629MODULE_LICENSE("GPL");630MODULE_ALIAS("platform:mlxreg-fan");631