From patchwork Thu Mar 4 10:58:24 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: 12115871 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,URIBL_BLOCKED,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 42EEBC433E0 for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 14A9064F34 for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239226AbhCDLAr (ORCPT ); Thu, 4 Mar 2021 06:00:47 -0500 Received: from mail-wm1-f43.google.com ([209.85.128.43]:36369 "EHLO mail-wm1-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239106AbhCDLAl (ORCPT ); Thu, 4 Mar 2021 06:00:41 -0500 Received: by mail-wm1-f43.google.com with SMTP id k66so9222736wmf.1; Thu, 04 Mar 2021 03:00:25 -0800 (PST) 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=RANBnD46ojmlSMccdilRdjvDcaZ6u/VFb9a869Iq5XU=; b=k/KvLQlzVFSSdzxEXi7HR8pHR1NFyjTyoj1PQztsHJzjFkyarqMGc7lqkIb6yzjYt3 akO7VeysmsYANNaru9AhiAZa2bNKcPy2R5Dei/FhBUGQL109Xd8RO/pr3yrCMA6PVtOG 3ejX09LHtTqF2B68BI7UZiMOxJvhvmMYGEI59mlXlbS/BzOGUuNT1BWmUKUy9pJtUiwc gzAaAlc03DuTiS5RUYEpr/75+OUj5tT1QerPRUAeNWBosQC/p5/Mgdlse4Gt25EqASXt RnlpiDWwPNUOEV5C51C0youuoQbGgrr5bRNUDIMzNr0qwMe3eXkMHCfFKsD5Ig/LWKX8 Kg3A== X-Gm-Message-State: AOAM531+b+YLChCQLnHwpqugzoOXTQv57Q5GBvP63j/hphtK23V0jK4A u9lZitv4lErsWtkFKRYPxVY= X-Google-Smtp-Source: ABdhPJy9psosJAJzPkFtViYYM9+1QFnG3jbrArOHYWSu0xYl6j08YYMahfmJOMk7q24BUS7maJ9bSA== X-Received: by 2002:a1c:ddc6:: with SMTP id u189mr3361967wmg.171.1614855600261; Thu, 04 Mar 2021 03:00:00 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id d85sm9420246wmd.15.2021.03.04.02.59.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 02:59:59 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/7] hwmon: (max31790) Rework to use regmap Date: Thu, 4 Mar 2021 11:58:24 +0100 Message-Id: <20210304105830.507176-1-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) 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 | 148 +++++++++++++++++++++++++++------------ 2 files changed, 105 insertions(+), 44 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 86e6c71db685..ca413985b5f9 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -12,6 +12,7 @@ #include #include #include +#include #include /* MAX31790 registers */ @@ -46,11 +47,35 @@ #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_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, +}; + /* * 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 */ @@ -67,53 +92,72 @@ struct max31790_data { 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 regmap *regmap = data->regmap; struct max31790_data *ret = data; int i; int rv; + int val; + u8 val_bulk[2]; 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); + rv = regmap_read(regmap, + MAX31790_REG_FAN_FAULT_STATUS1, + &val); if (rv < 0) goto abort; - data->fault_status = rv & 0x3F; + data->fault_status = val & 0x3F; - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_FAULT_STATUS2); + rv = regmap_read(regmap, + MAX31790_REG_FAN_FAULT_STATUS2, + &val); if (rv < 0) goto abort; - data->fault_status |= (rv & 0x3F) << 6; + data->fault_status |= (val & 0x3F) << 6; for (i = 0; i < NR_CHANNEL; i++) { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TACH_COUNT(i)); + rv = regmap_bulk_read(regmap, + MAX31790_REG_TACH_COUNT(i), + val_bulk, + 2); if (rv < 0) goto abort; - data->tach[i] = rv; + data->tach[i] = BULK_TO_U16(val_bulk[0], + val_bulk[1]); if (data->fan_config[i] & MAX31790_FAN_CFG_TACH_INPUT) { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TACH_COUNT(NR_CHANNEL - + i)); + rv = regmap_bulk_read(regmap, + MAX31790_REG_TACH_COUNT(NR_CHANNEL + + i), + val_bulk, + 2); if (rv < 0) goto abort; - data->tach[NR_CHANNEL + i] = rv; + + data->tach[NR_CHANNEL + i] = + BULK_TO_U16(val_bulk[0], + val_bulk[1]); } else { - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_PWMOUT(i)); + rv = regmap_bulk_read(regmap, + MAX31790_REG_PWMOUT(i), + val_bulk, + 2); if (rv < 0) goto abort; - data->pwm[i] = rv; + data->pwm[i] = BULK_TO_U16(val_bulk[0], + val_bulk[1]); - rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_TARGET_COUNT(i)); + rv = regmap_bulk_read(regmap, + MAX31790_REG_TARGET_COUNT(i), + val_bulk, + 2); if (rv < 0) goto abort; - data->target_count[i] = rv; + data->target_count[i] = + BULK_TO_U16(val_bulk[0], + val_bulk[1]); } } @@ -191,11 +235,12 @@ 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; int sr; + u8 bulk_val[2]; mutex_lock(&data->update_lock); @@ -207,9 +252,9 @@ 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; @@ -218,10 +263,13 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, target_count = clamp_val(target_count, 0x1, 0x7FF); data->target_count[channel] = target_count << 5; + bulk_val[0] = U16_MSB(data->target_count[channel]); + bulk_val[1] = U16_LSB(data->target_count[channel]); - err = i2c_smbus_write_word_swapped(client, + err = regmap_bulk_write(regmap, MAX31790_REG_TARGET_COUNT(channel), - data->target_count[channel]); + bulk_val, + 2); break; default: err = -EOPNOTSUPP; @@ -287,9 +335,10 @@ 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; + u8 bulk_val[2]; mutex_lock(&data->update_lock); @@ -300,9 +349,12 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, break; } data->pwm[channel] = val << 8; - err = i2c_smbus_write_word_swapped(client, - MAX31790_REG_PWMOUT(channel), - data->pwm[channel]); + bulk_val[0] = U16_MSB(data->pwm[channel]); + bulk_val[1] = U16_LSB(data->pwm[channel]); + err = regmap_bulk_write(regmap, + MAX31790_REG_PWMOUT(channel), + bulk_val, + 2); break; case hwmon_pwm_enable: fan_config = data->fan_config[channel]; @@ -321,9 +373,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,23 +478,25 @@ 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; + int i, rv, val; for (i = 0; i < NR_CHANNEL; i++) { - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_CONFIG(i)); + rv = regmap_read(regmap, + MAX31790_REG_FAN_CONFIG(i), + &val); if (rv < 0) return rv; - data->fan_config[i] = rv; + data->fan_config[i] = val; - rv = i2c_smbus_read_byte_data(client, - MAX31790_REG_FAN_DYNAMICS(i)); + rv = regmap_read(regmap, + MAX31790_REG_FAN_DYNAMICS(i), + &val); if (rv < 0) return rv; - data->fan_dynamics[i] = rv; + data->fan_dynamics[i] = val; } return 0; @@ -464,13 +518,19 @@ 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 Thu Mar 4 10:58:25 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: 12115875 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,URIBL_BLOCKED,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 66755C433E9 for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3D67464F36 for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239228AbhCDLAs (ORCPT ); Thu, 4 Mar 2021 06:00:48 -0500 Received: from mail-wm1-f53.google.com ([209.85.128.53]:53827 "EHLO mail-wm1-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239229AbhCDLAn (ORCPT ); Thu, 4 Mar 2021 06:00:43 -0500 Received: by mail-wm1-f53.google.com with SMTP id e23so7618172wmh.3; Thu, 04 Mar 2021 03:00:27 -0800 (PST) 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=gITzLsPooGBCWGwALskXkLIYTlTGl7+1EaRVJt+auPo=; b=mODerpZspRZ1TKs3U9200cuXgFmdu65t28RrxjtQ7Zbkz00tfAwHVNpuB9zDX9rW23 +1Be/qNU4Eml0OTHgnoYs1FSiUa12wHK50S7MGHdzY1wSPomAfxOcncvEoXJiuk9P49M BVlvLaInDWumasoOAbymSYoNZSqMQbD3noXKRnWw0R+Fmkm9Vi78jSN6v0osgni/SiV+ cO7eFTagPAUfebeBdCp8vS+Jf5HJ7fnelrn0tRG1qe6Oim5DCxUfnwRjkOGMOH8amnTg m/S9uImu5wTUV5m+ZTknbmxnhx68BQvaGfCmbNiu0nZhhXywDf8SV+uQc1VjnOazqw3l FRSg== X-Gm-Message-State: AOAM531zKIZlpm+TYL7vJBqH2X9O9g3JtVgF5JjByAydi2Y2NGLWqgdB gsi2YNaoaPSisixmRuZ2Vtg= X-Google-Smtp-Source: ABdhPJwX06wnmL23sMxGTTDb1nNF7ziKKE4TP114bK7t1ZHxXwW7XChwpNk2qlVDXaCzT8aZ8v2CnQ== X-Received: by 2002:a05:600c:4f0b:: with SMTP id l11mr3344765wmq.102.1614855602255; Thu, 04 Mar 2021 03:00:02 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id h20sm9208749wmb.1.2021.03.04.03.00.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:02 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/7] hwmon: (max31790) Fix and split pwm*_enable Date: Thu, 4 Mar 2021 11:58:25 +0100 Message-Id: <20210304105830.507176-2-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) 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), but what that does is that it sets PWM to 0% duty cycle (which is the opposite to full-speed) AND it also turns off fan speed monitoring. Because of this, I implemented the 0 value by setting PWM mode to 100%. This method does come with a problem: it is impossible to differentiate between full-speed and PWM mode just from the values on the chip. The new code solves this by saving a value indicating whether we're in full-speed mode. This value is initialized to 0, so full-speed mode won't persist across reboots. 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 | 8 ++- drivers/hwmon/max31790.c | 107 ++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index f301385d8cef..8979c8a02cd1 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -34,10 +34,12 @@ 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=full speed, 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 ca413985b5f9..eca5ec615734 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -39,6 +39,7 @@ #define FAN_RPM_MIN 120 #define FAN_RPM_MAX 7864320 +#define MAX_PWM 0XFF80 #define RPM_FROM_REG(reg, sr) (((reg) >> 4) ? \ ((60 * (sr) * 8192) / ((reg) >> 4)) : \ @@ -79,6 +80,7 @@ struct max31790_data { struct mutex update_lock; bool valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ + bool full_speed[NR_CHANNEL]; /* register values */ u8 fan_config[NR_CHANNEL]; @@ -226,6 +228,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, case hwmon_fan_fault: *val = !!(data->fault_status & (1 << channel)); return 0; + case hwmon_fan_enable: + *val = !!(data->fan_config[channel] & MAX31790_FAN_CFG_TACH_INPUT_EN); + return 0; default: return -EOPNOTSUPP; } @@ -271,6 +276,15 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, bulk_val, 2); 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; @@ -298,6 +312,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; } @@ -319,12 +338,12 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel, *val = data->pwm[channel] >> 8; return 0; case hwmon_pwm_enable: - if (fan_config & MAX31790_FAN_CFG_RPM_MODE) + if (data->full_speed[channel]) + *val = 0; + else if (fan_config & MAX31790_FAN_CFG_RPM_MODE) *val = 2; - else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN) + else *val = 1; - else - *val = 0; return 0; default: return -EOPNOTSUPP; @@ -344,7 +363,7 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, switch (attr) { case hwmon_pwm_input: - if (val < 0 || val > 255) { + if (data->full_speed[channel] || val < 0 || val > 255) { err = -EINVAL; break; } @@ -358,16 +377,10 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, 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 || val == 1) { + fan_config &= ~MAX31790_FAN_CFG_RPM_MODE; } else if (val == 2) { - fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN | - MAX31790_FAN_CFG_RPM_MODE; + fan_config |= MAX31790_FAN_CFG_RPM_MODE; } else { err = -EINVAL; break; @@ -376,6 +389,34 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, err = regmap_write(regmap, MAX31790_REG_FAN_CONFIG(channel), fan_config); + + /* + * The chip sets PWM to zero when using its "monitor only" mode + * and 0 means full speed. + */ + if (val == 0) { + data->full_speed[channel] = true; + data->pwm[channel] = MAX_PWM; + bulk_val[0] = U16_MSB(data->pwm[channel]); + bulk_val[1] = U16_LSB(data->pwm[channel]); + err = regmap_bulk_write(regmap, + MAX31790_REG_PWMOUT(channel), + bulk_val, + 2); + } else { + data->full_speed[channel] = false; + } + + /* + * RPM mode implies enabled TACH input, so enable it in RPM + * mode. + */ + if (val == 2) { + 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; @@ -445,25 +486,25 @@ 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, - 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_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), NULL }; @@ -491,6 +532,8 @@ static int max31790_init_client(struct regmap *regmap, return rv; data->fan_config[i] = val; + data->full_speed[i] = false; + rv = regmap_read(regmap, MAX31790_REG_FAN_DYNAMICS(i), &val); From patchwork Thu Mar 4 10:58:26 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: 12115873 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,URIBL_BLOCKED,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 9748EC4332D for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7AC4864F3A for ; Thu, 4 Mar 2021 11:01:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239239AbhCDLAt (ORCPT ); Thu, 4 Mar 2021 06:00:49 -0500 Received: from mail-wm1-f53.google.com ([209.85.128.53]:54887 "EHLO mail-wm1-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239230AbhCDLAp (ORCPT ); Thu, 4 Mar 2021 06:00:45 -0500 Received: by mail-wm1-f53.google.com with SMTP id u187so7621004wmg.4; Thu, 04 Mar 2021 03:00:29 -0800 (PST) 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=UA1xOo+7lSBsreIAb0OwBzKlvaeXYlH2J9yBywuvyqU=; b=U3On3lI2hzw0Ewi+cYWoOXQ/xO8HfbP4XYUNutJDF9jHEBwqULfSSpJ1YGbfBbP+or FHIzIEsiVWyvYhbs7m17YOsvn1ihGX7NWsMlbw2O9UQZOfqxRMWv73GT1B8Z2YUKUkwc JRWwE88UIyFx9kL1gPCnyXsR40Ml9HZ33jSPB5eAdjEAVb1a7jF79CQLDCR8o1+ofdqT L8wZ5GoHfATtppJmpteXyl8cua6P7Sti0aJLgY1p+S6B+KAMlW4TFQGadATWh6JSB8a9 Sd4P86vBxwgnJKXaEvifF4In4WHKfWluWGzbrjVMEuDJhzyFL6INLaW+56Ll19Gkmb+q u6Xg== X-Gm-Message-State: AOAM532+YCS25St/gLcTl8R1gh6J9d+CFTwS/FtiRC7ubveI8YPvp1b+ 3m8l2MrtjZ1Iu2NMHBp0yfsjcxEZ0Jg2/A== X-Google-Smtp-Source: ABdhPJwf70HWklqACtsSmsyVd6d86C6J9i8jKQmGi/2+MqN8VwJlvVkWOaympweSqBfqQ2D4g2yAbA== X-Received: by 2002:a1c:2b05:: with SMTP id r5mr3244192wmr.179.1614855604117; Thu, 04 Mar 2021 03:00:04 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id s16sm7952093wru.91.2021.03.04.03.00.03 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:03 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/7] hwmon: (max31790) Allow setting pulses Date: Thu, 4 Mar 2021 11:58:26 +0100 Message-Id: <20210304105830.507176-3-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org In the old code, the value calculated RPM_FROM_REG is misleading. The left-hand side of the division is correct (as per the datasheet, page 11). The misleading part is the right-hand side: the datasheet says it is should be "number of pulses * TACH count". The TACH count is the value of the register which is a 11-bit left-justified value. This means that the register value should be shifted by 5 if we want the actual value. However, in the old code, the value is shifted by 4 with no way to set the pulses per revolution. This essentially means, that the default pulses per revolution is 2, because shifting the right-hand side one less bit means that the final value is doubled by 2. In the end, what happens is, that the old code works as if fan*_pulses had the default value of 2 all the time. This is somewhat correct, but in my opinion the intention isn't entirely clear, at first glance, shifting by 4 instead of 5 seems like a bug (after one checks the datasheet). Pulses per revolution should be a configurable because otherwise there's no way to correctly calculate the RPM of the fan. This patch adds the option to set pulses per revolution. The hwmon documentation for fan*_pulses says that it shouldn't be present unless the chip has a register to save this value. This seems non-sensical, because setting the pulses is essential to properly calculate RPM. The value is saved inside the driver's data structure. Signed-off-by: Václav Kubernát --- Documentation/hwmon/max31790.rst | 1 + drivers/hwmon/max31790.c | 57 +++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index 8979c8a02cd1..8d86698b25de 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -36,6 +36,7 @@ Sysfs entries ================== === ============================================================= fan[1-12]_enable RW enable fan speed monitoring +fan[1-12]_pulses RW pulses per fan revolution (default: 2) 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 diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index eca5ec615734..74a81e5e3383 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -41,10 +41,12 @@ #define FAN_RPM_MAX 7864320 #define MAX_PWM 0XFF80 -#define RPM_FROM_REG(reg, sr) (((reg) >> 4) ? \ - ((60 * (sr) * 8192) / ((reg) >> 4)) : \ - FAN_RPM_MAX) -#define RPM_TO_REG(rpm, sr) ((60 * (sr) * 8192) / ((rpm) * 2)) +#define RPM_FROM_REG(reg, sr, pulses) \ + (((reg) >> 5) ? \ + ((60 * (sr) * 8192) / ((reg) >> 5) / (pulses)) : \ + FAN_RPM_MAX) +#define RPM_TO_REG(rpm, sr, pulses) \ + ((60 * (sr) * 8192) / ((rpm) * (pulses))) #define NR_CHANNEL 6 @@ -81,6 +83,7 @@ struct max31790_data { bool valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ bool full_speed[NR_CHANNEL]; + u8 pulses[NR_CHANNEL]; /* register values */ u8 fan_config[NR_CHANNEL]; @@ -217,12 +220,16 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, switch (attr) { case hwmon_fan_input: sr = get_tach_period(data->fan_dynamics[channel]); - rpm = RPM_FROM_REG(data->tach[channel], sr); + rpm = RPM_FROM_REG(data->tach[channel], + sr, + data->pulses[channel]); *val = rpm; return 0; case hwmon_fan_target: sr = get_tach_period(data->fan_dynamics[channel]); - rpm = RPM_FROM_REG(data->target_count[channel], sr); + rpm = RPM_FROM_REG(data->target_count[channel], + sr, + data->pulses[channel]); *val = rpm; return 0; case hwmon_fan_fault: @@ -231,6 +238,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_pulses: + *val = data->pulses[channel]; + return 0; default: return -EOPNOTSUPP; } @@ -264,7 +274,7 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, break; sr = get_tach_period(data->fan_dynamics[channel]); - target_count = RPM_TO_REG(val, sr); + target_count = RPM_TO_REG(val, sr, data->pulses[channel]); target_count = clamp_val(target_count, 0x1, 0x7FF); data->target_count[channel] = target_count << 5; @@ -285,6 +295,9 @@ 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_pulses: + data->pulses[channel] = val; + break; default: err = -EOPNOTSUPP; break; @@ -317,6 +330,10 @@ 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_pulses: + if (channel < NR_CHANNEL) + return 0644; + return 0; default: return 0; } @@ -486,18 +503,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_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_PULSES | 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, @@ -534,6 +551,8 @@ static int max31790_init_client(struct regmap *regmap, data->full_speed[i] = false; + data->pulses[i] = 2; + rv = regmap_read(regmap, MAX31790_REG_FAN_DYNAMICS(i), &val); From patchwork Thu Mar 4 10:58:27 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: 12115887 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,URIBL_BLOCKED,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 CC26DC43381 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 89D7064F37 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239279AbhCDLBT (ORCPT ); Thu, 4 Mar 2021 06:01:19 -0500 Received: from mail-wm1-f44.google.com ([209.85.128.44]:51115 "EHLO mail-wm1-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239233AbhCDLAr (ORCPT ); Thu, 4 Mar 2021 06:00:47 -0500 Received: by mail-wm1-f44.google.com with SMTP id i9so7644239wml.0; Thu, 04 Mar 2021 03:00:31 -0800 (PST) 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=D2TtDMxqLNkT1Ekg9r6IgrQnZtb/5fla5rvVsmZNlkY=; b=Pylp4eNyEHIucKCg4wyHdRHdirj20/MHCuzRejewU8ny2E/PqgRZ6+UFQp+qc/6dK+ X2RIlp6QUBbaMn/YLy2kOSdXoPR29eCWMlyqwNdZat9VAshrYSguAbAFykuZUsVk8zYC 8N/VKZnMigfFAUFWYyzHf/WPVm4YAe9q5P6vy+pYmWLuOVTDv9aXeaVGjkDY01V1l7Mk 2ERUrjyZiQEdw4cHr8HFljGe7HiCd5m4XJpQ3z5uFeQJ6cRcKuYLhXAIamEeKNdHagWL ERDQYj4bDmgecH1KieWJpPMa1yVYF1aBJTQAcQ6XOakiOmVKAR9ANh8NJx8fJaIegUIU tLNg== X-Gm-Message-State: AOAM531Ya2oNywpdK+HLml4bXPyeyMFbHqVce6zXWRyPA2Ba7ry+POek dvw8479YTfp7564KLgl6Jhk= X-Google-Smtp-Source: ABdhPJyVLnjJzinKf5VF4NBZXhSFuEkEmSqRw2GcmBEHY7Q5pQe8sTujfmkbHqGRQeTx2DXhjbGpSg== X-Received: by 2002:a1c:e383:: with SMTP id a125mr3320217wmh.125.1614855606143; Thu, 04 Mar 2021 03:00:06 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id a3sm35811711wrt.68.2021.03.04.03.00.05 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:05 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/7] hwmon: (max31790) Show 0 RPM/fault when input disabled Date: Thu, 4 Mar 2021 11:58:27 +0100 Message-Id: <20210304105830.507176-4-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) 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 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 74a81e5e3383..fde08c95d942 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -219,6 +219,11 @@ 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)) { + *val = 0; + return 0; + } sr = get_tach_period(data->fan_dynamics[channel]); rpm = RPM_FROM_REG(data->tach[channel], sr, @@ -233,6 +238,11 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, *val = rpm; return 0; case hwmon_fan_fault: + if (!(data->fan_config[channel] & + MAX31790_FAN_CFG_TACH_INPUT_EN)) { + *val = 0; + return 0; + } *val = !!(data->fault_status & (1 << channel)); return 0; case hwmon_fan_enable: From patchwork Thu Mar 4 10:58:28 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: 12115885 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.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UPPERCASE_50_75,URIBL_BLOCKED, 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 99012C433E0 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6605B64F34 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239242AbhCDLBU (ORCPT ); Thu, 4 Mar 2021 06:01:20 -0500 Received: from mail-wr1-f42.google.com ([209.85.221.42]:43088 "EHLO mail-wr1-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239241AbhCDLAu (ORCPT ); Thu, 4 Mar 2021 06:00:50 -0500 Received: by mail-wr1-f42.google.com with SMTP id w11so27100203wrr.10; Thu, 04 Mar 2021 03:00:34 -0800 (PST) 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=IQ2tQGgAEXKRhsWFbmI1TfLpFlPfR41QCn14sTysJrw=; b=H5oUom8uq3voXGFQ8Xq/32pyK3SbqJxSPt9LCXqulnhcYRF9ntfuWd9suV+PLD0K7T t1KPNa9MGj+E+wfDZSeJtT9gbeHZVAIak3ZhTilbFoP/Twh3UV0FkBD9Dlk/i6o7gmTR gq2wvVOIHV6xkUWXLl+7HG4L3oPLBzYYg7XthF9Oa5dSikl22PmcTsfzfeXR1dn24KWQ g86swu68g+59j66OUfsOTVtCTj1RVnRjPcdPFSoR8skJQeunJo5nWcPxKER7vo6XLjen yR79Za9YkcR/l4ydw/xBURRpMOTbYzv1MOejpiQdcRGoRrmMfgZ1o92QTXeMUx836tE8 BnJg== X-Gm-Message-State: AOAM533Yn+aX6jGLA/UhqTkU/D0jkFnL3oIbcZa4aMeIn5zSw9yGhLKW mJ2jDP/6I7UX9oJBGlBSHxvqrSZkBr7CMA== X-Google-Smtp-Source: ABdhPJw9bQspoohOvwpDIhVmFsonXtzC3kfulY0Gx33t3k5ocY2y8FNLx3D0WUEU7HURJzhrn1GKEg== X-Received: by 2002:adf:e409:: with SMTP id g9mr3250789wrm.423.1614855608516; Thu, 04 Mar 2021 03:00:08 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id f2sm33717045wrq.34.2021.03.04.03.00.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:08 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/7] hwmon: (max31790) Refactor HWMON_CHANNEL_INFO Date: Thu, 4 Mar 2021 11:58:28 +0100 Message-Id: <20210304105830.507176-5-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org The line was starting to get a little long. Signed-off-by: Václav Kubernát --- drivers/hwmon/max31790.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index fde08c95d942..d4f259dd4e19 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -56,6 +56,19 @@ #define U16_MSB(num) (((num) & 0xFF00) >> 8) #define U16_LSB(num) ((num) & 0x00FF) +#define FAN_INFO_1_TO_6 \ + (HWMON_F_PULSES | \ + HWMON_F_ENABLE | \ + HWMON_F_INPUT | \ + HWMON_F_TARGET | \ + HWMON_F_FAULT) + +#define FAN_INFO_7_TO_12 \ + (HWMON_F_PULSES | \ + HWMON_F_ENABLE | \ + HWMON_F_INPUT | \ + HWMON_F_FAULT) + static const struct regmap_range max31790_ro_range = { .range_min = MAX31790_REG_TACH_COUNT(0), .range_max = MAX31790_REG_PWMOUT(0) - 1, @@ -513,18 +526,18 @@ static umode_t max31790_is_visible(const void *data, static const struct hwmon_channel_info *max31790_info[] = { HWMON_CHANNEL_INFO(fan, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT, - HWMON_F_PULSES | HWMON_F_ENABLE | HWMON_F_INPUT | HWMON_F_FAULT), + FAN_INFO_1_TO_6, + FAN_INFO_1_TO_6, + FAN_INFO_1_TO_6, + FAN_INFO_1_TO_6, + FAN_INFO_1_TO_6, + FAN_INFO_1_TO_6, + FAN_INFO_7_TO_12, + FAN_INFO_7_TO_12, + FAN_INFO_7_TO_12, + FAN_INFO_7_TO_12, + FAN_INFO_7_TO_12, + FAN_INFO_7_TO_12), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, From patchwork Thu Mar 4 10:58:29 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: 12115889 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,URIBL_BLOCKED,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 D2D74C4332B for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A7A0E64F34 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239274AbhCDLBU (ORCPT ); Thu, 4 Mar 2021 06:01:20 -0500 Received: from mail-wr1-f51.google.com ([209.85.221.51]:45982 "EHLO mail-wr1-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239246AbhCDLAv (ORCPT ); Thu, 4 Mar 2021 06:00:51 -0500 Received: by mail-wr1-f51.google.com with SMTP id e10so26893195wro.12; Thu, 04 Mar 2021 03:00:36 -0800 (PST) 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=j11ELa20Vtg3isYzKy25uBKJEW/3+jwmRaEWBM3QmLE=; b=EielAtLuBt7I/4vibrAXxL1zF7aQmMYc6Nb58ubh7EaXivAC6WBA7GWJvUWSOIxSFd 31TPdKzFqyIurIBFnZrevT+xRuCm9C0sb7thK9DXd/XdGkV3ks1UaAf7sjrEnygW785b wKon9FVOryOiMz4F6zHTP9i9wogkgpjCYumgXnHYRusVrVAfqT6HpRtccXcRAU6oU8F8 sZgfS4KfZKeBkEgLtcqFbRBqo49ya3YHdZlPOeB5Eq/XD11vFLUNZsB+Jg2iEbwxpftF w61PB3u3eN2AmAkXLIO1FhVYF15SMwYMfz6FcpnGivIPWqgC095RX35Ox2ugTPCTsE4T 18uQ== X-Gm-Message-State: AOAM533lIkfWPw0hSQdn7F/38hRKBBsUg2hQXZnOya3dZEnOFbhhHzVi +A3+H2SoZWjWyHvzon4fxBY= X-Google-Smtp-Source: ABdhPJzsVXvIh0xa6gr7OSr1ofLBYNBmFNIrxTNrsazVAQV8bVFC5uVtLPX9SSpzJs7QkIcLXR0E7A== X-Received: by 2002:a5d:4445:: with SMTP id x5mr3581784wrr.30.1614855610437; Thu, 04 Mar 2021 03:00:10 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id s16sm7952579wru.91.2021.03.04.03.00.09 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:10 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6/7] hwmon: (max31790) Allow setting fan*_div Date: Thu, 4 Mar 2021 11:58:29 +0100 Message-Id: <20210304105830.507176-6-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) 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 | 46 +++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index 8d86698b25de..627816fa45fb 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -39,6 +39,7 @@ fan[1-12]_enable RW enable fan speed monitoring fan[1-12]_pulses RW pulses per fan revolution (default: 2) 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=full speed, 1=manual (pwm) mode, 2=rpm mode setting rpm mode sets fan*_enable to 1 diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index d4f259dd4e19..12eab8817c8a 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -57,7 +57,8 @@ #define U16_LSB(num) ((num) & 0x00FF) #define FAN_INFO_1_TO_6 \ - (HWMON_F_PULSES | \ + (HWMON_F_DIV | \ + HWMON_F_PULSES | \ HWMON_F_ENABLE | \ HWMON_F_INPUT | \ HWMON_F_TARGET | \ @@ -221,6 +222,26 @@ static u8 bits_for_tach_period(int rpm) return bits; } +static int bits_for_speed_range(int 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) { @@ -264,6 +285,9 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, case hwmon_fan_pulses: *val = data->pulses[channel]; return 0; + case hwmon_fan_div: + *val = get_tach_period(data->fan_config[channel]); + return 0; default: return -EOPNOTSUPP; } @@ -321,6 +345,25 @@ static int max31790_write_fan(struct device *dev, u32 attr, int channel, case hwmon_fan_pulses: data->pulses[channel] = val; 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; @@ -353,6 +396,7 @@ 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_div: case hwmon_fan_pulses: if (channel < NR_CHANNEL) return 0644; From patchwork Thu Mar 4 10:58:30 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: 12115891 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,URIBL_BLOCKED,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 1007FC4332E for ; Thu, 4 Mar 2021 11:02:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DD8AF64F49 for ; Thu, 4 Mar 2021 11:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239233AbhCDLBV (ORCPT ); Thu, 4 Mar 2021 06:01:21 -0500 Received: from mail-wr1-f46.google.com ([209.85.221.46]:33347 "EHLO mail-wr1-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239251AbhCDLAy (ORCPT ); Thu, 4 Mar 2021 06:00:54 -0500 Received: by mail-wr1-f46.google.com with SMTP id 7so27146762wrz.0; Thu, 04 Mar 2021 03:00:38 -0800 (PST) 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=rlACR9GlcEGYi0JxxJSxFKSxWtcSncE/VZbbXtmns9I=; b=jAbdWMq1IkDGwFYDcQSK5qKDbLNbrklgoblo0H0u0AyVUWea2ykOoDzOAMpNMFTPRf oUzQzDbUb3iFuZ7SOtKwoZUiw2d1L9ahsoLMuIO5Grm8uedO18OykXCW45De0ovfttq/ cKctxA7YHAjBvJRpO3W6dgQjAzVufVLvnUME+EAkuW9OvMY2g/mK87Fv2DK5FiqRG+CB 712gn7mwSUlELO3da7LAdOxo0wTwv6MZRCOustMtWhmMNA+tza4CKiI4MEq2pm1wQuK+ PY5SuLqUwwPCAIzgfMX5z1ZfItRloH0Y98UsnRAx4VaTXCvbTx58us6it5iWDic0ItAR fu0g== X-Gm-Message-State: AOAM531lU3VwJvDmMSagmeWG4IbsZxYIjLCorkzR2/TRxG6hWCEkkwRy vxPyfEI4aE5lshTL6/CD944= X-Google-Smtp-Source: ABdhPJzIRAAXqglgIm52oOPM4/B5D5LtG5/Wv2XgZurXuQsCbL8a1JNhNXdvJX8XWZMmErAeMxj9mA== X-Received: by 2002:adf:e84f:: with SMTP id d15mr3364431wrn.394.1614855612414; Thu, 04 Mar 2021 03:00:12 -0800 (PST) Received: from localhost ([2a02:8308:387:c900:a7b5:b859:9449:c07b]) by smtp.gmail.com with ESMTPSA id x13sm35184151wrt.75.2021.03.04.03.00.11 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 04 Mar 2021 03:00:12 -0800 (PST) From: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= Cc: =?utf-8?b?VsOhY2xhdiBLdWJlcm7DoXQ=?= , Jean Delvare , Guenter Roeck , Jonathan Corbet , linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 7/7] hwmon: (max31790) Update documentation Date: Thu, 4 Mar 2021 11:58:30 +0100 Message-Id: <20210304105830.507176-7-kubernat@cesnet.cz> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210304105830.507176-1-kubernat@cesnet.cz> References: <20210304105830.507176-1-kubernat@cesnet.cz> MIME-Version: 1.0 To: unlisted-recipients:; (no To-header on input) 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 it 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 | 48 +++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index 627816fa45fb..d5ab7caa491a 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -30,6 +30,51 @@ 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 +--------------------- +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". + +PWM mode +- Fan speed is controlled by writing a value to pwm[1-6]. + +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 driver uses `regmap`, so it +should be easy to read the values of the registers from userspace. + +The fan fault value latches. To reset it, set a value to pwm[1-6] +or fan[1-6]_target. + +About fan[1-12]_pulses +---------------------- +You should set this depending on the fan you use. It affects what values +are in fan[1-12]_input and also what gets written to 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 ------------- @@ -40,7 +85,8 @@ fan[1-12]_pulses RW pulses per fan revolution (default: 2) 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=full speed, 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)