From nobody Sun Feb 8 03:29:21 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6AD72EDEC76 for ; Wed, 13 Sep 2023 15:22:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237913AbjIMPWm (ORCPT ); Wed, 13 Sep 2023 11:22:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237422AbjIMPWj (ORCPT ); Wed, 13 Sep 2023 11:22:39 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 02E491724; Wed, 13 Sep 2023 08:22:36 -0700 (PDT) Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 38DDh9ei006883; Wed, 13 Sep 2023 11:22:16 -0400 Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3t2y8f562c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2023 11:22:16 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 38DFMFOQ004934 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 Sep 2023 11:22:15 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 13 Sep 2023 11:22:14 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 13 Sep 2023 11:22:14 -0400 Received: from daniel-Precision-5530.ad.analog.com ([10.48.65.230]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 38DFLmjB007886; Wed, 13 Sep 2023 11:22:09 -0400 From: Daniel Matyas CC: Daniel Matyas , Jean Delvare , Guenter Roeck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH 1/4] hwmon: max31827: Make code cleaner Date: Wed, 13 Sep 2023 18:21:31 +0300 Message-ID: <20230913152135.457892-2-daniel.matyas@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230913152135.457892-1-daniel.matyas@analog.com> References: <20230913152135.457892-1-daniel.matyas@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: M94kou5Mj2C1ZGBtuNV8XO3iKcEeyKBe X-Proofpoint-GUID: M94kou5Mj2C1ZGBtuNV8XO3iKcEeyKBe X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-13_09,2023-09-13_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 phishscore=0 malwarescore=0 adultscore=0 priorityscore=1501 impostorscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2308100000 definitions=main-2309130125 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Now the wait time for one-shot is 140ms, instead of the old 141 (removed the 1ms error). Used enums and while loops to replace switch for selecting and getting update interval from conversion rate bits. Divided the write_alarm_val function into 2 functions. The new function is more generic: it can be used not only for alarm writes, but for any kind of writes which require the device to be in shutdown mode. Signed-off-by: Daniel Matyas --- Documentation/hwmon/max31827.rst | 4 +- drivers/hwmon/max31827.c | 127 ++++++++++++++----------------- 2 files changed, 58 insertions(+), 73 deletions(-) diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max3182= 7.rst index b0971d05b8a4..9a1055a007cf 100644 --- a/Documentation/hwmon/max31827.rst +++ b/Documentation/hwmon/max31827.rst @@ -73,8 +73,8 @@ the conversion frequency to 1 conv/s. The conversion time= varies depending on the resolution. The conversion time doubles with every bit of increased resolution. For 10 bit resolution 35ms are needed, while for 12 bit resolu= tion (default) 140ms. When chip is in shutdown mode and a read operation is -requested, one-shot is triggered, the device waits for 140 (conversion tim= e) + 1 -(error) ms, and only after that is the temperature value register read. +requested, one-shot is triggered, the device waits for 140 (conversion tim= e) ms, +and only after that is the temperature value register read. =20 The LSB of the temperature values is 0.0625 degrees Celsius, but the value= s of the temperatures are displayed in milli-degrees. This means, that some dat= a is diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c index 602f4e4f81ff..f05762219995 100644 --- a/drivers/hwmon/max31827.c +++ b/drivers/hwmon/max31827.c @@ -25,20 +25,32 @@ #define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) #define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) =20 -#define MAX31827_12_BIT_CNV_TIME 141 - -#define MAX31827_CNV_1_DIV_64_HZ 0x1 -#define MAX31827_CNV_1_DIV_32_HZ 0x2 -#define MAX31827_CNV_1_DIV_16_HZ 0x3 -#define MAX31827_CNV_1_DIV_4_HZ 0x4 -#define MAX31827_CNV_1_HZ 0x5 -#define MAX31827_CNV_4_HZ 0x6 -#define MAX31827_CNV_8_HZ 0x7 +#define MAX31827_12_BIT_CNV_TIME 140 =20 #define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) #define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000) #define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0) =20 +enum max31827_cnv { + MAX31827_CNV_1_DIV_64_HZ =3D 1, + MAX31827_CNV_1_DIV_32_HZ, + MAX31827_CNV_1_DIV_16_HZ, + MAX31827_CNV_1_DIV_4_HZ, + MAX31827_CNV_1_HZ, + MAX31827_CNV_4_HZ, + MAX31827_CNV_8_HZ, +}; + +static const u16 max31827_conversions[] =3D { + [MAX31827_CNV_1_DIV_64_HZ] =3D 64000, + [MAX31827_CNV_1_DIV_32_HZ] =3D 32000, + [MAX31827_CNV_1_DIV_16_HZ] =3D 16000, + [MAX31827_CNV_1_DIV_4_HZ] =3D 4000, + [MAX31827_CNV_1_HZ] =3D 1000, + [MAX31827_CNV_4_HZ] =3D 250, + [MAX31827_CNV_8_HZ] =3D 125, +}; + struct max31827_state { /* * Prevent simultaneous access to the i2c client. @@ -54,15 +66,13 @@ static const struct regmap_config max31827_regmap =3D { .max_register =3D 0xA, }; =20 -static int write_alarm_val(struct max31827_state *st, unsigned int reg, - long val) +static int shutdown_write(struct max31827_state *st, unsigned int reg, + unsigned int val) { unsigned int cfg; - unsigned int tmp; + unsigned int cnv_rate; int ret; =20 - val =3D MAX31827_M_DGR_TO_16_BIT(val); - /* * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold * register values are changed over I2C, the part must be in shutdown @@ -82,9 +92,10 @@ static int write_alarm_val(struct max31827_state *st, un= signed int reg, if (ret) goto unlock; =20 - tmp =3D cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK | + cnv_rate =3D MAX31827_CONFIGURATION_CNV_RATE_MASK & cfg; + cfg =3D cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK | MAX31827_CONFIGURATION_CNV_RATE_MASK); - ret =3D regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, tmp); + ret =3D regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg); if (ret) goto unlock; =20 @@ -92,13 +103,23 @@ static int write_alarm_val(struct max31827_state *st, = unsigned int reg, if (ret) goto unlock; =20 - ret =3D regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg); + ret =3D regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_CNV_RATE_MASK, + cnv_rate); =20 unlock: mutex_unlock(&st->lock); return ret; } =20 +static int write_alarm_val(struct max31827_state *st, unsigned int reg, + long val) +{ + val =3D MAX31827_M_DGR_TO_16_BIT(val); + + return shutdown_write(st, reg, val); +} + static umode_t max31827_is_visible(const void *state, enum hwmon_sensor_types type, u32 attr, int channel) @@ -243,32 +264,7 @@ static int max31827_read(struct device *dev, enum hwmo= n_sensor_types type, =20 uval =3D FIELD_GET(MAX31827_CONFIGURATION_CNV_RATE_MASK, uval); - switch (uval) { - case MAX31827_CNV_1_DIV_64_HZ: - *val =3D 64000; - break; - case MAX31827_CNV_1_DIV_32_HZ: - *val =3D 32000; - break; - case MAX31827_CNV_1_DIV_16_HZ: - *val =3D 16000; - break; - case MAX31827_CNV_1_DIV_4_HZ: - *val =3D 4000; - break; - case MAX31827_CNV_1_HZ: - *val =3D 1000; - break; - case MAX31827_CNV_4_HZ: - *val =3D 250; - break; - case MAX31827_CNV_8_HZ: - *val =3D 125; - break; - default: - *val =3D 0; - break; - } + *val =3D max31827_conversions[uval]; } break; =20 @@ -284,6 +280,7 @@ static int max31827_write(struct device *dev, enum hwmo= n_sensor_types type, u32 attr, int channel, long val) { struct max31827_state *st =3D dev_get_drvdata(dev); + int res =3D 1; int ret; =20 switch (type) { @@ -333,39 +330,27 @@ static int max31827_write(struct device *dev, enum hw= mon_sensor_types type, if (!st->enable) return -EINVAL; =20 - switch (val) { - case 125: - val =3D MAX31827_CNV_8_HZ; - break; - case 250: - val =3D MAX31827_CNV_4_HZ; - break; - case 1000: - val =3D MAX31827_CNV_1_HZ; - break; - case 4000: - val =3D MAX31827_CNV_1_DIV_4_HZ; - break; - case 16000: - val =3D MAX31827_CNV_1_DIV_16_HZ; - break; - case 32000: - val =3D MAX31827_CNV_1_DIV_32_HZ; - break; - case 64000: - val =3D MAX31827_CNV_1_DIV_64_HZ; - break; - default: - return -EINVAL; - } + /* + * Convert the desired conversion rate into register + * bits. res is already initialized with 1. + * + * This was inspired by lm73 driver. + */ + while (res < ARRAY_SIZE(max31827_conversions) && + val < max31827_conversions[res]) + res++; + + if (res =3D=3D ARRAY_SIZE(max31827_conversions) || + val !=3D max31827_conversions[res]) + return -EOPNOTSUPP; =20 - val =3D FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, - val); + res =3D FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, + res); =20 return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG, MAX31827_CONFIGURATION_CNV_RATE_MASK, - val); + res); } break; =20 --=20 2.34.1 From nobody Sun Feb 8 03:29:21 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1D1BEDEC76 for ; Wed, 13 Sep 2023 15:22:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233184AbjIMPWz (ORCPT ); Wed, 13 Sep 2023 11:22:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239215AbjIMPWu (ORCPT ); Wed, 13 Sep 2023 11:22:50 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E7E201BEC; Wed, 13 Sep 2023 08:22:43 -0700 (PDT) Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 38DDNbMk007131; Wed, 13 Sep 2023 11:22:25 -0400 Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3t2y8f563g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2023 11:22:24 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 38DFMNpw004937 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 Sep 2023 11:22:23 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 13 Sep 2023 11:22:22 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 13 Sep 2023 11:22:22 -0400 Received: from daniel-Precision-5530.ad.analog.com ([10.48.65.230]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 38DFLmjC007886; Wed, 13 Sep 2023 11:22:16 -0400 From: Daniel Matyas CC: Daniel Matyas , Jean Delvare , Guenter Roeck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH 2/4] dt-bindings: hwmon: Added new properties to the devicetree Date: Wed, 13 Sep 2023 18:21:32 +0300 Message-ID: <20230913152135.457892-3-daniel.matyas@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230913152135.457892-1-daniel.matyas@analog.com> References: <20230913152135.457892-1-daniel.matyas@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: _z_s-ZBdPl4UijuCYQUZkHi74r9CjPEp X-Proofpoint-GUID: _z_s-ZBdPl4UijuCYQUZkHi74r9CjPEp X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-13_09,2023-09-13_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 phishscore=0 malwarescore=0 adultscore=0 priorityscore=1501 impostorscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2308100000 definitions=main-2309130125 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" These attributes are: - adi,comp-int - boolean property - adi,alrm-pol - can be 0, 1 (if not present, default value) - adi,flt-q - can be 1, 2, 4, 8 (if not present, default value) - adi,timeout-enable - boolean property These modify the corresponding bits in the configuration register. Signed-off-by: Daniel Matyas --- .../bindings/hwmon/adi,max31827.yaml | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml b/Do= cumentation/devicetree/bindings/hwmon/adi,max31827.yaml index 2dc8b07b4d3b..6bde71bdb8dd 100644 --- a/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml +++ b/Documentation/devicetree/bindings/hwmon/adi,max31827.yaml @@ -32,6 +32,37 @@ properties: Must have values in the interval (1.6V; 3.6V) in order for the devic= e to function correctly. =20 + adi,comp-int: + description: + If present interrupt mode is used. If not present comparator mode is= used + (default). + type: boolean + + adi,alrm-pol: + description: + Sets the alarms active state. + - 0 =3D active low + - 1 =3D active high + For max31827 and max31828 the default alarm polarity is low. For max= 31829 + it is high. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + adi,flt-q: + description: + Select how many consecutive temperature faults must occur before + overtemperature or undertemperature faults are indicated in the + corresponding status bits. + For max31827 default fault queue is 1. For max31828 and max31829 it = is 4. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 4, 8] + + adi,timeout-enable: + description: + Enables timeout. Bus timeout resets the I2C-compatible interface whe= n SCL + is low for more than 30ms (nominal). + type: boolean + required: - compatible - reg @@ -49,6 +80,10 @@ examples: compatible =3D "adi,max31827"; reg =3D <0x42>; vref-supply =3D <®_vdd>; + adi,comp-int; + adi,alrm-pol =3D <0>; + adi,flt-q =3D <1>; + adi,timeout-enable; }; }; ... --=20 2.34.1 From nobody Sun Feb 8 03:29:21 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6544AEDEC71 for ; Wed, 13 Sep 2023 15:22:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239435AbjIMPW6 (ORCPT ); Wed, 13 Sep 2023 11:22:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235951AbjIMPWv (ORCPT ); Wed, 13 Sep 2023 11:22:51 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 490571BC7; Wed, 13 Sep 2023 08:22:46 -0700 (PDT) Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 38DEEHYt006418; Wed, 13 Sep 2023 11:22:27 -0400 Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3t2y8f563r-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2023 11:22:27 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 38DFMQCV004940 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 Sep 2023 11:22:26 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 13 Sep 2023 11:22:25 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 13 Sep 2023 11:22:25 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 13 Sep 2023 11:22:25 -0400 Received: from daniel-Precision-5530.ad.analog.com ([10.48.65.230]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 38DFLmjD007886; Wed, 13 Sep 2023 11:22:20 -0400 From: Daniel Matyas CC: Daniel Matyas , Jean Delvare , Guenter Roeck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH 3/4] hwmon: max31827: Handle new properties from the devicetree Date: Wed, 13 Sep 2023 18:21:33 +0300 Message-ID: <20230913152135.457892-4-daniel.matyas@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230913152135.457892-1-daniel.matyas@analog.com> References: <20230913152135.457892-1-daniel.matyas@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: heyb1qUt5La3BdiFHl9CybmkStKD-fWc X-Proofpoint-GUID: heyb1qUt5La3BdiFHl9CybmkStKD-fWc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-13_09,2023-09-13_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 phishscore=0 malwarescore=0 adultscore=0 priorityscore=1501 impostorscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2308100000 definitions=main-2309130125 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Used fwnode to retrieve data from the devicetree in the init_client function. Added support for devices max31828 and max31829. For these devices, when adi,flt-q and/or adi,alrm-pol are not mentioned, the default configuration is loaded. Signed-off-by: Daniel Matyas --- Documentation/hwmon/max31827.rst | 47 ++++++++-- drivers/hwmon/max31827.c | 142 +++++++++++++++++++++++++++---- 2 files changed, 165 insertions(+), 24 deletions(-) diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max3182= 7.rst index 9a1055a007cf..e0eca1eb5c06 100644 --- a/Documentation/hwmon/max31827.rst +++ b/Documentation/hwmon/max31827.rst @@ -52,13 +52,21 @@ MAX31827 has low and over temperature alarms with an ef= fective value and a hysteresis value: -40 and -30 degrees for under temperature alarm and +100= and +90 degrees for over temperature alarm. =20 -The alarm can be configured in comparator and interrupt mode. Currently on= ly -comparator mode is implemented. In Comparator mode, the OT/UT status bits = have a -value of 1 when the temperature rises above the TH value or falls below TL, -which is also subject to the Fault Queue selection. OT status returns to 0= when -the temperature drops below the TH_HYST value or when shutdown mode is ent= ered. -Similarly, UT status returns to 0 when the temperature rises above TL_HYST= value -or when shutdown mode is entered. +The alarm can be configured in comparator and interrupt mode from the +devicetree. In Comparator mode, the OT/UT status bits have a value of 1 wh= en the +temperature rises above the TH value or falls below TL, which is also subj= ect to +the Fault Queue selection. OT status returns to 0 when the temperature dro= ps +below the TH_HYST value or when shutdown mode is entered. Similarly, UT st= atus +returns to 0 when the temperature rises above TL_HYST value or when shutdo= wn +mode is entered. + +In interrupt mode exceeding TH also sets OT status to 1, which remains set= until +a read operation is performed on the configuration/status register (max or= min +attribute); at this point, it returns to 0. Once OT status is set to 1 from +exceeding TH and reset, it is set to 1 again only when the temperature dro= ps +below TH_HYST. The output remains asserted until it is reset by a read. It= is +set again if the temperature rises above TH, and so on. The same logic app= lies +to the operation of the UT status bit. =20 Putting the MAX31827 into shutdown mode also resets the OT/UT status bits.= Note that if the mode is changed while OT/UT status bits are set, an OT/UT stat= us @@ -68,6 +76,17 @@ clear the status bits before changing the operating mode. =20 The conversions can be manual with the one-shot functionality and automati= c with a set frequency. When powered on, the chip measures temperatures with 1 co= nv/s. +The conversion rate can be modified with update_interval attribute of the = chip. +Conversion/second =3D 1/update_interval. Thus, the available options accor= ding to +the data sheet are: + - 64000 (ms) =3D 1 conv/64 sec + - 32000 (ms) =3D 1 conv/32 sec + - 16000 (ms) =3D 1 conv/16 sec + - 4000 (ms) =3D 1 conv/4 sec + - 1000 (ms) =3D 1 conv/sec (default) + - 250 (ms) =3D 4 conv/sec + - 125 (ms) =3D 8 conv/sec + Enabling the device when it is already enabled has the side effect of sett= ing the conversion frequency to 1 conv/s. The conversion time varies depending= on the resolution. The conversion time doubles with every bit of increased @@ -83,8 +102,18 @@ in the writing of alarm values too. For positive number= s the user-input value will always be rounded down to the nearest possible value, for negative nu= mbers the user-input will always be rounded up to the nearest possible value. =20 +Bus timeout resets the I2C-compatible interface when SCL is low for more t= han +30ms (nominal). + +Alarm polarity determines if the active state of the alarm is low or high.= The +behavior for both settings is dependent on the Fault Queue setting. The AL= ARM +pin is an open-drain output and requires a pullup resistor to operate. + +The Fault Queue bits select how many consecutive temperature faults must o= ccur +before overtemperature or undertemperature faults are indicated in the +corresponding status bits. + Notes ----- =20 -Currently fault queue, alarm polarity and resolution cannot be modified. -PEC is not implemented either. +PEC and resolution are not implemented. diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c index f05762219995..4dc14642775a 100644 --- a/drivers/hwmon/max31827.c +++ b/drivers/hwmon/max31827.c @@ -12,6 +12,19 @@ #include #include #include +#include +#include + +/* + * gcc turns __builtin_ffsll() into a call to __ffsdi2(), which is not pro= vided + * by every architecture. __ffs64() is available on all architectures, but= the + * result is not defined if no bits are set. + */ +#define max31827__bf_shf(x) \ + ({ \ + typeof(x) x_ =3D (x); \ + ((x_) !=3D 0) ? __ffs64(x_) : 0x0; \ + }) =20 #define MAX31827_T_REG 0x0 #define MAX31827_CONFIGURATION_REG 0x2 @@ -22,15 +35,25 @@ =20 #define MAX31827_CONFIGURATION_1SHOT_MASK BIT(0) #define MAX31827_CONFIGURATION_CNV_RATE_MASK GENMASK(3, 1) -#define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) -#define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) +#define MAX31827_CONFIGURATION_TIMEOUT_MASK BIT(5) +#define MAX31827_CONFIGURATION_RESOLUTION_MASK GENMASK(7, 6) +#define MAX31827_CONFIGURATION_ALRM_POL_MASK BIT(8) +#define MAX31827_CONFIGURATION_COMP_INT_MASK BIT(9) +#define MAX31827_CONFIGURATION_FLT_Q_MASK GENMASK(11, 10) +#define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) +#define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) =20 #define MAX31827_12_BIT_CNV_TIME 140 =20 +#define MAX31827_FLT_Q_1 0x0 +#define MAX31827_FLT_Q_4 0x2 + #define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) #define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000) #define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0) =20 +enum chips { max31827, max31828, max31829 }; + enum max31827_cnv { MAX31827_CNV_1_DIV_64_HZ =3D 1, MAX31827_CNV_1_DIV_32_HZ, @@ -58,6 +81,7 @@ struct max31827_state { struct mutex lock; struct regmap *regmap; bool enable; + struct i2c_client *client; }; =20 static const struct regmap_config max31827_regmap =3D { @@ -361,14 +385,93 @@ static int max31827_write(struct device *dev, enum hw= mon_sensor_types type, return -EOPNOTSUPP; } =20 -static int max31827_init_client(struct max31827_state *st) +static const struct i2c_device_id max31827_i2c_ids[] =3D { + { "max31827", max31827 }, + { "max31828", max31828 }, + { "max31829", max31829 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); + +static int max31827_init_client(struct max31827_state *st, + struct fwnode_handle *fwnode) { + bool prop; + u32 data, lsb_idx; + unsigned int res =3D 0; + enum chips type; + int ret; + st->enable =3D true; + res |=3D MAX31827_DEVICE_ENABLE(1); + + res |=3D MAX31827_CONFIGURATION_RESOLUTION_MASK; =20 - return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG, - MAX31827_CONFIGURATION_1SHOT_MASK | - MAX31827_CONFIGURATION_CNV_RATE_MASK, - MAX31827_DEVICE_ENABLE(1)); + prop =3D fwnode_property_read_bool(fwnode, "adi,comp-int"); + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_COMP_INT_MASK, prop); + + prop =3D fwnode_property_read_bool(fwnode, "adi,timeout-enable"); + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_TIMEOUT_MASK, !prop); + + if (st->client->dev.of_node) + type =3D (enum chips)of_device_get_match_data(&st->client->dev); + else + type =3D i2c_match_id(max31827_i2c_ids, st->client)->driver_data; + + if (fwnode_property_present(fwnode, "adi,alrm-pol")) { + ret =3D fwnode_property_read_u32(fwnode, "adi,alrm-pol", &data); + if (ret) + return ret; + + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_ALRM_POL_MASK, !!data); + } else { + switch (type) { + case max31827: + case max31828: + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_ALRM_POL_MASK, + 0x0); + break; + case max31829: + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_ALRM_POL_MASK, + 0x1); + break; + default: + return -EOPNOTSUPP; + } + } + + if (fwnode_property_present(fwnode, "adi,flt-q")) { + ret =3D fwnode_property_read_u32(fwnode, "adi,flt-q", &data); + if (ret) + return ret; + + /* + * Convert the desired fault queue into register bits. + */ + lsb_idx =3D max31827__bf_shf(data); + if (lsb_idx > 3 || data !=3D BIT(lsb_idx)) { + dev_err(&st->client->dev, "Invalid data in fault queue\n"); + return -EOPNOTSUPP; + } + + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_FLT_Q_MASK, lsb_idx); + } else { + switch (type) { + case max31827: + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_FLT_Q_MASK, + MAX31827_FLT_Q_1); + break; + case max31828: + case max31829: + res |=3D FIELD_PREP(MAX31827_CONFIGURATION_FLT_Q_MASK, + MAX31827_FLT_Q_4); + break; + default: + return -EOPNOTSUPP; + } + } + + return regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, res); } =20 static const struct hwmon_channel_info *max31827_info[] =3D { @@ -396,6 +499,7 @@ static int max31827_probe(struct i2c_client *client) struct device *dev =3D &client->dev; struct device *hwmon_dev; struct max31827_state *st; + struct fwnode_handle *fwnode; int err; =20 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) @@ -412,7 +516,10 @@ static int max31827_probe(struct i2c_client *client) return dev_err_probe(dev, PTR_ERR(st->regmap), "Failed to allocate regmap.\n"); =20 - err =3D max31827_init_client(st); + st->client =3D client; + fwnode =3D dev_fwnode(dev); + + err =3D max31827_init_client(st, fwnode); if (err) return err; =20 @@ -423,14 +530,19 @@ static int max31827_probe(struct i2c_client *client) return PTR_ERR_OR_ZERO(hwmon_dev); } =20 -static const struct i2c_device_id max31827_i2c_ids[] =3D { - { "max31827", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); - static const struct of_device_id max31827_of_match[] =3D { - { .compatible =3D "adi,max31827" }, + { + .compatible =3D "adi,max31827", + .data =3D (void *)max31827 + }, + { + .compatible =3D "adi,max31828", + .data =3D (void *)max31828 + }, + { + .compatible =3D "adi,max31829", + .data =3D (void *)max31829 + }, { } }; MODULE_DEVICE_TABLE(of, max31827_of_match); --=20 2.34.1 From nobody Sun Feb 8 03:29:21 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2EA53EDEC75 for ; Wed, 13 Sep 2023 15:25:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229448AbjIMP0A (ORCPT ); Wed, 13 Sep 2023 11:26:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233512AbjIMPW4 (ORCPT ); Wed, 13 Sep 2023 11:22:56 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D8671BC7; Wed, 13 Sep 2023 08:22:52 -0700 (PDT) Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 38DDqBTv006444; Wed, 13 Sep 2023 11:22:32 -0400 Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3t2y8f5646-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2023 11:22:32 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 38DFMVVU004943 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 13 Sep 2023 11:22:31 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 13 Sep 2023 11:22:30 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 13 Sep 2023 11:22:30 -0400 Received: from daniel-Precision-5530.ad.analog.com ([10.48.65.230]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 38DFLmjE007886; Wed, 13 Sep 2023 11:22:24 -0400 From: Daniel Matyas CC: Daniel Matyas , Jean Delvare , Guenter Roeck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH 4/4] hwmon: max31827: Add custom attribute for resolution Date: Wed, 13 Sep 2023 18:21:34 +0300 Message-ID: <20230913152135.457892-5-daniel.matyas@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230913152135.457892-1-daniel.matyas@analog.com> References: <20230913152135.457892-1-daniel.matyas@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: 87jm6WOrHg2ThbcFJjNEWOyFKY072FjT X-Proofpoint-GUID: 87jm6WOrHg2ThbcFJjNEWOyFKY072FjT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.601,FMLib:17.11.176.26 definitions=2023-09-13_09,2023-09-13_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 phishscore=0 malwarescore=0 adultscore=0 priorityscore=1501 impostorscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2308100000 definitions=main-2309130125 To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Added custom channel-specific (temp1) attribute for resolution. The wait time for a conversion in one-shot mode (enable =3D 0) depends on the resolution. When resolution is 12-bit, the conversion time is 140ms, but the minimum update_interval is 125ms. Handled this problem by waiting an additional 15ms (125ms + 15ms =3D 140ms). Signed-off-by: Daniel Matyas --- Documentation/hwmon/max31827.rst | 28 +++++-- drivers/hwmon/max31827.c | 136 +++++++++++++++++++++++++++---- 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/Documentation/hwmon/max31827.rst b/Documentation/hwmon/max3182= 7.rst index e0eca1eb5c06..219ab8abfd6a 100644 --- a/Documentation/hwmon/max31827.rst +++ b/Documentation/hwmon/max31827.rst @@ -89,11 +89,27 @@ the data sheet are: =20 Enabling the device when it is already enabled has the side effect of sett= ing the conversion frequency to 1 conv/s. The conversion time varies depending= on -the resolution. The conversion time doubles with every bit of increased -resolution. For 10 bit resolution 35ms are needed, while for 12 bit resolu= tion -(default) 140ms. When chip is in shutdown mode and a read operation is -requested, one-shot is triggered, the device waits for 140 (conversion tim= e) ms, -and only after that is the temperature value register read. +the resolution. + +The conversion time doubles with every bit of increased resolution. The +available resolutions are: + - 8 bit -> 8.75 ms conversion time + - 9 bit -> 17.5 ms conversion time + - 10 bit -> 35 ms conversion time + - 12 bit (default) -> 140 ms conversion time + +There is a temp1_resolution attribute which indicates the unit change in t= he +input temperature in milli-degrees C. + - 1000 mC -> 8 bit + - 500 mC -> 9 bit + - 250 mC -> 10 bit + - 62 mC -> 12 bit (default) - actually this is 62.5, but the file + returns 62 + +When chip is in shutdown mode and a read operation is requested, one-shot = is +triggered, the device waits for ms, and only after that = is +the temperature value register read. Note that the conversion times are ro= unded +up to the nearest possible integer. =20 The LSB of the temperature values is 0.0625 degrees Celsius, but the value= s of the temperatures are displayed in milli-degrees. This means, that some dat= a is @@ -116,4 +132,4 @@ corresponding status bits. Notes ----- =20 -PEC and resolution are not implemented. +PEC is not implemented. diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c index 4dc14642775a..396292c0bc32 100644 --- a/drivers/hwmon/max31827.c +++ b/drivers/hwmon/max31827.c @@ -43,6 +43,9 @@ #define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK BIT(14) #define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK BIT(15) =20 +#define MAX31827_8_BIT_CNV_TIME 9 +#define MAX31827_9_BIT_CNV_TIME 18 +#define MAX31827_10_BIT_CNV_TIME 35 #define MAX31827_12_BIT_CNV_TIME 140 =20 #define MAX31827_FLT_Q_1 0x0 @@ -51,6 +54,7 @@ #define MAX31827_16_BIT_TO_M_DGR(x) (sign_extend32(x, 15) * 1000 / 16) #define MAX31827_M_DGR_TO_16_BIT(x) (((x) << 4) / 1000) #define MAX31827_DEVICE_ENABLE(x) ((x) ? 0xA : 0x0) +#define MAX31827_FLT_Q =20 enum chips { max31827, max31828, max31829 }; =20 @@ -74,6 +78,27 @@ static const u16 max31827_conversions[] =3D { [MAX31827_CNV_8_HZ] =3D 125, }; =20 +enum max31827_resolution { + MAX31827_RES_8_BIT =3D 0, + MAX31827_RES_9_BIT, + MAX31827_RES_10_BIT, + MAX31827_RES_12_BIT, +}; + +static const u16 max31827_resolutions[] =3D { + [MAX31827_RES_8_BIT] =3D 1000, + [MAX31827_RES_9_BIT] =3D 500, + [MAX31827_RES_10_BIT] =3D 250, + [MAX31827_RES_12_BIT] =3D 62, +}; + +static const u16 max31827_conv_times[] =3D { + [MAX31827_RES_8_BIT] =3D MAX31827_8_BIT_CNV_TIME, + [MAX31827_RES_9_BIT] =3D MAX31827_9_BIT_CNV_TIME, + [MAX31827_RES_10_BIT] =3D MAX31827_10_BIT_CNV_TIME, + [MAX31827_RES_12_BIT] =3D MAX31827_12_BIT_CNV_TIME, +}; + struct max31827_state { /* * Prevent simultaneous access to the i2c client. @@ -81,6 +106,8 @@ struct max31827_state { struct mutex lock; struct regmap *regmap; bool enable; + unsigned int resolution; + unsigned int update_interval; struct i2c_client *client; }; =20 @@ -98,9 +125,9 @@ static int shutdown_write(struct max31827_state *st, uns= igned int reg, int ret; =20 /* - * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold - * register values are changed over I2C, the part must be in shutdown - * mode. + * Before the Temperature Threshold Alarm, Alarm Hysteresis Threshold + * and Resolution bits from Configuration register are changed over I2C, + * the part must be in shutdown mode. * * Mutex is used to ensure, that some other process doesn't change the * configuration register. @@ -211,9 +238,18 @@ static int max31827_read(struct device *dev, enum hwmo= n_sensor_types type, mutex_unlock(&st->lock); return ret; } - - msleep(MAX31827_12_BIT_CNV_TIME); + msleep(max31827_conv_times[st->resolution]); } + + /* + * For 12-bit resolution the conversion time is 140 ms, + * thus an additional 15 ms is needed to complete the + * conversion: 125 ms + 15 ms =3D 140 ms + */ + if (max31827_resolutions[st->resolution] =3D=3D 12 && + st->update_interval =3D=3D 125) + usleep_range(15000, 20000); + ret =3D regmap_read(st->regmap, MAX31827_T_REG, &uval); =20 mutex_unlock(&st->lock); @@ -371,10 +407,14 @@ static int max31827_write(struct device *dev, enum hw= mon_sensor_types type, res =3D FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK, res); =20 - return regmap_update_bits(st->regmap, - MAX31827_CONFIGURATION_REG, - MAX31827_CONFIGURATION_CNV_RATE_MASK, - res); + ret =3D regmap_update_bits(st->regmap, + MAX31827_CONFIGURATION_REG, + MAX31827_CONFIGURATION_CNV_RATE_MASK, + res); + if (ret) + return ret; + + st->update_interval =3D val; } break; =20 @@ -385,11 +425,79 @@ static int max31827_write(struct device *dev, enum hw= mon_sensor_types type, return -EOPNOTSUPP; } =20 +static ssize_t temp1_resolution_show(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct max31827_state *st =3D dev_get_drvdata(dev); + unsigned int val; + int ret; + + ret =3D regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &val); + if (ret) + return ret; + + val =3D FIELD_GET(MAX31827_CONFIGURATION_RESOLUTION_MASK, val); + + return scnprintf(buf, PAGE_SIZE, "%u\n", max31827_resolutions[val]); +} + +static ssize_t temp1_resolution_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct max31827_state *st =3D dev_get_drvdata(dev); + unsigned int idx =3D 0; + unsigned int val, cfg; + int ret; + + ret =3D kstrtouint(buf, 10, &val); + if (ret) + return ret; + + /* + * Convert the desired conversion rate into register + * bits. idx is already initialized with 1. + * + * This was inspired by lm73 driver. + */ + while (idx < ARRAY_SIZE(max31827_resolutions) && + val < max31827_resolutions[idx]) + idx++; + + if (idx =3D=3D ARRAY_SIZE(max31827_resolutions) || + val !=3D max31827_resolutions[idx]) + return -EOPNOTSUPP; + + st->resolution =3D idx; + + ret =3D regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &cfg); + if (ret) + return ret; + + cfg =3D (cfg & ~MAX31827_CONFIGURATION_RESOLUTION_MASK) | + FIELD_PREP(MAX31827_CONFIGURATION_RESOLUTION_MASK, idx); + cfg &=3D ~(MAX31827_CONFIGURATION_CNV_RATE_MASK | + MAX31827_CONFIGURATION_1SHOT_MASK); + + ret =3D shutdown_write(st, MAX31827_CONFIGURATION_REG, cfg); + + return (ret) ? ret : count; +} + +static DEVICE_ATTR_RW(temp1_resolution); + +static struct attribute *max31827_attrs[] =3D { + &dev_attr_temp1_resolution.attr, + NULL +}; +ATTRIBUTE_GROUPS(max31827); + static const struct i2c_device_id max31827_i2c_ids[] =3D { - { "max31827", max31827 }, - { "max31828", max31828 }, - { "max31829", max31829 }, - { } + { "max31827", max31827 }, + { "max31828", max31828 }, + { "max31829", max31829 }, + { } }; MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); =20 @@ -525,7 +633,7 @@ static int max31827_probe(struct i2c_client *client) =20 hwmon_dev =3D devm_hwmon_device_register_with_info(dev, client->name, st, &max31827_chip_info, - NULL); + max31827_groups); =20 return PTR_ERR_OR_ZERO(hwmon_dev); } --=20 2.34.1