From nobody Mon Apr 6 09:42:46 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 3FEC6ECAAD5 for ; Thu, 8 Sep 2022 08:25:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230026AbiIHIZJ (ORCPT ); Thu, 8 Sep 2022 04:25:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231491AbiIHIY7 (ORCPT ); Thu, 8 Sep 2022 04:24:59 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8290A491D6; Thu, 8 Sep 2022 01:24:56 -0700 (PDT) Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 28865Rfv010128; Thu, 8 Sep 2022 04:24:41 -0400 Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3jc0s7c1sj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 08 Sep 2022 04:24:41 -0400 Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 2888Od83026131 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 8 Sep 2022 04:24:39 -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; Thu, 8 Sep 2022 04:24:38 -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; Thu, 8 Sep 2022 04:24:38 -0400 Received: from ibrahim-vm.ad.analog.com (IST-LT-39247.ad.analog.com [10.25.16.132]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 2888OHWA032231; Thu, 8 Sep 2022 04:24:27 -0400 From: Ibrahim Tilki To: , CC: Ibrahim Tilki , , , , Nurettin Bolucu Subject: [PATCH RESEND v6 1/4] drivers: hwmon: Add max31760 fan speed controller driver Date: Thu, 8 Sep 2022 11:23:55 +0300 Message-ID: <20220908082358.186268-2-Ibrahim.Tilki@analog.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> References: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: tGeiUf-SYVD5rA52jxOoX8YJd3PdOXcQ X-Proofpoint-ORIG-GUID: tGeiUf-SYVD5rA52jxOoX8YJd3PdOXcQ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.528,FMLib:17.11.122.1 definitions=2022-09-08_06,2022-09-07_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 mlxscore=0 spamscore=0 mlxlogscore=999 suspectscore=0 adultscore=0 malwarescore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2209080029 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" MAX31760 is a precision fan speed controller with nonvolatile lookup table. Device has one internal and one external temperature sensor support. Controls two fans and measures their speeds. Generates hardware alerts when programmable max and critical temperatures are exceeded. Signed-off-by: Ibrahim Tilki Reviewed-by: Nurettin Bolucu Reported-by: kernel test robot --- drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 + drivers/hwmon/max31760.c | 594 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 607 insertions(+) create mode 100644 drivers/hwmon/max31760.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e70d9614b..46ae3c4c4 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1066,6 +1066,18 @@ config SENSORS_MAX31730 This driver can also be built as a module. If so, the module will be called max31730. =20 +config SENSORS_MAX31760 + tristate "MAX31760 fan speed controller" + depends on I2C + select REGMAP_I2C + help + Support for the Analog Devices MAX31760 Precision Fan-Speed + Controller. MAX31760 integrates temperature sensing along with + precision PWM fan control. + + This driver can also be built as a module. If so, the module + will be called max31760. + config SENSORS_MAX6620 tristate "Maxim MAX6620 fan controller" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 007e829d1..1c0fa4dd8 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -140,6 +140,7 @@ obj-$(CONFIG_SENSORS_MAX1668) +=3D max1668.o obj-$(CONFIG_SENSORS_MAX197) +=3D max197.o obj-$(CONFIG_SENSORS_MAX31722) +=3D max31722.o obj-$(CONFIG_SENSORS_MAX31730) +=3D max31730.o +obj-$(CONFIG_SENSORS_MAX31760) +=3D max31760.o obj-$(CONFIG_SENSORS_MAX6620) +=3D max6620.o obj-$(CONFIG_SENSORS_MAX6621) +=3D max6621.o obj-$(CONFIG_SENSORS_MAX6639) +=3D max6639.o diff --git a/drivers/hwmon/max31760.c b/drivers/hwmon/max31760.c new file mode 100644 index 000000000..7ff542011 --- /dev/null +++ b/drivers/hwmon/max31760.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_CR1 0x00 +#define CR1_HYST BIT(5) +#define CR1_DRV GENMASK(4, 3) +#define CR1_TEMP_SRC GENMASK(1, 0) +#define REG_CR2 0x01 +#define CR2_STBY BIT(7) +#define CR2_ALERTS BIT(6) +#define CR2_DFC BIT(0) +#define REG_CR3 0x02 +#define REG_PWMR 0x50 +#define REG_PWMV 0x51 +#define REG_STATUS 0x5A +#define STATUS_ALARM_CRIT(ch) BIT(2 + 2 * (ch)) +#define STATUS_ALARM_MAX(ch) BIT(3 + 2 * (ch)) +#define STATUS_RDFA BIT(6) + +#define REG_TACH(ch) (0x52 + (ch) * 2) +#define REG_TEMP_INPUT(ch) (0x56 + (ch) * 2) +#define REG_TEMP_MAX(ch) (0x06 + (ch) * 2) +#define REG_TEMP_CRIT(ch) (0x0A + (ch) * 2) + +#define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) +#define TEMP11_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \ + 127875), 125) * 32) + +#define LUT_SIZE 48 + +#define REG_LUT(index) (0x20 + (index)) + +struct max31760_state { + struct regmap *regmap; + + struct lut_attribute { + char name[24]; + struct sensor_device_attribute sda; + } lut[LUT_SIZE]; + + struct attribute *attrs[LUT_SIZE + 2]; + struct attribute_group group; + const struct attribute_group *groups[2]; +}; + +static bool max31760_volatile_reg(struct device *dev, unsigned int reg) +{ + return reg > 0x50; +} + +static const struct regmap_config regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D 0x5B, + .cache_type =3D REGCACHE_RBTREE, + .volatile_reg =3D max31760_volatile_reg, +}; + +static const int max31760_pwm_freq[] =3D {33, 150, 1500, 25000}; + +static int tach_to_rpm(u16 tach) +{ + if (tach =3D=3D 0) + tach =3D 1; + + return 60 * 100000 / tach / 2; +} + +static int max31760_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + unsigned int regval; + unsigned int reg_temp; + s16 temp; + u8 reg[2]; + int ret; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_fault: + ret =3D regmap_read(state->regmap, REG_STATUS, ®val); + if (ret) + return ret; + + *val =3D FIELD_GET(STATUS_RDFA, regval); + + return 0; + case hwmon_temp_max_alarm: + ret =3D regmap_read(state->regmap, REG_STATUS, ®val); + if (ret) + return ret; + + if (channel) + *val =3D FIELD_GET(STATUS_ALARM_MAX(1), regval); + else + *val =3D FIELD_GET(STATUS_ALARM_MAX(0), regval); + + return 0; + case hwmon_temp_crit_alarm: + ret =3D regmap_read(state->regmap, REG_STATUS, ®val); + if (ret) + return ret; + + if (channel) + *val =3D FIELD_GET(STATUS_ALARM_CRIT(1), regval); + else + *val =3D FIELD_GET(STATUS_ALARM_CRIT(0), regval); + + return 0; + case hwmon_temp_input: + reg_temp =3D REG_TEMP_INPUT(channel); + break; + case hwmon_temp_max: + reg_temp =3D REG_TEMP_MAX(channel); + break; + case hwmon_temp_crit: + reg_temp =3D REG_TEMP_CRIT(channel); + break; + default: + return -EOPNOTSUPP; + } + + ret =3D regmap_bulk_read(state->regmap, reg_temp, reg, 2); + if (ret) + return ret; + + temp =3D (reg[0] << 8) | reg[1]; + + *val =3D TEMP11_FROM_REG(temp); + + return 0; + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + ret =3D regmap_bulk_read(state->regmap, REG_TACH(channel), reg, 2); + if (ret) + return ret; + + *val =3D tach_to_rpm(reg[0] * 256 + reg[1]); + + return 0; + case hwmon_fan_fault: + ret =3D regmap_read(state->regmap, REG_STATUS, ®val); + if (ret) + return ret; + + if (channel) + *val =3D FIELD_GET(BIT(1), regval); + else + *val =3D FIELD_GET(BIT(0), regval); + + return 0; + case hwmon_fan_enable: + ret =3D regmap_read(state->regmap, REG_CR3, ®val); + if (ret) + return ret; + + if (channel) + *val =3D FIELD_GET(BIT(1), regval); + else + *val =3D FIELD_GET(BIT(0), regval); + + return 0; + default: + return -EOPNOTSUPP; + } + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_input: + ret =3D regmap_read(state->regmap, REG_PWMV, ®val); + if (ret) + return ret; + + *val =3D regval; + + return 0; + case hwmon_pwm_freq: + ret =3D regmap_read(state->regmap, REG_CR1, ®val); + if (ret) + return ret; + + regval =3D FIELD_GET(CR1_DRV, regval); + if (regval >=3D ARRAY_SIZE(max31760_pwm_freq)) + return -EINVAL; + + *val =3D max31760_pwm_freq[regval]; + + return 0; + case hwmon_pwm_enable: + ret =3D regmap_read(state->regmap, REG_CR2, ®val); + if (ret) + return ret; + + *val =3D 2 - FIELD_GET(CR2_DFC, regval); + + return 0; + case hwmon_pwm_auto_channels_temp: + ret =3D regmap_read(state->regmap, REG_CR1, ®val); + if (ret) + return ret; + + switch (FIELD_GET(CR1_TEMP_SRC, regval)) { + case 0: + *val =3D 2; + break; + case 1: + *val =3D 1; + break; + case 2: + case 3: + *val =3D 3; + break; + default: + return -EINVAL; + } + + return 0; + default: + return -EOPNOTSUPP; + } + default: + return -EOPNOTSUPP; + } +} + +static int max31760_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + unsigned int pwm_index; + unsigned int reg_temp; + int temp; + u8 reg_val[2]; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_max: + reg_temp =3D REG_TEMP_MAX(channel); + break; + case hwmon_temp_crit: + reg_temp =3D REG_TEMP_CRIT(channel); + break; + default: + return -EOPNOTSUPP; + } + + temp =3D TEMP11_TO_REG(val); + reg_val[0] =3D temp >> 8; + reg_val[1] =3D temp & 0xFF; + + return regmap_bulk_write(state->regmap, reg_temp, reg_val, 2); + case hwmon_fan: + switch (attr) { + case hwmon_fan_enable: + if (val =3D=3D 0) + return regmap_clear_bits(state->regmap, REG_CR3, BIT(channel)); + + if (val =3D=3D 1) + return regmap_set_bits(state->regmap, REG_CR3, BIT(channel)); + + return -EOPNOTSUPP; + default: + return -EOPNOTSUPP; + } + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_input: + if (val < 0 || val > 255) + return -EINVAL; + + return regmap_write(state->regmap, REG_PWMR, val); + case hwmon_pwm_enable: + if (val =3D=3D 1) + return regmap_set_bits(state->regmap, REG_CR2, CR2_DFC); + + if (val =3D=3D 2) + return regmap_clear_bits(state->regmap, REG_CR2, CR2_DFC); + + return -EOPNOTSUPP; + case hwmon_pwm_freq: + pwm_index =3D find_closest(val, max31760_pwm_freq, + ARRAY_SIZE(max31760_pwm_freq)); + + return regmap_update_bits(state->regmap, + REG_CR1, CR1_DRV, + FIELD_PREP(CR1_DRV, pwm_index)); + case hwmon_pwm_auto_channels_temp: + switch (val) { + case 1: + break; + case 2: + val =3D 0; + break; + case 3: + val =3D 2; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(state->regmap, REG_CR1, CR1_TEMP_SRC, val); + default: + return -EOPNOTSUPP; + } + default: + return -EOPNOTSUPP; + } +} + +static const struct hwmon_channel_info *max31760_info[] =3D { + HWMON_CHANNEL_INFO(chip, + HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ENABLE, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ENABLE), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_FAULT | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_ENABLE | HWMON_PWM_FREQ | HWMON_PWM_INPUT | + HWMON_PWM_AUTO_CHANNELS_TEMP), + NULL +}; + +static umode_t max31760_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_max_alarm: + case hwmon_temp_crit_alarm: + case hwmon_temp_fault: + case hwmon_temp_label: + return 0444; + case hwmon_temp_max: + case hwmon_temp_crit: + return 0644; + default: + return 0; + } + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + case hwmon_fan_fault: + return 0444; + case hwmon_fan_enable: + return 0644; + default: + return 0; + } + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_enable: + case hwmon_pwm_input: + case hwmon_pwm_freq: + case hwmon_pwm_auto_channels_temp: + return 0644; + default: + return 0; + } + default: + return 0; + } +} + +int max31760_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_temp: + if (attr !=3D hwmon_temp_label) + return -EOPNOTSUPP; + + *str =3D channel ? "local" : "remote"; + + return 0; + default: + return -EOPNOTSUPP; + } +} + +static const struct hwmon_ops max31760_hwmon_ops =3D { + .is_visible =3D max31760_is_visible, + .read =3D max31760_read, + .write =3D max31760_write, + .read_string =3D max31760_read_string +}; + +static const struct hwmon_chip_info max31760_chip_info =3D { + .ops =3D &max31760_hwmon_ops, + .info =3D max31760_info, +}; + +static ssize_t lut_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *sda =3D to_sensor_dev_attr(devattr); + struct max31760_state *state =3D dev_get_drvdata(dev); + int ret; + unsigned int regval; + + ret =3D regmap_read(state->regmap, REG_LUT(sda->index), ®val); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", regval); +} + +static ssize_t lut_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sda =3D to_sensor_dev_attr(devattr); + struct max31760_state *state =3D dev_get_drvdata(dev); + int ret; + u8 pwm; + + ret =3D kstrtou8(buf, 10, &pwm); + if (ret) + return ret; + + ret =3D regmap_write(state->regmap, REG_LUT(sda->index), pwm); + if (ret) + return ret; + + return count; +} + +static ssize_t pwm1_auto_point_temp_hyst_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + unsigned int regval; + int ret; + + ret =3D regmap_read(state->regmap, REG_CR1, ®val); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", (1 + (int)FIELD_GET(CR1_HYST, regval)) * 2= 000); +} + +static ssize_t pwm1_auto_point_temp_hyst_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + unsigned int hyst; + int ret; + + ret =3D kstrtou32(buf, 10, &hyst); + if (ret) + return ret; + + if (hyst < 3000) + ret =3D regmap_clear_bits(state->regmap, REG_CR1, CR1_HYST); + else + ret =3D regmap_set_bits(state->regmap, REG_CR1, CR1_HYST); + + if (ret) + return ret; + + return count; +} + +static DEVICE_ATTR_RW(pwm1_auto_point_temp_hyst); + +static void max31760_create_lut_nodes(struct max31760_state *state) +{ + int i; + struct sensor_device_attribute *sda; + struct lut_attribute *lut; + + for (i =3D 0; i < LUT_SIZE; ++i) { + lut =3D &state->lut[i]; + sda =3D &lut->sda; + + snprintf(lut->name, sizeof(lut->name), + "pwm1_auto_point%d_pwm", i + 1); + + sda->dev_attr.attr.mode =3D 0644; + sda->index =3D i; + sda->dev_attr.show =3D lut_show; + sda->dev_attr.store =3D lut_store; + sda->dev_attr.attr.name =3D lut->name; + + sysfs_attr_init(&sda->dev_attr.attr); + + state->attrs[i] =3D &sda->dev_attr.attr; + } + + state->attrs[i] =3D &dev_attr_pwm1_auto_point_temp_hyst.attr; + + state->group.attrs =3D state->attrs; + state->groups[0] =3D &state->group; +} + +static int max31760_probe(struct i2c_client *client) +{ + struct device *dev =3D &client->dev; + struct max31760_state *state; + struct device *hwmon_dev; + int ret; + + state =3D devm_kzalloc(dev, sizeof(struct max31760_state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->regmap =3D devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(state->regmap)) + return dev_err_probe(dev, + PTR_ERR(state->regmap), + "regmap initialization failed\n"); + + dev_set_drvdata(dev, state); + + /* Set alert output to comparator mode */ + ret =3D regmap_set_bits(state->regmap, REG_CR2, CR2_ALERTS); + if (ret) + return dev_err_probe(dev, ret, "cannot write register\n"); + + max31760_create_lut_nodes(state); + + hwmon_dev =3D devm_hwmon_device_register_with_info(dev, client->name, + state, + &max31760_chip_info, + state->groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct of_device_id max31760_of_match[] =3D { + {.compatible =3D "adi,max31760"}, + { } +}; +MODULE_DEVICE_TABLE(of, max31760_of_match); + +static const struct i2c_device_id max31760_id[] =3D { + {"max31760"}, + { } +}; +MODULE_DEVICE_TABLE(i2c, max31760_id); + +static int __maybe_unused max31760_suspend(struct device *dev) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + + return regmap_set_bits(state->regmap, REG_CR2, CR2_STBY); +} + +static int __maybe_unused max31760_resume(struct device *dev) +{ + struct max31760_state *state =3D dev_get_drvdata(dev); + + return regmap_clear_bits(state->regmap, REG_CR2, CR2_STBY); +} + +static SIMPLE_DEV_PM_OPS(max31760_pm_ops, max31760_suspend, max31760_resum= e); + +static struct i2c_driver max31760_driver =3D { + .class =3D I2C_CLASS_HWMON, + .driver =3D { + .name =3D "max31760", + .of_match_table =3D of_match_ptr(max31760_of_match), + .pm =3D pm_ptr(&max31760_pm_ops) + }, + .probe_new =3D max31760_probe, + .id_table =3D max31760_id +}; +module_i2c_driver(max31760_driver); + +MODULE_AUTHOR("Ibrahim Tilki "); +MODULE_DESCRIPTION("Analog Devices MAX31760 Fan Speed Controller"); +MODULE_SOFTDEP("pre: regmap_i2c"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); --=20 2.36.1 From nobody Mon Apr 6 09:42:46 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 A61EFC38145 for ; Thu, 8 Sep 2022 08:25:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231513AbiIHIZC (ORCPT ); Thu, 8 Sep 2022 04:25:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36900 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231315AbiIHIY6 (ORCPT ); Thu, 8 Sep 2022 04:24:58 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEBDC4DB0A; Thu, 8 Sep 2022 01:24:56 -0700 (PDT) Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2887VG2a030682; Thu, 8 Sep 2022 04:24:42 -0400 Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3jf8ybshry-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 08 Sep 2022 04:24:42 -0400 Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 2888Oe94026141 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 8 Sep 2022 04:24:40 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 8 Sep 2022 04:24:39 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Thu, 8 Sep 2022 04:24:39 -0400 Received: from ibrahim-vm.ad.analog.com (IST-LT-39247.ad.analog.com [10.25.16.132]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 2888OHWB032231; Thu, 8 Sep 2022 04:24:31 -0400 From: Ibrahim Tilki To: , CC: Ibrahim Tilki , , , Subject: [PATCH RESEND v6 2/4] docs: hwmon: add max31760 documentation Date: Thu, 8 Sep 2022 11:23:56 +0300 Message-ID: <20220908082358.186268-3-Ibrahim.Tilki@analog.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> References: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: rqoYxd55YXNALoTSYgyrKO8c2LlyTLSF X-Proofpoint-ORIG-GUID: rqoYxd55YXNALoTSYgyrKO8c2LlyTLSF X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.528,FMLib:17.11.122.1 definitions=2022-09-08_06,2022-09-07_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 impostorscore=0 priorityscore=1501 malwarescore=0 mlxlogscore=999 lowpriorityscore=0 mlxscore=0 bulkscore=0 spamscore=0 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2209080029 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adding documentation for max31760 fan speed controller Signed-off-by: Ibrahim Tilki --- Documentation/hwmon/index.rst | 1 + Documentation/hwmon/max31760.rst | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 Documentation/hwmon/max31760.rst diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index f7113b0f8..dba260013 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -133,6 +133,7 @@ Hardware Monitoring Kernel Drivers max20751 max31722 max31730 + max31760 max31785 max31790 max34440 diff --git a/Documentation/hwmon/max31760.rst b/Documentation/hwmon/max3176= 0.rst new file mode 100644 index 000000000..b1b55fb84 --- /dev/null +++ b/Documentation/hwmon/max31760.rst @@ -0,0 +1,77 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +Kernel driver max31760 +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Supported chips: + * Analog Devices MAX31760 + + Prefix: 'max31760' + + Addresses scanned: none + + Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31760.pdf + + +Author: Ibrahim Tilki + +Description +----------- + +The MAX31760 integrates temperature sensing along with precision PWM fan +control. It accurately measures its local die temperature and the remote +temperature of a discrete diode-connected transistor, such as a 2N3906, +or a thermal diode commonly found on CPUs, graphics processor units (GPUs), +and other ASICs. Multiple temperature thresholds, such as local +high/overtemperature (OT) and remote high/overtemperature, can be set by an +I2C-compatible interface. Fan speed is controlled based on the temperature +reading as an index to a 48-byte lookup table (LUT) containing +user-programmed PWM values. The flexible LUT-based architecture enables +the user to program a smooth nonlinear fan speed vs. temperature transfer +function to minimize acoustic fan noise. Two tachometer inputs allow +measuring the speeds of two fans independently. When the local or remote +OT threshold is exceeded, the SHDN pin is asserted low and can be used to +shut down the system. A dedicated ALERT pin reports that either a local or +remote high-temperature threshold has been exceeded. + +Temperature measurement range: from -55=C2=B0C to 125=C2=B0C + +Temperature Resolution: 11 Bits, =C2=B10.125=C2=B0C + +Please refer how to instantiate this driver: Documentation/i2c/instantiati= ng-devices.rst + +Lookup table for auto fan control +--------------------------------- + +=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +LUT Index Name +=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +1 PWM value for T < +18=C2=B0C +2 PWM value for +18=C2=B0C =E2=89=A4 T < +20=C2=B0C +3 PWM value for +20=C2=B0C =E2=89=A4 T < +22=C2=B0C +... ... +47 PWM value for +108=C2=B0C =E2=89=A4 T < +110=C2=B0C +48 PWM value for T =E2=89=A5 +110=C2=B0C +=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Sysfs entries +------------- + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +fan[1-2]_input Fan speed (in RPM) +fan[1-2]_enable Enable fan readings and fan fault alarms +fan[1-2]_fault Fan fault status +temp[1-2]_label "Remote" and "Local" temperature channel l= abels +temp[1-2]_input Temperature sensor readings (in millidegre= es Celsius) +temp1_fault Remote temperature sensor fault status +temp[1-2]_max Temperature max value. Asserts "ALERT" pin= when exceeded +temp[1-2]_max_alarm Temperature max alarm status +temp[1-2]_crit Temperature critical value. Asserts "SHDN"= pin when exceeded +temp[1-2]_crit_alarm Temperature critical alarm status +pwm1 PWM value for direct fan control +pwm1_enable 1: direct fan control, 2: temperature base= d auto fan control +pwm1_freq PWM frequency in hertz +pwm1_auto_channels_temp Temperature source for auto fan control. 1= : temp1, 2: temp2, 3: max(temp1, temp2) +pwm1_auto_point[1-48]_pwm PWM value for LUT point +pwm1_auto_point_temp_hyst Temperature hysteresis for auto fan contro= l. Can be either 2000mC or 4000mC +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --=20 2.36.1 From nobody Mon Apr 6 09:42:46 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 1C884ECAAD5 for ; Thu, 8 Sep 2022 08:25:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231559AbiIHIZT (ORCPT ); Thu, 8 Sep 2022 04:25:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230446AbiIHIZE (ORCPT ); Thu, 8 Sep 2022 04:25:04 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09C6A564CC; Thu, 8 Sep 2022 01:25:00 -0700 (PDT) Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2887hn4F030778; Thu, 8 Sep 2022 04:24:45 -0400 Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3jf8ybshs7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 08 Sep 2022 04:24:45 -0400 Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 2888OiZo026156 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 8 Sep 2022 04:24:44 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 8 Sep 2022 04:24:43 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Thu, 8 Sep 2022 04:24:43 -0400 Received: from ibrahim-vm.ad.analog.com (IST-LT-39247.ad.analog.com [10.25.16.132]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 2888OHWC032231; Thu, 8 Sep 2022 04:24:34 -0400 From: Ibrahim Tilki To: , CC: Ibrahim Tilki , , , Subject: [PATCH RESEND v6 3/4] dt-bindings: hwmon: Add bindings for max31760 Date: Thu, 8 Sep 2022 11:23:57 +0300 Message-ID: <20220908082358.186268-4-Ibrahim.Tilki@analog.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> References: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: 0XtgB1VpsqoKLINhSbRa_N1GSE-akJaQ X-Proofpoint-ORIG-GUID: 0XtgB1VpsqoKLINhSbRa_N1GSE-akJaQ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.528,FMLib:17.11.122.1 definitions=2022-09-08_06,2022-09-07_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 impostorscore=0 priorityscore=1501 malwarescore=0 mlxlogscore=949 lowpriorityscore=0 mlxscore=0 bulkscore=0 spamscore=0 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2209080029 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Adding bindings for Analog Devices MAX31760 Fan-Speed Controller Signed-off-by: Ibrahim Tilki --- .../bindings/hwmon/adi,max31760.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/adi,max31760.ya= ml diff --git a/Documentation/devicetree/bindings/hwmon/adi,max31760.yaml b/Do= cumentation/devicetree/bindings/hwmon/adi,max31760.yaml new file mode 100644 index 000000000..003ec1317 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/adi,max31760.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/adi,max31760.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices MAX31760 Fan-Speed Controller + +maintainers: + - Ibrahim Tilki + +description: | + Analog Devices MAX31760 Fan-Speed Controller + https://datasheets.maximintegrated.com/en/ds/MAX31760.pdf + +properties: + compatible: + enum: + - adi,max31760 + + reg: + description: | + I2C address of slave device. + items: + minimum: 0x50 + maximum: 0x57 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells =3D <1>; + #size-cells =3D <0>; + + max31760@50 { + reg =3D <0x50>; + compatible =3D "adi,max31760"; + }; + }; --=20 2.36.1 From nobody Mon Apr 6 09:42:46 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 951B7ECAAD5 for ; Thu, 8 Sep 2022 08:25:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231566AbiIHIZZ (ORCPT ); Thu, 8 Sep 2022 04:25:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231519AbiIHIZF (ORCPT ); Thu, 8 Sep 2022 04:25:05 -0400 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 281EC67173; Thu, 8 Sep 2022 01:25:04 -0700 (PDT) Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2887bLEA031612; Thu, 8 Sep 2022 04:24:47 -0400 Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3jf8ybshsb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 08 Sep 2022 04:24:47 -0400 Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 2888Ok0o026167 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 8 Sep 2022 04:24:46 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 8 Sep 2022 04:24:45 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) 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; Thu, 8 Sep 2022 04:24:45 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Thu, 8 Sep 2022 04:24:45 -0400 Received: from ibrahim-vm.ad.analog.com (IST-LT-39247.ad.analog.com [10.25.16.132]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 2888OHWD032231; Thu, 8 Sep 2022 04:24:37 -0400 From: Ibrahim Tilki To: , CC: Ibrahim Tilki , , , Subject: [PATCH RESEND v6 4/4] MAINTAINERS: Add maintainer for hwmon/max31760 Date: Thu, 8 Sep 2022 11:23:58 +0300 Message-ID: <20220908082358.186268-5-Ibrahim.Tilki@analog.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> References: <20220908082358.186268-1-Ibrahim.Tilki@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: BGmeeZCsSPTFEdcZ8sIK6bCZqu0rOhWF X-Proofpoint-ORIG-GUID: BGmeeZCsSPTFEdcZ8sIK6bCZqu0rOhWF X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.895,Hydra:6.0.528,FMLib:17.11.122.1 definitions=2022-09-08_06,2022-09-07_02,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 impostorscore=0 priorityscore=1501 malwarescore=0 mlxlogscore=754 lowpriorityscore=0 mlxscore=0 bulkscore=0 spamscore=0 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2207270000 definitions=main-2209080029 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add maintainer for hwmon/max31760 driver Signed-off-by: Ibrahim Tilki --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d30f26e07..76c7d6606 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1334,6 +1334,15 @@ F: drivers/iio/amplifiers/hmc425a.c F: drivers/staging/iio/*/ad* X: drivers/iio/*/adjd* =20 +ANALOG DEVICES INC MAX31760 DRIVER +M: Ibrahim Tilki +S: Maintained +W: http://wiki.analog.com/ +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/hwmon/adi,max31760.yaml +F: Documentation/hwmon/max31760.rst +F: drivers/hwmon/max31760.c + ANALOGBITS PLL LIBRARIES M: Paul Walmsley S: Supported --=20 2.36.1