Lines Matching +full:use +full:- +full:internal +full:- +full:divider
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
34 * FAN datasheet defines the formula for RPM calculations as RPM = 15/t-high.
35 * The logic in a programmable device measures the time t-high by sampling the
36 * tachometer every t-sample (with the default value 11.32 uS) and increment
38 * RPM = 15 / (t-sample * (K + Regval)), where:
40 * - 0xff - represents tachometer fault;
41 * - 0xfe - represents tachometer minimum value , which is 4444 RPM;
42 * - 0x00 - represents tachometer maximum value , which is 300000 RPM;
46 * used: RPM = 15 / ((Regval + K) * 11.32) * 10^(-6)), which in the
49 * - for Regval 0x00, RPM will be 15000000 * 100 / (44 * 1132) = 30115;
50 * - for Regval 0xfe, RPM will be 15000000 * 100 / ((254 + 44) * 1132) = 4446;
52 * RPM = 15000000 * 100 / ((Regval + samples) * divider).
65 * struct mlxreg_fan_tacho - tachometer data (internal use):
78 * struct mlxreg_fan_pwm - PWM data (internal use):
89 * struct mlxreg_fan - private data (internal use):
96 * @divider: divider value for tachometer RPM calculation;
107 int divider; member
123 tacho = &fan->tacho[channel]; in mlxreg_fan_read()
126 err = regmap_read(fan->regmap, tacho->reg, ®val); in mlxreg_fan_read()
130 if (MLXREG_FAN_GET_FAULT(regval, tacho->mask)) { in mlxreg_fan_read()
131 /* FAN is broken - return zero for FAN speed. */ in mlxreg_fan_read()
136 *val = MLXREG_FAN_GET_RPM(regval, fan->divider, in mlxreg_fan_read()
137 fan->samples); in mlxreg_fan_read()
141 err = regmap_read(fan->regmap, tacho->reg, ®val); in mlxreg_fan_read()
145 *val = MLXREG_FAN_GET_FAULT(regval, tacho->mask); in mlxreg_fan_read()
149 return -EOPNOTSUPP; in mlxreg_fan_read()
156 err = regmap_read(fan->regmap, fan->pwm.reg, ®val); in mlxreg_fan_read()
164 return -EOPNOTSUPP; in mlxreg_fan_read()
169 return -EOPNOTSUPP; in mlxreg_fan_read()
187 return -EINVAL; in mlxreg_fan_write()
188 return regmap_write(fan->regmap, fan->pwm.reg, val); in mlxreg_fan_write()
190 return -EOPNOTSUPP; in mlxreg_fan_write()
195 return -EOPNOTSUPP; in mlxreg_fan_write()
198 return -EOPNOTSUPP; in mlxreg_fan_write()
207 if (!(((struct mlxreg_fan *)data)->tacho[channel].connected)) in mlxreg_fan_is_visible()
220 if (!(((struct mlxreg_fan *)data)->pwm.connected)) in mlxreg_fan_is_visible()
279 struct mlxreg_fan *fan = cdev->devdata; in mlxreg_fan_get_cur_state()
283 err = regmap_read(fan->regmap, fan->pwm.reg, ®val); in mlxreg_fan_get_cur_state()
285 dev_err(fan->dev, "Failed to query PWM duty\n"); in mlxreg_fan_get_cur_state()
298 struct mlxreg_fan *fan = cdev->devdata; in mlxreg_fan_set_cur_state()
306 * minimum. If it is - update cooling levels accordingly and update in mlxreg_fan_set_cur_state()
309 * changed from 4 to 6, fan->cooling_levels[0 to 5] will be changed all in mlxreg_fan_set_cur_state()
310 * from 4 to 6. And state 5 (fan->cooling_levels[4]) should be in mlxreg_fan_set_cur_state()
316 * For configuration non-zero value is to be returned to avoid thermal in mlxreg_fan_set_cur_state()
320 state -= MLXREG_FAN_MAX_STATE; in mlxreg_fan_set_cur_state()
322 fan->cooling_levels[i] = state; in mlxreg_fan_set_cur_state()
324 fan->cooling_levels[i] = i; in mlxreg_fan_set_cur_state()
326 err = regmap_read(fan->regmap, fan->pwm.reg, ®val); in mlxreg_fan_set_cur_state()
328 dev_err(fan->dev, "Failed to query PWM duty\n"); in mlxreg_fan_set_cur_state()
340 return -EINVAL; in mlxreg_fan_set_cur_state()
343 state = fan->cooling_levels[state]; in mlxreg_fan_set_cur_state()
344 err = regmap_write(fan->regmap, fan->pwm.reg, in mlxreg_fan_set_cur_state()
347 dev_err(fan->dev, "Failed to write PWM duty\n"); in mlxreg_fan_set_cur_state()
365 err = regmap_read(fan->regmap, data->capability, ®val); in mlxreg_fan_connect_verify()
367 dev_err(fan->dev, "Failed to query capability register 0x%08x\n", in mlxreg_fan_connect_verify()
368 data->capability); in mlxreg_fan_connect_verify()
372 return !!(regval & data->bit); in mlxreg_fan_connect_verify()
381 err = regmap_read(fan->regmap, data->capability, ®val); in mlxreg_fan_speed_divider_get()
383 dev_err(fan->dev, "Failed to query capability register 0x%08x\n", in mlxreg_fan_speed_divider_get()
384 data->capability); in mlxreg_fan_speed_divider_get()
389 * Set divider value according to the capability register, in case it in mlxreg_fan_speed_divider_get()
390 * contains valid value. Otherwise use default value. The purpose of in mlxreg_fan_speed_divider_get()
395 fan->divider = regval * MLXREG_FAN_TACHO_DIV_MIN; in mlxreg_fan_speed_divider_get()
403 struct mlxreg_core_data *data = pdata->data; in mlxreg_fan_config()
408 fan->samples = MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF; in mlxreg_fan_config()
409 fan->divider = MLXREG_FAN_TACHO_DIV_DEF; in mlxreg_fan_config()
410 for (i = 0; i < pdata->counter; i++, data++) { in mlxreg_fan_config()
411 if (strnstr(data->label, "tacho", sizeof(data->label))) { in mlxreg_fan_config()
413 dev_err(fan->dev, "too many tacho entries: %s\n", in mlxreg_fan_config()
414 data->label); in mlxreg_fan_config()
415 return -EINVAL; in mlxreg_fan_config()
418 if (data->capability) { in mlxreg_fan_config()
428 fan->tacho[tacho_num].reg = data->reg; in mlxreg_fan_config()
429 fan->tacho[tacho_num].mask = data->mask; in mlxreg_fan_config()
430 fan->tacho[tacho_num++].connected = true; in mlxreg_fan_config()
431 } else if (strnstr(data->label, "pwm", sizeof(data->label))) { in mlxreg_fan_config()
432 if (fan->pwm.connected) { in mlxreg_fan_config()
433 dev_err(fan->dev, "duplicate pwm entry: %s\n", in mlxreg_fan_config()
434 data->label); in mlxreg_fan_config()
435 return -EINVAL; in mlxreg_fan_config()
437 fan->pwm.reg = data->reg; in mlxreg_fan_config()
438 fan->pwm.connected = true; in mlxreg_fan_config()
439 } else if (strnstr(data->label, "conf", sizeof(data->label))) { in mlxreg_fan_config()
441 dev_err(fan->dev, "duplicate conf entry: %s\n", in mlxreg_fan_config()
442 data->label); in mlxreg_fan_config()
443 return -EINVAL; in mlxreg_fan_config()
446 if (!data->mask && !data->bit && !data->capability) { in mlxreg_fan_config()
447 dev_err(fan->dev, "invalid conf entry params: %s\n", in mlxreg_fan_config()
448 data->label); in mlxreg_fan_config()
449 return -EINVAL; in mlxreg_fan_config()
451 if (data->capability) { in mlxreg_fan_config()
456 if (data->mask) in mlxreg_fan_config()
457 fan->samples = data->mask; in mlxreg_fan_config()
458 if (data->bit) in mlxreg_fan_config()
459 fan->divider = data->bit; in mlxreg_fan_config()
463 dev_err(fan->dev, "invalid label: %s\n", data->label); in mlxreg_fan_config()
464 return -EINVAL; in mlxreg_fan_config()
470 fan->cooling_levels[i] = MLXREG_FAN_SPEED_MIN_LEVEL; in mlxreg_fan_config()
472 fan->cooling_levels[i] = i; in mlxreg_fan_config()
480 struct device *dev = &pdev->dev; in mlxreg_fan_probe()
488 return -EINVAL; in mlxreg_fan_probe()
493 return -ENOMEM; in mlxreg_fan_probe()
495 fan->dev = dev; in mlxreg_fan_probe()
496 fan->regmap = pdata->regmap; in mlxreg_fan_probe()
512 fan->cdev = devm_thermal_of_cooling_device_register(dev, in mlxreg_fan_probe()
514 if (IS_ERR(fan->cdev)) { in mlxreg_fan_probe()
516 return PTR_ERR(fan->cdev); in mlxreg_fan_probe()
525 .name = "mlxreg-fan",
535 MODULE_ALIAS("platform:mlxreg-fan");