I have a system that has very over spec'd fans so the amount of noise when they
run at 100% duty cycle is considerable. We have userspace monitoring tools that
will configure appropriate fan control parameters but there is a bit of a delay
between the kernel loading the driver and the userland tools catching up to
configure the fan control. This series adds device properties that allow the
PWM duty cycle to be specified via device properties so the PWM duty cycle can
be reduced as soon as possible.
Apologies for sending the quick v2 but the v1 I sent was an earlier local
iteration than what I meant to send out.
Chris Packham (2):
dt-bindings: hwmon: Document adt7475 PWM initial duty cycle
hwmon: (adt7475) Add support for configuring initial PWM duty cycle
.../devicetree/bindings/hwmon/adt7475.yaml | 27 ++++++++-
drivers/hwmon/adt7475.c | 58 +++++++++++++++++++
2 files changed, 84 insertions(+), 1 deletion(-)
--
2.43.2
By default the PWM duty cycle in hardware is 100%. On some systems this
can cause unwanted fan noise. Add the ability to take an initial PWM
duty cycle and frequency via device properties.
Signed-off-by: Chris Packham <[email protected]>
---
Notes:
Changes in v2:
- Use correct device property string for frequency
- Allow -EINVAL and only warn on error
- Use a frequency of 0 to indicate that the hardware should be left as-is
drivers/hwmon/adt7475.c | 58 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 4224ffb30483..14bd618488f8 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -1662,6 +1662,56 @@ static int adt7475_set_pwm_polarity(struct i2c_client *client)
return 0;
}
+static int adt7475_set_pwm_initial_freq(struct i2c_client *client)
+{
+ int ret, out, i;
+ u32 freqs[ADT7475_PWM_COUNT];
+ int data;
+
+ ret = device_property_read_u32_array(&client->dev,
+ "adi,pwm-initial-frequency", freqs,
+ ARRAY_SIZE(freqs));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+ if (!freqs[i])
+ continue;
+ out = find_closest(freqs[i], pwmfreq_table, ARRAY_SIZE(pwmfreq_table));
+ data = adt7475_read(TEMP_TRANGE_REG(i));
+ if (data < 0)
+ return data;
+ data &= ~0xf;
+ data |= out;
+
+ ret = i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(i), data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int adt7475_set_pwm_initial_duty(struct i2c_client *client)
+{
+ int ret, i;
+ u32 dutys[ADT7475_PWM_COUNT];
+
+ ret = device_property_read_u32_array(&client->dev,
+ "adi,pwm-initial-duty-cycle", dutys,
+ ARRAY_SIZE(dutys));
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+ ret = i2c_smbus_write_byte_data(client, PWM_MAX_REG(i), dutys[i] & 0xff);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int adt7475_probe(struct i2c_client *client)
{
enum chips chip;
@@ -1778,6 +1828,14 @@ static int adt7475_probe(struct i2c_client *client)
if (ret && ret != -EINVAL)
dev_warn(&client->dev, "Error configuring pwm polarity\n");
+ ret = adt7475_set_pwm_initial_freq(client);
+ if (ret && ret != -EINVAL)
+ dev_warn(&client->dev, "Error configuring pwm frequency\n");
+
+ ret = adt7475_set_pwm_initial_duty(client);
+ if (ret && ret != -EINVAL)
+ dev_warn(&client->dev, "Error configuring pwm duty cycle\n");
+
/* Start monitoring */
switch (chip) {
case adt7475:
--
2.43.2