From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=79.135.106.111 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794616895; b=nEwHkBF7iouAgZ//feXbEZGesLGVor9puc8JmHvXG6fgRDLe0uimR53ptOVN+ZYQGGfT ujy2OoVnshSjiKOg4YVW5EK/LfKz2QcZho81lFmIhM04Sx/pyi35t5pyPS9tR251Ug7Dl SY+ikHPxHzUgccAmbYtQx1vks1C793wp/J2Wl8OZARl2fZ1EFb+zXh9Rg6UMBUVp0ECZE sSltWc+RjRaTPeTXKejZyOnHPfMjb4xdWfYg4FBHZI/V2CYyApcDnKvChCXXXnympgeUy oyHSQxpNTda6zrb8NIH7Q/IPmrJpjl0owoTi1IG5o+foUEbh0E+Ydapv/9+B7VBkY6A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794616895; h=DMARC-Filter:DKIM-Signature:X-Pm-Submission-Id:From:To:Cc:Subject: Date:Message-ID:X-Mailer:In-Reply-To:References:MIME-Version: Content-Type:Content-Transfer-Encoding; bh=Nyegwcpmm0sYJA2oCUO7KIb5tM8jZWvdrot5uii3JS8=; b=wbVv1QpLIE3TglTTGk6c9sP5Et516MgTmdIwSaP2srfDo0w2tH+upmp7r2SfIXH04bAZ LNJcjeTmCuYjmOqt4GTO89DchvBjw1uvMv3hOcrKDvwbZ3rkCT/h9tGh1tYbPe/UUx9M1 KS9CXosNLQ1NvCXgnkah6b1cjZOnnFVqIHWgM0daZqZAORggW0p+FUb8f4KZ04Og/OzO3 EgSabV2HyxzdwzsI6oL3rRkTDOG5aynfTiitU9EP+eaawGia6fjKn2ps48jTu92Q458Qb iBCFkaiVvlq+PsWxD4OJdWkcnbrA1jeKzMUKqpEkm607aPnh/q0Zj6LHMx3HPUNUTbA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=dsg.is; spf=pass smtp.mailfrom=dsg.is; dkim=pass header.d=dsg.is header.i=@dsg.is header.a=rsa-sha256 header.s=protonmail2 header.b=IOrGsmBR; arc=none smtp.remote-ip=79.135.106.111 Received: from mail-106111.protonmail.ch (mail-106111.protonmail.ch [79.135.106.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 234AE606A89F; Sat, 14 Nov 2026 00:41:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 234AE606A89F Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=dsg.is Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=dsg.is Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=dsg.is header.i=@dsg.is header.a=rsa-sha256 header.s=protonmail2 header.b=IOrGsmBR DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dsg.is; s=protonmail2; t=1794616891; x=1794876091; bh=Nyegwcpmm0sYJA2oCUO7KIb5tM8jZWvdrot5uii3JS8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=IOrGsmBRRaD7cI0JZ+NJbz2m08SdWkscguW88ws5/i/ib5ujajhsNODb6CYUgj2Y4 z3ktjYZ4cGY7ss97tvtPr+JUoNB9XN0CpcrAIzNf6mQ8cA3kmPZCtMt8ALB1cVB66a d5CYJkvS4wsF423hu00ZQQWBBsigaITCBqzKiWF/wA88gyB9EiTBr3h2vlA1gkRpFC mp3GdgHZTow/t+uwUCPPkzK2MiNwRLtpnng8QVmKXGGEPmhGAqTe+pnGI0ugMH/q8j 7HyuSSNuvakunufkad73aR9vL82LuZ+J3mQVcjw4KEb3aw7s5RBuvFQP00i63IucfJ fcQ+gORZm5AsQ== X-Pm-Submission-Id: 4jRFgC0Ph0z2ScQG From: =?UTF-8?q?Dav=C3=AD=C3=B0=20Steinn=20Geirsson?= To: Guenter Roeck , Jean Delvare , linux-hwmon@vger.kernel.org Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , devicetree@vger.kernel.org, =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-pwm@vger.kernel.org, Jonathan Corbet , Shuah Khan , Randy Dunlap , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, =?UTF-8?q?Dav=C3=AD=C3=B0=20Steinn=20Geirsson?= Subject: [PATCH 2/4] hwmon: (adt7475) Convert to hwmon_device_register_with_info() Date: Sat, 14 Nov 2026 00:41:08 +0000 Message-ID: <20261114004110.328050-3-david@dsg.is> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261114004110.328050-1-david@dsg.is> References: <20261114004110.328050-1-david@dsg.is> X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the driver from hwmon_device_register_with_groups() to hwmon_device_register_with_info(). The standard voltage, temperature, fan and PWM attributes move to hwmon_ops. The chip-specific attributes stay driver-defined and are passed as extra groups: the automatic fan control points, temperature smoothing, PWM stall disable, pwm_use_point2_pwm_at_crit and the VID attributes. The driver keeps data->lock, although the hwmon core serialises the hwmon_ops callbacks. The attributes in the extra groups run outside that serialisation, and they share the register cache and its periodic update with the hwmon_ops callbacks. They do not take hwmon_lock() instead, to keep this conversion free of locking changes. The sysfs attribute names, permissions, values and register writes are unchanged. This was checked with i2c-stub on all four chip types and several register images, comparing the attribute list, every value read and written, and the final register contents before and after the conversion. The hwmon core parses the standard attributes with kstrtol() and returns its error, which gives two differences for input that is out of range: - Writing a number that does not fit in a long now fails with -ERANGE instead of -EINVAL. - fanN_min was parsed with kstrtoul(), so values above LONG_MAX were accepted (and set the lowest limit). They now fail with -ERANGE. On 32-bit systems this applies from 2147483648 rpm, far beyond any real fan. Signed-off-by: Davíð Steinn Geirsson --- This patch was written with Claude Code, using the models Claude Opus 5.5 and Claude Fable 5.2. They wrote the code and the initial commit message draft, which I cleaned up. I directed the design, reviewed the result, compared against the datasheet as far as I could, and ran tests including on actual hardware. drivers/hwmon/adt7475.c | 952 ++++++++++++++++++++-------------------- 1 file changed, 467 insertions(+), 485 deletions(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index cd1ce846e2fd..d5bdb8011e6d 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -222,7 +222,7 @@ struct adt7475_data { u8 vid; u8 vrm; - const struct attribute_group *groups[10]; + const struct attribute_group *groups[4]; }; static struct i2c_driver adt7475_driver; @@ -332,85 +332,15 @@ static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) i2c_smbus_write_byte_data(client, reg, val & 0xFF); } -static ssize_t voltage_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - unsigned short val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - switch (sattr->nr) { - case ALARM: - return sprintf(buf, "%d\n", - (data->alarms >> sattr->index) & 1); - default: - val = data->voltage[sattr->nr][sattr->index]; - return sprintf(buf, "%d\n", - reg2volt(sattr->index, val, data->bypass_attn)); - } -} - -static ssize_t voltage_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct adt7475_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - unsigned char reg; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - data->voltage[sattr->nr][sattr->index] = - volt2reg(sattr->index, val, data->bypass_attn); - - if (sattr->index < ADT7475_VOLTAGE_COUNT) { - if (sattr->nr == MIN) - reg = VOLTAGE_MIN_REG(sattr->index); - else - reg = VOLTAGE_MAX_REG(sattr->index); - } else if (sattr->index == 5) { - if (sattr->nr == MIN) - reg = REG_VTT_MIN; - else - reg = REG_VTT_MAX; - } else { - if (sattr->nr == MIN) - reg = REG_IMON_MIN; - else - reg = REG_IMON_MAX; - } - - i2c_smbus_write_byte_data(client, reg, - data->voltage[sattr->nr][sattr->index] >> 2); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t temp_show(struct device *dev, struct device_attribute *attr, - char *buf) +static int adt7475_temp_value(struct adt7475_data *data, int nr, int index) { - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); int out; - if (IS_ERR(data)) - return PTR_ERR(data); - - switch (sattr->nr) { + switch (nr) { case HYSTERSIS: mutex_lock(&data->lock); - out = data->temp[sattr->nr][sattr->index]; - if (sattr->index != 1) + out = data->temp[nr][index]; + if (index != 1) out = (out >> 4) & 0xF; else out = (out & 0xF); @@ -418,7 +348,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, * Show the value as an absolute number tied to * THERM */ - out = reg2temp(data, data->temp[THERM][sattr->index]) - + out = reg2temp(data, data->temp[THERM][index]) - out * 1000; mutex_unlock(&data->lock); break; @@ -429,7 +359,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, * setting in CONFIG5 */ mutex_lock(&data->lock); - out = (s8)data->temp[sattr->nr][sattr->index]; + out = (s8)data->temp[nr][index]; if (data->config5 & CONFIG5_TEMPOFFSET) out *= 1000; else @@ -438,50 +368,58 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, break; case ALARM: - out = (data->alarms >> (sattr->index + 4)) & 1; + out = (data->alarms >> (index + 4)) & 1; break; case FAULT: /* Note - only for remote1 and remote2 */ - out = !!(data->alarms & (sattr->index ? 0x8000 : 0x4000)); + out = !!(data->alarms & (index ? 0x8000 : 0x4000)); break; default: /* All other temp values are in the configured format */ - out = reg2temp(data, data->temp[sattr->nr][sattr->index]); + out = reg2temp(data, data->temp[nr][index]); } - return sprintf(buf, "%d\n", out); + return out; } -static ssize_t temp_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct adt7475_data *data = adt7475_update_device(dev); struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct adt7475_data *data = dev_get_drvdata(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + return sprintf(buf, "%d\n", + adt7475_temp_value(data, sattr->nr, sattr->index)); +} + +static void adt7475_temp_set(struct adt7475_data *data, int nr, int index, + long val) +{ struct i2c_client *client = data->client; unsigned char reg = 0; u8 out; int temp; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; mutex_lock(&data->lock); /* We need the config register in all cases for temp <-> reg conv. */ data->config5 = adt7475_read(REG_CONFIG5); - switch (sattr->nr) { + switch (nr) { case OFFSET: if (data->config5 & CONFIG5_TEMPOFFSET) { val = clamp_val(val, -63000, 127000); - out = data->temp[OFFSET][sattr->index] = val / 1000; + data->temp[OFFSET][index] = val / 1000; } else { val = clamp_val(val, -63000, 64000); - out = data->temp[OFFSET][sattr->index] = val / 500; + data->temp[OFFSET][index] = val / 500; } + out = data->temp[OFFSET][index]; break; case HYSTERSIS: @@ -491,53 +429,53 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr, */ /* Read fresh THERM and HYSTERSIS values from the chip */ - data->temp[THERM][sattr->index] = - adt7475_read(TEMP_THERM_REG(sattr->index)) << 2; + data->temp[THERM][index] = + adt7475_read(TEMP_THERM_REG(index)) << 2; adt7475_read_hystersis(client); - temp = reg2temp(data, data->temp[THERM][sattr->index]); + temp = reg2temp(data, data->temp[THERM][index]); val = clamp_val(val, temp - 15000, temp); val = (temp - val) / 1000; - if (sattr->index != 1) { - data->temp[HYSTERSIS][sattr->index] &= 0x0F; - data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4; + if (index != 1) { + data->temp[HYSTERSIS][index] &= 0x0F; + data->temp[HYSTERSIS][index] |= (val & 0xF) << 4; } else { - data->temp[HYSTERSIS][sattr->index] &= 0xF0; - data->temp[HYSTERSIS][sattr->index] |= (val & 0xF); + data->temp[HYSTERSIS][index] &= 0xF0; + data->temp[HYSTERSIS][index] |= (val & 0xF); } - out = data->temp[HYSTERSIS][sattr->index]; + out = data->temp[HYSTERSIS][index]; break; default: - data->temp[sattr->nr][sattr->index] = temp2reg(data, val); + data->temp[nr][index] = temp2reg(data, val); /* * We maintain an extra 2 digits of precision for simplicity * - shift those back off before writing the value */ - out = (u8) (data->temp[sattr->nr][sattr->index] >> 2); + out = (u8)(data->temp[nr][index] >> 2); } - switch (sattr->nr) { + switch (nr) { case MIN: - reg = TEMP_MIN_REG(sattr->index); + reg = TEMP_MIN_REG(index); break; case MAX: - reg = TEMP_MAX_REG(sattr->index); + reg = TEMP_MAX_REG(index); break; case OFFSET: - reg = TEMP_OFFSET_REG(sattr->index); + reg = TEMP_OFFSET_REG(index); break; case AUTOMIN: - reg = TEMP_TMIN_REG(sattr->index); + reg = TEMP_TMIN_REG(index); break; case THERM: - reg = TEMP_THERM_REG(sattr->index); + reg = TEMP_THERM_REG(index); break; case HYSTERSIS: - if (sattr->index != 2) + if (index != 2) reg = REG_REMOTE1_HYSTERSIS; else reg = REG_REMOTE2_HYSTERSIS; @@ -548,6 +486,20 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr, i2c_smbus_write_byte_data(client, reg, out); mutex_unlock(&data->lock); +} + +static ssize_t temp_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct adt7475_data *data = dev_get_drvdata(dev); + long val; + + if (kstrtol(buf, 10, &val)) + return -EINVAL; + + adt7475_temp_set(data, sattr->nr, sattr->index, val); + return count; } @@ -704,47 +656,6 @@ static ssize_t point2_store(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t tach_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int out; - - if (IS_ERR(data)) - return PTR_ERR(data); - - if (sattr->nr == ALARM) - out = (data->alarms >> (sattr->index + 10)) & 1; - else - out = tach2rpm(data->tach[sattr->nr][sattr->index]); - - return sprintf(buf, "%d\n", out); -} - -static ssize_t tach_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct adt7475_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - data->tach[MIN][sattr->index] = rpm2tach(val); - - adt7475_write_word(client, TACH_MIN_REG(sattr->index), - data->tach[MIN][sattr->index]); - - mutex_unlock(&data->lock); - return count; -} - static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -757,76 +668,57 @@ static ssize_t pwm_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]); } -static ssize_t pwmchan_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->pwmchan[sattr->index]); -} - -static ssize_t pwmctrl_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->pwmctl[sattr->index]); -} - -static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static void adt7475_pwm_set(struct adt7475_data *data, int nr, int index, + long val) { - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct adt7475_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; unsigned char reg = 0; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; mutex_lock(&data->lock); - switch (sattr->nr) { + switch (nr) { case INPUT: /* Get a fresh value for CONTROL */ - data->pwm[CONTROL][sattr->index] = - adt7475_read(PWM_CONFIG_REG(sattr->index)); + data->pwm[CONTROL][index] = + adt7475_read(PWM_CONFIG_REG(index)); /* * If we are not in manual mode, then we shouldn't allow * the user to set the pwm speed */ - if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) { + if (((data->pwm[CONTROL][index] >> 5) & 7) != 7) { mutex_unlock(&data->lock); - return count; + return; } - reg = PWM_REG(sattr->index); + reg = PWM_REG(index); break; case MIN: - reg = PWM_MIN_REG(sattr->index); + reg = PWM_MIN_REG(index); break; case MAX: - reg = PWM_MAX_REG(sattr->index); + reg = PWM_MAX_REG(index); break; } - data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF); - i2c_smbus_write_byte_data(client, reg, - data->pwm[sattr->nr][sattr->index]); + data->pwm[nr][index] = clamp_val(val, 0, 0xFF); + i2c_smbus_write_byte_data(client, reg, data->pwm[nr][index]); mutex_unlock(&data->lock); +} + +static ssize_t pwm_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct adt7475_data *data = dev_get_drvdata(dev); + long val; + + if (kstrtol(buf, 10, &val)) + return -EINVAL; + + adt7475_pwm_set(data, sattr->nr, sattr->index, val); return count; } @@ -926,263 +818,475 @@ static int hw_set_pwm(struct i2c_client *client, int index, return 0; } -static ssize_t pwmchan_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +/* List of frequencies for the PWM */ +static const int pwmfreq_table[] = { + 11, 14, 22, 29, 35, 44, 58, 88, 22500 +}; + +static ssize_t pwm_use_point2_pwm_at_crit_show(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY)); +} + +static ssize_t pwm_use_point2_pwm_at_crit_store(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); struct adt7475_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - int r; long val; if (kstrtol(buf, 10, &val)) return -EINVAL; + if (val != 0 && val != 1) + return -EINVAL; mutex_lock(&data->lock); - /* Read Modify Write PWM values */ - adt7475_read_pwm(client, sattr->index); - r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val); - if (r) - count = r; + data->config4 = i2c_smbus_read_byte_data(client, REG_CONFIG4); + if (val) + data->config4 |= CONFIG4_MAXDUTY; + else + data->config4 &= ~CONFIG4_MAXDUTY; + i2c_smbus_write_byte_data(client, REG_CONFIG4, data->config4); mutex_unlock(&data->lock); return count; } -static ssize_t pwmctrl_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t vrm_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct adt7475_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", (int)data->vrm); +} + +static ssize_t vrm_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); struct adt7475_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - int r; long val; if (kstrtol(buf, 10, &val)) return -EINVAL; - - mutex_lock(&data->lock); - /* Read Modify Write PWM values */ - adt7475_read_pwm(client, sattr->index); - r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]); - if (r) - count = r; - mutex_unlock(&data->lock); + if (val < 0 || val > 255) + return -EINVAL; + data->vrm = val; return count; } -/* List of frequencies for the PWM */ -static const int pwmfreq_table[] = { - 11, 14, 22, 29, 35, 44, 58, 88, 22500 -}; +static ssize_t cpu0_vid_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); -static ssize_t pwmfreq_show(struct device *dev, struct device_attribute *attr, - char *buf) + if (IS_ERR(data)) + return PTR_ERR(data); + + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} + +/* STATUS bit of each voltage input's alarm, in alarms */ +static const u8 adt7475_in_alarm_bit[] = { 0, 1, 2, 3, 8, 31, 30 }; + +static int adt7475_in_read(struct device *dev, u32 attr, int channel, + long *val) { struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int idx; if (IS_ERR(data)) return PTR_ERR(data); - idx = clamp_val(data->range[sattr->index] & 0xf, 0, - ARRAY_SIZE(pwmfreq_table) - 1); - return sprintf(buf, "%d\n", pwmfreq_table[idx]); + switch (attr) { + case hwmon_in_input: + *val = reg2volt(channel, data->voltage[INPUT][channel], + data->bypass_attn); + return 0; + case hwmon_in_min: + *val = reg2volt(channel, data->voltage[MIN][channel], + data->bypass_attn); + return 0; + case hwmon_in_max: + *val = reg2volt(channel, data->voltage[MAX][channel], + data->bypass_attn); + return 0; + case hwmon_in_alarm: + *val = (data->alarms >> adt7475_in_alarm_bit[channel]) & 1; + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t pwmfreq_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +static int adt7475_in_write(struct device *dev, u32 attr, int channel, + long val) { - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); struct adt7475_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - int out; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; + unsigned char reg; + int nr; - out = find_closest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table)); + switch (attr) { + case hwmon_in_min: + nr = MIN; + break; + case hwmon_in_max: + nr = MAX; + break; + default: + return -EOPNOTSUPP; + } mutex_lock(&data->lock); - data->range[sattr->index] = - adt7475_read(TEMP_TRANGE_REG(sattr->index)); - data->range[sattr->index] &= ~0xf; - data->range[sattr->index] |= out; + data->voltage[nr][channel] = volt2reg(channel, val, data->bypass_attn); - i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), - data->range[sattr->index]); + if (channel < ADT7475_VOLTAGE_COUNT) + reg = nr == MIN ? VOLTAGE_MIN_REG(channel) : + VOLTAGE_MAX_REG(channel); + else if (channel == 5) + reg = nr == MIN ? REG_VTT_MIN : REG_VTT_MAX; + else + reg = nr == MIN ? REG_IMON_MIN : REG_IMON_MAX; + i2c_smbus_write_byte_data(client, reg, + data->voltage[nr][channel] >> 2); mutex_unlock(&data->lock); - return count; + + return 0; } -static ssize_t pwm_use_point2_pwm_at_crit_show(struct device *dev, - struct device_attribute *devattr, - char *buf) +static int adt7475_temp_nr(u32 attr) +{ + switch (attr) { + case hwmon_temp_input: + return INPUT; + case hwmon_temp_min: + return MIN; + case hwmon_temp_max: + return MAX; + case hwmon_temp_offset: + return OFFSET; + case hwmon_temp_crit: + return THERM; + case hwmon_temp_crit_hyst: + return HYSTERSIS; + case hwmon_temp_alarm: + return ALARM; + case hwmon_temp_fault: + return FAULT; + default: + return -EOPNOTSUPP; + } +} + +static int adt7475_temp_read(struct device *dev, u32 attr, int channel, + long *val) +{ + struct adt7475_data *data; + int nr = adt7475_temp_nr(attr); + + if (nr < 0) + return nr; + + data = adt7475_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + + *val = adt7475_temp_value(data, nr, channel); + + return 0; +} + +static int adt7475_temp_write(struct device *dev, u32 attr, int channel, + long val) +{ + struct adt7475_data *data = dev_get_drvdata(dev); + int nr = adt7475_temp_nr(attr); + + switch (nr) { + case MIN: + case MAX: + case OFFSET: + case THERM: + case HYSTERSIS: + adt7475_temp_set(data, nr, channel, val); + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int adt7475_fan_read(struct device *dev, u32 attr, int channel, + long *val) { struct adt7475_data *data = adt7475_update_device(dev); if (IS_ERR(data)) return PTR_ERR(data); - return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY)); + switch (attr) { + case hwmon_fan_input: + *val = tach2rpm(data->tach[INPUT][channel]); + return 0; + case hwmon_fan_min: + *val = tach2rpm(data->tach[MIN][channel]); + return 0; + case hwmon_fan_alarm: + *val = (data->alarms >> (channel + 10)) & 1; + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t pwm_use_point2_pwm_at_crit_store(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) +static int adt7475_fan_write(struct device *dev, u32 attr, int channel, + long val) { struct adt7475_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - long val; - if (kstrtol(buf, 10, &val)) - return -EINVAL; - if (val != 0 && val != 1) + if (attr != hwmon_fan_min) + return -EOPNOTSUPP; + + /* fanN_min takes an unsigned value */ + if (val < 0) return -EINVAL; mutex_lock(&data->lock); - data->config4 = i2c_smbus_read_byte_data(client, REG_CONFIG4); - if (val) - data->config4 |= CONFIG4_MAXDUTY; - else - data->config4 &= ~CONFIG4_MAXDUTY; - i2c_smbus_write_byte_data(client, REG_CONFIG4, data->config4); + + data->tach[MIN][channel] = rpm2tach(val); + + adt7475_write_word(data->client, TACH_MIN_REG(channel), + data->tach[MIN][channel]); + mutex_unlock(&data->lock); - return count; + return 0; } -static ssize_t vrm_show(struct device *dev, struct device_attribute *devattr, - char *buf) +static int adt7475_pwm_read(struct device *dev, u32 attr, int channel, + long *val) { - struct adt7475_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", (int)data->vrm); + struct adt7475_data *data = adt7475_update_device(dev); + int idx; + + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (attr) { + case hwmon_pwm_input: + *val = data->pwm[INPUT][channel]; + return 0; + case hwmon_pwm_enable: + *val = data->pwmctl[channel]; + return 0; + case hwmon_pwm_auto_channels_temp: + *val = data->pwmchan[channel]; + return 0; + case hwmon_pwm_freq: + idx = clamp_val(data->range[channel] & 0xf, 0, + ARRAY_SIZE(pwmfreq_table) - 1); + *val = pwmfreq_table[idx]; + return 0; + default: + return -EOPNOTSUPP; + } } -static ssize_t vrm_store(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) +static int adt7475_pwm_write(struct device *dev, u32 attr, int channel, + long val) { struct adt7475_data *data = dev_get_drvdata(dev); - long val; + struct i2c_client *client = data->client; + int ret = 0; + int out; - if (kstrtol(buf, 10, &val)) - return -EINVAL; - if (val < 0 || val > 255) - return -EINVAL; - data->vrm = val; + switch (attr) { + case hwmon_pwm_input: + adt7475_pwm_set(data, INPUT, channel, val); + break; - return count; + case hwmon_pwm_enable: + mutex_lock(&data->lock); + /* Read Modify Write PWM values */ + adt7475_read_pwm(client, channel); + ret = hw_set_pwm(client, channel, val, data->pwmchan[channel]); + mutex_unlock(&data->lock); + break; + + case hwmon_pwm_auto_channels_temp: + mutex_lock(&data->lock); + /* Read Modify Write PWM values */ + adt7475_read_pwm(client, channel); + ret = hw_set_pwm(client, channel, data->pwmctl[channel], val); + mutex_unlock(&data->lock); + break; + + case hwmon_pwm_freq: + out = find_closest(val, pwmfreq_table, + ARRAY_SIZE(pwmfreq_table)); + + mutex_lock(&data->lock); + + data->range[channel] = + adt7475_read(TEMP_TRANGE_REG(channel)); + data->range[channel] &= ~0xf; + data->range[channel] |= out; + + i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(channel), + data->range[channel]); + + mutex_unlock(&data->lock); + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; } -static ssize_t cpu0_vid_show(struct device *dev, - struct device_attribute *devattr, char *buf) +static int adt7475_hwmon_read(struct device *dev, + enum hwmon_sensor_types type, u32 attr, + int channel, long *val) { - struct adt7475_data *data = adt7475_update_device(dev); + switch (type) { + case hwmon_in: + return adt7475_in_read(dev, attr, channel, val); + case hwmon_temp: + return adt7475_temp_read(dev, attr, channel, val); + case hwmon_fan: + return adt7475_fan_read(dev, attr, channel, val); + case hwmon_pwm: + return adt7475_pwm_read(dev, attr, channel, val); + default: + return -EOPNOTSUPP; + } +} - if (IS_ERR(data)) - return PTR_ERR(data); +static int adt7475_hwmon_write(struct device *dev, + enum hwmon_sensor_types type, u32 attr, + int channel, long val) +{ + switch (type) { + case hwmon_in: + return adt7475_in_write(dev, attr, channel, val); + case hwmon_temp: + return adt7475_temp_write(dev, attr, channel, val); + case hwmon_fan: + return adt7475_fan_write(dev, attr, channel, val); + case hwmon_pwm: + return adt7475_pwm_write(dev, attr, channel, val); + default: + return -EOPNOTSUPP; + } +} - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +static umode_t adt7475_is_visible(const void *_data, + enum hwmon_sensor_types type, u32 attr, + int channel) +{ + const struct adt7475_data *data = _data; + + switch (type) { + case hwmon_in: + if (!(data->has_voltage & BIT(channel))) + return 0; + if (attr == hwmon_in_min || attr == hwmon_in_max) + return 0644; + return 0444; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_alarm: + case hwmon_temp_fault: + return 0444; + default: + return 0644; + } + case hwmon_fan: + if (channel == 3 && !data->has_fan4) + return 0; + if (attr == hwmon_fan_min) + return 0644; + return 0444; + case hwmon_pwm: + if (channel == 1 && !data->has_pwm2) + return 0; + return 0644; + default: + return 0; + } } -static SENSOR_DEVICE_ATTR_2_RO(in0_input, voltage, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RW(in0_max, voltage, MAX, 0); -static SENSOR_DEVICE_ATTR_2_RW(in0_min, voltage, MIN, 0); -static SENSOR_DEVICE_ATTR_2_RO(in0_alarm, voltage, ALARM, 0); -static SENSOR_DEVICE_ATTR_2_RO(in1_input, voltage, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RW(in1_max, voltage, MAX, 1); -static SENSOR_DEVICE_ATTR_2_RW(in1_min, voltage, MIN, 1); -static SENSOR_DEVICE_ATTR_2_RO(in1_alarm, voltage, ALARM, 1); -static SENSOR_DEVICE_ATTR_2_RO(in2_input, voltage, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RW(in2_max, voltage, MAX, 2); -static SENSOR_DEVICE_ATTR_2_RW(in2_min, voltage, MIN, 2); -static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, voltage, ALARM, 2); -static SENSOR_DEVICE_ATTR_2_RO(in3_input, voltage, INPUT, 3); -static SENSOR_DEVICE_ATTR_2_RW(in3_max, voltage, MAX, 3); -static SENSOR_DEVICE_ATTR_2_RW(in3_min, voltage, MIN, 3); -static SENSOR_DEVICE_ATTR_2_RO(in3_alarm, voltage, ALARM, 3); -static SENSOR_DEVICE_ATTR_2_RO(in4_input, voltage, INPUT, 4); -static SENSOR_DEVICE_ATTR_2_RW(in4_max, voltage, MAX, 4); -static SENSOR_DEVICE_ATTR_2_RW(in4_min, voltage, MIN, 4); -static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, voltage, ALARM, 8); -static SENSOR_DEVICE_ATTR_2_RO(in5_input, voltage, INPUT, 5); -static SENSOR_DEVICE_ATTR_2_RW(in5_max, voltage, MAX, 5); -static SENSOR_DEVICE_ATTR_2_RW(in5_min, voltage, MIN, 5); -static SENSOR_DEVICE_ATTR_2_RO(in5_alarm, voltage, ALARM, 31); -static SENSOR_DEVICE_ATTR_2_RO(in6_input, voltage, INPUT, 6); -static SENSOR_DEVICE_ATTR_2_RW(in6_max, voltage, MAX, 6); -static SENSOR_DEVICE_ATTR_2_RW(in6_min, voltage, MIN, 6); -static SENSOR_DEVICE_ATTR_2_RO(in6_alarm, voltage, ALARM, 30); -static SENSOR_DEVICE_ATTR_2_RO(temp1_input, temp, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp1_alarm, temp, ALARM, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp1_fault, temp, FAULT, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, MAX, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_min, temp, MIN, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_offset, temp, OFFSET, 0); +static const struct hwmon_ops adt7475_hwmon_ops = { + .is_visible = adt7475_is_visible, + .read = adt7475_hwmon_read, + .write = adt7475_hwmon_write, +}; + +#define ADT7475_IN_CONFIG (HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | \ + HWMON_I_ALARM) +#define ADT7475_TEMP_CONFIG (HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | \ + HWMON_T_OFFSET | HWMON_T_CRIT | \ + HWMON_T_CRIT_HYST | HWMON_T_ALARM) +#define ADT7475_FAN_CONFIG (HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM) +#define ADT7475_PWM_CONFIG (HWMON_PWM_INPUT | HWMON_PWM_ENABLE | \ + HWMON_PWM_FREQ | HWMON_PWM_AUTO_CHANNELS_TEMP) + +static const struct hwmon_channel_info * const adt7475_info[] = { + HWMON_CHANNEL_INFO(in, + ADT7475_IN_CONFIG, /* in0: +2.5V */ + ADT7475_IN_CONFIG, /* in1: Vccp */ + ADT7475_IN_CONFIG, /* in2: Vcc */ + ADT7475_IN_CONFIG, /* in3: +5V */ + ADT7475_IN_CONFIG, /* in4: +12V */ + ADT7475_IN_CONFIG, /* in5: Vtt */ + ADT7475_IN_CONFIG), /* in6: Imon */ + HWMON_CHANNEL_INFO(temp, + ADT7475_TEMP_CONFIG | HWMON_T_FAULT, /* remote 1 */ + ADT7475_TEMP_CONFIG, /* local */ + ADT7475_TEMP_CONFIG | HWMON_T_FAULT), /* remote 2 */ + HWMON_CHANNEL_INFO(fan, + ADT7475_FAN_CONFIG, + ADT7475_FAN_CONFIG, + ADT7475_FAN_CONFIG, + ADT7475_FAN_CONFIG), + HWMON_CHANNEL_INFO(pwm, + ADT7475_PWM_CONFIG, + ADT7475_PWM_CONFIG, + ADT7475_PWM_CONFIG), + NULL +}; + +static const struct hwmon_chip_info adt7475_chip_info = { + .ops = &adt7475_hwmon_ops, + .info = adt7475_info, +}; + static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point1_temp, temp, AUTOMIN, 0); static SENSOR_DEVICE_ATTR_2_RW(temp1_auto_point2_temp, point2, 0, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, THERM, 0); -static SENSOR_DEVICE_ATTR_2_RW(temp1_crit_hyst, temp, HYSTERSIS, 0); static SENSOR_DEVICE_ATTR_2_RW(temp1_smoothing, temp_st, 0, 0); -static SENSOR_DEVICE_ATTR_2_RO(temp2_input, temp, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RO(temp2_alarm, temp, ALARM, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp, MAX, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_min, temp, MIN, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_offset, temp, OFFSET, 1); static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point1_temp, temp, AUTOMIN, 1); static SENSOR_DEVICE_ATTR_2_RW(temp2_auto_point2_temp, point2, 0, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_crit, temp, THERM, 1); -static SENSOR_DEVICE_ATTR_2_RW(temp2_crit_hyst, temp, HYSTERSIS, 1); static SENSOR_DEVICE_ATTR_2_RW(temp2_smoothing, temp_st, 0, 1); -static SENSOR_DEVICE_ATTR_2_RO(temp3_input, temp, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_alarm, temp, ALARM, 2); -static SENSOR_DEVICE_ATTR_2_RO(temp3_fault, temp, FAULT, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_max, temp, MAX, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_min, temp, MIN, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_offset, temp, OFFSET, 2); static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_point1_temp, temp, AUTOMIN, 2); static SENSOR_DEVICE_ATTR_2_RW(temp3_auto_point2_temp, point2, 0, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_crit, temp, THERM, 2); -static SENSOR_DEVICE_ATTR_2_RW(temp3_crit_hyst, temp, HYSTERSIS, 2); static SENSOR_DEVICE_ATTR_2_RW(temp3_smoothing, temp_st, 0, 2); -static SENSOR_DEVICE_ATTR_2_RO(fan1_input, tach, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RW(fan1_min, tach, MIN, 0); -static SENSOR_DEVICE_ATTR_2_RO(fan1_alarm, tach, ALARM, 0); -static SENSOR_DEVICE_ATTR_2_RO(fan2_input, tach, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RW(fan2_min, tach, MIN, 1); -static SENSOR_DEVICE_ATTR_2_RO(fan2_alarm, tach, ALARM, 1); -static SENSOR_DEVICE_ATTR_2_RO(fan3_input, tach, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RW(fan3_min, tach, MIN, 2); -static SENSOR_DEVICE_ATTR_2_RO(fan3_alarm, tach, ALARM, 2); -static SENSOR_DEVICE_ATTR_2_RO(fan4_input, tach, INPUT, 3); -static SENSOR_DEVICE_ATTR_2_RW(fan4_min, tach, MIN, 3); -static SENSOR_DEVICE_ATTR_2_RO(fan4_alarm, tach, ALARM, 3); -static SENSOR_DEVICE_ATTR_2_RW(pwm1, pwm, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RW(pwm1_freq, pwmfreq, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RW(pwm1_enable, pwmctrl, INPUT, 0); -static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_channels_temp, pwmchan, INPUT, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, pwm, MIN, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, pwm, MAX, 0); static SENSOR_DEVICE_ATTR_2_RW(pwm1_stall_disable, stall_disable, 0, 0); -static SENSOR_DEVICE_ATTR_2_RW(pwm2, pwm, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RW(pwm2_freq, pwmfreq, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RW(pwm2_enable, pwmctrl, INPUT, 1); -static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_channels_temp, pwmchan, INPUT, 1); static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm, pwm, MIN, 1); static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm, pwm, MAX, 1); static SENSOR_DEVICE_ATTR_2_RW(pwm2_stall_disable, stall_disable, 0, 1); -static SENSOR_DEVICE_ATTR_2_RW(pwm3, pwm, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RW(pwm3_freq, pwmfreq, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RW(pwm3_enable, pwmctrl, INPUT, 2); -static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_channels_temp, pwmchan, INPUT, 2); static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_pwm, pwm, MIN, 2); static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_pwm, pwm, MAX, 2); static SENSOR_DEVICE_ATTR_2_RW(pwm3_stall_disable, stall_disable, 0, 2); @@ -1194,66 +1298,18 @@ static DEVICE_ATTR_RW(vrm); static DEVICE_ATTR_RO(cpu0_vid); static struct attribute *adt7475_attrs[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, &sensor_dev_attr_temp1_smoothing.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, &sensor_dev_attr_temp2_smoothing.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, &sensor_dev_attr_temp3_smoothing.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm1_stall_disable.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm3_stall_disable.dev_attr.attr, @@ -1261,64 +1317,13 @@ static struct attribute *adt7475_attrs[] = { NULL, }; -static struct attribute *fan4_attrs[] = { - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - NULL -}; - static struct attribute *pwm2_attrs[] = { - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, &sensor_dev_attr_pwm2_stall_disable.dev_attr.attr, NULL }; -static struct attribute *in0_attrs[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in3_attrs[] = { - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in4_attrs[] = { - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in5_attrs[] = { - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in6_attrs[] = { - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - NULL -}; - static struct attribute *vid_attrs[] = { &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, @@ -1326,13 +1331,7 @@ static struct attribute *vid_attrs[] = { }; static const struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; -static const struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; static const struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; -static const struct attribute_group in0_attr_group = { .attrs = in0_attrs }; -static const struct attribute_group in3_attr_group = { .attrs = in3_attrs }; -static const struct attribute_group in4_attr_group = { .attrs = in4_attrs }; -static const struct attribute_group in5_attr_group = { .attrs = in5_attrs }; -static const struct attribute_group in6_attr_group = { .attrs = in6_attrs }; static const struct attribute_group vid_attr_group = { .attrs = vid_attrs }; static int adt7475_detect(struct i2c_client *client, @@ -1932,36 +1931,19 @@ static int adt7475_probe(struct i2c_client *client) data->groups[group_num++] = &adt7475_attr_group; /* Features that can be disabled individually */ - if (data->has_fan4) { - data->groups[group_num++] = &fan4_attr_group; - } if (data->has_pwm2) { data->groups[group_num++] = &pwm2_attr_group; } - if (data->has_voltage & (1 << 0)) { - data->groups[group_num++] = &in0_attr_group; - } - if (data->has_voltage & (1 << 3)) { - data->groups[group_num++] = &in3_attr_group; - } - if (data->has_voltage & (1 << 4)) { - data->groups[group_num++] = &in4_attr_group; - } - if (data->has_voltage & (1 << 5)) { - data->groups[group_num++] = &in5_attr_group; - } - if (data->has_voltage & (1 << 6)) { - data->groups[group_num++] = &in6_attr_group; - } if (data->has_vid) { data->vrm = vid_which_vrm(); data->groups[group_num] = &vid_attr_group; } /* register device with all the acquired attributes */ - hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, - client->name, data, - data->groups); + hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, + client->name, data, + &adt7475_chip_info, + data->groups); if (IS_ERR(hwmon_dev)) { ret = PTR_ERR(hwmon_dev); -- 2.56.0