Skip to content

Commit

Permalink
hwmon: (mlxreg-fan) Extend driver to support multiply cooling devices
Browse files Browse the repository at this point in the history
Add support for additional cooling devices in order to support the
systems, which can be equipped with up-to four PWM controllers.

Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Vadim Pasternak authored and Guenter Roeck committed Oct 12, 2021
1 parent 150f1e0 commit d7efb2e
Showing 1 changed file with 47 additions and 26 deletions.
73 changes: 47 additions & 26 deletions drivers/hwmon/mlxreg-fan.c
Original file line number Diff line number Diff line change
@@ -63,6 +63,8 @@
MLXREG_FAN_MAX_DUTY, \
MLXREG_FAN_MAX_STATE))

struct mlxreg_fan;

/*
* struct mlxreg_fan_tacho - tachometer data (internal use):
*
@@ -81,12 +83,18 @@ struct mlxreg_fan_tacho {
/*
* struct mlxreg_fan_pwm - PWM data (internal use):
*
* @fan: private data;
* @connected: indicates if PWM is connected;
* @reg: register offset;
* @cooling: cooling device levels;
* @cdev: cooling device;
*/
struct mlxreg_fan_pwm {
struct mlxreg_fan *fan;
bool connected;
u32 reg;
u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1];
struct thermal_cooling_device *cdev;
};

/*
@@ -99,8 +107,6 @@ struct mlxreg_fan_pwm {
* @tachos_per_drwr - number of tachometers per drawer;
* @samples: minimum allowed samples per pulse;
* @divider: divider value for tachometer RPM calculation;
* @cooling: cooling device levels;
* @cdev: cooling device;
*/
struct mlxreg_fan {
struct device *dev;
@@ -111,8 +117,6 @@ struct mlxreg_fan {
int tachos_per_drwr;
int samples;
int divider;
u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1];
struct thermal_cooling_device *cdev;
};

static int
@@ -305,11 +309,12 @@ static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev,
unsigned long *state)

{
struct mlxreg_fan *fan = cdev->devdata;
struct mlxreg_fan_pwm *pwm = cdev->devdata;
struct mlxreg_fan *fan = pwm->fan;
u32 regval;
int err;

err = regmap_read(fan->regmap, fan->pwm[0].reg, &regval);
err = regmap_read(fan->regmap, pwm->reg, &regval);
if (err) {
dev_err(fan->dev, "Failed to query PWM duty\n");
return err;
@@ -324,7 +329,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
unsigned long state)

{
struct mlxreg_fan *fan = cdev->devdata;
struct mlxreg_fan_pwm *pwm = cdev->devdata;
struct mlxreg_fan *fan = pwm->fan;
unsigned long cur_state;
int i, config = 0;
u32 regval;
@@ -348,11 +354,11 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
config = 1;
state -= MLXREG_FAN_MAX_STATE;
for (i = 0; i < state; i++)
fan->cooling_levels[i] = state;
pwm->cooling_levels[i] = state;
for (i = state; i <= MLXREG_FAN_MAX_STATE; i++)
fan->cooling_levels[i] = i;
pwm->cooling_levels[i] = i;

err = regmap_read(fan->regmap, fan->pwm[0].reg, &regval);
err = regmap_read(fan->regmap, pwm->reg, &regval);
if (err) {
dev_err(fan->dev, "Failed to query PWM duty\n");
return err;
@@ -369,8 +375,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
return -EINVAL;

/* Normalize the state to the valid speed range. */
state = fan->cooling_levels[state];
err = regmap_write(fan->regmap, fan->pwm[0].reg,
state = pwm->cooling_levels[state];
err = regmap_write(fan->regmap, pwm->reg,
MLXREG_FAN_PWM_STATE2DUTY(state));
if (err) {
dev_err(fan->dev, "Failed to write PWM duty\n");
@@ -541,11 +547,32 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan,
fan->tachos_per_drwr = tacho_avail / drwr_avail;
}

/* Init cooling levels per PWM state. */
for (i = 0; i < MLXREG_FAN_SPEED_MIN_LEVEL; i++)
fan->cooling_levels[i] = MLXREG_FAN_SPEED_MIN_LEVEL;
for (i = MLXREG_FAN_SPEED_MIN_LEVEL; i <= MLXREG_FAN_MAX_STATE; i++)
fan->cooling_levels[i] = i;
return 0;
}

static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan)
{
int i, j;

for (i = 0; i <= MLXREG_FAN_MAX_PWM; i++) {
struct mlxreg_fan_pwm *pwm = &fan->pwm[i];

if (!pwm->connected)
continue;
pwm->fan = fan;
pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, "mlxreg_fan", pwm,
&mlxreg_fan_cooling_ops);
if (IS_ERR(pwm->cdev)) {
dev_err(dev, "Failed to register cooling device\n");
return PTR_ERR(pwm->cdev);
}

/* Init cooling levels per PWM state. */
for (j = 0; j < MLXREG_FAN_SPEED_MIN_LEVEL; j++)
pwm->cooling_levels[j] = MLXREG_FAN_SPEED_MIN_LEVEL;
for (j = MLXREG_FAN_SPEED_MIN_LEVEL; j <= MLXREG_FAN_MAX_STATE; j++)
pwm->cooling_levels[j] = j;
}

return 0;
}
@@ -584,16 +611,10 @@ static int mlxreg_fan_probe(struct platform_device *pdev)
return PTR_ERR(hwm);
}

if (IS_REACHABLE(CONFIG_THERMAL)) {
fan->cdev = devm_thermal_of_cooling_device_register(dev,
NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops);
if (IS_ERR(fan->cdev)) {
dev_err(dev, "Failed to register cooling device\n");
return PTR_ERR(fan->cdev);
}
}
if (IS_REACHABLE(CONFIG_THERMAL))
err = mlxreg_fan_cooling_config(dev, fan);

return 0;
return err;
}

static struct platform_driver mlxreg_fan_driver = {

0 comments on commit d7efb2e

Please sign in to comment.