Lines Matching +full:pwm +full:- +full:fan
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
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 the
29 * tachometer every t-sample (with the default value 11.32 uS) and increment
31 * RPM = 15 / (t-sample * (K + Regval)), where:
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;
39 * used: RPM = 15 / ((Regval + K) * 11.32) * 10^(-6)), which in the
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;
60 * struct mlxreg_fan_tacho - tachometer data (internal use):
77 * struct mlxreg_fan_pwm - PWM data (internal use):
79 * @fan: private data;
80 * @connected: indicates if PWM is connected;
88 struct mlxreg_fan *fan; member
97 * struct mlxreg_fan - private data (internal use):
102 * @pwm: PWM data;
103 * @tachos_per_drwr - number of tachometers per drawer;
112 struct mlxreg_fan_pwm pwm[MLXREG_FAN_MAX_PWM]; member
125 struct mlxreg_fan *fan = dev_get_drvdata(dev); in mlxreg_fan_read() local
127 struct mlxreg_fan_pwm *pwm; in mlxreg_fan_read() local
133 tacho = &fan->tacho[channel]; in mlxreg_fan_read()
137 * Check FAN presence: FAN related bit in presence register is one, in mlxreg_fan_read()
138 * if FAN is physically connected, zero - otherwise. in mlxreg_fan_read()
140 if (tacho->prsnt && fan->tachos_per_drwr) { in mlxreg_fan_read()
141 err = regmap_read(fan->regmap, tacho->prsnt, ®val); in mlxreg_fan_read()
146 * Map channel to presence bit - drawer can be equipped with in mlxreg_fan_read()
150 if (BIT(rol32(channel, tacho->shift) / fan->tachos_per_drwr) & in mlxreg_fan_read()
152 /* FAN is not connected - return zero for FAN speed. */ in mlxreg_fan_read()
158 err = regmap_read(fan->regmap, tacho->reg, ®val); in mlxreg_fan_read()
162 if (MLXREG_FAN_GET_FAULT(regval, tacho->mask)) { in mlxreg_fan_read()
163 /* FAN is broken - return zero for FAN speed. */ in mlxreg_fan_read()
168 *val = MLXREG_FAN_GET_RPM(regval, fan->divider, in mlxreg_fan_read()
169 fan->samples); in mlxreg_fan_read()
173 err = regmap_read(fan->regmap, tacho->reg, ®val); in mlxreg_fan_read()
177 *val = MLXREG_FAN_GET_FAULT(regval, tacho->mask); in mlxreg_fan_read()
181 return -EOPNOTSUPP; in mlxreg_fan_read()
186 pwm = &fan->pwm[channel]; in mlxreg_fan_read()
189 err = regmap_read(fan->regmap, pwm->reg, ®val); in mlxreg_fan_read()
197 return -EOPNOTSUPP; in mlxreg_fan_read()
202 return -EOPNOTSUPP; in mlxreg_fan_read()
212 struct mlxreg_fan *fan = dev_get_drvdata(dev); in mlxreg_fan_write() local
213 struct mlxreg_fan_pwm *pwm; in mlxreg_fan_write() local
221 return -EINVAL; in mlxreg_fan_write()
222 pwm = &fan->pwm[channel]; in mlxreg_fan_write()
223 /* If thermal is configured - handle PWM limit setting. */ in mlxreg_fan_write()
225 pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(val); in mlxreg_fan_write()
227 * Update PWM only in case requested state is not less than the in mlxreg_fan_write()
230 if (pwm->last_hwmon_state >= pwm->last_thermal_state) in mlxreg_fan_write()
231 return _mlxreg_fan_set_cur_state(pwm->cdev, in mlxreg_fan_write()
232 pwm->last_hwmon_state, in mlxreg_fan_write()
236 return regmap_write(fan->regmap, pwm->reg, val); in mlxreg_fan_write()
238 return -EOPNOTSUPP; in mlxreg_fan_write()
243 return -EOPNOTSUPP; in mlxreg_fan_write()
246 return -EOPNOTSUPP; in mlxreg_fan_write()
255 if (!(((struct mlxreg_fan *)data)->tacho[channel].connected)) in mlxreg_fan_is_visible()
268 if (!(((struct mlxreg_fan *)data)->pwm[channel].connected)) in mlxreg_fan_is_visible()
294 HWMON_CHANNEL_INFO(fan,
319 HWMON_CHANNEL_INFO(pwm,
349 struct mlxreg_fan_pwm *pwm = cdev->devdata; in mlxreg_fan_get_cur_state() local
350 struct mlxreg_fan *fan = pwm->fan; in mlxreg_fan_get_cur_state() local
354 err = regmap_read(fan->regmap, pwm->reg, ®val); in mlxreg_fan_get_cur_state()
356 dev_err(fan->dev, "Failed to query PWM duty\n"); in mlxreg_fan_get_cur_state()
368 struct mlxreg_fan_pwm *pwm = cdev->devdata; in _mlxreg_fan_set_cur_state() local
369 struct mlxreg_fan *fan = pwm->fan; in _mlxreg_fan_set_cur_state() local
373 return -EINVAL; in _mlxreg_fan_set_cur_state()
377 pwm->last_thermal_state = state; in _mlxreg_fan_set_cur_state()
379 state = max_t(unsigned long, state, pwm->last_hwmon_state); in _mlxreg_fan_set_cur_state()
380 err = regmap_write(fan->regmap, pwm->reg, in _mlxreg_fan_set_cur_state()
383 dev_err(fan->dev, "Failed to write PWM duty\n"); in _mlxreg_fan_set_cur_state()
402 static int mlxreg_fan_connect_verify(struct mlxreg_fan *fan, in mlxreg_fan_connect_verify() argument
408 err = regmap_read(fan->regmap, data->capability, ®val); in mlxreg_fan_connect_verify()
410 dev_err(fan->dev, "Failed to query capability register 0x%08x\n", in mlxreg_fan_connect_verify()
411 data->capability); in mlxreg_fan_connect_verify()
415 return data->slot ? (data->slot <= regval ? 1 : 0) : !!(regval & data->bit); in mlxreg_fan_connect_verify()
418 static int mlxreg_pwm_connect_verify(struct mlxreg_fan *fan, in mlxreg_pwm_connect_verify() argument
424 err = regmap_read(fan->regmap, data->reg, ®val); in mlxreg_pwm_connect_verify()
426 dev_err(fan->dev, "Failed to query pwm register 0x%08x\n", in mlxreg_pwm_connect_verify()
427 data->reg); in mlxreg_pwm_connect_verify()
434 static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan, in mlxreg_fan_speed_divider_get() argument
440 err = regmap_read(fan->regmap, data->capability, ®val); in mlxreg_fan_speed_divider_get()
442 dev_err(fan->dev, "Failed to query capability register 0x%08x\n", in mlxreg_fan_speed_divider_get()
443 data->capability); in mlxreg_fan_speed_divider_get()
454 fan->divider = regval * MLXREG_FAN_TACHO_DIV_MIN; in mlxreg_fan_speed_divider_get()
459 static int mlxreg_fan_config(struct mlxreg_fan *fan, in mlxreg_fan_config() argument
463 struct mlxreg_core_data *data = pdata->data; in mlxreg_fan_config()
467 fan->samples = MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF; in mlxreg_fan_config()
468 fan->divider = MLXREG_FAN_TACHO_DIV_DEF; in mlxreg_fan_config()
469 for (i = 0; i < pdata->counter; i++, data++) { in mlxreg_fan_config()
470 if (strnstr(data->label, "tacho", sizeof(data->label))) { in mlxreg_fan_config()
472 dev_err(fan->dev, "too many tacho entries: %s\n", in mlxreg_fan_config()
473 data->label); in mlxreg_fan_config()
474 return -EINVAL; in mlxreg_fan_config()
477 if (data->capability) { in mlxreg_fan_config()
478 err = mlxreg_fan_connect_verify(fan, data); in mlxreg_fan_config()
487 fan->tacho[tacho_num].reg = data->reg; in mlxreg_fan_config()
488 fan->tacho[tacho_num].mask = data->mask; in mlxreg_fan_config()
489 fan->tacho[tacho_num].prsnt = data->reg_prsnt; in mlxreg_fan_config()
490 fan->tacho[tacho_num++].connected = true; in mlxreg_fan_config()
492 } else if (strnstr(data->label, "pwm", sizeof(data->label))) { in mlxreg_fan_config()
494 dev_err(fan->dev, "too many pwm entries: %s\n", in mlxreg_fan_config()
495 data->label); in mlxreg_fan_config()
496 return -EINVAL; in mlxreg_fan_config()
499 /* Validate if more then one PWM is connected. */ in mlxreg_fan_config()
501 err = mlxreg_pwm_connect_verify(fan, data); in mlxreg_fan_config()
508 fan->pwm[pwm_num].reg = data->reg; in mlxreg_fan_config()
509 fan->pwm[pwm_num].connected = true; in mlxreg_fan_config()
511 } else if (strnstr(data->label, "conf", sizeof(data->label))) { in mlxreg_fan_config()
513 dev_err(fan->dev, "duplicate conf entry: %s\n", in mlxreg_fan_config()
514 data->label); in mlxreg_fan_config()
515 return -EINVAL; in mlxreg_fan_config()
518 if (!data->mask && !data->bit && !data->capability) { in mlxreg_fan_config()
519 dev_err(fan->dev, "invalid conf entry params: %s\n", in mlxreg_fan_config()
520 data->label); in mlxreg_fan_config()
521 return -EINVAL; in mlxreg_fan_config()
523 if (data->capability) { in mlxreg_fan_config()
524 err = mlxreg_fan_speed_divider_get(fan, data); in mlxreg_fan_config()
528 if (data->mask) in mlxreg_fan_config()
529 fan->samples = data->mask; in mlxreg_fan_config()
530 if (data->bit) in mlxreg_fan_config()
531 fan->divider = data->bit; in mlxreg_fan_config()
535 dev_err(fan->dev, "invalid label: %s\n", data->label); in mlxreg_fan_config()
536 return -EINVAL; in mlxreg_fan_config()
540 if (pdata->capability) { in mlxreg_fan_config()
544 /* Obtain the number of FAN drawers, supported by system. */ in mlxreg_fan_config()
545 err = regmap_read(fan->regmap, pdata->capability, ®val); in mlxreg_fan_config()
547 dev_err(fan->dev, "Failed to query capability register 0x%08x\n", in mlxreg_fan_config()
548 pdata->capability); in mlxreg_fan_config()
557 if (pdata->version) in mlxreg_fan_config()
562 dev_err(fan->dev, "Configuration is invalid: drawers num %d tachos num %d\n", in mlxreg_fan_config()
564 return -EINVAL; in mlxreg_fan_config()
568 fan->tachos_per_drwr = tacho_avail / drwr_avail; in mlxreg_fan_config()
574 static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan) in mlxreg_fan_cooling_config() argument
579 struct mlxreg_fan_pwm *pwm = &fan->pwm[i]; in mlxreg_fan_cooling_config() local
581 if (!pwm->connected) in mlxreg_fan_cooling_config()
583 pwm->fan = fan; in mlxreg_fan_cooling_config()
584 /* Set minimal PWM speed. */ in mlxreg_fan_cooling_config()
585 pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(MLXREG_FAN_MIN_DUTY); in mlxreg_fan_cooling_config()
586 pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, mlxreg_fan_name[i], in mlxreg_fan_cooling_config()
587 pwm, &mlxreg_fan_cooling_ops); in mlxreg_fan_cooling_config()
588 if (IS_ERR(pwm->cdev)) { in mlxreg_fan_cooling_config()
590 return PTR_ERR(pwm->cdev); in mlxreg_fan_cooling_config()
600 struct device *dev = &pdev->dev; in mlxreg_fan_probe()
601 struct mlxreg_fan *fan; in mlxreg_fan_probe() local
608 return -EINVAL; in mlxreg_fan_probe()
611 fan = devm_kzalloc(dev, sizeof(*fan), GFP_KERNEL); in mlxreg_fan_probe()
612 if (!fan) in mlxreg_fan_probe()
613 return -ENOMEM; in mlxreg_fan_probe()
615 fan->dev = dev; in mlxreg_fan_probe()
616 fan->regmap = pdata->regmap; in mlxreg_fan_probe()
618 err = mlxreg_fan_config(fan, pdata); in mlxreg_fan_probe()
623 fan, in mlxreg_fan_probe()
632 err = mlxreg_fan_cooling_config(dev, fan); in mlxreg_fan_probe()
639 .name = "mlxreg-fan",
647 MODULE_DESCRIPTION("Mellanox FAN driver");
649 MODULE_ALIAS("platform:mlxreg-fan");