Add pwm[1-8]_enable to sysfs

They can be used to switch manual vs. firmware-configured fan mode.
This commit is contained in:
xaizek 2024-01-27 12:17:48 +02:00
parent 8495d82062
commit 735c472f76
No known key found for this signature in database
GPG key ID: 99DC5E4DB05F6BE2
2 changed files with 99 additions and 1 deletions

View file

@ -135,6 +135,7 @@ This module was tested on Ubuntu 20.04 with all kernel available on motherboard
- Add support for MSI B460M Bazooka having NCT6687 with another device ID
- Add support to use generic voltage input without multiplier, allows sensors custom conf
- Support giving fan control back to the firmware
<br>
## VOLTAGE MANUAL CONFIGURATION
@ -217,6 +218,31 @@ echo 128 > pwm6
echo 255 > pwm6
```
### `pwm[1-8]_enable`
Gets/sets controls mode of fan/temperature control.
Accepted values:
* `1` - manual speed management through `pwm[1-8]`
* `99` - whatever automatic mode was configured by firmware
(this is a deliberately weird value to be dropped after adding more
modes)
Example:
```
# fix a fan at current speed (`echo pwm6` will be constant from now on)
echo 1 > pwm6_enable
# switch back to automatic control set up by firmware (`echo pwm6` is again dynamic after this)
echo 99 > pwm6_enable
# switch to ~25% of max speed
echo 64 > pwm6
# automatic
echo 99 > pwm6_enable
# back to ~25% (it seems to be remembered)
echo 1 > pwm6_enable
```
## VERIFIED
**1. Fan speed control**

View file

@ -47,6 +47,13 @@ enum kinds
nct6687
};
enum pwm_mode
{
manual_mode = 1,
// There are multiple automatic modes, none of which is configurable by this module yet.
firmware_mode = 99,
};
static bool force;
static bool manual;
@ -337,6 +344,7 @@ struct nct6687_data
bool _restoreDefaultFanControlRequired[NCT6687_NUM_REG_FAN];
u8 pwm[NCT6687_NUM_REG_PWM];
enum pwm_mode pwm_mode[NCT6687_NUM_REG_PWM];
/* Remember extra register values over suspend/resume */
u8 hwm_cfg;
@ -573,6 +581,16 @@ static void nct6687_update_voltage(struct nct6687_data *data)
pr_debug("nct6687_update_voltage\n");
}
static enum pwm_mode nct6687_get_pwm_mode(struct nct6687_data *data, int index)
{
u16 bitMask = 0x01 << index;
if (nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(index)) & bitMask)
{
return manual_mode;
}
return firmware_mode;
}
static void nct6687_update_fans(struct nct6687_data *data)
{
int i;
@ -591,6 +609,7 @@ static void nct6687_update_fans(struct nct6687_data *data)
for (i = 0; i < NCT6687_NUM_REG_PWM; i++)
{
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
data->pwm_mode[i] = nct6687_get_pwm_mode(data, i);
pr_debug("nct6687_update_fans[%d], pwm=%d", i, data->pwm[i]);
}
@ -797,7 +816,53 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, cons
return count;
}
static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct nct6687_data *data = nct6687_update_device(dev);
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
return sprintf(buf, "%d\n", data->pwm_mode[sattr->nr]);
}
static ssize_t store_pwm_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
struct nct6687_data *data = dev_get_drvdata(dev);
int index = sattr->nr;
unsigned long val;
u16 mode;
u8 bitMask;
if (index >= NCT6687_NUM_REG_FAN || kstrtoul(buf, 10, &val))
return -EINVAL;
if (val != manual_mode && val != firmware_mode)
return -EINVAL;
mutex_lock(&data->update_lock);
nct6687_save_fan_control(data, index);
mode = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(index));
bitMask = (u8)(0x01 << index);
if (val == manual_mode)
{
mode = (u8)(mode | bitMask);
}
else if (val == firmware_mode)
{
mode = (u8)(mode & ~bitMask);
}
nct6687_write(data, NCT6687_REG_FAN_CTRL_MODE(index), mode);
mutex_unlock(&data->update_lock);
return count;
}
SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, store_pwm, 0);
SENSOR_TEMPLATE_2(pwm_mode, "pwm%d_enable", S_IRUGO, show_pwm_mode, store_pwm_mode, 0, 0);
static void nct6687_save_fan_control(struct nct6687_data *data, int index)
{
@ -843,6 +908,7 @@ static umode_t nct6687_pwm_is_visible(struct kobject *kobj, struct attribute *at
static struct sensor_device_template *nct6687_attributes_pwm_template[] = {
&sensor_dev_template_pwm,
&sensor_dev_template_pwm_mode,
NULL,
};
@ -946,8 +1012,14 @@ static void nct6687_setup_pwm(struct nct6687_data *data)
{
data->_initialFanPwmCommand[i] = nct6687_read(data, NCT6687_REG_FAN_PWM_COMMAND(i));
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
data->pwm_mode[i] = nct6687_get_pwm_mode(data, i);
pr_debug("nct6687_setup_pwm[%d], addr=%04X, pwm=%d, _initialFanPwmCommand=%d\n", i, NCT6687_REG_FAN_PWM_COMMAND(i), data->pwm[i], data->_initialFanPwmCommand[i]);
pr_debug("nct6687_setup_pwm[%d], addr=%04X, pwm=%d, pwm_mode=%d, _initialFanPwmCommand=%d\n",
i,
NCT6687_REG_FAN_PWM_COMMAND(i),
data->pwm[i],
data->pwm_mode[i],
data->_initialFanPwmCommand[i]);
}
}