Skip to content

Instantly share code, notes, and snippets.

@dominikpaulus
Created June 8, 2024 20:26
Show Gist options
  • Save dominikpaulus/278886a1955397972bf2ecdd80d69b42 to your computer and use it in GitHub Desktop.
Save dominikpaulus/278886a1955397972bf2ecdd80d69b42 to your computer and use it in GitHub Desktop.
Kernel patch to support (rudimentary) fan control in the FTS Teutates kernel driver
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c
index a3a0766..49a7cd5 100644
--- a/drivers/hwmon/ftsteutates.c
+++ b/drivers/hwmon/ftsteutates.c
@@ -79,6 +79,7 @@ struct fts_data {
u8 fan_present;
u8 fan_input[FTS_NO_FAN_SENSORS]; /* in rps */
u8 fan_source[FTS_NO_FAN_SENSORS];
+ u8 pwm_input[FTS_NO_FAN_SENSORS];
u8 fan_alarm;
};
@@ -86,6 +87,8 @@ struct fts_data {
#define FTS_REG_FAN_SOURCE(idx) ((idx) + 0x30)
#define FTS_REG_FAN_CONTROL(idx) (((idx) << 16) + 0x4881)
+#define FTS_REG_FAN_PWM(idx) (((idx) << 8) + 0x4886)
+
#define FTS_REG_TEMP_INPUT(idx) ((idx) + 0x40)
#define FTS_REG_TEMP_CONTROL(idx) (((idx) << 16) + 0x0681)
@@ -184,9 +187,15 @@ static int fts_update_device(struct fts_data *data)
if (err < 0)
goto exit;
data->fan_source[i] = err;
+
+ err = fts_read_byte(data->client, FTS_REG_FAN_PWM(i));
+ if (err < 0)
+ goto exit;
+ data->pwm_input[i] = err;
} else {
data->fan_input[i] = 0;
data->fan_source[i] = FTS_FAN_SOURCE_INVALID;
+ data->pwm_input[i] = 0;
}
}
@@ -365,6 +374,14 @@ static umode_t fts_is_visible(const void *devdata, enum hwmon_sensor_types type,
}
break;
case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_enable:
+ case hwmon_pwm_input:
+ return 0644;
+ default:
+ break;
+ }
+ break;
case hwmon_in:
return 0444;
default:
@@ -423,6 +440,12 @@ static int fts_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
break;
case hwmon_pwm:
switch (attr) {
+ case hwmon_pwm_input:
+ *val = data->pwm_input[channel];
+ return 0;
+ case hwmon_pwm_enable:
+ *val = 1;
+ return 0;
case hwmon_pwm_auto_channels_temp:
if (data->fan_source[channel] == FTS_FAN_SOURCE_INVALID)
*val = 0;
@@ -484,6 +507,29 @@ static int fts_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
break;
}
break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ if (val < 0 || val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ ret = fts_write_byte(data->client, FTS_REG_FAN_PWM(channel), val);
+ if (ret >= 0)
+ data->valid = false;
+
+ mutex_unlock(&data->update_lock);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+ case hwmon_pwm_enable:
+ return 0;
+ default:
+ break;
+ }
+ break;
case hwmon_fan:
switch (attr) {
case hwmon_fan_alarm:
@@ -551,14 +597,14 @@ static const struct hwmon_channel_info * const fts_info[] = {
HWMON_F_INPUT | HWMON_F_ALARM | HWMON_F_FAULT
),
HWMON_CHANNEL_INFO(pwm,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP,
- HWMON_PWM_AUTO_CHANNELS_TEMP
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE
),
HWMON_CHANNEL_INFO(in,
HWMON_I_INPUT,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment