From patchwork Wed May 12 01:30:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= X-Patchwork-Id: 12252469 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD4D6C433B4 for ; Wed, 12 May 2021 01:31:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8BAD261927 for ; Wed, 12 May 2021 01:31:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229924AbhELBcG (ORCPT ); Tue, 11 May 2021 21:32:06 -0400 Received: from mail-ej1-f50.google.com ([209.85.218.50]:40911 "EHLO mail-ej1-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229736AbhELBcG (ORCPT ); Tue, 11 May 2021 21:32:06 -0400 Received: by mail-ej1-f50.google.com with SMTP id n2so32537742ejy.7; Tue, 11 May 2021 18:30:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=8vN57tc+R9hCBTn9Gn7iqqxIUedyS/lu3ldsWeszRTk=; b=jo+5AaauKV8XwgBZEc++siXOuVZ+36ArcLYUdWpXPKeQw5/OuTkJQAqtD3wOt/tdAR VuS57UMunDx5Y0Zkqe6vBqNgB+sHFp/UF8Z5IpOHEi5OxT90aHW5cyU9aq+cSb1c8GGq rlVPTewCu0P1fuBCYjy/BeRXbuOb9Hcd/IeVE0WEtC7/FFBehbN309TJfOr6ze8U2n5v cO/m+R9brzRmt6Y/N8G3bUQxKo0B4NwibhMaLNmm8eWUpGFxN6D0Dx4hKsSXhzOe+/WH JgIk22XYXwEi965KOiGl6wPMO4yDDkmMQ2Ua7vJ/5cZflqiFTaOhNDdE+XQ2g6i6ZYoK W2Gw== X-Gm-Message-State: AOAM531Dglqcedszgy998qf6/RRRJ54X1vh48WHrpiX56KVy+Nf7f/eX Ig0C8saqUMsBxjT9Zl4MjZ4= X-Google-Smtp-Source: ABdhPJynP0+45XLQLKgIsayB/9bUdi9a50i/8RizbVOnKU+z7SAOu3OJvNOvh6znf181H1sJZKy0AA== X-Received: by 2002:a17:906:7302:: with SMTP id di2mr16064552ejc.409.1620783058107; Tue, 11 May 2021 18:30:58 -0700 (PDT) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id w2sm14460577edl.53.2021.05.11.18.30.57 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 May 2021 18:30:57 -0700 (PDT) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= To: Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Subject: [PATCH v5 1/5] hwmon: (max31790) Rework to use regmap Date: Wed, 12 May 2021 03:30:47 +0200 Message-Id: <20210512013052.903297-1-kubernat@cesnet.cz> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org Converting the driver to use regmap makes it more generic. It also makes it a lot easier to debug through debugfs. Signed-off-by: Václav Kubernát --- drivers/hwmon/Kconfig | 1 + drivers/hwmon/max31790.c | 254 ++++++++++++++++++++------------------- 2 files changed, 133 insertions(+), 122 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 54f04e61fb83..c2ec57672c4e 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1092,6 +1092,7 @@ config SENSORS_MAX6697 config SENSORS_MAX31790 tristate "Maxim MAX31790 sensor chip" depends on I2C + select REGMAP_I2C help If you say yes here you get support for 6-Channel PWM-Output Fan RPM Controller. diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 2c6b333a28e9..e3765ce4444a 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -12,6 +12,7 @@ #include #include #include +#include #include /* MAX31790 registers */ @@ -46,92 +47,53 @@ #define NR_CHANNEL 6 +#define MAX31790_REG_USER_BYTE_67 0x67 + +#define BULK_TO_U16(msb, lsb) (((msb) << 8) + (lsb)) +#define U16_MSB(num) (((num) & 0xFF00) >> 8) +#define U16_LSB(num) ((num) & 0x00FF) + +static const struct regmap_range max31790_ro_range = { + .range_min = MAX31790_REG_TACH_COUNT(0), + .range_max = MAX31790_REG_PWMOUT(0) - 1, +}; + +static const struct regmap_access_table max31790_wr_table = { + .no_ranges = &max31790_ro_range, + .n_no_ranges = 1, +}; + +static const struct regmap_range max31790_volatile_ranges[] = { + regmap_reg_range(MAX31790_REG_TACH_COUNT(0), MAX31790_REG_TACH_COUNT(12)), + regmap_reg_range(MAX31790_REG_FAN_FAULT_STATUS2, MAX31790_REG_FAN_FAULT_STATUS1), +}; + +static const struct regmap_access_table max31790_volatile_table = { + .no_ranges = max31790_volatile_ranges, + .n_no_ranges = 2, + .n_yes_ranges = 0 +}; + +static const struct regmap_config max31790_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .reg_stride = 1, + .max_register = MAX31790_REG_USER_BYTE_67, + .wr_table = &max31790_wr_table, + .volatile_table = &max31790_volatile_table +}; + /* * Client data (each client gets its own) */ struct max31790_data { - struct i2c_client *client; + struct regmap *regmap; + struct mutex update_lock; - bool valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* register values */ u8 fan_config[NR_CHANNEL]; u8 fan_dynamics[NR_CHANNEL]; - u16 fault_status; - u16 tach[NR_CHANNEL * 2]; - u16 pwm[NR_CHANNEL]; - u16 target_count[NR_CHANNEL]; }; -static struct max31790_data *max31790_update_device(struct device *dev) -{ - struct max31790_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - struct max31790_data *ret = data; - int i; - int rv; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_FAULT_STATUS1); - if (rv < 0) - goto abort; - data->fault_status = rv & 0x3F; - - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_FAULT_STATUS2); - if (rv < 0) - goto abort; - data->fault_status |= (rv & 0x3F) << 6; - - for (i = 0; i < NR_CHANNEL; i++) { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TACH_COUNT(i)); - if (rv < 0) - goto abort; - data->tach[i] = rv; - - if (data->fan_config[i] - & MAX31790_FAN_CFG_TACH_INPUT) { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TACH_COUNT(NR_CHANNEL - + i)); - if (rv < 0) - goto abort; - data->tach[NR_CHANNEL + i] = rv; - } else { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_PWMOUT(i)); - if (rv < 0) - goto abort; - data->pwm[i] = rv; - - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TARGET_COUNT(i)); - if (rv < 0) - goto abort; - data->target_count[i] = rv; - } - } - - data->last_updated = jiffies; - data->valid = true; - } - goto done; - -abort: - data->valid = false; - ret = ERR_PTR(rv); - -done: - mutex_unlock(&data->update_lock); - - return ret; -} - static const u8 tach_period[8] = { 1, 2, 4, 8, 16, 32, 32, 32 }; static u8 get_tach_period(u8 fan_dynamics) @@ -159,28 +121,75 @@ static u8 bits_for_tach_period(int rpm) return bits; } +static int read_reg_byte(struct regmap *regmap, u8 reg) +{ + int rv; + int val; + + rv = regmap_read(regmap, reg, &val); + if (rv < 0) + return rv; + + return val; +} + +static int read_reg_word(struct regmap *regmap, u8 reg) +{ + int rv; + u8 val_bulk[2]; + + rv = regmap_bulk_read(regmap, reg, val_bulk, 2); + if (rv < 0) + return rv; + + return BULK_TO_U16(val_bulk[0], val_bulk[1]); +} + +static int write_reg_word(struct regmap *regmap, u8 reg, u16 val) +{ + u8 bulk_val[2]; + + bulk_val[0] = U16_MSB(val); + bulk_val[1] = U16_LSB(val); + + return regmap_bulk_write(regmap, reg, bulk_val, 2); +} + static int max31790_read_fan(struct device *dev, u32 attr, int channel, long *val) { - struct max31790_data *data = max31790_update_device(dev); - int sr, rpm; - - if (IS_ERR(data)) - return PTR_ERR(data); + struct max31790_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + int tach, fault; switch (attr) { case hwmon_fan_input: - sr = get_tach_period(data->fan_dynamics[channel]); - rpm = RPM_FROM_REG(data->tach[channel], sr); - *val = rpm; + tach = read_reg_word(regmap, MAX31790_REG_TACH_COUNT(channel)); + if (tach < 0) + return tach; + + *val = RPM_FROM_REG(tach, get_tach_period(data->fan_dynamics[channel])); return 0; case hwmon_fan_target: - sr = get_tach_period(data->fan_dynamics[channel]); - rpm = RPM_FROM_REG(data->target_count[channel], sr); - *val = rpm; + tach = read_reg_word(regmap, MAX31790_REG_TARGET_COUNT(channel)); + if (tach < 0) + return tach; + + *val = RPM_FROM_REG(tach, get_tach_period(data->fan_dynamics[channel])); return 0; case hwmon_fan_fault: - *val = !!(data->fault_status & (1 << channel)); + if (channel > 6) + fault = read_reg_byte(regmap, MAX31790_REG_FAN_FAULT_STATUS2); + else + fault = read_reg_byte(regmap, MAX31790_REG_FAN_FAULT_STATUS1); + + if (fault < 0) + return fault; + + if (channel > 6) + *val = !!(fault & (1 << (channel - 6))); + else + *val = !!(fault & (1 << channel)); return 0; default: return -EOPNOTSUPP; @@ -191,7 +200,7 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, long val) { struct max31790_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; + struct regmap *regmap = data->regmap; int target_count; int err = 0; u8 bits; @@ -207,9 +216,10 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, ((data->fan_dynamics[channel] & ~MAX31790_FAN_DYN_SR_MASK) | (bits << MAX31790_FAN_DYN_SR_SHIFT)); - err = i2c_smbus_write_byte_data(client, - MAX31790_REG_FAN_DYNAMICS(channel), - data->fan_dynamics[channel]); + + err = regmap_write(regmap, + MAX31790_REG_FAN_DYNAMICS(channel), + data->fan_dynamics[channel]); if (err < 0) break; @@ -217,11 +227,11 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, target_count = RPM_TO_REG(val, sr); target_count = clamp_val(target_count, 0x1, 0x7FF); - data->target_count[channel] = target_count << 5; + target_count = target_count << 5; - err = i2c_smbus_write_word_swapped(client, - MAX31790_REG_TARGET_COUNT(channel), - data->target_count[channel]); + err = write_reg_word(regmap, + MAX31790_REG_TARGET_COUNT(channel), + target_count); break; default: err = -EOPNOTSUPP; @@ -258,22 +268,22 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) static int max31790_read_pwm(struct device *dev, u32 attr, int channel, long *val) { - struct max31790_data *data = max31790_update_device(dev); - u8 fan_config; - - if (IS_ERR(data)) - return PTR_ERR(data); - - fan_config = data->fan_config[channel]; + struct max31790_data *data = dev_get_drvdata(dev); + struct regmap *regmap = data->regmap; + int read; switch (attr) { case hwmon_pwm_input: - *val = data->pwm[channel] >> 8; + read = read_reg_word(regmap, MAX31790_REG_PWMOUT(channel)); + if (read < 0) + return read; + + *val = read >> 8; return 0; case hwmon_pwm_enable: - if (fan_config & MAX31790_FAN_CFG_RPM_MODE) + if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) *val = 2; - else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN) + else if (data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN) *val = 1; else *val = 0; @@ -287,7 +297,7 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, long val) { struct max31790_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; + struct regmap *regmap = data->regmap; u8 fan_config; int err = 0; @@ -299,10 +309,7 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, err = -EINVAL; break; } - data->pwm[channel] = val << 8; - err = i2c_smbus_write_word_swapped(client, - MAX31790_REG_PWMOUT(channel), - data->pwm[channel]); + err = write_reg_word(regmap, MAX31790_REG_PWMOUT(channel), val << 8); break; case hwmon_pwm_enable: fan_config = data->fan_config[channel]; @@ -321,9 +328,9 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, break; } data->fan_config[channel] = fan_config; - err = i2c_smbus_write_byte_data(client, - MAX31790_REG_FAN_CONFIG(channel), - fan_config); + err = regmap_write(regmap, + MAX31790_REG_FAN_CONFIG(channel), + fan_config); break; default: err = -EOPNOTSUPP; @@ -426,20 +433,18 @@ static const struct hwmon_chip_info max31790_chip_info = { .info = max31790_info, }; -static int max31790_init_client(struct i2c_client *client, +static int max31790_init_client(struct regmap *regmap, struct max31790_data *data) { int i, rv; for (i = 0; i < NR_CHANNEL; i++) { - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_CONFIG(i)); + rv = read_reg_byte(regmap, MAX31790_REG_FAN_CONFIG(i % NR_CHANNEL)); if (rv < 0) return rv; data->fan_config[i] = rv; - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_DYNAMICS(i)); + rv = read_reg_byte(regmap, MAX31790_REG_FAN_DYNAMICS(i)); if (rv < 0) return rv; data->fan_dynamics[i] = rv; @@ -464,13 +469,18 @@ static int max31790_probe(struct i2c_client *client) if (!data) return -ENOMEM; - data->client = client; mutex_init(&data->update_lock); + data->regmap = devm_regmap_init_i2c(client, &max31790_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(dev, "failed to allocate register map\n"); + return PTR_ERR(data->regmap); + } + /* * Initialize the max31790 chip */ - err = max31790_init_client(client, data); + err = max31790_init_client(data->regmap, data); if (err) return err; From patchwork Wed May 12 01:30:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= X-Patchwork-Id: 12252471 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 19181C433B4 for ; Wed, 12 May 2021 01:31:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EEBEC6192B for ; Wed, 12 May 2021 01:31:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230023AbhELBcJ (ORCPT ); Tue, 11 May 2021 21:32:09 -0400 Received: from mail-ed1-f48.google.com ([209.85.208.48]:39693 "EHLO mail-ed1-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230017AbhELBcJ (ORCPT ); Tue, 11 May 2021 21:32:09 -0400 Received: by mail-ed1-f48.google.com with SMTP id g14so25126880edy.6; Tue, 11 May 2021 18:31:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W2LPQNpqysjiedw+vGFOOc8M6RDI6cAuhNGnMNZnU6c=; b=WlyE4qMxN1rchWv7alG+SsaZMGoOB/fo0cMaSBo17gJoqTOJEEZKY6EtL0sffug9cD XtYQy5TjDRzI7L5m4pPLTyyuIHECD71EvAVNk1wk6q9N3GqHKEtaoCyum9gq63AjRtT5 f4pj0s3hY2UAbTg35w6Z3qsDKYZ4EvGSuOLZOFVupmuaiMxu9EyZrMftmtqN9FQ/Kfwq 6hixGN1LSPQ9gRjvhDJyHpG2ILKrrPVQbgI8arzBkqAKhvKxvOpkUhee2ZFdbnm9Vk4P Ar35UaE3+zN4tNdG+HoWX+8N4o4SR6cFNUrcoFfzeGh1qv7xGnrK5FbR9e9DuytMd+3V hgdw== X-Gm-Message-State: AOAM531k49581xclB20Wr6cvDfOXhBezckgSS17Zqnd1dHccjZuJZl/I Hc39LkuKIkgVoAkNySIDKlAqPlBPg4o+uacU X-Google-Smtp-Source: ABdhPJzl3v0rxrX2LiFs6k/Q8CjrZtRJLam7OzZbR99ax5BEWmHbB82rNYaEg/C0qJYRw35DZszKTg== X-Received: by 2002:a05:6402:c9b:: with SMTP id cm27mr33714666edb.258.1620783060449; Tue, 11 May 2021 18:31:00 -0700 (PDT) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id e19sm15524069edv.10.2021.05.11.18.30.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 May 2021 18:30:59 -0700 (PDT) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= To: Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Subject: [PATCH v5 2/5] hwmon: (max31790) Fix and split pwm*_enable Date: Wed, 12 May 2021 03:30:48 +0200 Message-Id: <20210512013052.903297-2-kubernat@cesnet.cz> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512013052.903297-1-kubernat@cesnet.cz> References: <20210512013052.903297-1-kubernat@cesnet.cz> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org In the old code, pwm*_enable does two things. Firstly, it sets whether the chip should run in PWM or RPM mode. Secondly, it tells the chip whether it should monitor fan RPM. However, these two settings aren't tied together, so they shouldn't be set with a single value. In the new code, fan*_enable now controls fan RPM monitoring (pwm*_enable no longer controls that). According to the sysfs hwmon documentation, pwm*_enable has three possible values, 0 for "no control / full-speed", 1 for manual mode, and 2+ for automatic. The old code works fine for 1 and 2, but 0 only differs from 1 in that it just turns off fan speed monitoring. The chip actually does have a way to turn off fan controls (and only monitor), and what that does is that it sets PWM to 0% duty cycle. In the new code, 0 in pwm*_enable turns off the "control" feature of the chip. These two changes are closely connected together, mainly because the detection of the pwm*_enable value depended on whether fan speed monitoring is enabled (which is now controlled as written in the first paragraph). Signed-off-by: Václav Kubernát --- Documentation/hwmon/max31790.rst | 10 ++-- drivers/hwmon/max31790.c | 78 +++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index f301385d8cef..d2ac4e926905 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -34,10 +34,14 @@ also be configured to serve as tachometer inputs. Sysfs entries ------------- -================== === ======================================================= +================== === ============================================================= +fan[1-12]_enable RW enable fan speed monitoring fan[1-12]_input RO fan tachometer speed in RPM fan[1-12]_fault RO fan experienced fault fan[1-6]_target RW desired fan speed in RPM -pwm[1-6]_enable RW regulator mode, 0=disabled, 1=manual mode, 2=rpm mode +pwm[1-6]_enable RW regulator mode, 0=no control, sets 0% PWM, + 1=manual (pwm) mode, + 2=rpm mode + setting rpm mode sets fan*_enable to 1 pwm[1-6] RW fan target duty cycle (0-255) -================== === ======================================================= +================== === ============================================================= diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index e3765ce4444a..5d4c551df010 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -30,6 +30,7 @@ #define MAX31790_FAN_CFG_RPM_MODE 0x80 #define MAX31790_FAN_CFG_TACH_INPUT_EN 0x08 #define MAX31790_FAN_CFG_TACH_INPUT 0x01 +#define MAX31790_FAN_CFG_CTRL_MON 0x10 /* Fan Dynamics register bits */ #define MAX31790_FAN_DYN_SR_SHIFT 5 @@ -191,6 +192,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, else *val = !!(fault & (1 << channel)); return 0; + case hwmon_fan_enable: + *val = !!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN); + return 0; default: return -EOPNOTSUPP; } @@ -233,6 +237,15 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, MAX31790_REG_TARGET_COUNT(channel), target_count); break; + case hwmon_fan_enable: + if (val == 0) + data->fan_config[channel] &= ~MAX31790_FAN_CFG_TACH_INPUT_EN; + else + data->fan_config[channel] |= MAX31790_FAN_CFG_TACH_INPUT_EN; + err = regmap_write(regmap, + MAX31790_REG_FAN_CONFIG(channel), + data->fan_config[channel]); + break; default: err = -EOPNOTSUPP; break; @@ -260,6 +273,11 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) !(fan_config & MAX31790_FAN_CFG_TACH_INPUT)) return 0644; return 0; + case hwmon_fan_enable: + if (channel < NR_CHANNEL || + (fan_config & MAX31790_FAN_CFG_TACH_INPUT)) + return 0644; + return 0; default: return 0; } @@ -281,12 +299,12 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel, *val = read >> 8; return 0; case hwmon_pwm_enable: - if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) + if (data->fan_config[channel] & MAX31790_FAN_CFG_CTRL_MON) + *val = 0; + else if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) *val = 2; - else if (data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN) + else *val = 1; - else - *val = 0; return 0; default: return -EOPNOTSUPP; @@ -298,35 +316,41 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, { struct max31790_data *data = dev_get_drvdata(dev); struct regmap *regmap = data->regmap; - u8 fan_config; + u8 fan_config = data->fan_config[channel]; int err = 0; mutex_lock(&data->update_lock); switch (attr) { case hwmon_pwm_input: - if (val < 0 || val > 255) { + if (fan_config & MAX31790_FAN_CFG_CTRL_MON || val < 0 || val > 255) { err = -EINVAL; break; } + err = write_reg_word(regmap, MAX31790_REG_PWMOUT(channel), val << 8); break; case hwmon_pwm_enable: fan_config = data->fan_config[channel]; - if (val == 0) { - fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN | - MAX31790_FAN_CFG_RPM_MODE); - } else if (val == 1) { - fan_config = (fan_config | - MAX31790_FAN_CFG_TACH_INPUT_EN) & - ~MAX31790_FAN_CFG_RPM_MODE; + if (val == 0) + fan_config |= MAX31790_FAN_CFG_CTRL_MON; + else if (val == 1) { + fan_config &= ~(MAX31790_FAN_CFG_RPM_MODE | MAX31790_FAN_CFG_CTRL_MON); } else if (val == 2) { - fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN | - MAX31790_FAN_CFG_RPM_MODE; + fan_config &= ~(MAX31790_FAN_CFG_CTRL_MON); + fan_config |= MAX31790_FAN_CFG_RPM_MODE; } else { err = -EINVAL; break; } + + /* + * RPM mode implies enabled TACH input, so enable it in RPM + * mode. + */ + if (val == 2) + fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN; + data->fan_config[channel] = fan_config; err = regmap_write(regmap, MAX31790_REG_FAN_CONFIG(channel), @@ -400,18 +424,18 @@ static umode_t max31790_is_visible(const void *data, static const struct hwmon_channel_info *max31790_info[] = { HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_INPUT | HWMON_F_FAULT), + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, From patchwork Wed May 12 01:30:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= X-Patchwork-Id: 12252473 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28AB9C433B4 for ; Wed, 12 May 2021 01:31:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 07DCC61928 for ; Wed, 12 May 2021 01:31:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230096AbhELBcN (ORCPT ); Tue, 11 May 2021 21:32:13 -0400 Received: from mail-ej1-f48.google.com ([209.85.218.48]:43969 "EHLO mail-ej1-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230095AbhELBcL (ORCPT ); Tue, 11 May 2021 21:32:11 -0400 Received: by mail-ej1-f48.google.com with SMTP id l4so32535398ejc.10; Tue, 11 May 2021 18:31:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=utrWOu42FjJA8Nbe/rYRDIaHKdb4rk7dPi0KGMnX07w=; b=VCRDcJmIWWYwZ35CKOC5ZrldQpXdEQDn/dTbv2FlpY1OyRu9CQh8HAq70xFVWityBy vnIt788xIsH0y9k2ShxOGGbJsxaL8i3IdP/cOVG6nKmL7zG7xjCx7rsPNTfs6UahOzAp Fgoc0Jvj5+Faf7Z4GX+dDs/WrO570cB6nCJo0fUN3AXWu9toZkaUIKzEsD1oan8Jv8uH LKETtobugH6NNhU4/Yo7P9ahybeKXxhKP29StmBcrhGVStpDVE1+b6F3LEhvK6joOINS DxQbfsmegFV2RhhXZLw2ij/sipb/aFr1Ru5T3OvLKRQDvPthGz/CQ+6rH68ECe/DZ6fP Wq/A== X-Gm-Message-State: AOAM5324Wtz4GlTID81rI8iSIxTvFaEy74HNKRdvVXeH8XTN7yi92Jxj D9HBvgo/HzW6zX2mLqQe5JE= X-Google-Smtp-Source: ABdhPJwQoNZvtD9Bf4lGU4rP6qs+F+DXYHt1XeKq8a7reswJSBfb22wjxF4iopf7TA+z6DFdPPicgg== X-Received: by 2002:a17:906:33da:: with SMTP id w26mr35348167eja.472.1620783062958; Tue, 11 May 2021 18:31:02 -0700 (PDT) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id c3sm2276855edn.16.2021.05.11.18.31.02 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 May 2021 18:31:02 -0700 (PDT) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= To: Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Subject: [PATCH v5 3/5] hwmon: (max31790) Show 0 RPM/fault when input disabled Date: Wed, 12 May 2021 03:30:49 +0200 Message-Id: <20210512013052.903297-3-kubernat@cesnet.cz> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512013052.903297-1-kubernat@cesnet.cz> References: <20210512013052.903297-1-kubernat@cesnet.cz> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org When fan speed input is disabled, it makes no sense to show values in fan*_input and fan*_fault. Signed-off-by: Václav Kubernát --- drivers/hwmon/max31790.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 5d4c551df010..6e0ffbcf0d28 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -165,6 +165,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, switch (attr) { case hwmon_fan_input: + if (!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN)) + return -ENODATA; + tach = read_reg_word(regmap, MAX31790_REG_TACH_COUNT(channel)); if (tach < 0) return tach; @@ -179,6 +182,11 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, *val = RPM_FROM_REG(tach, get_tach_period(data->fan_dynamics[channel])); return 0; case hwmon_fan_fault: + if (!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN)) { + *val = 0; + return 0; + } + if (channel > 6) fault = read_reg_byte(regmap, MAX31790_REG_FAN_FAULT_STATUS2); else From patchwork Wed May 12 01:30:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= X-Patchwork-Id: 12252475 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75278C43462 for ; Wed, 12 May 2021 01:31:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4DFD86192C for ; Wed, 12 May 2021 01:31:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230130AbhELBcP (ORCPT ); Tue, 11 May 2021 21:32:15 -0400 Received: from mail-ej1-f54.google.com ([209.85.218.54]:41967 "EHLO mail-ej1-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230115AbhELBcN (ORCPT ); Tue, 11 May 2021 21:32:13 -0400 Received: by mail-ej1-f54.google.com with SMTP id k10so1319568ejj.8; Tue, 11 May 2021 18:31:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WR8i/rokrQe4V/fyl2CE+ag89vjaZtSHH0UvjfhpJvg=; b=iI3gt5CNLk+bxd2PWL2ZS9hJdPly7pQBWr242FUhMdW7lvQV7nDznWlpivhXk2XcZR q62WJLXSWDSYCHD0JByIMc+hhNoLC0NjaX5c86LMz5agPPtxKblNK95URm+axjB3dvNz a8fkUS0xZ3O7bxMk+8GW+BnCtiEyd2htZCIl3LKF3dxqeBzREkJ0b/7p+H7molh6rYfx UkHeYPbaxh698InVQ9AP7hmHDd/i81MJMpq7+4labLODNZ5TIVUdtGMaSeOl1Wy9yRSK OQVhjUNRlypfMU8f/z9a39ow6IuY/a006bmbVV8sn3zhpiz8WWwEL9Eorvdkpah0O9Fu M0cg== X-Gm-Message-State: AOAM532goJmuAa3CttQ9VDxx7SF+QxTBQAFMCzFCdqDqJefwJ9dzD88U qmFazD6Dcubk2fCRy0iZi80= X-Google-Smtp-Source: ABdhPJx8nK0bEhXKYi4BSCT5Hr17+qoZha1enSj9IQhomR/frypSwQS4z45IB67UIFXzUAVFYizHng== X-Received: by 2002:a17:906:251a:: with SMTP id i26mr35059652ejb.367.1620783065474; Tue, 11 May 2021 18:31:05 -0700 (PDT) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id cr21sm12613160ejc.2.2021.05.11.18.31.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 May 2021 18:31:04 -0700 (PDT) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= To: Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Subject: [PATCH v5 4/5] hwmon: (max31790) Allow setting fan*_div Date: Wed, 12 May 2021 03:30:50 +0200 Message-Id: <20210512013052.903297-4-kubernat@cesnet.cz> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512013052.903297-1-kubernat@cesnet.cz> References: <20210512013052.903297-1-kubernat@cesnet.cz> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org Right now, the divisor (which determines the speed range) is only set when in RPM mode. However, the speed range also affects the input RPM, which means, to get more accurate readings, this speed range needs to be set. Signed-off-by: Václav Kubernát --- Documentation/hwmon/max31790.rst | 1 + drivers/hwmon/max31790.c | 66 ++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index d2ac4e926905..35afa5f0395a 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -38,6 +38,7 @@ Sysfs entries fan[1-12]_enable RW enable fan speed monitoring fan[1-12]_input RO fan tachometer speed in RPM fan[1-12]_fault RO fan experienced fault +fan[1-12]_div RW set the measurable speed range, not available in RPM mode fan[1-6]_target RW desired fan speed in RPM pwm[1-6]_enable RW regulator mode, 0=no control, sets 0% PWM, 1=manual (pwm) mode, diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 6e0ffbcf0d28..8b04f4c01752 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -156,6 +156,26 @@ static int write_reg_word(struct regmap *regmap, u8 reg, u16 val) return regmap_bulk_write(regmap, reg, bulk_val, 2); } +static int bits_for_speed_range(long speed_range) +{ + switch (speed_range) { + case 1: + return 0x0; + case 2: + return 0x1; + case 4: + return 0x2; + case 8: + return 0x3; + case 16: + return 0x4; + case 32: + return 0x5; + default: + return -1; + } +} + static int max31790_read_fan(struct device *dev, u32 attr, int channel, long *val) { @@ -203,6 +223,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, case hwmon_fan_enable: *val = !!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN); return 0; + case hwmon_fan_div: + *val = get_tach_period(data->fan_config[channel]); + return 0; default: return -EOPNOTSUPP; } @@ -254,6 +277,24 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, MAX31790_REG_FAN_CONFIG(channel), data->fan_config[channel]); break; + case hwmon_fan_div: + if (data->fan_config[channel] & MAX31790_FAN_CFG_RPM_MODE) { + err = -EINVAL; + break; + } + sr = bits_for_speed_range(val); + if (sr < 0) { + err = -EINVAL; + break; + } + + data->fan_dynamics[channel] = ((data->fan_dynamics[channel] & + ~MAX31790_FAN_DYN_SR_MASK) | + (sr << MAX31790_FAN_DYN_SR_SHIFT)); + err = regmap_write(regmap, + MAX31790_REG_FAN_DYNAMICS(channel), + data->fan_dynamics[channel]); + break; default: err = -EOPNOTSUPP; break; @@ -282,6 +323,7 @@ static umode_t max31790_fan_is_visible(const void *_data, u32 attr, int channel) return 0644; return 0; case hwmon_fan_enable: + case hwmon_fan_div: if (channel < NR_CHANNEL || (fan_config & MAX31790_FAN_CFG_TACH_INPUT)) return 0644; @@ -432,18 +474,18 @@ static umode_t max31790_is_visible(const void *data, static const struct hwmon_channel_info *max31790_info[] = { HWMON_CHANNEL_INFO(fan, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT), + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_DIV | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, From patchwork Wed May 12 01:30:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= X-Patchwork-Id: 12252477 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69E06C43461 for ; Wed, 12 May 2021 01:31:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4CD486192B for ; Wed, 12 May 2021 01:31:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230176AbhELBcR (ORCPT ); Tue, 11 May 2021 21:32:17 -0400 Received: from mail-ed1-f54.google.com ([209.85.208.54]:39710 "EHLO mail-ed1-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230124AbhELBcQ (ORCPT ); Tue, 11 May 2021 21:32:16 -0400 Received: by mail-ed1-f54.google.com with SMTP id g14so25127129edy.6; Tue, 11 May 2021 18:31:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fu9dr07tUrhZL/WE8RSa90SkTQUI7KqZiD+NnVvcBNI=; b=EaoJJAnVVq6mIBQd1C40I2iQRLzYXwwot0CkZmkrEv9Uofa+kR2t9FDKcrgg8l6XRj Rb1ItU5BV556NUlYJaaG/RTYrgx36A0jnym1rpAenKpdUEAy7A3nySyF1L/Tkbx1oNbb cZZRyMxSxI4b1VwzMK1OCHoAyNglePBjuw7TZTc8HPBiv5fO12/T1YxL6ZqRcF27nKrm WsiK53lJQZvOyTraU3OoOGkp02MvYkY/rqPQR+OO7nZsTHDbPX8klUbeBB2Bhx7uNtcA jJOAk/V7hWp/RZGHO+iTOeqVpEhWWIqjxhJhyantGSAzDQFmkN9Z/meZk3tZZsfkue/G Y97A== X-Gm-Message-State: AOAM532rWdCmltBx3BopSbmQUYrSSCkx0OyyXFp7SXB0lsjyXxWnHa2D ajwzWXggDkxkdxOpsAdfwchojNU68Qhzy9VX X-Google-Smtp-Source: ABdhPJzAdcv0Bb9731uLtmAWjJy47qC/e5oW2m31UeiNPkzIOCOa2RJXFmF94wgb+JQYfKm2KcK1BQ== X-Received: by 2002:a05:6402:1807:: with SMTP id g7mr39398970edy.335.1620783067881; Tue, 11 May 2021 18:31:07 -0700 (PDT) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id o3sm16416033edr.84.2021.05.11.18.31.06 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 11 May 2021 18:31:07 -0700 (PDT) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= To: Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Subject: [PATCH v5 5/5] hwmon: (max31790) Update documentation Date: Wed, 12 May 2021 03:30:51 +0200 Message-Id: <20210512013052.903297-5-kubernat@cesnet.cz> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512013052.903297-1-kubernat@cesnet.cz> References: <20210512013052.903297-1-kubernat@cesnet.cz> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org The conditions for fan fault and its connection to the PWM mode are now documented. The pwm_rate_of_change and fan_window are now mentioned. According to our testing with Sunon PF36281BX-000U-S99, these values are crucial in how RPM mode works and how long it takes for the RPM to stabilize. For example, setting 5000 RPM (the fan goes up to 23000), the pwm_rate_of_change needed to be changed to the lowest possible value, otherwise the chip would just go from pwm 0 to pwm 60 back and forth and never achieving 5000 RPM (and also signaling fan fault). Based on this testing, we found out that the pwm_rate_of_change and fan_window values need to be changed manually by the user, based on the user's exact fan configuration. Signed-off-by: Václav Kubernát --- Documentation/hwmon/max31790.rst | 41 +++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index 35afa5f0395a..e70aae9f71a2 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -30,6 +30,44 @@ monitoring and control of fan RPM as well as detection of fan failure. Six pins are dedicated tachometer inputs. Any of the six PWM outputs can also be configured to serve as tachometer inputs. +About pwm[1-6]_enable +--------------------- +0 - full-speed + The chip doesn't have a specific way to set "full speed", so setting + pwm[1-6]_enable to 0 is just "set PWM mode with 255 duty cycle". +1 - PWM mode + Fan speed is controlled by writing a value to pwm[1-6]. +2 - RPM mode + Fan speed is controlled by writing a value to fan[1-6]_target. + +About fan[1-6]_fault +-------------------- +In PWM (or full-speed) mode, if the input RPM goes below what is set +in fan[1-6]_target, fan[1-6]_fault gets set to 1. In other words, +fan[1-6]_target works as the minimum input RPM before a fan fault goes off. + +In RPM mode, fan fault is set when the fan spins "too slowly" (exact +conditions are in the datasheet). RPM mode depends on four variables: + target_speed: This is set by fan[1-6]_target. + speed_range: This is set automatically when setting target_speed + or manually by fan[1-12]_div. + pwm_rate_of_change: NOT set by the driver. + fan_window: NOT set by the driver. + +The last two values are not set by the driver, because there's no generic way to +compute them. You should set them manually through i2c (in the bootloader for +example). Check the datasheet for details. + +The fan fault value latches, to reset it, set a value to pwm[1-6] +or fan[1-6]_target. + +About fan[1-12]_div +------------------- +This value affects the measurable range of the chip. The driver sets this value +automatically in RPM based on fan[1-6]_target. In PWM mode, you should set this +value manually based on the details from the datasheet. Setting the speed range +is disabled while in RPM mode to prevent overwriting the automatically +calculated value. Sysfs entries ------------- @@ -39,7 +77,8 @@ fan[1-12]_enable RW enable fan speed monitoring fan[1-12]_input RO fan tachometer speed in RPM fan[1-12]_fault RO fan experienced fault fan[1-12]_div RW set the measurable speed range, not available in RPM mode -fan[1-6]_target RW desired fan speed in RPM +fan[1-6]_target RW RPM mode = desired fan speed + PWM mode = minimum fan speed until fault pwm[1-6]_enable RW regulator mode, 0=no control, sets 0% PWM, 1=manual (pwm) mode, 2=rpm mode