From ada61aa0b1184a8fda1a89a340c7d6cc4e59aee5 Mon Sep 17 00:00:00 2001 From: Yang Yingliang <yangyingliang@huawei.com> Date: Tue, 12 Oct 2021 19:27:58 +0800 Subject: hwmon: Fix possible memleak in __hwmon_device_register() I got memory leak as follows when doing fault injection test: unreferenced object 0xffff888102740438 (size 8): comm "27", pid 859, jiffies 4295031351 (age 143.992s) hex dump (first 8 bytes): 68 77 6d 6f 6e 30 00 00 hwmon0.. backtrace: [<00000000544b5996>] __kmalloc_track_caller+0x1a6/0x300 [<00000000df0d62b9>] kvasprintf+0xad/0x140 [<00000000d3d2a3da>] kvasprintf_const+0x62/0x190 [<000000005f8f0f29>] kobject_set_name_vargs+0x56/0x140 [<00000000b739e4b9>] dev_set_name+0xb0/0xe0 [<0000000095b69c25>] __hwmon_device_register+0xf19/0x1e50 [hwmon] [<00000000a7e65b52>] hwmon_device_register_with_info+0xcb/0x110 [hwmon] [<000000006f181e86>] devm_hwmon_device_register_with_info+0x85/0x100 [hwmon] [<0000000081bdc567>] tmp421_probe+0x2d2/0x465 [tmp421] [<00000000502cc3f8>] i2c_device_probe+0x4e1/0xbb0 [<00000000f90bda3b>] really_probe+0x285/0xc30 [<000000007eac7b77>] __driver_probe_device+0x35f/0x4f0 [<000000004953d43d>] driver_probe_device+0x4f/0x140 [<000000002ada2d41>] __device_attach_driver+0x24c/0x330 [<00000000b3977977>] bus_for_each_drv+0x15d/0x1e0 [<000000005bf2a8e3>] __device_attach+0x267/0x410 When device_register() returns an error, the name allocated in dev_set_name() will be leaked, the put_device() should be used instead of calling hwmon_dev_release() to give up the device reference, then the name will be freed in kobject_cleanup(). Reported-by: Hulk Robot <hulkci@huawei.com> Fixes: bab2243ce189 ("hwmon: Introduce hwmon_device_register_with_groups") Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Link: https://lore.kernel.org/r/20211012112758.2681084-1-yangyingliang@huawei.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/hwmon.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 8d3b1dae31df..3501a3ead4ba 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -796,8 +796,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata, dev_set_drvdata(hdev, drvdata); dev_set_name(hdev, HWMON_ID_FORMAT, id); err = device_register(hdev); - if (err) - goto free_hwmon; + if (err) { + put_device(hdev); + goto ida_remove; + } INIT_LIST_HEAD(&hwdev->tzdata); -- cgit v1.2.3 From 6665e10a2ec3cadfe026d4f28a2e3193fe392035 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Mon, 23 Aug 2021 19:07:24 +0200 Subject: hwmon: (i5500_temp) Convert to devm_hwmon_device_register_with_info Use devm_hwmon_device_register_with_info() to simplify code and use register defines instead of hardcoded values. Also use the BIT() macro for the alarms. Only compile-tested. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20210823170724.7662-1-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/i5500_temp.c | 114 ++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 53 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/i5500_temp.c b/drivers/hwmon/i5500_temp.c index 360f5aee1394..05f68e9c9477 100644 --- a/drivers/hwmon/i5500_temp.c +++ b/drivers/hwmon/i5500_temp.c @@ -5,6 +5,7 @@ * Copyright (C) 2012, 2014 Jean Delvare <jdelvare@suse.de> */ +#include <linux/bitops.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -12,7 +13,6 @@ #include <linux/device.h> #include <linux/pci.h> #include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> @@ -29,69 +29,78 @@ #define REG_CTCTRL 0xF7 #define REG_TSTIMER 0xF8 -/* - * Sysfs stuff - */ - -/* Sensor resolution : 0.5 degree C */ -static ssize_t temp1_input_show(struct device *dev, - struct device_attribute *devattr, char *buf) +static umode_t i5500_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr, + int channel) { - struct pci_dev *pdev = to_pci_dev(dev->parent); - long temp; - u16 tsthrhi; - s8 tsfsc; - - pci_read_config_word(pdev, REG_TSTHRHI, &tsthrhi); - pci_read_config_byte(pdev, REG_TSFSC, &tsfsc); - temp = ((long)tsthrhi - tsfsc) * 500; - - return sprintf(buf, "%ld\n", temp); + return 0444; } -static ssize_t thresh_show(struct device *dev, - struct device_attribute *devattr, char *buf) +static int i5500_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, + long *val) { struct pci_dev *pdev = to_pci_dev(dev->parent); - int reg = to_sensor_dev_attr(devattr)->index; - long temp; u16 tsthr; + s8 tsfsc; + u8 ctsts; - pci_read_config_word(pdev, reg, &tsthr); - temp = tsthr * 500; + switch (type) { + case hwmon_temp: + switch (attr) { + /* Sensor resolution : 0.5 degree C */ + case hwmon_temp_input: + pci_read_config_word(pdev, REG_TSTHRHI, &tsthr); + pci_read_config_byte(pdev, REG_TSFSC, &tsfsc); + *val = (tsthr - tsfsc) * 500; + return 0; + case hwmon_temp_max: + pci_read_config_word(pdev, REG_TSTHRHI, &tsthr); + *val = tsthr * 500; + return 0; + case hwmon_temp_max_hyst: + pci_read_config_word(pdev, REG_TSTHRLO, &tsthr); + *val = tsthr * 500; + return 0; + case hwmon_temp_crit: + pci_read_config_word(pdev, REG_TSTHRCATA, &tsthr); + *val = tsthr * 500; + return 0; + case hwmon_temp_max_alarm: + pci_read_config_byte(pdev, REG_CTSTS, &ctsts); + *val = !!(ctsts & BIT(1)); + return 0; + case hwmon_temp_crit_alarm: + pci_read_config_byte(pdev, REG_CTSTS, &ctsts); + *val = !!(ctsts & BIT(0)); + return 0; + default: + break; + } + break; + default: + break; + } - return sprintf(buf, "%ld\n", temp); + return -EOPNOTSUPP; } -static ssize_t alarm_show(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev->parent); - int nr = to_sensor_dev_attr(devattr)->index; - u8 ctsts; - - pci_read_config_byte(pdev, REG_CTSTS, &ctsts); - return sprintf(buf, "%u\n", (unsigned int)ctsts & (1 << nr)); -} +static const struct hwmon_ops i5500_ops = { + .is_visible = i5500_is_visible, + .read = i5500_read, +}; -static DEVICE_ATTR_RO(temp1_input); -static SENSOR_DEVICE_ATTR_RO(temp1_crit, thresh, 0xE2); -static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, thresh, 0xEC); -static SENSOR_DEVICE_ATTR_RO(temp1_max, thresh, 0xEE); -static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0); -static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1); - -static struct attribute *i5500_temp_attrs[] = { - &dev_attr_temp1_input.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, +static const struct hwmon_channel_info *i5500_info[] = { + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_CRIT | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM + ), NULL }; -ATTRIBUTE_GROUPS(i5500_temp); +static const struct hwmon_chip_info i5500_chip_info = { + .ops = &i5500_ops, + .info = i5500_info, +}; static const struct pci_device_id i5500_temp_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3438) }, @@ -121,9 +130,8 @@ static int i5500_temp_probe(struct pci_dev *pdev, return -ENODEV; } - hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, - "intel5500", NULL, - i5500_temp_groups); + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "intel5500", NULL, + &i5500_chip_info, NULL); return PTR_ERR_OR_ZERO(hwmon_dev); } -- cgit v1.2.3 From d73287eed73fa024af704e269eca542e3bb213bb Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Sun, 5 Sep 2021 21:00:49 +0200 Subject: hwmon: (raspberrypi) Use generic notification mechanism Use hwmon_notify_event() to make the code easier to understand and to also generate udev events. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20210905190049.11381-1-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/raspberrypi-hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c index 805d396aa81b..573f53d52912 100644 --- a/drivers/hwmon/raspberrypi-hwmon.c +++ b/drivers/hwmon/raspberrypi-hwmon.c @@ -53,7 +53,7 @@ static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data) else dev_info(data->hwmon_dev, "Voltage normalised\n"); - sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm"); + hwmon_notify_event(data->hwmon_dev, hwmon_in, hwmon_in_lcrit_alarm, 0); } static void get_values_poll(struct work_struct *work) -- cgit v1.2.3 From e8ac01e5db329cf4ac2b36ef66b9d877330a990c Mon Sep 17 00:00:00 2001 From: Arun Saravanan Balachandran <Arun_Saravanan_Balac@dell.com> Date: Mon, 13 Sep 2021 13:40:15 +0000 Subject: hwmon: Add Maxim MAX6620 hardware monitoring driver Add hardware monitoring driver for Maxim MAX6620 Fan controller Originally-from: L. Grunenberg <contact@lgrunenberg.de> Originally-from: Cumulus Networks <support@cumulusnetworks.com> Originally-from: Shuotian Cheng <shuche@microsoft.com> Signed-off-by: Arun Saravanan Balachandran <Arun_Saravanan_Balac@dell.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/index.rst | 1 + Documentation/hwmon/max6620.rst | 46 ++++ drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/max6620.c | 514 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 572 insertions(+) create mode 100644 Documentation/hwmon/max6620.rst create mode 100644 drivers/hwmon/max6620.c (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index f790f1260c33..7046bf1870d9 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -130,6 +130,7 @@ Hardware Monitoring Kernel Drivers max31785 max31790 max34440 + max6620 max6639 max6642 max6650 diff --git a/Documentation/hwmon/max6620.rst b/Documentation/hwmon/max6620.rst new file mode 100644 index 000000000000..84c1c44d3de4 --- /dev/null +++ b/Documentation/hwmon/max6620.rst @@ -0,0 +1,46 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +Kernel driver max6620 +===================== + +Supported chips: + + Maxim MAX6620 + + Prefix: 'max6620' + + Addresses scanned: none + + Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf + +Authors: + - L\. Grunenberg <contact@lgrunenberg.de> + - Cumulus Networks <support@cumulusnetworks.com> + - Shuotian Cheng <shuche@microsoft.com> + - Arun Saravanan Balachandran <Arun_Saravanan_Balac@dell.com> + +Description +----------- + +This driver implements support for Maxim MAX6620 fan controller. + +The driver configures the fan controller in RPM mode. To give the readings more +range or accuracy, the desired value can be set by a programmable register +(1, 2, 4, 8, 16 or 32). Set higher values for larger speeds. + +The driver provides the following sensor access in sysfs: + +================ ======= ===================================================== +fan[1-4]_alarm ro Fan alarm. +fan[1-4]_div rw Sets the nominal RPM range of the fan. Valid values + are 1, 2, 4, 8, 16 and 32. +fan[1-4]_input ro Fan speed in RPM. +fan[1-4]_target rw Desired fan speed in RPM. +================ ======= ===================================================== + +Usage notes +----------- + +This driver does not auto-detect devices. You will have to instantiate the +devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for +details. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c4578e8f34bb..91ec36aac059 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1032,6 +1032,16 @@ config SENSORS_MAX31730 This driver can also be built as a module. If so, the module will be called max31730. +config SENSORS_MAX6620 + tristate "Maxim MAX6620 fan controller" + depends on I2C + help + If you say yes here you get support for the MAX6620 + fan controller. + + This driver can also be built as a module. If so, the module + will be called max6620. + config SENSORS_MAX6621 tristate "Maxim MAX6621 sensor chip" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 162940270661..baee6a8d4dd1 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -135,6 +135,7 @@ obj-$(CONFIG_SENSORS_MAX1668) += max1668.o obj-$(CONFIG_SENSORS_MAX197) += max197.o obj-$(CONFIG_SENSORS_MAX31722) += max31722.o obj-$(CONFIG_SENSORS_MAX31730) += max31730.o +obj-$(CONFIG_SENSORS_MAX6620) += max6620.o obj-$(CONFIG_SENSORS_MAX6621) += max6621.o obj-$(CONFIG_SENSORS_MAX6639) += max6639.o obj-$(CONFIG_SENSORS_MAX6642) += max6642.o diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c new file mode 100644 index 000000000000..202b6438179d --- /dev/null +++ b/drivers/hwmon/max6620.c @@ -0,0 +1,514 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Hardware monitoring driver for Maxim MAX6620 + * + * Originally from L. Grunenberg. + * (C) 2012 by L. Grunenberg <contact@lgrunenberg.de> + * + * Copyright (c) 2021 Dell Inc. or its subsidiaries. All Rights Reserved. + * + * based on code written by : + * 2007 by Hans J. Koch <hjk@hansjkoch.de> + * John Morris <john.morris@spirentcom.com> + * Copyright (c) 2003 Spirent Communications + * and Claus Gindhart <claus.gindhart@kontron.com> + * + * This module has only been tested with the MAX6620 chip. + * + * The datasheet was last seen at: + * + * http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf + * + */ + +#include <linux/bits.h> +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/slab.h> + +/* + * MAX 6620 registers + */ + +#define MAX6620_REG_CONFIG 0x00 +#define MAX6620_REG_FAULT 0x01 +#define MAX6620_REG_CONF_FAN0 0x02 +#define MAX6620_REG_CONF_FAN1 0x03 +#define MAX6620_REG_CONF_FAN2 0x04 +#define MAX6620_REG_CONF_FAN3 0x05 +#define MAX6620_REG_DYN_FAN0 0x06 +#define MAX6620_REG_DYN_FAN1 0x07 +#define MAX6620_REG_DYN_FAN2 0x08 +#define MAX6620_REG_DYN_FAN3 0x09 +#define MAX6620_REG_TACH0 0x10 +#define MAX6620_REG_TACH1 0x12 +#define MAX6620_REG_TACH2 0x14 +#define MAX6620_REG_TACH3 0x16 +#define MAX6620_REG_VOLT0 0x18 +#define MAX6620_REG_VOLT1 0x1A +#define MAX6620_REG_VOLT2 0x1C +#define MAX6620_REG_VOLT3 0x1E +#define MAX6620_REG_TAR0 0x20 +#define MAX6620_REG_TAR1 0x22 +#define MAX6620_REG_TAR2 0x24 +#define MAX6620_REG_TAR3 0x26 +#define MAX6620_REG_DAC0 0x28 +#define MAX6620_REG_DAC1 0x2A +#define MAX6620_REG_DAC2 0x2C +#define MAX6620_REG_DAC3 0x2E + +/* + * Config register bits + */ + +#define MAX6620_CFG_RUN BIT(7) +#define MAX6620_CFG_POR BIT(6) +#define MAX6620_CFG_TIMEOUT BIT(5) +#define MAX6620_CFG_FULLFAN BIT(4) +#define MAX6620_CFG_OSC BIT(3) +#define MAX6620_CFG_WD_MASK (BIT(2) | BIT(1)) +#define MAX6620_CFG_WD_2 BIT(1) +#define MAX6620_CFG_WD_6 BIT(2) +#define MAX6620_CFG_WD10 (BIT(2) | BIT(1)) +#define MAX6620_CFG_WD BIT(0) + +/* + * Failure status register bits + */ + +#define MAX6620_FAIL_TACH0 BIT(4) +#define MAX6620_FAIL_TACH1 BIT(5) +#define MAX6620_FAIL_TACH2 BIT(6) +#define MAX6620_FAIL_TACH3 BIT(7) +#define MAX6620_FAIL_MASK0 BIT(0) +#define MAX6620_FAIL_MASK1 BIT(1) +#define MAX6620_FAIL_MASK2 BIT(2) +#define MAX6620_FAIL_MASK3 BIT(3) + +#define MAX6620_CLOCK_FREQ 8192 /* Clock frequency in Hz */ +#define MAX6620_PULSE_PER_REV 2 /* Tachometer pulses per revolution */ + +/* Minimum and maximum values of the FAN-RPM */ +#define FAN_RPM_MIN 240 +#define FAN_RPM_MAX 30000 + +static const u8 config_reg[] = { + MAX6620_REG_CONF_FAN0, + MAX6620_REG_CONF_FAN1, + MAX6620_REG_CONF_FAN2, + MAX6620_REG_CONF_FAN3, +}; + +static const u8 dyn_reg[] = { + MAX6620_REG_DYN_FAN0, + MAX6620_REG_DYN_FAN1, + MAX6620_REG_DYN_FAN2, + MAX6620_REG_DYN_FAN3, +}; + +static const u8 tach_reg[] = { + MAX6620_REG_TACH0, + MAX6620_REG_TACH1, + MAX6620_REG_TACH2, + MAX6620_REG_TACH3, +}; + +static const u8 target_reg[] = { + MAX6620_REG_TAR0, + MAX6620_REG_TAR1, + MAX6620_REG_TAR2, + MAX6620_REG_TAR3, +}; + +/* + * Client data (each client gets its own) + */ + +struct max6620_data { + struct i2c_client *client; + struct mutex update_lock; + bool valid; /* false until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* register values */ + u8 fancfg[4]; + u8 fandyn[4]; + u8 fault; + u16 tach[4]; + u16 target[4]; +}; + +static u8 max6620_fan_div_from_reg(u8 val) +{ + return BIT((val & 0xE0) >> 5); +} + +static u16 max6620_fan_rpm_to_tach(u8 div, int rpm) +{ + return (60 * div * MAX6620_CLOCK_FREQ) / (rpm * MAX6620_PULSE_PER_REV); +} + +static int max6620_fan_tach_to_rpm(u8 div, u16 tach) +{ + return (60 * div * MAX6620_CLOCK_FREQ) / (tach * MAX6620_PULSE_PER_REV); +} + +static int max6620_update_device(struct device *dev) +{ + struct max6620_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + int ret = 0; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + for (i = 0; i < 4; i++) { + ret = i2c_smbus_read_byte_data(client, config_reg[i]); + if (ret < 0) + goto error; + data->fancfg[i] = ret; + + ret = i2c_smbus_read_byte_data(client, dyn_reg[i]); + if (ret < 0) + goto error; + data->fandyn[i] = ret; + + ret = i2c_smbus_read_byte_data(client, tach_reg[i]); + if (ret < 0) + goto error; + data->tach[i] = (ret << 3) & 0x7f8; + ret = i2c_smbus_read_byte_data(client, tach_reg[i] + 1); + if (ret < 0) + goto error; + data->tach[i] |= (ret >> 5) & 0x7; + + ret = i2c_smbus_read_byte_data(client, target_reg[i]); + if (ret < 0) + goto error; + data->target[i] = (ret << 3) & 0x7f8; + ret = i2c_smbus_read_byte_data(client, target_reg[i] + 1); + if (ret < 0) + goto error; + data->target[i] |= (ret >> 5) & 0x7; + } + + /* + * Alarms are cleared on read in case the condition that + * caused the alarm is removed. Keep the value latched here + * for providing the register through different alarm files. + */ + ret = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT); + if (ret < 0) + goto error; + data->fault |= (ret >> 4) & (ret & 0x0F); + + data->last_updated = jiffies; + data->valid = true; + } + +error: + mutex_unlock(&data->update_lock); + return ret; +} + +static umode_t +max6620_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, + int channel) +{ + switch (type) { + case hwmon_fan: + switch (attr) { + case hwmon_fan_alarm: + case hwmon_fan_input: + return 0444; + case hwmon_fan_div: + case hwmon_fan_target: + return 0644; + default: + break; + } + break; + default: + break; + } + + return 0; +} + +static int +max6620_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long *val) +{ + struct max6620_data *data; + struct i2c_client *client; + int ret; + u8 div; + u8 val1; + u8 val2; + + ret = max6620_update_device(dev); + if (ret < 0) + return ret; + data = dev_get_drvdata(dev); + client = data->client; + + switch (type) { + case hwmon_fan: + switch (attr) { + case hwmon_fan_alarm: + mutex_lock(&data->update_lock); + *val = !!(data->fault & BIT(channel)); + + /* Setting TACH count to re-enable fan fault detection */ + if (*val == 1) { + val1 = (data->target[channel] >> 3) & 0xff; + val2 = (data->target[channel] << 5) & 0xe0; + ret = i2c_smbus_write_byte_data(client, + target_reg[channel], val1); + if (ret < 0) { + mutex_unlock(&data->update_lock); + return ret; + } + ret = i2c_smbus_write_byte_data(client, + target_reg[channel] + 1, val2); + if (ret < 0) { + mutex_unlock(&data->update_lock); + return ret; + } + + data->fault &= ~BIT(channel); + } + mutex_unlock(&data->update_lock); + + break; + case hwmon_fan_div: + *val = max6620_fan_div_from_reg(data->fandyn[channel]); + break; + case hwmon_fan_input: + if (data->tach[channel] == 0) { + *val = 0; + } else { + div = max6620_fan_div_from_reg(data->fandyn[channel]); + *val = max6620_fan_tach_to_rpm(div, data->tach[channel]); + } + break; + case hwmon_fan_target: + if (data->target[channel] == 0) { + *val = 0; + } else { + div = max6620_fan_div_from_reg(data->fandyn[channel]); + *val = max6620_fan_tach_to_rpm(div, data->target[channel]); + } + break; + default: + return -EOPNOTSUPP; + } + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int +max6620_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long val) +{ + struct max6620_data *data; + struct i2c_client *client; + int ret; + u8 div; + u16 tach; + u8 val1; + u8 val2; + + ret = max6620_update_device(dev); + if (ret < 0) + return ret; + data = dev_get_drvdata(dev); + client = data->client; + mutex_lock(&data->update_lock); + + switch (type) { + case hwmon_fan: + switch (attr) { + case hwmon_fan_div: + switch (val) { + case 1: + div = 0; + break; + case 2: + div = 1; + break; + case 4: + div = 2; + break; + case 8: + div = 3; + break; + case 16: + div = 4; + break; + case 32: + div = 5; + break; + default: + ret = -EINVAL; + goto error; + } + data->fandyn[channel] &= 0x1F; + data->fandyn[channel] |= div << 5; + ret = i2c_smbus_write_byte_data(client, dyn_reg[channel], + data->fandyn[channel]); + break; + case hwmon_fan_target: + val = clamp_val(val, FAN_RPM_MIN, FAN_RPM_MAX); + div = max6620_fan_div_from_reg(data->fandyn[channel]); + tach = max6620_fan_rpm_to_tach(div, val); + val1 = (tach >> 3) & 0xff; + val2 = (tach << 5) & 0xe0; + ret = i2c_smbus_write_byte_data(client, target_reg[channel], val1); + if (ret < 0) + break; + ret = i2c_smbus_write_byte_data(client, target_reg[channel] + 1, val2); + if (ret < 0) + break; + + /* Setting TACH count re-enables fan fault detection */ + data->fault &= ~BIT(channel); + + break; + default: + ret = -EOPNOTSUPP; + break; + } + break; + + default: + ret = -EOPNOTSUPP; + break; + } + +error: + mutex_unlock(&data->update_lock); + return ret; +} + +static const struct hwmon_channel_info *max6620_info[] = { + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM), + NULL +}; + +static const struct hwmon_ops max6620_hwmon_ops = { + .read = max6620_read, + .write = max6620_write, + .is_visible = max6620_is_visible, +}; + +static const struct hwmon_chip_info max6620_chip_info = { + .ops = &max6620_hwmon_ops, + .info = max6620_info, +}; + +static int max6620_init_client(struct max6620_data *data) +{ + struct i2c_client *client = data->client; + int config; + int err; + int i; + int reg; + + config = i2c_smbus_read_byte_data(client, MAX6620_REG_CONFIG); + if (config < 0) { + dev_err(&client->dev, "Error reading config, aborting.\n"); + return config; + } + + /* + * Set bit 4, disable other fans from going full speed on a fail + * failure. + */ + err = i2c_smbus_write_byte_data(client, MAX6620_REG_CONFIG, config | 0x10); + if (err < 0) { + dev_err(&client->dev, "Config write error, aborting.\n"); + return err; + } + + for (i = 0; i < 4; i++) { + reg = i2c_smbus_read_byte_data(client, config_reg[i]); + if (reg < 0) + return reg; + data->fancfg[i] = reg; + + /* Enable RPM mode */ + data->fancfg[i] |= 0xa8; + err = i2c_smbus_write_byte_data(client, config_reg[i], data->fancfg[i]); + if (err < 0) + return err; + + /* 2 counts (001) and Rate change 100 (0.125 secs) */ + data->fandyn[i] = 0x30; + err = i2c_smbus_write_byte_data(client, dyn_reg[i], data->fandyn[i]); + if (err < 0) + return err; + } + return 0; +} + +static int max6620_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct max6620_data *data; + struct device *hwmon_dev; + int err; + + data = devm_kzalloc(dev, sizeof(struct max6620_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + mutex_init(&data->update_lock); + + err = max6620_init_client(data); + if (err) + return err; + + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, + data, + &max6620_chip_info, + NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id max6620_id[] = { + { "max6620", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max6620_id); + +static struct i2c_driver max6620_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "max6620", + }, + .probe_new = max6620_probe, + .id_table = max6620_id, +}; + +module_i2c_driver(max6620_driver); + +MODULE_AUTHOR("Lucas Grunenberg"); +MODULE_DESCRIPTION("MAX6620 sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From bc8de07e8812548cc19161af3a2b83849ff03045 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak <vadimp@nvidia.com> Date: Thu, 16 Sep 2021 22:47:17 +0300 Subject: hwmon: (mlxreg-fan) Extend the maximum number of tachometers Extend support of maximum tachometers from 12 to 14 in order to support new systems, equipped with more fans. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Link: https://lore.kernel.org/r/20210916194719.871413-2-vadimp@nvidia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index 89fe7b9fe26b..0f5b109817a7 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -12,7 +12,7 @@ #include <linux/regmap.h> #include <linux/thermal.h> -#define MLXREG_FAN_MAX_TACHO 12 +#define MLXREG_FAN_MAX_TACHO 14 #define MLXREG_FAN_MAX_STATE 10 #define MLXREG_FAN_MIN_DUTY 51 /* 20% */ #define MLXREG_FAN_MAX_DUTY 255 /* 100% */ @@ -266,6 +266,8 @@ static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = { HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT), -- cgit v1.2.3 From 150f1e0c6fa886e18e35594ae2ba5c81b5df1898 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak <vadimp@nvidia.com> Date: Thu, 16 Sep 2021 22:47:18 +0300 Subject: hwmon: (mlxreg-fan) Extend driver to support multiply PWM Add additional PWM attributes in order to support the systems, which can be equipped with up-to four PWM controllers. System capability of additional PWM support is validated through the reading of relevant registers. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Link: https://lore.kernel.org/r/20210916194719.871413-3-vadimp@nvidia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 55 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index 0f5b109817a7..1a146cc4b0fd 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -13,6 +13,8 @@ #include <linux/thermal.h> #define MLXREG_FAN_MAX_TACHO 14 +#define MLXREG_FAN_MAX_PWM 4 +#define MLXREG_FAN_PWM_NOT_CONNECTED 0xff #define MLXREG_FAN_MAX_STATE 10 #define MLXREG_FAN_MIN_DUTY 51 /* 20% */ #define MLXREG_FAN_MAX_DUTY 255 /* 100% */ @@ -105,7 +107,7 @@ struct mlxreg_fan { void *regmap; struct mlxreg_core_platform_data *pdata; struct mlxreg_fan_tacho tacho[MLXREG_FAN_MAX_TACHO]; - struct mlxreg_fan_pwm pwm; + struct mlxreg_fan_pwm pwm[MLXREG_FAN_MAX_PWM]; int tachos_per_drwr; int samples; int divider; @@ -119,6 +121,7 @@ mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, { struct mlxreg_fan *fan = dev_get_drvdata(dev); struct mlxreg_fan_tacho *tacho; + struct mlxreg_fan_pwm *pwm; u32 regval; int err; @@ -169,9 +172,10 @@ mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, break; case hwmon_pwm: + pwm = &fan->pwm[channel]; switch (attr) { case hwmon_pwm_input: - err = regmap_read(fan->regmap, fan->pwm.reg, ®val); + err = regmap_read(fan->regmap, pwm->reg, ®val); if (err) return err; @@ -195,6 +199,7 @@ mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val) { struct mlxreg_fan *fan = dev_get_drvdata(dev); + struct mlxreg_fan_pwm *pwm; switch (type) { case hwmon_pwm: @@ -203,7 +208,8 @@ mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, if (val < MLXREG_FAN_MIN_DUTY || val > MLXREG_FAN_MAX_DUTY) return -EINVAL; - return regmap_write(fan->regmap, fan->pwm.reg, val); + pwm = &fan->pwm[channel]; + return regmap_write(fan->regmap, pwm->reg, val); default: return -EOPNOTSUPP; } @@ -235,7 +241,7 @@ mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, break; case hwmon_pwm: - if (!(((struct mlxreg_fan *)data)->pwm.connected)) + if (!(((struct mlxreg_fan *)data)->pwm[channel].connected)) return 0; switch (attr) { @@ -270,6 +276,9 @@ static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = { HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT), HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT, + HWMON_PWM_INPUT, + HWMON_PWM_INPUT, HWMON_PWM_INPUT), NULL }; @@ -300,7 +309,7 @@ static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev, u32 regval; int err; - err = regmap_read(fan->regmap, fan->pwm.reg, ®val); + err = regmap_read(fan->regmap, fan->pwm[0].reg, ®val); if (err) { dev_err(fan->dev, "Failed to query PWM duty\n"); return err; @@ -343,7 +352,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, for (i = state; i <= MLXREG_FAN_MAX_STATE; i++) fan->cooling_levels[i] = i; - err = regmap_read(fan->regmap, fan->pwm.reg, ®val); + err = regmap_read(fan->regmap, fan->pwm[0].reg, ®val); if (err) { dev_err(fan->dev, "Failed to query PWM duty\n"); return err; @@ -361,7 +370,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, /* Normalize the state to the valid speed range. */ state = fan->cooling_levels[state]; - err = regmap_write(fan->regmap, fan->pwm.reg, + err = regmap_write(fan->regmap, fan->pwm[0].reg, MLXREG_FAN_PWM_STATE2DUTY(state)); if (err) { dev_err(fan->dev, "Failed to write PWM duty\n"); @@ -392,6 +401,22 @@ static int mlxreg_fan_connect_verify(struct mlxreg_fan *fan, return !!(regval & data->bit); } +static int mlxreg_pwm_connect_verify(struct mlxreg_fan *fan, + struct mlxreg_core_data *data) +{ + u32 regval; + int err; + + err = regmap_read(fan->regmap, data->reg, ®val); + if (err) { + dev_err(fan->dev, "Failed to query pwm register 0x%08x\n", + data->reg); + return err; + } + + return regval != MLXREG_FAN_PWM_NOT_CONNECTED; +} + static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan, struct mlxreg_core_data *data) { @@ -420,8 +445,8 @@ static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan, static int mlxreg_fan_config(struct mlxreg_fan *fan, struct mlxreg_core_platform_data *pdata) { + int tacho_num = 0, tacho_avail = 0, pwm_num = 0, i; struct mlxreg_core_data *data = pdata->data; - int tacho_num = 0, tacho_avail = 0, i; bool configured = false; int err; @@ -451,13 +476,19 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan, fan->tacho[tacho_num++].connected = true; tacho_avail++; } else if (strnstr(data->label, "pwm", sizeof(data->label))) { - if (fan->pwm.connected) { - dev_err(fan->dev, "duplicate pwm entry: %s\n", + if (pwm_num == MLXREG_FAN_MAX_TACHO) { + dev_err(fan->dev, "too many pwm entries: %s\n", data->label); return -EINVAL; } - fan->pwm.reg = data->reg; - fan->pwm.connected = true; + + err = mlxreg_pwm_connect_verify(fan, data); + if (err) + return err; + + fan->pwm[pwm_num].reg = data->reg; + fan->pwm[pwm_num].connected = true; + pwm_num++; } else if (strnstr(data->label, "conf", sizeof(data->label))) { if (configured) { dev_err(fan->dev, "duplicate conf entry: %s\n", -- cgit v1.2.3 From d7efb2ebc7b3c952104b9ebfbf88da97ea99a0a0 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak <vadimp@nvidia.com> Date: Fri, 17 Sep 2021 00:31:28 +0300 Subject: hwmon: (mlxreg-fan) Extend driver to support multiply cooling devices Add support for additional cooling devices in order to support the systems, which can be equipped with up-to four PWM controllers. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 73 +++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index 1a146cc4b0fd..35228ed112d7 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -63,6 +63,8 @@ MLXREG_FAN_MAX_DUTY, \ MLXREG_FAN_MAX_STATE)) +struct mlxreg_fan; + /* * struct mlxreg_fan_tacho - tachometer data (internal use): * @@ -81,12 +83,18 @@ struct mlxreg_fan_tacho { /* * struct mlxreg_fan_pwm - PWM data (internal use): * + * @fan: private data; * @connected: indicates if PWM is connected; * @reg: register offset; + * @cooling: cooling device levels; + * @cdev: cooling device; */ struct mlxreg_fan_pwm { + struct mlxreg_fan *fan; bool connected; u32 reg; + u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1]; + struct thermal_cooling_device *cdev; }; /* @@ -99,8 +107,6 @@ struct mlxreg_fan_pwm { * @tachos_per_drwr - number of tachometers per drawer; * @samples: minimum allowed samples per pulse; * @divider: divider value for tachometer RPM calculation; - * @cooling: cooling device levels; - * @cdev: cooling device; */ struct mlxreg_fan { struct device *dev; @@ -111,8 +117,6 @@ struct mlxreg_fan { int tachos_per_drwr; int samples; int divider; - u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1]; - struct thermal_cooling_device *cdev; }; static int @@ -305,11 +309,12 @@ static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { - struct mlxreg_fan *fan = cdev->devdata; + struct mlxreg_fan_pwm *pwm = cdev->devdata; + struct mlxreg_fan *fan = pwm->fan; u32 regval; int err; - err = regmap_read(fan->regmap, fan->pwm[0].reg, ®val); + err = regmap_read(fan->regmap, pwm->reg, ®val); if (err) { dev_err(fan->dev, "Failed to query PWM duty\n"); return err; @@ -324,7 +329,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { - struct mlxreg_fan *fan = cdev->devdata; + struct mlxreg_fan_pwm *pwm = cdev->devdata; + struct mlxreg_fan *fan = pwm->fan; unsigned long cur_state; int i, config = 0; u32 regval; @@ -348,11 +354,11 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, config = 1; state -= MLXREG_FAN_MAX_STATE; for (i = 0; i < state; i++) - fan->cooling_levels[i] = state; + pwm->cooling_levels[i] = state; for (i = state; i <= MLXREG_FAN_MAX_STATE; i++) - fan->cooling_levels[i] = i; + pwm->cooling_levels[i] = i; - err = regmap_read(fan->regmap, fan->pwm[0].reg, ®val); + err = regmap_read(fan->regmap, pwm->reg, ®val); if (err) { dev_err(fan->dev, "Failed to query PWM duty\n"); return err; @@ -369,8 +375,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, return -EINVAL; /* Normalize the state to the valid speed range. */ - state = fan->cooling_levels[state]; - err = regmap_write(fan->regmap, fan->pwm[0].reg, + state = pwm->cooling_levels[state]; + err = regmap_write(fan->regmap, pwm->reg, MLXREG_FAN_PWM_STATE2DUTY(state)); if (err) { dev_err(fan->dev, "Failed to write PWM duty\n"); @@ -541,11 +547,32 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan, fan->tachos_per_drwr = tacho_avail / drwr_avail; } - /* Init cooling levels per PWM state. */ - for (i = 0; i < MLXREG_FAN_SPEED_MIN_LEVEL; i++) - fan->cooling_levels[i] = MLXREG_FAN_SPEED_MIN_LEVEL; - for (i = MLXREG_FAN_SPEED_MIN_LEVEL; i <= MLXREG_FAN_MAX_STATE; i++) - fan->cooling_levels[i] = i; + return 0; +} + +static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan) +{ + int i, j; + + for (i = 0; i <= MLXREG_FAN_MAX_PWM; i++) { + struct mlxreg_fan_pwm *pwm = &fan->pwm[i]; + + if (!pwm->connected) + continue; + pwm->fan = fan; + pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, "mlxreg_fan", pwm, + &mlxreg_fan_cooling_ops); + if (IS_ERR(pwm->cdev)) { + dev_err(dev, "Failed to register cooling device\n"); + return PTR_ERR(pwm->cdev); + } + + /* Init cooling levels per PWM state. */ + for (j = 0; j < MLXREG_FAN_SPEED_MIN_LEVEL; j++) + pwm->cooling_levels[j] = MLXREG_FAN_SPEED_MIN_LEVEL; + for (j = MLXREG_FAN_SPEED_MIN_LEVEL; j <= MLXREG_FAN_MAX_STATE; j++) + pwm->cooling_levels[j] = j; + } return 0; } @@ -584,16 +611,10 @@ static int mlxreg_fan_probe(struct platform_device *pdev) return PTR_ERR(hwm); } - if (IS_REACHABLE(CONFIG_THERMAL)) { - fan->cdev = devm_thermal_of_cooling_device_register(dev, - NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops); - if (IS_ERR(fan->cdev)) { - dev_err(dev, "Failed to register cooling device\n"); - return PTR_ERR(fan->cdev); - } - } + if (IS_REACHABLE(CONFIG_THERMAL)) + err = mlxreg_fan_cooling_config(dev, fan); - return 0; + return err; } static struct platform_driver mlxreg_fan_driver = { -- cgit v1.2.3 From 2e7b9886968b89f0b4cbc59b8e6ed47fd4edd0dd Mon Sep 17 00:00:00 2001 From: Denis Pauk <pauk.denis@gmail.com> Date: Sat, 18 Sep 2021 01:02:38 +0300 Subject: hwmon: (nct6775) Use superio_*() function pointers in sio_data. Prepare for platform specific callbacks usage: * Rearrange code for directly use struct nct6775_sio_data in superio_*() functions. * Use superio function pointers in nct6775_sio_data struct instead direct calls. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204807 Signed-off-by: Denis Pauk <pauk.denis@gmail.com> Co-developed-by: Bernhard Seibold <mail@bernhard-seibold.de> Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de> Cc: Andy Shevchenko <andriy.shevchenko@intel.com> Cc: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20210917220240.56553-2-pauk.denis@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6775.c | 189 ++++++++++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 85 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 5bd15622a85f..9b503c88e20d 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -133,30 +133,46 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; -static inline void -superio_outb(int ioreg, int reg, int val) +struct nct6775_sio_data { + int sioreg; + enum kinds kind; + + /* superio_() callbacks */ + void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val); + int (*sio_inb)(struct nct6775_sio_data *sio_data, int reg); + void (*sio_select)(struct nct6775_sio_data *sio_data, int ld); + int (*sio_enter)(struct nct6775_sio_data *sio_data); + void (*sio_exit)(struct nct6775_sio_data *sio_data); +}; + +static void superio_outb(struct nct6775_sio_data *sio_data, int reg, int val) { + int ioreg = sio_data->sioreg; + outb(reg, ioreg); outb(val, ioreg + 1); } -static inline int -superio_inb(int ioreg, int reg) +static int superio_inb(struct nct6775_sio_data *sio_data, int reg) { + int ioreg = sio_data->sioreg; + outb(reg, ioreg); return inb(ioreg + 1); } -static inline void -superio_select(int ioreg, int ld) +static void superio_select(struct nct6775_sio_data *sio_data, int ld) { + int ioreg = sio_data->sioreg; + outb(SIO_REG_LDSEL, ioreg); outb(ld, ioreg + 1); } -static inline int -superio_enter(int ioreg) +static int superio_enter(struct nct6775_sio_data *sio_data) { + int ioreg = sio_data->sioreg; + /* * Try to reserve <ioreg> and <ioreg + 1> for exclusive access. */ @@ -169,9 +185,10 @@ superio_enter(int ioreg) return 0; } -static inline void -superio_exit(int ioreg) +static void superio_exit(struct nct6775_sio_data *sio_data) { + int ioreg = sio_data->sioreg; + outb(0xaa, ioreg); outb(0x02, ioreg); outb(0x02, ioreg + 1); @@ -1217,11 +1234,6 @@ struct nct6775_data { u8 sio_reg_enable; }; -struct nct6775_sio_data { - int sioreg; - enum kinds kind; -}; - struct sensor_device_template { struct device_attribute dev_attr; union { @@ -3410,6 +3422,7 @@ clear_caseopen(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct nct6775_data *data = dev_get_drvdata(dev); + struct nct6775_sio_data *sio_data = dev_get_platdata(dev); int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE; unsigned long val; u8 reg; @@ -3425,19 +3438,19 @@ clear_caseopen(struct device *dev, struct device_attribute *attr, * The CR registers are the same for all chips, and not all chips * support clearing the caseopen status through "regular" registers. */ - ret = superio_enter(data->sioreg); + ret = sio_data->sio_enter(sio_data); if (ret) { count = ret; goto error; } - superio_select(data->sioreg, NCT6775_LD_ACPI); - reg = superio_inb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]); + sio_data->sio_select(sio_data, NCT6775_LD_ACPI); + reg = sio_data->sio_inb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr]); reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr]; - superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); + sio_data->sio_outb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr]; - superio_outb(data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); - superio_exit(data->sioreg); + sio_data->sio_outb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); + sio_data->sio_exit(sio_data); data->valid = false; /* Force cache refresh */ error: @@ -3542,29 +3555,28 @@ static inline void nct6775_init_device(struct nct6775_data *data) } static void -nct6775_check_fan_inputs(struct nct6775_data *data) +nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio_data) { bool fan3pin = false, fan4pin = false, fan4min = false; bool fan5pin = false, fan6pin = false, fan7pin = false; bool pwm3pin = false, pwm4pin = false, pwm5pin = false; bool pwm6pin = false, pwm7pin = false; - int sioreg = data->sioreg; /* Store SIO_REG_ENABLE for use during resume */ - superio_select(sioreg, NCT6775_LD_HWM); - data->sio_reg_enable = superio_inb(sioreg, SIO_REG_ENABLE); + sio_data->sio_select(sio_data, NCT6775_LD_HWM); + data->sio_reg_enable = sio_data->sio_inb(sio_data, SIO_REG_ENABLE); /* fan4 and fan5 share some pins with the GPIO and serial flash */ if (data->kind == nct6775) { - int cr2c = superio_inb(sioreg, 0x2c); + int cr2c = sio_data->sio_inb(sio_data, 0x2c); fan3pin = cr2c & BIT(6); pwm3pin = cr2c & BIT(7); /* On NCT6775, fan4 shares pins with the fdc interface */ - fan4pin = !(superio_inb(sioreg, 0x2A) & 0x80); + fan4pin = !(sio_data->sio_inb(sio_data, 0x2A) & 0x80); } else if (data->kind == nct6776) { - bool gpok = superio_inb(sioreg, 0x27) & 0x80; + bool gpok = sio_data->sio_inb(sio_data, 0x27) & 0x80; const char *board_vendor, *board_name; board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); @@ -3580,7 +3592,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data) if (!strcmp(board_name, "Z77 Pro4-M")) { if ((data->sio_reg_enable & 0xe0) != 0xe0) { data->sio_reg_enable |= 0xe0; - superio_outb(sioreg, SIO_REG_ENABLE, + sio_data->sio_outb(sio_data, SIO_REG_ENABLE, data->sio_reg_enable); } } @@ -3589,32 +3601,32 @@ nct6775_check_fan_inputs(struct nct6775_data *data) if (data->sio_reg_enable & 0x80) fan3pin = gpok; else - fan3pin = !(superio_inb(sioreg, 0x24) & 0x40); + fan3pin = !(sio_data->sio_inb(sio_data, 0x24) & 0x40); if (data->sio_reg_enable & 0x40) fan4pin = gpok; else - fan4pin = superio_inb(sioreg, 0x1C) & 0x01; + fan4pin = sio_data->sio_inb(sio_data, 0x1C) & 0x01; if (data->sio_reg_enable & 0x20) fan5pin = gpok; else - fan5pin = superio_inb(sioreg, 0x1C) & 0x02; + fan5pin = sio_data->sio_inb(sio_data, 0x1C) & 0x02; fan4min = fan4pin; pwm3pin = fan3pin; } else if (data->kind == nct6106) { - int cr24 = superio_inb(sioreg, 0x24); + int cr24 = sio_data->sio_inb(sio_data, 0x24); fan3pin = !(cr24 & 0x80); pwm3pin = cr24 & 0x08; } else if (data->kind == nct6116) { - int cr1a = superio_inb(sioreg, 0x1a); - int cr1b = superio_inb(sioreg, 0x1b); - int cr24 = superio_inb(sioreg, 0x24); - int cr2a = superio_inb(sioreg, 0x2a); - int cr2b = superio_inb(sioreg, 0x2b); - int cr2f = superio_inb(sioreg, 0x2f); + int cr1a = sio_data->sio_inb(sio_data, 0x1a); + int cr1b = sio_data->sio_inb(sio_data, 0x1b); + int cr24 = sio_data->sio_inb(sio_data, 0x24); + int cr2a = sio_data->sio_inb(sio_data, 0x2a); + int cr2b = sio_data->sio_inb(sio_data, 0x2b); + int cr2f = sio_data->sio_inb(sio_data, 0x2f); fan3pin = !(cr2b & 0x10); fan4pin = (cr2b & 0x80) || // pin 1(2) @@ -3630,24 +3642,24 @@ nct6775_check_fan_inputs(struct nct6775_data *data) * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D, * NCT6797D, NCT6798D */ - int cr1a = superio_inb(sioreg, 0x1a); - int cr1b = superio_inb(sioreg, 0x1b); - int cr1c = superio_inb(sioreg, 0x1c); - int cr1d = superio_inb(sioreg, 0x1d); - int cr2a = superio_inb(sioreg, 0x2a); - int cr2b = superio_inb(sioreg, 0x2b); - int cr2d = superio_inb(sioreg, 0x2d); - int cr2f = superio_inb(sioreg, 0x2f); + int cr1a = sio_data->sio_inb(sio_data, 0x1a); + int cr1b = sio_data->sio_inb(sio_data, 0x1b); + int cr1c = sio_data->sio_inb(sio_data, 0x1c); + int cr1d = sio_data->sio_inb(sio_data, 0x1d); + int cr2a = sio_data->sio_inb(sio_data, 0x2a); + int cr2b = sio_data->sio_inb(sio_data, 0x2b); + int cr2d = sio_data->sio_inb(sio_data, 0x2d); + int cr2f = sio_data->sio_inb(sio_data, 0x2f); bool dsw_en = cr2f & BIT(3); bool ddr4_en = cr2f & BIT(4); int cre0; int creb; int cred; - superio_select(sioreg, NCT6775_LD_12); - cre0 = superio_inb(sioreg, 0xe0); - creb = superio_inb(sioreg, 0xeb); - cred = superio_inb(sioreg, 0xed); + sio_data->sio_select(sio_data, NCT6775_LD_12); + cre0 = sio_data->sio_inb(sio_data, 0xe0); + creb = sio_data->sio_inb(sio_data, 0xeb); + cred = sio_data->sio_inb(sio_data, 0xed); fan3pin = !(cr1c & BIT(5)); fan4pin = !(cr1c & BIT(6)); @@ -4502,11 +4514,11 @@ static int nct6775_probe(struct platform_device *pdev) /* Initialize the chip */ nct6775_init_device(data); - err = superio_enter(sio_data->sioreg); + err = sio_data->sio_enter(sio_data); if (err) return err; - cr2a = superio_inb(sio_data->sioreg, 0x2a); + cr2a = sio_data->sio_inb(sio_data, 0x2a); switch (data->kind) { case nct6775: data->have_vid = (cr2a & 0x40); @@ -4532,17 +4544,17 @@ static int nct6775_probe(struct platform_device *pdev) * We can get the VID input values directly at logical device D 0xe3. */ if (data->have_vid) { - superio_select(sio_data->sioreg, NCT6775_LD_VID); - data->vid = superio_inb(sio_data->sioreg, 0xe3); + sio_data->sio_select(sio_data, NCT6775_LD_VID); + data->vid = sio_data->sio_inb(sio_data, 0xe3); data->vrm = vid_which_vrm(); } if (fan_debounce) { u8 tmp; - superio_select(sio_data->sioreg, NCT6775_LD_HWM); - tmp = superio_inb(sio_data->sioreg, - NCT6775_REG_CR_FAN_DEBOUNCE); + sio_data->sio_select(sio_data, NCT6775_LD_HWM); + tmp = sio_data->sio_inb(sio_data, + NCT6775_REG_CR_FAN_DEBOUNCE); switch (data->kind) { case nct6106: case nct6116: @@ -4565,15 +4577,15 @@ static int nct6775_probe(struct platform_device *pdev) tmp |= 0x7e; break; } - superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE, + sio_data->sio_outb(sio_data, NCT6775_REG_CR_FAN_DEBOUNCE, tmp); dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n", data->name); } - nct6775_check_fan_inputs(data); + nct6775_check_fan_inputs(data, sio_data); - superio_exit(sio_data->sioreg); + sio_data->sio_exit(sio_data); /* Read fan clock dividers immediately */ nct6775_init_fan_common(dev, data); @@ -4613,15 +4625,15 @@ static int nct6775_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(hwmon_dev); } -static void nct6791_enable_io_mapping(int sioaddr) +static void nct6791_enable_io_mapping(struct nct6775_sio_data *sio_data) { int val; - val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE); + val = sio_data->sio_inb(sio_data, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE); if (val & 0x10) { pr_info("Enabling hardware monitor logical device mappings.\n"); - superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE, - val & ~0x10); + sio_data->sio_outb(sio_data, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE, + val & ~0x10); } } @@ -4643,29 +4655,29 @@ static int __maybe_unused nct6775_suspend(struct device *dev) static int __maybe_unused nct6775_resume(struct device *dev) { struct nct6775_data *data = dev_get_drvdata(dev); - int sioreg = data->sioreg; + struct nct6775_sio_data *sio_data = dev_get_platdata(dev); int i, j, err = 0; u8 reg; mutex_lock(&data->update_lock); data->bank = 0xff; /* Force initial bank selection */ - err = superio_enter(sioreg); + err = sio_data->sio_enter(sio_data); if (err) goto abort; - superio_select(sioreg, NCT6775_LD_HWM); - reg = superio_inb(sioreg, SIO_REG_ENABLE); + sio_data->sio_select(sio_data, NCT6775_LD_HWM); + reg = sio_data->sio_inb(sio_data, SIO_REG_ENABLE); if (reg != data->sio_reg_enable) - superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable); + sio_data->sio_outb(sio_data, SIO_REG_ENABLE, data->sio_reg_enable); if (data->kind == nct6791 || data->kind == nct6792 || data->kind == nct6793 || data->kind == nct6795 || data->kind == nct6796 || data->kind == nct6797 || data->kind == nct6798) - nct6791_enable_io_mapping(sioreg); + nct6791_enable_io_mapping(sio_data); - superio_exit(sioreg); + sio_data->sio_exit(sio_data); /* Restore limits */ for (i = 0; i < data->in_num; i++) { @@ -4728,12 +4740,14 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) int err; int addr; - err = superio_enter(sioaddr); + sio_data->sioreg = sioaddr; + + err = sio_data->sio_enter(sio_data); if (err) return err; - val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | - superio_inb(sioaddr, SIO_REG_DEVID + 1); + val = (sio_data->sio_inb(sio_data, SIO_REG_DEVID) << 8) | + sio_data->sio_inb(sio_data, SIO_REG_DEVID + 1); if (force_id && val != 0xffff) val = force_id; @@ -4777,38 +4791,37 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) default: if (val != 0xffff) pr_debug("unsupported chip ID: 0x%04x\n", val); - superio_exit(sioaddr); + sio_data->sio_exit(sio_data); return -ENODEV; } /* We have a known chip, find the HWM I/O address */ - superio_select(sioaddr, NCT6775_LD_HWM); - val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) - | superio_inb(sioaddr, SIO_REG_ADDR + 1); + sio_data->sio_select(sio_data, NCT6775_LD_HWM); + val = (sio_data->sio_inb(sio_data, SIO_REG_ADDR) << 8) + | sio_data->sio_inb(sio_data, SIO_REG_ADDR + 1); addr = val & IOREGION_ALIGNMENT; if (addr == 0) { pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); - superio_exit(sioaddr); + sio_data->sio_exit(sio_data); return -ENODEV; } /* Activate logical device if needed */ - val = superio_inb(sioaddr, SIO_REG_ENABLE); + val = sio_data->sio_inb(sio_data, SIO_REG_ENABLE); if (!(val & 0x01)) { pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n"); - superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); + sio_data->sio_outb(sio_data, SIO_REG_ENABLE, val | 0x01); } if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || sio_data->kind == nct6793 || sio_data->kind == nct6795 || sio_data->kind == nct6796 || sio_data->kind == nct6797 || sio_data->kind == nct6798) - nct6791_enable_io_mapping(sioaddr); + nct6791_enable_io_mapping(sio_data); - superio_exit(sioaddr); + sio_data->sio_exit(sio_data); pr_info("Found %s or compatible chip at %#x:%#x\n", nct6775_sio_names[sio_data->kind], sioaddr, addr); - sio_data->sioreg = sioaddr; return addr; } @@ -4842,6 +4855,12 @@ static int __init sensors_nct6775_init(void) * nct6775 hardware monitor, and call probe() */ for (i = 0; i < ARRAY_SIZE(pdev); i++) { + sio_data.sio_outb = superio_outb; + sio_data.sio_inb = superio_inb; + sio_data.sio_select = superio_select; + sio_data.sio_enter = superio_enter; + sio_data.sio_exit = superio_exit; + address = nct6775_find(sioaddr[i], &sio_data); if (address <= 0) continue; -- cgit v1.2.3 From 4914036eb66bdffe4cf4150c7d055c18d389d398 Mon Sep 17 00:00:00 2001 From: Denis Pauk <pauk.denis@gmail.com> Date: Sat, 18 Sep 2021 01:02:39 +0300 Subject: hwmon: (nct6775) Use nct6775_*() function pointers in nct6775_data. Prepare for platform specific callbacks usage: * Use nct6775 function pointers in struct nct6775_data instead direct calls. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204807 Signed-off-by: Denis Pauk <pauk.denis@gmail.com> Co-developed-by: Bernhard Seibold <mail@bernhard-seibold.de> Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de> Cc: Andy Shevchenko <andriy.shevchenko@intel.com> Cc: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20210917220240.56553-3-pauk.denis@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6775.c | 283 ++++++++++++++++++++++++------------------------ 1 file changed, 143 insertions(+), 140 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 9b503c88e20d..4253eed7f5b0 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -1232,6 +1232,10 @@ struct nct6775_data { u8 fandiv1; u8 fandiv2; u8 sio_reg_enable; + + /* nct6775_*() callbacks */ + u16 (*read_value)(struct nct6775_data *data, u16 reg); + int (*write_value)(struct nct6775_data *data, u16 reg, u16 value); }; struct sensor_device_template { @@ -1471,7 +1475,7 @@ static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg) { u16 res; - res = nct6775_read_value(data, reg); + res = data->read_value(data, reg); if (!is_word_sized(data, reg)) res <<= 8; @@ -1482,7 +1486,7 @@ static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value) { if (!is_word_sized(data, reg)) value >>= 8; - return nct6775_write_value(data, reg, value); + return data->write_value(data, reg, value); } /* This function assumes that the caller holds data->update_lock */ @@ -1492,24 +1496,24 @@ static void nct6775_write_fan_div(struct nct6775_data *data, int nr) switch (nr) { case 0: - reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70) + reg = (data->read_value(data, NCT6775_REG_FANDIV1) & 0x70) | (data->fan_div[0] & 0x7); - nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); + data->write_value(data, NCT6775_REG_FANDIV1, reg); break; case 1: - reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7) + reg = (data->read_value(data, NCT6775_REG_FANDIV1) & 0x7) | ((data->fan_div[1] << 4) & 0x70); - nct6775_write_value(data, NCT6775_REG_FANDIV1, reg); + data->write_value(data, NCT6775_REG_FANDIV1, reg); break; case 2: - reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70) + reg = (data->read_value(data, NCT6775_REG_FANDIV2) & 0x70) | (data->fan_div[2] & 0x7); - nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); + data->write_value(data, NCT6775_REG_FANDIV2, reg); break; case 3: - reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7) + reg = (data->read_value(data, NCT6775_REG_FANDIV2) & 0x7) | ((data->fan_div[3] << 4) & 0x70); - nct6775_write_value(data, NCT6775_REG_FANDIV2, reg); + data->write_value(data, NCT6775_REG_FANDIV2, reg); break; } } @@ -1524,10 +1528,10 @@ static void nct6775_update_fan_div(struct nct6775_data *data) { u8 i; - i = nct6775_read_value(data, NCT6775_REG_FANDIV1); + i = data->read_value(data, NCT6775_REG_FANDIV1); data->fan_div[0] = i & 0x7; data->fan_div[1] = (i & 0x70) >> 4; - i = nct6775_read_value(data, NCT6775_REG_FANDIV2); + i = data->read_value(data, NCT6775_REG_FANDIV2); data->fan_div[2] = i & 0x7; if (data->has_fan & BIT(3)) data->fan_div[3] = (i & 0x70) >> 4; @@ -1575,11 +1579,11 @@ static void nct6775_init_fan_common(struct device *dev, */ for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { if (data->has_fan_min & BIT(i)) { - reg = nct6775_read_value(data, data->REG_FAN_MIN[i]); + reg = data->read_value(data, data->REG_FAN_MIN[i]); if (!reg) - nct6775_write_value(data, data->REG_FAN_MIN[i], - data->has_fan_div ? 0xff - : 0xff1f); + data->write_value(data, data->REG_FAN_MIN[i], + data->has_fan_div ? 0xff + : 0xff1f); } } } @@ -1623,8 +1627,8 @@ static void nct6775_select_fan_div(struct device *dev, } if (fan_min != data->fan_min[nr]) { data->fan_min[nr] = fan_min; - nct6775_write_value(data, data->REG_FAN_MIN[nr], - fan_min); + data->write_value(data, data->REG_FAN_MIN[nr], + fan_min); } } data->fan_div[nr] = fan_div; @@ -1644,16 +1648,15 @@ static void nct6775_update_pwm(struct device *dev) continue; duty_is_dc = data->REG_PWM_MODE[i] && - (nct6775_read_value(data, data->REG_PWM_MODE[i]) + (data->read_value(data, data->REG_PWM_MODE[i]) & data->PWM_MODE_MASK[i]); data->pwm_mode[i] = !duty_is_dc; - fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]); + fanmodecfg = data->read_value(data, data->REG_FAN_MODE[i]); for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) { if (data->REG_PWM[j] && data->REG_PWM[j][i]) { - data->pwm[j][i] - = nct6775_read_value(data, - data->REG_PWM[j][i]); + data->pwm[j][i] = data->read_value(data, + data->REG_PWM[j][i]); } } @@ -1668,17 +1671,17 @@ static void nct6775_update_pwm(struct device *dev) u8 t = fanmodecfg & 0x0f; if (data->REG_TOLERANCE_H) { - t |= (nct6775_read_value(data, + t |= (data->read_value(data, data->REG_TOLERANCE_H[i]) & 0x70) >> 1; } data->target_speed_tolerance[i] = t; } data->temp_tolerance[1][i] = - nct6775_read_value(data, - data->REG_CRITICAL_TEMP_TOLERANCE[i]); + data->read_value(data, + data->REG_CRITICAL_TEMP_TOLERANCE[i]); - reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]); + reg = data->read_value(data, data->REG_TEMP_SEL[i]); data->pwm_temp_sel[i] = reg & 0x1f; /* If fan can stop, report floor as 0 */ if (reg & 0x80) @@ -1687,7 +1690,7 @@ static void nct6775_update_pwm(struct device *dev) if (!data->REG_WEIGHT_TEMP_SEL[i]) continue; - reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]); + reg = data->read_value(data, data->REG_WEIGHT_TEMP_SEL[i]); data->pwm_weight_temp_sel[i] = reg & 0x1f; /* If weight is disabled, report weight source as 0 */ if (!(reg & 0x80)) @@ -1695,9 +1698,8 @@ static void nct6775_update_pwm(struct device *dev) /* Weight temp data */ for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) { - data->weight_temp[j][i] - = nct6775_read_value(data, - data->REG_WEIGHT_TEMP[j][i]); + data->weight_temp[j][i] = data->read_value(data, + data->REG_WEIGHT_TEMP[j][i]); } } } @@ -1715,10 +1717,10 @@ static void nct6775_update_pwm_limits(struct device *dev) for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) { data->fan_time[j][i] = - nct6775_read_value(data, data->REG_FAN_TIME[j][i]); + data->read_value(data, data->REG_FAN_TIME[j][i]); } - reg_t = nct6775_read_value(data, data->REG_TARGET[i]); + reg_t = data->read_value(data, data->REG_TARGET[i]); /* Update only in matching mode or if never updated */ if (!data->target_temp[i] || data->pwm_enable[i] == thermal_cruise) @@ -1726,7 +1728,7 @@ static void nct6775_update_pwm_limits(struct device *dev) if (!data->target_speed[i] || data->pwm_enable[i] == speed_cruise) { if (data->REG_TOLERANCE_H) { - reg_t |= (nct6775_read_value(data, + reg_t |= (data->read_value(data, data->REG_TOLERANCE_H[i]) & 0x0f) << 8; } data->target_speed[i] = reg_t; @@ -1734,21 +1736,21 @@ static void nct6775_update_pwm_limits(struct device *dev) for (j = 0; j < data->auto_pwm_num; j++) { data->auto_pwm[i][j] = - nct6775_read_value(data, - NCT6775_AUTO_PWM(data, i, j)); + data->read_value(data, + NCT6775_AUTO_PWM(data, i, j)); data->auto_temp[i][j] = - nct6775_read_value(data, - NCT6775_AUTO_TEMP(data, i, j)); + data->read_value(data, + NCT6775_AUTO_TEMP(data, i, j)); } /* critical auto_pwm temperature data */ data->auto_temp[i][data->auto_pwm_num] = - nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]); + data->read_value(data, data->REG_CRITICAL_TEMP[i]); switch (data->kind) { case nct6775: - reg = nct6775_read_value(data, - NCT6775_REG_CRITICAL_ENAB[i]); + reg = data->read_value(data, + NCT6775_REG_CRITICAL_ENAB[i]); data->auto_pwm[i][data->auto_pwm_num] = (reg & 0x02) ? 0xff : 0x00; break; @@ -1765,10 +1767,10 @@ static void nct6775_update_pwm_limits(struct device *dev) case nct6796: case nct6797: case nct6798: - reg = nct6775_read_value(data, + reg = data->read_value(data, data->REG_CRITICAL_PWM_ENABLE[i]); if (reg & data->CRITICAL_PWM_ENABLE_MASK) - reg = nct6775_read_value(data, + reg = data->read_value(data, data->REG_CRITICAL_PWM[i]); else reg = 0xff; @@ -1795,11 +1797,11 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) if (!(data->have_in & BIT(i))) continue; - data->in[i][0] = nct6775_read_value(data, - data->REG_VIN[i]); - data->in[i][1] = nct6775_read_value(data, + data->in[i][0] = data->read_value(data, + data->REG_VIN[i]); + data->in[i][1] = data->read_value(data, data->REG_IN_MINMAX[0][i]); - data->in[i][2] = nct6775_read_value(data, + data->in[i][2] = data->read_value(data, data->REG_IN_MINMAX[1][i]); } @@ -1810,18 +1812,18 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) if (!(data->has_fan & BIT(i))) continue; - reg = nct6775_read_value(data, data->REG_FAN[i]); + reg = data->read_value(data, data->REG_FAN[i]); data->rpm[i] = data->fan_from_reg(reg, data->fan_div[i]); if (data->has_fan_min & BIT(i)) - data->fan_min[i] = nct6775_read_value(data, + data->fan_min[i] = data->read_value(data, data->REG_FAN_MIN[i]); if (data->REG_FAN_PULSES[i]) { data->fan_pulses[i] = - (nct6775_read_value(data, - data->REG_FAN_PULSES[i]) + (data->read_value(data, + data->REG_FAN_PULSES[i]) >> data->FAN_PULSE_SHIFT[i]) & 0x03; } @@ -1837,15 +1839,14 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) continue; for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) { if (data->reg_temp[j][i]) - data->temp[j][i] - = nct6775_read_temp(data, - data->reg_temp[j][i]); + data->temp[j][i] = nct6775_read_temp(data, + data->reg_temp[j][i]); } if (i >= NUM_TEMP_FIXED || !(data->have_temp_fixed & BIT(i))) continue; - data->temp_offset[i] - = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]); + data->temp_offset[i] = data->read_value(data, + data->REG_TEMP_OFFSET[i]); } data->alarms = 0; @@ -1854,7 +1855,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) if (!data->REG_ALARM[i]) continue; - alarm = nct6775_read_value(data, data->REG_ALARM[i]); + alarm = data->read_value(data, data->REG_ALARM[i]); data->alarms |= ((u64)alarm) << (i << 3); } @@ -1864,7 +1865,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev) if (!data->REG_BEEP[i]) continue; - beep = nct6775_read_value(data, data->REG_BEEP[i]); + beep = data->read_value(data, data->REG_BEEP[i]); data->beeps |= ((u64)beep) << (i << 3); } @@ -1906,8 +1907,8 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf, return err; mutex_lock(&data->update_lock); data->in[nr][index] = in_to_reg(val, nr); - nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], - data->in[nr][index]); + data->write_value(data, data->REG_IN_MINMAX[index - 1][nr], + data->in[nr][index]); mutex_unlock(&data->update_lock); return count; } @@ -1931,8 +1932,8 @@ static int find_temp_source(struct nct6775_data *data, int index, int count) for (nr = 0; nr < count; nr++) { int src; - src = nct6775_read_value(data, - data->REG_TEMP_SOURCE[nr]) & 0x1f; + src = data->read_value(data, + data->REG_TEMP_SOURCE[nr]) & 0x1f; if (src == source) return nr; } @@ -1993,8 +1994,8 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf, data->beeps |= (1ULL << nr); else data->beeps &= ~(1ULL << nr); - nct6775_write_value(data, data->REG_BEEP[regindex], - (data->beeps >> (regindex << 3)) & 0xff); + data->write_value(data, data->REG_BEEP[regindex], + (data->beeps >> (regindex << 3)) & 0xff); mutex_unlock(&data->update_lock); return count; } @@ -2049,8 +2050,8 @@ store_temp_beep(struct device *dev, struct device_attribute *attr, data->beeps |= (1ULL << bit); else data->beeps &= ~(1ULL << bit); - nct6775_write_value(data, data->REG_BEEP[regindex], - (data->beeps >> (regindex << 3)) & 0xff); + data->write_value(data, data->REG_BEEP[regindex], + (data->beeps >> (regindex << 3)) & 0xff); mutex_unlock(&data->update_lock); return count; @@ -2217,7 +2218,7 @@ write_div: } write_min: - nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]); + data->write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -2253,10 +2254,10 @@ store_fan_pulses(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->fan_pulses[nr] = val & 3; - reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]); + reg = data->read_value(data, data->REG_FAN_PULSES[nr]); reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]); reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr]; - nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg); + data->write_value(data, data->REG_FAN_PULSES[nr], reg); mutex_unlock(&data->update_lock); return count; @@ -2390,7 +2391,7 @@ store_temp_offset(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->temp_offset[nr] = val; - nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val); + data->write_value(data, data->REG_TEMP_OFFSET[nr], val); mutex_unlock(&data->update_lock); return count; @@ -2429,8 +2430,8 @@ store_temp_type(struct device *dev, struct device_attribute *attr, data->temp_type[nr] = val; vbit = 0x02 << nr; dbit = data->DIODE_MASK << nr; - vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit; - diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit; + vbat = data->read_value(data, data->REG_VBAT) & ~vbit; + diode = data->read_value(data, data->REG_DIODE) & ~dbit; switch (val) { case 1: /* CPU diode (diode, current mode) */ vbat |= vbit; @@ -2442,8 +2443,8 @@ store_temp_type(struct device *dev, struct device_attribute *attr, case 4: /* thermistor */ break; } - nct6775_write_value(data, data->REG_VBAT, vbat); - nct6775_write_value(data, data->REG_DIODE, diode); + data->write_value(data, data->REG_VBAT, vbat); + data->write_value(data, data->REG_DIODE, diode); mutex_unlock(&data->update_lock); return count; @@ -2567,11 +2568,11 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->pwm_mode[nr] = val; - reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]); + reg = data->read_value(data, data->REG_PWM_MODE[nr]); reg &= ~data->PWM_MODE_MASK[nr]; if (!val) reg |= data->PWM_MODE_MASK[nr]; - nct6775_write_value(data, data->REG_PWM_MODE[nr], reg); + data->write_value(data, data->REG_PWM_MODE[nr], reg); mutex_unlock(&data->update_lock); return count; } @@ -2590,7 +2591,7 @@ show_pwm(struct device *dev, struct device_attribute *attr, char *buf) * Otherwise, show the configured value. */ if (index == 0 && data->pwm_enable[nr] > manual) - pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]); + pwm = data->read_value(data, data->REG_PWM_READ[nr]); else pwm = data->pwm[index][nr]; @@ -2619,13 +2620,13 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, mutex_lock(&data->update_lock); data->pwm[index][nr] = val; - nct6775_write_value(data, data->REG_PWM[index][nr], val); + data->write_value(data, data->REG_PWM[index][nr], val); if (index == 2) { /* floor: disable if val == 0 */ - reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); + reg = data->read_value(data, data->REG_TEMP_SEL[nr]); reg &= 0x7f; if (val) reg |= 0x80; - nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); + data->write_value(data, data->REG_TEMP_SEL[nr], reg); } mutex_unlock(&data->update_lock); return count; @@ -2664,29 +2665,29 @@ static void pwm_update_registers(struct nct6775_data *data, int nr) case manual: break; case speed_cruise: - reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); + reg = data->read_value(data, data->REG_FAN_MODE[nr]); reg = (reg & ~data->tolerance_mask) | (data->target_speed_tolerance[nr] & data->tolerance_mask); - nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); - nct6775_write_value(data, data->REG_TARGET[nr], + data->write_value(data, data->REG_FAN_MODE[nr], reg); + data->write_value(data, data->REG_TARGET[nr], data->target_speed[nr] & 0xff); if (data->REG_TOLERANCE_H) { reg = (data->target_speed[nr] >> 8) & 0x0f; reg |= (data->target_speed_tolerance[nr] & 0x38) << 1; - nct6775_write_value(data, - data->REG_TOLERANCE_H[nr], - reg); + data->write_value(data, + data->REG_TOLERANCE_H[nr], + reg); } break; case thermal_cruise: - nct6775_write_value(data, data->REG_TARGET[nr], - data->target_temp[nr]); + data->write_value(data, data->REG_TARGET[nr], + data->target_temp[nr]); fallthrough; default: - reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); + reg = data->read_value(data, data->REG_FAN_MODE[nr]); reg = (reg & ~data->tolerance_mask) | data->temp_tolerance[0][nr]; - nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); + data->write_value(data, data->REG_FAN_MODE[nr], reg); break; } } @@ -2734,13 +2735,13 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, * turn off pwm control: select manual mode, set pwm to maximum */ data->pwm[0][nr] = 255; - nct6775_write_value(data, data->REG_PWM[0][nr], 255); + data->write_value(data, data->REG_PWM[0][nr], 255); } pwm_update_registers(data, nr); - reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); + reg = data->read_value(data, data->REG_FAN_MODE[nr]); reg &= 0x0f; reg |= pwm_enable_to_reg(val) << 4; - nct6775_write_value(data, data->REG_FAN_MODE[nr], reg); + data->write_value(data, data->REG_FAN_MODE[nr], reg); mutex_unlock(&data->update_lock); return count; } @@ -2793,10 +2794,10 @@ store_pwm_temp_sel(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); src = data->temp_src[val - 1]; data->pwm_temp_sel[nr] = src; - reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]); + reg = data->read_value(data, data->REG_TEMP_SEL[nr]); reg &= 0xe0; reg |= src; - nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg); + data->write_value(data, data->REG_TEMP_SEL[nr], reg); mutex_unlock(&data->update_lock); return count; @@ -2838,15 +2839,15 @@ store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr, if (val) { src = data->temp_src[val - 1]; data->pwm_weight_temp_sel[nr] = src; - reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); + reg = data->read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); reg &= 0xe0; reg |= (src | 0x80); - nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); + data->write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); } else { data->pwm_weight_temp_sel[nr] = 0; - reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); + reg = data->read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]); reg &= 0x7f; - nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); + data->write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg); } mutex_unlock(&data->update_lock); @@ -2958,9 +2959,9 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr, if (index) pwm_update_registers(data, nr); else - nct6775_write_value(data, - data->REG_CRITICAL_TEMP_TOLERANCE[nr], - val); + data->write_value(data, + data->REG_CRITICAL_TEMP_TOLERANCE[nr], + val); mutex_unlock(&data->update_lock); return count; } @@ -3083,7 +3084,7 @@ store_weight_temp(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->weight_temp[index][nr] = val; - nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); + data->write_value(data, data->REG_WEIGHT_TEMP[index][nr], val); mutex_unlock(&data->update_lock); return count; } @@ -3132,7 +3133,7 @@ store_fan_time(struct device *dev, struct device_attribute *attr, val = step_time_to_reg(val, data->pwm_mode[nr]); mutex_lock(&data->update_lock); data->fan_time[index][nr] = val; - nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val); + data->write_value(data, data->REG_FAN_TIME[index][nr], val); mutex_unlock(&data->update_lock); return count; } @@ -3174,21 +3175,21 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->auto_pwm[nr][point] = val; if (point < data->auto_pwm_num) { - nct6775_write_value(data, + data->write_value(data, NCT6775_AUTO_PWM(data, nr, point), data->auto_pwm[nr][point]); } else { switch (data->kind) { case nct6775: /* disable if needed (pwm == 0) */ - reg = nct6775_read_value(data, - NCT6775_REG_CRITICAL_ENAB[nr]); + reg = data->read_value(data, + NCT6775_REG_CRITICAL_ENAB[nr]); if (val) reg |= 0x02; else reg &= ~0x02; - nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr], - reg); + data->write_value(data, NCT6775_REG_CRITICAL_ENAB[nr], + reg); break; case nct6776: break; /* always enabled, nothing to do */ @@ -3202,17 +3203,17 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr, case nct6796: case nct6797: case nct6798: - nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], + data->write_value(data, data->REG_CRITICAL_PWM[nr], val); - reg = nct6775_read_value(data, + reg = data->read_value(data, data->REG_CRITICAL_PWM_ENABLE[nr]); if (val == 255) reg &= ~data->CRITICAL_PWM_ENABLE_MASK; else reg |= data->CRITICAL_PWM_ENABLE_MASK; - nct6775_write_value(data, - data->REG_CRITICAL_PWM_ENABLE[nr], - reg); + data->write_value(data, + data->REG_CRITICAL_PWM_ENABLE[nr], + reg); break; } } @@ -3255,11 +3256,11 @@ store_auto_temp(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000); if (point < data->auto_pwm_num) { - nct6775_write_value(data, + data->write_value(data, NCT6775_AUTO_TEMP(data, nr, point), data->auto_temp[nr][point]); } else { - nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr], + data->write_value(data, data->REG_CRITICAL_TEMP[nr], data->auto_temp[nr][point]); } mutex_unlock(&data->update_lock); @@ -3519,9 +3520,9 @@ static inline void nct6775_init_device(struct nct6775_data *data) /* Start monitoring if needed */ if (data->REG_CONFIG) { - tmp = nct6775_read_value(data, data->REG_CONFIG); + tmp = data->read_value(data, data->REG_CONFIG); if (!(tmp & 0x01)) - nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01); + data->write_value(data, data->REG_CONFIG, tmp | 0x01); } /* Enable temperature sensors if needed */ @@ -3530,18 +3531,18 @@ static inline void nct6775_init_device(struct nct6775_data *data) continue; if (!data->reg_temp_config[i]) continue; - tmp = nct6775_read_value(data, data->reg_temp_config[i]); + tmp = data->read_value(data, data->reg_temp_config[i]); if (tmp & 0x01) - nct6775_write_value(data, data->reg_temp_config[i], + data->write_value(data, data->reg_temp_config[i], tmp & 0xfe); } /* Enable VBAT monitoring if needed */ - tmp = nct6775_read_value(data, data->REG_VBAT); + tmp = data->read_value(data, data->REG_VBAT); if (!(tmp & 0x01)) - nct6775_write_value(data, data->REG_VBAT, tmp | 0x01); + data->write_value(data, data->REG_VBAT, tmp | 0x01); - diode = nct6775_read_value(data, data->REG_DIODE); + diode = data->read_value(data, data->REG_DIODE); for (i = 0; i < data->temp_fixed_num; i++) { if (!(data->have_temp_fixed & BIT(i))) @@ -3786,7 +3787,7 @@ static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, if (!regp[i]) continue; - src = nct6775_read_value(data, regp[i]); + src = data->read_value(data, regp[i]); src &= 0x1f; if (!src || (*mask & BIT(src))) continue; @@ -3794,7 +3795,7 @@ static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, continue; index = __ffs(*available); - nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src); + data->write_value(data, data->REG_TEMP_SOURCE[index], src); *available &= ~BIT(index); *mask |= BIT(src); } @@ -3830,6 +3831,8 @@ static int nct6775_probe(struct platform_device *pdev) data->kind = sio_data->kind; data->sioreg = sio_data->sioreg; data->addr = res->start; + data->read_value = nct6775_read_value; + data->write_value = nct6775_write_value; mutex_init(&data->update_lock); data->name = nct6775_device_names[data->kind]; data->bank = 0xff; /* Force initial bank selection */ @@ -4349,7 +4352,7 @@ static int nct6775_probe(struct platform_device *pdev) if (reg_temp[i] == 0) continue; - src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; + src = data->read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; if (!src || (mask & BIT(src))) available |= BIT(i); @@ -4369,7 +4372,7 @@ static int nct6775_probe(struct platform_device *pdev) if (reg_temp[i] == 0) continue; - src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; + src = data->read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f; if (!src || (mask & BIT(src))) continue; @@ -4429,7 +4432,7 @@ static int nct6775_probe(struct platform_device *pdev) if (reg_temp_mon[i] == 0) continue; - src = nct6775_read_value(data, data->REG_TEMP_SEL[i]) & 0x1f; + src = data->read_value(data, data->REG_TEMP_SEL[i]) & 0x1f; if (!src) continue; @@ -4642,10 +4645,10 @@ static int __maybe_unused nct6775_suspend(struct device *dev) struct nct6775_data *data = nct6775_update_device(dev); mutex_lock(&data->update_lock); - data->vbat = nct6775_read_value(data, data->REG_VBAT); + data->vbat = data->read_value(data, data->REG_VBAT); if (data->kind == nct6775) { - data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1); - data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2); + data->fandiv1 = data->read_value(data, NCT6775_REG_FANDIV1); + data->fandiv2 = data->read_value(data, NCT6775_REG_FANDIV2); } mutex_unlock(&data->update_lock); @@ -4684,18 +4687,18 @@ static int __maybe_unused nct6775_resume(struct device *dev) if (!(data->have_in & BIT(i))) continue; - nct6775_write_value(data, data->REG_IN_MINMAX[0][i], - data->in[i][1]); - nct6775_write_value(data, data->REG_IN_MINMAX[1][i], - data->in[i][2]); + data->write_value(data, data->REG_IN_MINMAX[0][i], + data->in[i][1]); + data->write_value(data, data->REG_IN_MINMAX[1][i], + data->in[i][2]); } for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { if (!(data->has_fan_min & BIT(i))) continue; - nct6775_write_value(data, data->REG_FAN_MIN[i], - data->fan_min[i]); + data->write_value(data, data->REG_FAN_MIN[i], + data->fan_min[i]); } for (i = 0; i < NUM_TEMP; i++) { @@ -4709,10 +4712,10 @@ static int __maybe_unused nct6775_resume(struct device *dev) } /* Restore other settings */ - nct6775_write_value(data, data->REG_VBAT, data->vbat); + data->write_value(data, data->REG_VBAT, data->vbat); if (data->kind == nct6775) { - nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1); - nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); + data->write_value(data, NCT6775_REG_FANDIV1, data->fandiv1); + data->write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); } abort: -- cgit v1.2.3 From 3fbbfc27f95530fccbcfb3a742af0bce6c59f656 Mon Sep 17 00:00:00 2001 From: Denis Pauk <pauk.denis@gmail.com> Date: Sat, 18 Sep 2021 01:02:40 +0300 Subject: hwmon: (nct6775) Support access via Asus WMI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support accessing the NCT677x via Asus WMI functions. On mainboards that support this way of accessing the chip, the driver will usually not work without this option since in these mainboards, ACPI will mark the I/O port as used. Code uses ACPI firmware interface to communicate with sensors with ASUS motherboards: * PRIME B460-PLUS, * ROG CROSSHAIR VIII IMPACT, * ROG STRIX B550-E GAMING, * ROG STRIX B550-F GAMING, * ROG STRIX B550-F GAMING (WI-FI), * ROG STRIX Z490-I GAMING, * TUF GAMING B550M-PLUS, * TUF GAMING B550M-PLUS (WI-FI), * TUF GAMING B550-PLUS, * TUF GAMING X570-PLUS, * TUF GAMING X570-PRO (WI-FI). BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204807 Signed-off-by: Denis Pauk <pauk.denis@gmail.com> Co-developed-by: Bernhard Seibold <mail@bernhard-seibold.de> Signed-off-by: Bernhard Seibold <mail@bernhard-seibold.de> Tested-by: Pär Ekholm <pehlm@pekholm.org> Tested-by: <to.eivind@gmail.com> Tested-by: Artem S. Tashkinov <aros@gmx.com> Tested-by: Vittorio Roberto Alfieri <me@rebtoor.com> Tested-by: Sahan Fernando <sahan.h.fernando@gmail.com> Cc: Andy Shevchenko <andriy.shevchenko@intel.com> Cc: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20210917220240.56553-4-pauk.denis@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/Kconfig | 1 + drivers/hwmon/nct6775.c | 240 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 220 insertions(+), 21 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 91ec36aac059..7fde4c6e1e7f 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1443,6 +1443,7 @@ config SENSORS_NCT6683 config SENSORS_NCT6775 tristate "Nuvoton NCT6775F and compatibles" depends on !PPC + depends on ACPI_WMI || ACPI_WMI=n select HWMON_VID help If you say yes here you get support for the hardware monitoring diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 4253eed7f5b0..aa58ead0ad43 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -55,6 +55,7 @@ #include <linux/dmi.h> #include <linux/io.h> #include <linux/nospec.h> +#include <linux/wmi.h> #include "lm75.h" #define USE_ALTERNATE @@ -132,10 +133,13 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal"); #define SIO_ID_MASK 0xFFF8 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; +enum sensor_access { access_direct, access_asuswmi }; struct nct6775_sio_data { int sioreg; + int ld; enum kinds kind; + enum sensor_access access; /* superio_() callbacks */ void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val); @@ -145,6 +149,91 @@ struct nct6775_sio_data { void (*sio_exit)(struct nct6775_sio_data *sio_data); }; +#define ASUSWMI_MONITORING_GUID "466747A0-70EC-11DE-8A39-0800200C9A66" +#define ASUSWMI_METHODID_RSIO 0x5253494F +#define ASUSWMI_METHODID_WSIO 0x5753494F +#define ASUSWMI_METHODID_RHWM 0x5248574D +#define ASUSWMI_METHODID_WHWM 0x5748574D +#define ASUSWMI_UNSUPPORTED_METHOD 0xFFFFFFFE + +static int nct6775_asuswmi_evaluate_method(u32 method_id, u8 bank, u8 reg, u8 val, u32 *retval) +{ +#if IS_ENABLED(CONFIG_ACPI_WMI) + u32 args = bank | (reg << 8) | (val << 16); + struct acpi_buffer input = { (acpi_size) sizeof(args), &args }; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + union acpi_object *obj; + u32 tmp = ASUSWMI_UNSUPPORTED_METHOD; + + status = wmi_evaluate_method(ASUSWMI_MONITORING_GUID, 0, + method_id, &input, &output); + + if (ACPI_FAILURE(status)) + return -EIO; + + obj = output.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + tmp = obj->integer.value; + + if (retval) + *retval = tmp; + + kfree(obj); + + if (tmp == ASUSWMI_UNSUPPORTED_METHOD) + return -ENODEV; + return 0; +#else + return -EOPNOTSUPP; +#endif +} + +static inline int nct6775_asuswmi_write(u8 bank, u8 reg, u8 val) +{ + return nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_WHWM, bank, + reg, val, NULL); +} + +static inline int nct6775_asuswmi_read(u8 bank, u8 reg, u8 *val) +{ + u32 ret, tmp = 0; + + ret = nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_RHWM, bank, + reg, 0, &tmp); + *val = tmp; + return ret; +} + +static int superio_wmi_inb(struct nct6775_sio_data *sio_data, int reg) +{ + int tmp = 0; + + nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_RSIO, sio_data->ld, + reg, 0, &tmp); + return tmp; +} + +static void superio_wmi_outb(struct nct6775_sio_data *sio_data, int reg, int val) +{ + nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_WSIO, sio_data->ld, + reg, val, NULL); +} + +static void superio_wmi_select(struct nct6775_sio_data *sio_data, int ld) +{ + sio_data->ld = ld; +} + +static int superio_wmi_enter(struct nct6775_sio_data *sio_data) +{ + return 0; +} + +static void superio_wmi_exit(struct nct6775_sio_data *sio_data) +{ +} + static void superio_outb(struct nct6775_sio_data *sio_data, int reg, int val) { int ioreg = sio_data->sioreg; @@ -207,6 +296,7 @@ static void superio_exit(struct nct6775_sio_data *sio_data) #define NCT6775_REG_BANK 0x4E #define NCT6775_REG_CONFIG 0x40 +#define NCT6775_PORT_CHIPID 0x58 /* * Not currently used: @@ -1423,6 +1513,54 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg) return false; } +static inline void nct6775_wmi_set_bank(struct nct6775_data *data, u16 reg) +{ + u8 bank = reg >> 8; + + data->bank = bank; +} + +static u16 nct6775_wmi_read_value(struct nct6775_data *data, u16 reg) +{ + int res, err, word_sized = is_word_sized(data, reg); + u8 tmp = 0; + + nct6775_wmi_set_bank(data, reg); + + err = nct6775_asuswmi_read(data->bank, reg, &tmp); + if (err) + return 0; + + res = tmp; + if (word_sized) { + err = nct6775_asuswmi_read(data->bank, (reg & 0xff) + 1, &tmp); + if (err) + return 0; + + res = (res << 8) + tmp; + } + return res; +} + +static int nct6775_wmi_write_value(struct nct6775_data *data, u16 reg, u16 value) +{ + int res, word_sized = is_word_sized(data, reg); + + nct6775_wmi_set_bank(data, reg); + + if (word_sized) { + res = nct6775_asuswmi_write(data->bank, reg & 0xff, value >> 8); + if (res) + return res; + + res = nct6775_asuswmi_write(data->bank, (reg & 0xff) + 1, value); + } else { + res = nct6775_asuswmi_write(data->bank, reg & 0xff, value); + } + + return res; +} + /* * On older chips, only registers 0x50-0x5f are banked. * On more recent chips, all registers are banked. @@ -3818,10 +3956,12 @@ static int nct6775_probe(struct platform_device *pdev) struct device *hwmon_dev; int num_attr_groups = 0; - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, - DRVNAME)) - return -EBUSY; + if (sio_data->access == access_direct) { + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, + DRVNAME)) + return -EBUSY; + } data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data), GFP_KERNEL); @@ -3830,9 +3970,16 @@ static int nct6775_probe(struct platform_device *pdev) data->kind = sio_data->kind; data->sioreg = sio_data->sioreg; - data->addr = res->start; - data->read_value = nct6775_read_value; - data->write_value = nct6775_write_value; + + if (sio_data->access == access_direct) { + data->addr = res->start; + data->read_value = nct6775_read_value; + data->write_value = nct6775_write_value; + } else { + data->read_value = nct6775_wmi_read_value; + data->write_value = nct6775_wmi_write_value; + } + mutex_init(&data->update_lock); data->name = nct6775_device_names[data->kind]; data->bank = 0xff; /* Force initial bank selection */ @@ -4743,6 +4890,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) int err; int addr; + sio_data->access = access_direct; sio_data->sioreg = sioaddr; err = sio_data->sio_enter(sio_data); @@ -4837,6 +4985,23 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) */ static struct platform_device *pdev[2]; +static const char * const asus_wmi_boards[] = { + "PRIME B460-PLUS", + "ROG CROSSHAIR VIII DARK HERO", + "ROG CROSSHAIR VIII HERO", + "ROG CROSSHAIR VIII IMPACT", + "ROG STRIX B550-E GAMING", + "ROG STRIX B550-F GAMING", + "ROG STRIX B550-F GAMING (WI-FI)", + "ROG STRIX Z490-I GAMING", + "TUF GAMING B550M-PLUS", + "TUF GAMING B550M-PLUS (WI-FI)", + "TUF GAMING B550-PLUS", + "TUF GAMING X570-PLUS", + "TUF GAMING X570-PLUS (WI-FI)", + "TUF GAMING X570-PRO (WI-FI)", +}; + static int __init sensors_nct6775_init(void) { int i, err; @@ -4845,11 +5010,32 @@ static int __init sensors_nct6775_init(void) struct resource res; struct nct6775_sio_data sio_data; int sioaddr[2] = { 0x2e, 0x4e }; + enum sensor_access access = access_direct; + const char *board_vendor, *board_name; + u8 tmp; err = platform_driver_register(&nct6775_driver); if (err) return err; + board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); + board_name = dmi_get_system_info(DMI_BOARD_NAME); + + if (board_name && board_vendor && + !strcmp(board_vendor, "ASUSTeK COMPUTER INC.")) { + err = match_string(asus_wmi_boards, ARRAY_SIZE(asus_wmi_boards), + board_name); + if (err >= 0) { + /* if reading chip id via WMI succeeds, use WMI */ + if (!nct6775_asuswmi_read(0, NCT6775_PORT_CHIPID, &tmp)) { + pr_info("Using Asus WMI to access %#x chip.\n", tmp); + access = access_asuswmi; + } else { + pr_err("Can't read ChipID by Asus WMI.\n"); + } + } + } + /* * initialize sio_data->kind and sio_data->sioreg. * @@ -4870,6 +5056,16 @@ static int __init sensors_nct6775_init(void) found = true; + sio_data.access = access; + + if (access == access_asuswmi) { + sio_data.sio_outb = superio_wmi_outb; + sio_data.sio_inb = superio_wmi_inb; + sio_data.sio_select = superio_wmi_select; + sio_data.sio_enter = superio_wmi_enter; + sio_data.sio_exit = superio_wmi_exit; + } + pdev[i] = platform_device_alloc(DRVNAME, address); if (!pdev[i]) { err = -ENOMEM; @@ -4881,23 +5077,25 @@ static int __init sensors_nct6775_init(void) if (err) goto exit_device_put; - memset(&res, 0, sizeof(res)); - res.name = DRVNAME; - res.start = address + IOREGION_OFFSET; - res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; - res.flags = IORESOURCE_IO; + if (sio_data.access == access_direct) { + memset(&res, 0, sizeof(res)); + res.name = DRVNAME; + res.start = address + IOREGION_OFFSET; + res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; + res.flags = IORESOURCE_IO; + + err = acpi_check_resource_conflict(&res); + if (err) { + platform_device_put(pdev[i]); + pdev[i] = NULL; + continue; + } - err = acpi_check_resource_conflict(&res); - if (err) { - platform_device_put(pdev[i]); - pdev[i] = NULL; - continue; + err = platform_device_add_resources(pdev[i], &res, 1); + if (err) + goto exit_device_put; } - err = platform_device_add_resources(pdev[i], &res, 1); - if (err) - goto exit_device_put; - /* platform_device_add calls probe() */ err = platform_device_add(pdev[i]); if (err) -- cgit v1.2.3 From 000cc5bc49aafc83a131bab2becf9922f5eec658 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 20 Sep 2021 19:09:21 +0100 Subject: hwmon: (mlxreg-fan) Fix out of bounds read on array fan->pwm Array fan->pwm[] is MLXREG_FAN_MAX_PWM elements in size, however the for-loop has a off-by-one error causing index i to be out of range causing an out of bounds read on the array. Fix this by replacing the <= operator with < in the for-loop. Addresses-Coverity: ("Out-of-bounds read") Reported-by: Vadim Pasternak <vadimp@nvidia.com> Fixes: 35edbaab3bbf ("hwmon: (mlxreg-fan) Extend driver to support multiply cooling devices") Signed-off-by: Colin Ian King <colin.king@canonical.com> Link: https://lore.kernel.org/r/20210920180921.16246-1-colin.king@canonical.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index 35228ed112d7..feab9ec6a6ca 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -554,7 +554,7 @@ static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan) { int i, j; - for (i = 0; i <= MLXREG_FAN_MAX_PWM; i++) { + for (i = 0; i < MLXREG_FAN_MAX_PWM; i++) { struct mlxreg_fan_pwm *pwm = &fan->pwm[i]; if (!pwm->connected) -- cgit v1.2.3 From d55532f771372c60e01a67d1fa9789b71869eb27 Mon Sep 17 00:00:00 2001 From: Daniel Dawson <danielcdawson@gmail.com> Date: Tue, 21 Sep 2021 09:58:59 -0700 Subject: hwmon: (nct6683) Add another customer ID for NCT6683D sensor chip on some ASRock boards This value was found on a Z370M Pro4 rev. 1.01, with an NCT6683D-T chip. Signed-off-by: Daniel Dawson <danielcdawson@gmail.com> Link: https://lore.kernel.org/r/20210921165859.48714-1-danielcdawson@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6683.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c index 35f8635dc7f3..6a9f420e7d32 100644 --- a/drivers/hwmon/nct6683.c +++ b/drivers/hwmon/nct6683.c @@ -174,6 +174,7 @@ superio_exit(int ioreg) #define NCT6683_CUSTOMER_ID_MITAC 0xa0e #define NCT6683_CUSTOMER_ID_MSI 0x201 #define NCT6683_CUSTOMER_ID_ASROCK 0xe2c +#define NCT6683_CUSTOMER_ID_ASROCK2 0xe1b #define NCT6683_REG_BUILD_YEAR 0x604 #define NCT6683_REG_BUILD_MONTH 0x605 @@ -1221,6 +1222,8 @@ static int nct6683_probe(struct platform_device *pdev) break; case NCT6683_CUSTOMER_ID_ASROCK: break; + case NCT6683_CUSTOMER_ID_ASROCK2: + break; default: if (!force) return -ENODEV; -- cgit v1.2.3 From cae0233946c316884e4c40925c7d69b9221c02f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Fri, 24 Sep 2021 11:39:06 +0200 Subject: hwmon: (tmp421) introduce MAX_CHANNELS define There are few places where the maximal number of channels is used define the size of arrays but when raw number is used it is not clear that they really related to this quantity. This commit introduces MAX_CHANNELS define and uses it those places to give some context to the number. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/abc1a213a25b890b799b35ad94bb543a2ade7fc8.1632473318.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index b963a369c5ab..a4ac6e16d592 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -29,6 +29,7 @@ static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; +#define MAX_CHANNELS 4 /* The TMP421 registers */ #define TMP421_STATUS_REG 0x08 #define TMP421_CONFIG_REG_1 0x09 @@ -36,8 +37,8 @@ enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF -static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 }; -static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 }; +static const u8 TMP421_TEMP_MSB[MAX_CHANNELS] = { 0x00, 0x01, 0x02, 0x03 }; +static const u8 TMP421_TEMP_LSB[MAX_CHANNELS] = { 0x10, 0x11, 0x12, 0x13 }; /* Flags */ #define TMP421_CONFIG_SHUTDOWN 0x40 @@ -89,7 +90,7 @@ MODULE_DEVICE_TABLE(of, tmp421_of_match); struct tmp421_data { struct i2c_client *client; struct mutex update_lock; - u32 temp_config[5]; + u32 temp_config[MAX_CHANNELS + 1]; struct hwmon_channel_info temp_info; const struct hwmon_channel_info *info[2]; struct hwmon_chip_info chip; @@ -97,7 +98,7 @@ struct tmp421_data { unsigned long last_updated; unsigned long channels; u8 config; - s16 temp[4]; + s16 temp[MAX_CHANNELS]; }; static int temp_from_raw(u16 reg, bool extended) -- cgit v1.2.3 From ae59dc455a78fb73034dd1fbb337d7e59c27cbd8 Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:35 -0700 Subject: hwmon: (pmbus/lm25066) Add offset coefficients With the exception of the lm5066i, all the devices handled by this driver had been missing their offset ('b') coefficients for direct format readings. Cc: stable@vger.kernel.org Fixes: 58615a94f6a1 ("hwmon: (pmbus/lm25066) Add support for LM25056") Fixes: e53e6497fc9f ("hwmon: (pmbus/lm25066) Refactor device specific coefficients") Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-2-zev@bewilderbeest.net Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index d209e0afc2ca..1a660c4cd19f 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -55,22 +55,27 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { [lm25056] = { [PSC_VOLTAGE_IN] = { .m = 16296, + .b = 1343, .R = -2, }, [PSC_CURRENT_IN] = { .m = 13797, + .b = -1833, .R = -2, }, [PSC_CURRENT_IN_L] = { .m = 6726, + .b = -537, .R = -2, }, [PSC_POWER] = { .m = 5501, + .b = -2908, .R = -3, }, [PSC_POWER_L] = { .m = 26882, + .b = -5646, .R = -4, }, [PSC_TEMPERATURE] = { @@ -82,26 +87,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { [lm25066] = { [PSC_VOLTAGE_IN] = { .m = 22070, + .b = -1800, .R = -2, }, [PSC_VOLTAGE_OUT] = { .m = 22070, + .b = -1800, .R = -2, }, [PSC_CURRENT_IN] = { .m = 13661, + .b = -5200, .R = -2, }, [PSC_CURRENT_IN_L] = { .m = 6852, + .b = -3100, .R = -2, }, [PSC_POWER] = { .m = 736, + .b = -3300, .R = -2, }, [PSC_POWER_L] = { .m = 369, + .b = -1900, .R = -2, }, [PSC_TEMPERATURE] = { @@ -111,26 +122,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { [lm5064] = { [PSC_VOLTAGE_IN] = { .m = 4611, + .b = -642, .R = -2, }, [PSC_VOLTAGE_OUT] = { .m = 4621, + .b = 423, .R = -2, }, [PSC_CURRENT_IN] = { .m = 10742, + .b = 1552, .R = -2, }, [PSC_CURRENT_IN_L] = { .m = 5456, + .b = 2118, .R = -2, }, [PSC_POWER] = { .m = 1204, + .b = 8524, .R = -3, }, [PSC_POWER_L] = { .m = 612, + .b = 11202, .R = -3, }, [PSC_TEMPERATURE] = { @@ -140,26 +157,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { [lm5066] = { [PSC_VOLTAGE_IN] = { .m = 4587, + .b = -1200, .R = -2, }, [PSC_VOLTAGE_OUT] = { .m = 4587, + .b = -2400, .R = -2, }, [PSC_CURRENT_IN] = { .m = 10753, + .b = -1200, .R = -2, }, [PSC_CURRENT_IN_L] = { .m = 5405, + .b = -600, .R = -2, }, [PSC_POWER] = { .m = 1204, + .b = -6000, .R = -3, }, [PSC_POWER_L] = { .m = 605, + .b = -8000, .R = -3, }, [PSC_TEMPERATURE] = { -- cgit v1.2.3 From fa16188fa2053f23b1ed01cba5c43f4edc59005c Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:36 -0700 Subject: hwmon: (pmbus/lm25066) Adjust lm25066 PSC_CURRENT_IN_L mantissa At least as of Revision J, the datasheet has a slightly different value than what we'd had in the driver. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-3-zev@bewilderbeest.net Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 1a660c4cd19f..3616705aafde 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -101,7 +101,7 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { .R = -2, }, [PSC_CURRENT_IN_L] = { - .m = 6852, + .m = 6854, .b = -3100, .R = -2, }, -- cgit v1.2.3 From 6d2ff184cbe727db3b104e41d38fe77546735fcd Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:37 -0700 Subject: hwmon: (pmbus/lm25066) Avoid forward declaration of lm25066_id Reordering things to put the table before the probe function eliminates the need for it. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-4-zev@bewilderbeest.net Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 3616705aafde..4dc003ff859e 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -234,8 +234,6 @@ struct lm25066_data { #define to_lm25066_data(x) container_of(x, struct lm25066_data, info) -static const struct i2c_device_id lm25066_id[]; - static int lm25066_read_word_data(struct i2c_client *client, int page, int phase, int reg) { @@ -436,6 +434,16 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, return ret; } +static const struct i2c_device_id lm25066_id[] = { + {"lm25056", lm25056}, + {"lm25066", lm25066}, + {"lm5064", lm5064}, + {"lm5066", lm5066}, + {"lm5066i", lm5066i}, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm25066_id); + static int lm25066_probe(struct i2c_client *client) { int config; @@ -509,17 +517,6 @@ static int lm25066_probe(struct i2c_client *client) return pmbus_do_probe(client, info); } -static const struct i2c_device_id lm25066_id[] = { - {"lm25056", lm25056}, - {"lm25066", lm25066}, - {"lm5064", lm5064}, - {"lm5066", lm5066}, - {"lm5066i", lm5066i}, - { } -}; - -MODULE_DEVICE_TABLE(i2c, lm25066_id); - /* This is the driver that will be inserted */ static struct i2c_driver lm25066_driver = { .driver = { -- cgit v1.2.3 From b7931a7b0e0df4d2a25fedd895ad32c746b77bc1 Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:38 -0700 Subject: hwmon: (pmbus/lm25066) Let compiler determine outer dimension of lm25066_coeff Maintaining this manually is error prone (there are currently only five chips supported, not six); gcc can do it for us automatically. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Fixes: 666c14906b49 ("hwmon: (pmbus/lm25066) Drop support for LM25063") Link: https://lore.kernel.org/r/20210928092242.30036-5-zev@bewilderbeest.net Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 4dc003ff859e..1ff5407b6977 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -51,7 +51,7 @@ struct __coeff { #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) #define PSC_POWER_L (PSC_NUM_CLASSES + 1) -static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = { +static struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = { [lm25056] = { [PSC_VOLTAGE_IN] = { .m = 16296, -- cgit v1.2.3 From df60a5daa7fb15f2602a6195e6c08d77a8ce1cdb Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:39 -0700 Subject: hwmon: (pmbus/lm25066) Mark lm25066_coeff array const lm25066_coeff is read-only. Mark it as such. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-6-zev@bewilderbeest.net [groeck: Added description] Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 1ff5407b6977..dbbf8571c437 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -51,7 +51,7 @@ struct __coeff { #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) #define PSC_POWER_L (PSC_NUM_CLASSES + 1) -static struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = { +static const struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = { [lm25056] = { [PSC_VOLTAGE_IN] = { .m = 16296, @@ -449,7 +449,7 @@ static int lm25066_probe(struct i2c_client *client) int config; struct lm25066_data *data; struct pmbus_driver_info *info; - struct __coeff *coeff; + const struct __coeff *coeff; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) -- cgit v1.2.3 From b7792f3ea3924a3534e392c1d9125fdc93a60d70 Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:40 -0700 Subject: hwmon: (pmbus/lm25066) Add OF device ID table The driver doesn't have a struct of_device_id table but supported devices are registered via Device Trees. This is working on the assumption that a I2C device registered via OF will always match a legacy I2C device ID and that the MODALIAS reported will always be of the form i2c:<device>. But this could change in the future so the correct approach is to have an OF device ID table if the devices are registered via OF. Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-7-zev@bewilderbeest.net [groeck: Replaced reference to reasoning with reasoning, fixed checkpatch warnings, fixed compile warning comparing of_id->data w/ i2c_id->driver_data] Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/lm25066.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index dbbf8571c437..7dc5ffeab77d 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -14,6 +14,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/log2.h> +#include <linux/of_device.h> #include "pmbus.h" enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i }; @@ -444,12 +445,24 @@ static const struct i2c_device_id lm25066_id[] = { }; MODULE_DEVICE_TABLE(i2c, lm25066_id); +static const struct of_device_id __maybe_unused lm25066_of_match[] = { + { .compatible = "ti,lm25056", .data = (void *)lm25056, }, + { .compatible = "ti,lm25066", .data = (void *)lm25066, }, + { .compatible = "ti,lm5064", .data = (void *)lm5064, }, + { .compatible = "ti,lm5066", .data = (void *)lm5066, }, + { .compatible = "ti,lm5066i", .data = (void *)lm5066i, }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm25066_of_match); + static int lm25066_probe(struct i2c_client *client) { int config; struct lm25066_data *data; struct pmbus_driver_info *info; const struct __coeff *coeff; + const struct of_device_id *of_id; + const struct i2c_device_id *i2c_id; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) @@ -464,7 +477,14 @@ static int lm25066_probe(struct i2c_client *client) if (config < 0) return config; - data->id = i2c_match_id(lm25066_id, client)->driver_data; + i2c_id = i2c_match_id(lm25066_id, client); + + of_id = of_match_device(lm25066_of_match, &client->dev); + if (of_id && (unsigned long)of_id->data != i2c_id->driver_data) + dev_notice(&client->dev, "Device mismatch: %s in device tree, %s detected\n", + of_id->name, i2c_id->name); + + data->id = i2c_id->driver_data; info = &data->info; info->pages = 1; @@ -521,7 +541,8 @@ static int lm25066_probe(struct i2c_client *client) static struct i2c_driver lm25066_driver = { .driver = { .name = "lm25066", - }, + .of_match_table = of_match_ptr(lm25066_of_match), + }, .probe_new = lm25066_probe, .id_table = lm25066_id, }; -- cgit v1.2.3 From 94ee5fcc240fe9ffdd1c3206a48d5bdf425ea478 Mon Sep 17 00:00:00 2001 From: Zev Weiss <zev@bewilderbeest.net> Date: Tue, 28 Sep 2021 02:22:41 -0700 Subject: hwmon: (pmbus/lm25066) Support configurable sense resistor values The appropriate mantissa values for the lm25066 family's direct-format current and power readings are a function of the sense resistor employed between the SENSE and VIN pins of the chip. Instead of assuming that resistance is always the same 1mOhm as used in the datasheet, allow it to be configured via a device-tree property ("shunt-resistor-micro-ohms"). Signed-off-by: Zev Weiss <zev@bewilderbeest.net> Link: https://lore.kernel.org/r/20210928092242.30036-8-zev@bewilderbeest.net [groeck: Fixed checkpatch warnings] Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/lm25066.rst | 2 ++ drivers/hwmon/pmbus/lm25066.c | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/lm25066.rst b/Documentation/hwmon/lm25066.rst index 9f1d7e4d3ca1..a2098eb24090 100644 --- a/Documentation/hwmon/lm25066.rst +++ b/Documentation/hwmon/lm25066.rst @@ -79,6 +79,8 @@ This driver does not auto-detect devices. You will have to instantiate the devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for details. +The shunt (sense) resistor value can be configured by a device tree property; +see Documentation/devicetree/bindings/hwmon/pmbus/ti,lm25066.yaml for details. Platform data support --------------------- diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 7dc5ffeab77d..8402b41520eb 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c @@ -458,6 +458,7 @@ MODULE_DEVICE_TABLE(of, lm25066_of_match); static int lm25066_probe(struct i2c_client *client) { int config; + u32 shunt; struct lm25066_data *data; struct pmbus_driver_info *info; const struct __coeff *coeff; @@ -534,6 +535,16 @@ static int lm25066_probe(struct i2c_client *client) info->b[PSC_POWER] = coeff[PSC_POWER].b; } + /* + * Values in the TI datasheets are normalized for a 1mOhm sense + * resistor; assume that unless DT specifies a value explicitly. + */ + if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt)) + shunt = 1000; + + info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000; + info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000; + return pmbus_do_probe(client, info); } -- cgit v1.2.3 From 6e2baac88cddbb440095c45058bc666df3108a1f Mon Sep 17 00:00:00 2001 From: Denis Pauk <pauk.denis@gmail.com> Date: Sun, 3 Oct 2021 00:08:54 +0300 Subject: hwmon: (nct6775) Add additional ASUS motherboards. Add support: * PRIME B360-PLUS * PRIME X570-PRO * ROG CROSSHAIR VIII FORMULA * ROG STRIX B550-I GAMING * ROG STRIX X570-F GAMING * ROG STRIX Z390-E GAMING * TUF GAMING B550-PRO * TUF GAMING Z490-PLUS * TUF GAMING Z490-PLUS (WI-FI) BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204807 Signed-off-by: Denis Pauk <pauk.denis@gmail.com> Tested-by: matt-testalltheway <sefoci9222@rerunway.com> Tested-by: Kamil Dudka <kdudka@redhat.com> Tested-by: Robert Swiecki <robert@swiecki.net> Tested-by: Kamil Pietrzak <kpietrzak@disroot.org> Tested-by: Igor <igor@svelig.com> Tested-by: Tor Vic <torvic9@mailbox.org> Tested-by: Poezevara <nephartyz@gmail.com> Cc: Andy Shevchenko <andriy.shevchenko@intel.com> Cc: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Link: https://lore.kernel.org/r/20211002210857.709956-2-pauk.denis@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6775.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index aa58ead0ad43..8eaf86ea2433 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -4986,20 +4986,29 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) static struct platform_device *pdev[2]; static const char * const asus_wmi_boards[] = { + "PRIME B360-PLUS", "PRIME B460-PLUS", + "PRIME X570-PRO", "ROG CROSSHAIR VIII DARK HERO", + "ROG CROSSHAIR VIII FORMULA", "ROG CROSSHAIR VIII HERO", "ROG CROSSHAIR VIII IMPACT", "ROG STRIX B550-E GAMING", "ROG STRIX B550-F GAMING", "ROG STRIX B550-F GAMING (WI-FI)", + "ROG STRIX B550-I GAMING", + "ROG STRIX X570-F GAMING", + "ROG STRIX Z390-E GAMING", "ROG STRIX Z490-I GAMING", "TUF GAMING B550M-PLUS", "TUF GAMING B550M-PLUS (WI-FI)", "TUF GAMING B550-PLUS", + "TUF GAMING B550-PRO", "TUF GAMING X570-PLUS", "TUF GAMING X570-PLUS (WI-FI)", "TUF GAMING X570-PRO (WI-FI)", + "TUF GAMING Z490-PLUS", + "TUF GAMING Z490-PLUS (WI-FI)", }; static int __init sensors_nct6775_init(void) -- cgit v1.2.3 From a111ec399c60a860209205a9e303b4d4a9274968 Mon Sep 17 00:00:00 2001 From: Brandon Wyman <bjwyman@gmail.com> Date: Mon, 4 Oct 2021 14:43:38 +0000 Subject: hwmon: (pmbus/ibm-cffps) Add mfg_id debugfs entry Add support for the manufacturer ID to the debugfs entries. Signed-off-by: Brandon Wyman <bjwyman@gmail.com> Link: https://lore.kernel.org/r/20211004144339.2634330-1-bjwyman@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/ibm-cffps.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c index 53f7d1418bc9..226a60aea298 100644 --- a/drivers/hwmon/pmbus/ibm-cffps.c +++ b/drivers/hwmon/pmbus/ibm-cffps.c @@ -18,6 +18,7 @@ #include "pmbus.h" +#define CFFPS_MFG_ID_CMD 0x99 #define CFFPS_FRU_CMD 0x9A #define CFFPS_PN_CMD 0x9B #define CFFPS_HEADER_CMD 0x9C @@ -34,7 +35,7 @@ #define CFFPS_INPUT_HISTORY_SIZE 100 #define CFFPS_CCIN_REVISION GENMASK(7, 0) -#define CFFPS_CCIN_REVISION_LEGACY 0xde +#define CFFPS_CCIN_REVISION_LEGACY 0xde #define CFFPS_CCIN_VERSION GENMASK(15, 8) #define CFFPS_CCIN_VERSION_1 0x2b #define CFFPS_CCIN_VERSION_2 0x2e @@ -57,6 +58,7 @@ enum { CFFPS_DEBUGFS_INPUT_HISTORY = 0, + CFFPS_DEBUGFS_MFG_ID, CFFPS_DEBUGFS_FRU, CFFPS_DEBUGFS_PN, CFFPS_DEBUGFS_HEADER, @@ -158,6 +160,9 @@ static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf, switch (idx) { case CFFPS_DEBUGFS_INPUT_HISTORY: return ibm_cffps_read_input_history(psu, buf, count, ppos); + case CFFPS_DEBUGFS_MFG_ID: + cmd = CFFPS_MFG_ID_CMD; + break; case CFFPS_DEBUGFS_FRU: cmd = CFFPS_FRU_CMD; break; @@ -564,6 +569,9 @@ static int ibm_cffps_probe(struct i2c_client *client) debugfs_create_file("input_history", 0444, ibm_cffps_dir, &psu->debugfs_entries[CFFPS_DEBUGFS_INPUT_HISTORY], &ibm_cffps_fops); + debugfs_create_file("mfg_id", 0444, ibm_cffps_dir, + &psu->debugfs_entries[CFFPS_DEBUGFS_MFG_ID], + &ibm_cffps_fops); debugfs_create_file("fru", 0444, ibm_cffps_dir, &psu->debugfs_entries[CFFPS_DEBUGFS_FRU], &ibm_cffps_fops); -- cgit v1.2.3 From 8a5cfcfa9445987719b1f82b7bcabe5eb27187cf Mon Sep 17 00:00:00 2001 From: Brandon Wyman <bjwyman@gmail.com> Date: Mon, 4 Oct 2021 14:43:39 +0000 Subject: hwmon: (pmbus/ibm-cffps) Use MFR_ID to choose version There are multiple power supplies that will indicate CFFPS_CCIN_VERSION_1, use the manufacturer ID to determine if it should be treated as version cffps1 or version cffps2. Signed-off-by: Brandon Wyman <bjwyman@gmail.com> Link: https://lore.kernel.org/r/20211004144339.2634330-2-bjwyman@gmail.com [groeck: Fixed continuation line alignment] Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/pmbus/ibm-cffps.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c index 226a60aea298..e3294a1a54bb 100644 --- a/drivers/hwmon/pmbus/ibm-cffps.c +++ b/drivers/hwmon/pmbus/ibm-cffps.c @@ -508,16 +508,27 @@ static int ibm_cffps_probe(struct i2c_client *client) u16 ccin_revision = 0; u16 ccin_version = CFFPS_CCIN_VERSION_1; int ccin = i2c_smbus_read_word_swapped(client, CFFPS_CCIN_CMD); + char mfg_id[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; if (ccin > 0) { ccin_revision = FIELD_GET(CFFPS_CCIN_REVISION, ccin); ccin_version = FIELD_GET(CFFPS_CCIN_VERSION, ccin); } + rc = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, mfg_id); + if (rc < 0) { + dev_err(&client->dev, "Failed to read Manufacturer ID\n"); + return rc; + } + switch (ccin_version) { default: case CFFPS_CCIN_VERSION_1: - vs = cffps1; + if ((strncmp(mfg_id, "ACBE", 4) == 0) || + (strncmp(mfg_id, "ARTE", 4) == 0)) + vs = cffps1; + else + vs = cffps2; break; case CFFPS_CCIN_VERSION_2: vs = cffps2; -- cgit v1.2.3 From 1508fb29157e85ce7b4de3743fdf196a4ecfab2f Mon Sep 17 00:00:00 2001 From: Oleksandr Natalenko <oleksandr@natalenko.name> Date: Sun, 3 Oct 2021 15:33:42 +0200 Subject: hwmon: (nct6775) add Pro WS X570-ACE ASUS Pro WS X570-ACE board has got an nct6775 chip, but by default there's no use of it because of resource conflict: ``` ACPI Warning: SystemIO range 0x0000000000000295-0x0000000000000296 conflicts with OpRegion 0x0000000000000290-0x0000000000000299 (\AMW0.SHWM) (20210604/utaddress-204 ) ACPI: OSL: Resource conflict; ACPI support missing from driver? ACPI: OSL: Resource conflict: System may be unstable or behave erratically ``` A workaround is to use `acpi_enforce_resources=lax`, but a proper support needs to be added instead. This commit adds Pro WS X570-ACE to the list of boards that can be monitored using ASUS WMI. Tested by me on this hardware: ``` Base Board Information Manufacturer: ASUSTeK COMPUTER INC. Product Name: Pro WS X570-ACE BIOS Information Vendor: American Megatrends Inc. Version: 3801 Release Date: 07/30/2021 ``` Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name> Link: https://lore.kernel.org/r/20211003133344.9036-2-oleksandr@natalenko.name Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6775.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 8eaf86ea2433..f345e1902ad9 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -4986,6 +4986,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) static struct platform_device *pdev[2]; static const char * const asus_wmi_boards[] = { + "Pro WS X570-ACE", "PRIME B360-PLUS", "PRIME B460-PLUS", "PRIME X570-PRO", -- cgit v1.2.3 From b1c24237341f6fb910c6cb15489222a9f47258d6 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak <vadimp@nvidia.com> Date: Sun, 26 Sep 2021 08:35:40 +0300 Subject: hwmon: (mlxreg-fan) Modify PWM connectivity validation Validate PWM connectivity only for additional PWM - "pwm1" is connected on all systems, while "pwm2" - "pwm4" are optional. Validate connectivity only for optional attributes by reading of related "pwm{n}" registers - in case "pwm{n}" is not connected, register value is supposed to be 0xff. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Link: https://lore.kernel.org/r/20210926053541.1806937-2-vadimp@nvidia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index feab9ec6a6ca..8e5cd6991929 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -488,9 +488,14 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan, return -EINVAL; } - err = mlxreg_pwm_connect_verify(fan, data); - if (err) - return err; + /* Validate if more then one PWM is connected. */ + if (pwm_num) { + err = mlxreg_pwm_connect_verify(fan, data); + if (err < 0) + return err; + else if (!err) + continue; + } fan->pwm[pwm_num].reg = data->reg; fan->pwm[pwm_num].connected = true; -- cgit v1.2.3 From b2be2422c0c98b00f21c4331e2d9342bd58bfdba Mon Sep 17 00:00:00 2001 From: Vadim Pasternak <vadimp@nvidia.com> Date: Sun, 26 Sep 2021 08:35:41 +0300 Subject: hwmon: (mlxreg-fan) Support distinctive names per different cooling devices Provide different names for cooling devices registration to allow binding each cooling devices to relevant thermal zone. Thus, specific cooling device can be associated with related thermal sensor by setting thermal cooling device type for example to "mlxreg_fan2" and passing this type to thermal_zone_bind_cooling_device() through 'cdev->type'. Signed-off-by: Vadim Pasternak <vadimp@nvidia.com> Link: https://lore.kernel.org/r/20210926053541.1806937-3-vadimp@nvidia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/mlxreg-fan.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index 8e5cd6991929..4a8becdb0d58 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -263,6 +263,13 @@ mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, return 0; } +static char *mlxreg_fan_name[] = { + "mlxreg_fan", + "mlxreg_fan1", + "mlxreg_fan2", + "mlxreg_fan3", +}; + static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_FAULT, @@ -565,8 +572,8 @@ static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan) if (!pwm->connected) continue; pwm->fan = fan; - pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, "mlxreg_fan", pwm, - &mlxreg_fan_cooling_ops); + pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, mlxreg_fan_name[i], + pwm, &mlxreg_fan_cooling_ops); if (IS_ERR(pwm->cdev)) { dev_err(dev, "Failed to register cooling device\n"); return PTR_ERR(pwm->cdev); -- cgit v1.2.3 From b87783e855599efb93c8ce3d597bdcba8223f3b0 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel <o.rempel@pengutronix.de> Date: Thu, 7 Oct 2021 14:53:01 +0200 Subject: hwmon: (tmp103) Convert tmp103 to use new hwmon registration API Use devm_hwmon_device_register_with_info() which will make thermal framework work. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Link: https://lore.kernel.org/r/20211007125301.3030-1-o.rempel@pengutronix.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp103.c | 105 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 31 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index a7e202cc8323..5cab4436aa77 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -51,51 +51,92 @@ static inline u8 tmp103_mc_to_reg(int val) return DIV_ROUND_CLOSEST(val, 1000); } -static ssize_t tmp103_temp_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int tmp103_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *temp) { - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct regmap *regmap = dev_get_drvdata(dev); unsigned int regval; - int ret; + int err, reg; + + switch (attr) { + case hwmon_temp_input: + reg = TMP103_TEMP_REG; + break; + case hwmon_temp_min: + reg = TMP103_TLOW_REG; + break; + case hwmon_temp_max: + reg = TMP103_THIGH_REG; + break; + default: + return -EOPNOTSUPP; + } - ret = regmap_read(regmap, sda->index, ®val); - if (ret < 0) - return ret; + err = regmap_read(regmap, reg, ®val); + if (err < 0) + return err; + + *temp = tmp103_reg_to_mc(regval); - return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval)); + return 0; } -static ssize_t tmp103_temp_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int tmp103_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long temp) { - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct regmap *regmap = dev_get_drvdata(dev); - long val; - int ret; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; + int reg; + + switch (attr) { + case hwmon_temp_min: + reg = TMP103_TLOW_REG; + break; + case hwmon_temp_max: + reg = TMP103_THIGH_REG; + break; + default: + return -EOPNOTSUPP; + } - val = clamp_val(val, -55000, 127000); - ret = regmap_write(regmap, sda->index, tmp103_mc_to_reg(val)); - return ret ? ret : count; + temp = clamp_val(temp, -55000, 127000); + return regmap_write(regmap, reg, tmp103_mc_to_reg(temp)); } -static SENSOR_DEVICE_ATTR_RO(temp1_input, tmp103_temp, TMP103_TEMP_REG); +static umode_t tmp103_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + return 0444; + case hwmon_temp_min: + case hwmon_temp_max: + return 0644; + default: + return 0; + } +} -static SENSOR_DEVICE_ATTR_RW(temp1_min, tmp103_temp, TMP103_TLOW_REG); +static const struct hwmon_channel_info *tmp103_info[] = { + HWMON_CHANNEL_INFO(chip, + HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN), + NULL +}; -static SENSOR_DEVICE_ATTR_RW(temp1_max, tmp103_temp, TMP103_THIGH_REG); +static const struct hwmon_ops tmp103_hwmon_ops = { + .is_visible = tmp103_is_visible, + .read = tmp103_read, + .write = tmp103_write, +}; -static struct attribute *tmp103_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - NULL +static const struct hwmon_chip_info tmp103_chip_info = { + .ops = &tmp103_hwmon_ops, + .info = tmp103_info, }; -ATTRIBUTE_GROUPS(tmp103); static bool tmp103_regmap_is_volatile(struct device *dev, unsigned int reg) { @@ -130,8 +171,10 @@ static int tmp103_probe(struct i2c_client *client) } i2c_set_clientdata(client, regmap); - hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, - regmap, tmp103_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, + regmap, + &tmp103_chip_info, + NULL); return PTR_ERR_OR_ZERO(hwmon_dev); } -- cgit v1.2.3 From 952a11ca32a6046ab86bf885a7805c935f71d5c8 Mon Sep 17 00:00:00 2001 From: Paul Fertser <fercerpav@gmail.com> Date: Fri, 24 Sep 2021 22:52:02 +0300 Subject: hwmon: cleanup non-bool "valid" data fields We have bool so use it consistently in all the drivers. The following Coccinelle script was used: @@ identifier T; type t = { char, int }; @@ struct T { ... - t valid; + bool valid; ... } @@ identifier v; @@ ( - v->valid = 0 + v->valid = false | - v->valid = 1 + v->valid = true ) followed by sed to fixup the comments: sed '/bool valid;/{s/!=0/true/;s/zero/false/}' Few whitespace changes were fixed manually. All modified drivers were compile-tested. Signed-off-by: Paul Fertser <fercerpav@gmail.com> Link: https://lore.kernel.org/r/20210924195202.27917-1-fercerpav@gmail.com [groeck: Fixed up 'u8 valid' to 'boool valid' in atxp1.c] Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/abituguru3.c | 6 +++--- drivers/hwmon/ad7414.c | 4 ++-- drivers/hwmon/ad7418.c | 6 +++--- drivers/hwmon/adm1021.c | 4 ++-- drivers/hwmon/adm1025.c | 4 ++-- drivers/hwmon/adm1026.c | 4 ++-- drivers/hwmon/adm1029.c | 4 ++-- drivers/hwmon/adm1031.c | 6 +++--- drivers/hwmon/amc6821.c | 8 ++++---- drivers/hwmon/applesmc.c | 2 +- drivers/hwmon/asb100.c | 4 ++-- drivers/hwmon/asc7621.c | 4 ++-- drivers/hwmon/atxp1.c | 10 +++++----- drivers/hwmon/coretemp.c | 2 +- drivers/hwmon/dme1737.c | 4 ++-- drivers/hwmon/ds1621.c | 4 ++-- drivers/hwmon/ds620.c | 4 ++-- drivers/hwmon/emc6w201.c | 4 ++-- drivers/hwmon/f71805f.c | 4 ++-- drivers/hwmon/f71882fg.c | 4 ++-- drivers/hwmon/f75375s.c | 4 ++-- drivers/hwmon/fschmd.c | 4 ++-- drivers/hwmon/g760a.c | 2 +- drivers/hwmon/gl518sm.c | 4 ++-- drivers/hwmon/gl520sm.c | 4 ++-- drivers/hwmon/ibmaem.c | 2 +- drivers/hwmon/ibmpex.c | 4 ++-- drivers/hwmon/it87.c | 12 ++++++------ drivers/hwmon/lineage-pem.c | 2 +- drivers/hwmon/lm63.c | 6 +++--- drivers/hwmon/lm77.c | 4 ++-- drivers/hwmon/lm78.c | 4 ++-- drivers/hwmon/lm80.c | 6 +++--- drivers/hwmon/lm83.c | 4 ++-- drivers/hwmon/lm85.c | 4 ++-- drivers/hwmon/lm87.c | 4 ++-- drivers/hwmon/lm92.c | 4 ++-- drivers/hwmon/lm93.c | 4 ++-- drivers/hwmon/lm95241.c | 8 ++++---- drivers/hwmon/ltc4151.c | 2 +- drivers/hwmon/ltc4215.c | 2 +- drivers/hwmon/ltc4261.c | 4 ++-- drivers/hwmon/max16065.c | 2 +- drivers/hwmon/max1619.c | 4 ++-- drivers/hwmon/max1668.c | 4 ++-- drivers/hwmon/max6639.c | 4 ++-- drivers/hwmon/max6642.c | 2 +- drivers/hwmon/pc87360.c | 4 ++-- drivers/hwmon/sch5636.c | 4 ++-- drivers/hwmon/sht21.c | 4 ++-- drivers/hwmon/sis5595.c | 4 ++-- drivers/hwmon/smm665.c | 2 +- drivers/hwmon/smsc47b397.c | 4 ++-- drivers/hwmon/smsc47m192.c | 4 ++-- drivers/hwmon/thmc50.c | 4 ++-- drivers/hwmon/tmp401.c | 6 +++--- drivers/hwmon/tmp421.c | 6 +++--- drivers/hwmon/via686a.c | 4 ++-- drivers/hwmon/vt1211.c | 4 ++-- drivers/hwmon/vt8231.c | 4 ++-- drivers/hwmon/w83627ehf.c | 8 ++++---- drivers/hwmon/w83627hf.c | 6 +++--- drivers/hwmon/w83781d.c | 4 ++-- drivers/hwmon/w83791d.c | 4 ++-- drivers/hwmon/w83792d.c | 6 +++--- drivers/hwmon/w83793.c | 6 +++--- drivers/hwmon/w83795.c | 6 +++--- drivers/hwmon/w83l785ts.c | 4 ++-- drivers/hwmon/w83l786ng.c | 4 ++-- 69 files changed, 152 insertions(+), 152 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 112dd0d9377c..8229ad30c909 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -145,7 +145,7 @@ struct abituguru3_data { struct device *hwmon_dev; /* hwmon registered device */ struct mutex update_lock; /* protect access to data and uGuru */ unsigned short addr; /* uguru base address */ - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* @@ -1083,7 +1083,7 @@ static struct abituguru3_data *abituguru3_update_device(struct device *dev) mutex_lock(&data->update_lock); if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { /* Clear data->valid while updating */ - data->valid = 0; + data->valid = false; /* Read alarms */ if (abituguru3_read_increment_offset(data, ABIT_UGURU3_SETTINGS_BANK, @@ -1117,7 +1117,7 @@ static struct abituguru3_data *abituguru3_update_device(struct device *dev) goto LEAVE_UPDATE; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } LEAVE_UPDATE: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 6a765755d061..0afb89c4629d 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -37,7 +37,7 @@ static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW }; struct ad7414_data { struct i2c_client *client; struct mutex lock; /* atomic read data updates */ - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long next_update; /* In jiffies */ s16 temp_input; /* Register values */ s8 temps[ARRAY_SIZE(AD7414_REG_LIMIT)]; @@ -95,7 +95,7 @@ static struct ad7414_data *ad7414_update_device(struct device *dev) } data->next_update = jiffies + HZ + HZ / 2; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->lock); diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index d618f6b2f382..22bdb7e5b9e0 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -46,7 +46,7 @@ struct ad7418_data { enum chips type; struct mutex lock; int adc_max; /* number of ADC channels */ - char valid; + bool valid; unsigned long last_updated; /* In jiffies */ s16 temp[3]; /* Register values */ u16 in[4]; @@ -111,14 +111,14 @@ static int ad7418_update_device(struct device *dev) goto abort; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->lock); return 0; abort: - data->valid = 0; + data->valid = false; mutex_unlock(&data->lock); return val; } diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 71deb2cd20f5..38b447c6e8cd 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -72,7 +72,7 @@ struct adm1021_data { const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ char low_power; /* !=0 if device in low power mode */ unsigned long last_updated; /* In jiffies */ @@ -135,7 +135,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) ADM1023_REG_REM_OFFSET_PREC); } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index de51e01c061b..4352f6a884e8 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -97,7 +97,7 @@ struct adm1025_data { struct i2c_client *client; const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ u8 in[6]; /* register value */ @@ -148,7 +148,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev) ADM1025_REG_VID4) & 0x01) << 4); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 49cefbadb156..69b3ec752944 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -259,7 +259,7 @@ struct adm1026_data { const struct attribute_group *groups[3]; struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -459,7 +459,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev) data->last_config = jiffies; } /* last_config */ - data->valid = 1; + data->valid = true; mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 50b1df7b008c..3e1999413f32 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -99,7 +99,7 @@ static const u8 ADM1029_REG_FAN_DIV[] = { struct adm1029_data { struct i2c_client *client; struct mutex update_lock; /* protect register access */ - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values, signed for temperature, unsigned for other stuff */ @@ -143,7 +143,7 @@ static struct adm1029_data *adm1029_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index b538ace2d292..257ec53ae723 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -65,7 +65,7 @@ struct adm1031_data { const struct attribute_group *groups[3]; struct mutex update_lock; int chip_type; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned int update_interval; /* In milliseconds */ /* @@ -187,7 +187,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); @@ -650,7 +650,7 @@ static ssize_t fan_div_store(struct device *dev, data->fan_min[nr]); /* Invalidate the cache: fan speed is no longer valid */ - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return count; } diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index 6b1ce2242c61..0c16face3fd3 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -141,7 +141,7 @@ static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, struct amc6821_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* register values */ @@ -258,7 +258,7 @@ static struct amc6821_data *amc6821_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); return data; @@ -511,7 +511,7 @@ static ssize_t temp_auto_point_temp_store(struct device *dev, } mutex_lock(&data->update_lock); - data->valid = 0; + data->valid = false; switch (ix) { case 0: @@ -584,7 +584,7 @@ static ssize_t pwm1_auto_point_pwm_store(struct device *dev, } EXIT: - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return count; } diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index c31759794a29..fc6d6a9053ce 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -391,7 +391,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index) cache->len = info[0]; memcpy(cache->type, &info[1], 4); cache->flags = info[5]; - cache->valid = 1; + cache->valid = true; out: mutex_unlock(&smcreg.mutex); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index ba9fcf6f9264..8cf0bcb85eb4 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -186,7 +186,7 @@ struct asb100_data { /* array of 2 pointers to subclients */ struct i2c_client *lm75[2]; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ u8 in[7]; /* Register value */ u8 in_max[7]; /* Register value */ u8 in_min[7]; /* Register value */ @@ -993,7 +993,7 @@ static struct asb100_data *asb100_update_device(struct device *dev) (asb100_read_value(client, ASB100_REG_ALARM2) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; dev_dbg(&client->dev, "... device update complete\n"); } diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 600ffc7e1900..e835605a7456 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -77,7 +77,7 @@ struct asc7621_data { struct i2c_client client; struct device *class_dev; struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_high_reading; /* In jiffies */ unsigned long last_low_reading; /* In jiffies */ /* @@ -1032,7 +1032,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev) data->last_low_reading = jiffies; } /* last_reading */ - data->valid = 1; + data->valid = true; mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 1e08a5431f12..4fd8de8022bc 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -37,7 +37,7 @@ struct atxp1_data { struct i2c_client *client; struct mutex update_lock; unsigned long last_updated; - u8 valid; + bool valid; struct { u8 vid; /* VID output register */ u8 cpu_vid; /* VID input from CPU */ @@ -63,7 +63,7 @@ static struct atxp1_data *atxp1_update_device(struct device *dev) data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1); data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2); - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); @@ -136,7 +136,7 @@ static ssize_t cpu0_vid_store(struct device *dev, ATXP1_VID, cvid | ATXP1_VIDENA); } - data->valid = 0; + data->valid = false; return count; } @@ -180,7 +180,7 @@ static ssize_t gpio1_store(struct device *dev, struct device_attribute *attr, i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value); - data->valid = 0; + data->valid = false; } return count; @@ -224,7 +224,7 @@ static ssize_t gpio2_store(struct device *dev, struct device_attribute *attr, i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value); - data->valid = 0; + data->valid = false; } return count; diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index bb9211215a68..ccf0af5b988a 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -167,7 +167,7 @@ static ssize_t show_temp(struct device *dev, * really help at all. */ tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; - tdata->valid = 1; + tdata->valid = true; tdata->last_updated = jiffies; } diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index c1e4cfb40c3d..e3ad4c2d0038 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -203,7 +203,7 @@ struct dme1737_data { unsigned int addr; /* for ISA devices only */ struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_update; /* in jiffies */ unsigned long last_vbat; /* in jiffies */ enum chips type; @@ -778,7 +778,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) } data->last_update = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index bf1c4b7ecb40..0886abf6ebab 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -109,7 +109,7 @@ static const u8 DS1621_REG_TEMP[3] = { struct ds1621_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ enum chips kind; /* device type */ @@ -213,7 +213,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) new_conf); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 9ec722798c4a..82d7c3d58f49 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -56,7 +56,7 @@ static const u8 DS620_REG_TEMP[3] = { struct ds620_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ s16 temp[3]; /* Register values, word */ @@ -118,7 +118,7 @@ static struct ds620_data *ds620_update_client(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index ec5c98702bf5..29082c8463f4 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -45,7 +45,7 @@ enum subfeature { input, min, max }; struct emc6w201_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ @@ -162,7 +162,7 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 67b47de8263a..7f20edb0677c 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -165,7 +165,7 @@ struct f71805f_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_limits; /* In jiffies */ @@ -404,7 +404,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4dec793fd07d..4673d403759a 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -253,7 +253,7 @@ struct f71882fg_data { struct mutex update_lock; int temp_start; /* temp numbering start (0 or 1) */ - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ char auto_point_temp_signed; unsigned long last_updated; /* In jiffies */ unsigned long last_limits; /* In jiffies */ @@ -1359,7 +1359,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) F71882FG_REG_IN(nr)); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 3e567be60fb1..57c8a473698d 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -85,7 +85,7 @@ struct f75375_data { const char *name; int kind; struct mutex update_lock; /* protect register access */ - char valid; + bool valid; unsigned long last_updated; /* In jiffies */ unsigned long last_limits; /* In jiffies */ @@ -228,7 +228,7 @@ static struct f75375_data *f75375_update_device(struct device *dev) f75375_read8(client, F75375_REG_VOLT(nr)); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index 5191cd85a8d1..c26195e3aad7 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c @@ -264,7 +264,7 @@ struct fschmd_data { unsigned long watchdog_is_open; char watchdog_expect_close; char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* register values */ @@ -1356,7 +1356,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev) FSCHMD_REG_VOLT[data->kind][i]); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index a692f7b2f6f7..36717b524dbd 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -95,7 +95,7 @@ static struct g760a_data *g760a_update_client(struct device *dev) data->fan_sta = g760a_read_value(client, G760A_REG_FAN_STA); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 7aaee5a48243..dd683b0a648f 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -107,7 +107,7 @@ struct gl518_data { enum chips type; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 voltage_in[4]; /* Register values; [0] = VDD */ @@ -211,7 +211,7 @@ static struct gl518_data *gl518_update_device(struct device *dev) gl518_read_value(client, GL518_REG_VIN3); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 4ae1295cc3ea..096ba9797211 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -64,7 +64,7 @@ struct gl520_data { struct i2c_client *client; const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* zero until the following fields are valid */ + bool valid; /* false until the following fields are valid */ unsigned long last_updated; /* in jiffies */ u8 vid; @@ -174,7 +174,7 @@ static struct gl520_data *gl520_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index a4ec85207782..de6baf6ca3d1 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -127,7 +127,7 @@ struct aem_data { struct device *hwmon_dev; struct platform_device *pdev; struct mutex lock; - char valid; + bool valid; unsigned long last_updated; /* In jiffies */ u8 ver_major; u8 ver_minor; diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index b2ab83c9fd9a..f6ec165c0fa8 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -66,7 +66,7 @@ struct ibmpex_bmc_data { struct device *hwmon_dev; struct device *bmc_device; struct mutex lock; - char valid; + bool valid; unsigned long last_updated; /* In jiffies */ struct ipmi_addr address; @@ -239,7 +239,7 @@ static void ibmpex_update_device(struct ibmpex_bmc_data *data) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; out: mutex_unlock(&data->lock); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1f93134afcb9..0e543dbe0a6b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -519,7 +519,7 @@ struct it87_data { unsigned short addr; const char *name; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u16 in_scaled; /* Internal voltage sensors are scaled */ @@ -844,7 +844,7 @@ static struct it87_data *it87_update_device(struct device *dev) data->vid &= 0x3f; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); @@ -980,7 +980,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, regval |= 0x80; it87_write_value(data, IT87_REG_BEEP_ENABLE, regval); } - data->valid = 0; + data->valid = false; reg = IT87_REG_TEMP_OFFSET[nr]; break; } @@ -1079,7 +1079,7 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); if (has_temp_old_peci(data, nr)) it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); - data->valid = 0; /* Force cache refresh */ + data->valid = false; /* Force cache refresh */ mutex_unlock(&data->update_lock); return count; } @@ -1834,7 +1834,7 @@ static ssize_t clear_intrusion(struct device *dev, config |= BIT(5); it87_write_value(data, IT87_REG_CONFIG, config); /* Invalidate cache to force re-read */ - data->valid = 0; + data->valid = false; } mutex_unlock(&data->update_lock); @@ -3229,7 +3229,7 @@ static int __maybe_unused it87_resume(struct device *dev) it87_start_monitoring(data); /* force update */ - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index 1109fffa76fb..ef5a49cd9149 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -191,7 +191,7 @@ static struct pem_data *pem_update_device(struct device *dev) i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index c8f93c5d1ccc..339a145afc09 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -139,7 +139,7 @@ struct lm63_data { struct i2c_client *client; struct mutex update_lock; const struct attribute_group *groups[5]; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ char lut_valid; /* zero until lut fields are valid */ unsigned long last_updated; /* in jiffies */ unsigned long lut_last_updated; /* in jiffies */ @@ -289,7 +289,7 @@ static struct lm63_data *lm63_update_device(struct device *dev) LM63_REG_ALERT_STATUS) & 0x7F; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } lm63_update_lut(data); @@ -714,7 +714,7 @@ static ssize_t temp2_type_store(struct device *dev, reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02; i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM, reg | (data->trutherm ? 0x02 : 0x00)); - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return count; diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 7570c9d50ddc..df6af85e170a 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -55,7 +55,7 @@ static const u8 temp_regs[t_num_temp] = { struct lm77_data { struct i2c_client *client; struct mutex update_lock; - char valid; + bool valid; unsigned long last_updated; /* In jiffies */ int temp[t_num_temp]; /* index using temp_index */ u8 alarms; @@ -118,7 +118,7 @@ static struct lm77_data *lm77_update_device(struct device *dev) data->alarms = lm77_read_value(client, LM77_REG_TEMP) & 0x0007; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 1aa35ca0c6fe..5e129cbec1cb 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -117,7 +117,7 @@ struct lm78_data { int isa_addr; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[7]; /* Register value */ @@ -772,7 +772,7 @@ static struct lm78_data *lm78_update_device(struct device *dev) data->alarms = lm78_read_value(data, LM78_REG_ALARM1) + (lm78_read_value(data, LM78_REG_ALARM2) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; data->fan_div[2] = 1; } diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 97ab491d2922..e85e062bbf32 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -117,7 +117,7 @@ struct lm80_data { struct i2c_client *client; struct mutex update_lock; char error; /* !=0 if error occurred during last update */ - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[i_num_in][7]; /* Register value, 1st index is enum in_index */ @@ -236,14 +236,14 @@ static struct lm80_data *lm80_update_device(struct device *dev) data->alarms = prev_rv + (rv << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; data->error = 0; } goto done; abort: ret = ERR_PTR(rv); - data->valid = 0; + data->valid = false; data->error = 1; done: diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 2ff5ecce608e..74fd7aa373a3 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -105,7 +105,7 @@ struct lm83_data { struct i2c_client *client; const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ @@ -137,7 +137,7 @@ static struct lm83_data *lm83_update_device(struct device *dev) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index c7bf5de7b70f..88cf2012d34b 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -294,7 +294,7 @@ struct lm85_data { bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */ struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -541,7 +541,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) data->last_config = jiffies; } /* last_config */ - data->valid = 1; + data->valid = true; mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index b2d820125bb6..1750bc588856 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -141,7 +141,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; struct lm87_data { struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 channel; /* register value */ @@ -251,7 +251,7 @@ static struct lm87_data *lm87_update_device(struct device *dev) data->aout = lm87_read_value(client, LM87_REG_AOUT); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 9bf278cf0bd0..5bae6eedcaf1 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -99,7 +99,7 @@ static const u8 regs[t_num_regs] = { struct lm92_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ @@ -126,7 +126,7 @@ static struct lm92_data *lm92_update_device(struct device *dev) i2c_smbus_read_word_swapped(client, regs[i]); } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 78d6dfaf145b..dc67bf954b21 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -202,7 +202,7 @@ struct lm93_data { /* client update function */ void (*update)(struct lm93_data *, struct i2c_client *); - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ /* register values, arranged by block read groups */ struct block1_t block1; @@ -917,7 +917,7 @@ static struct lm93_data *lm93_update_device(struct device *dev) data->update(data, client); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 00dbc170c8c6..8ea46ff20be5 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -78,7 +78,7 @@ struct lm95241_data { struct mutex update_lock; unsigned long last_updated; /* in jiffies */ unsigned long interval; /* in milli-seconds */ - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ /* registers values */ u8 temp[ARRAY_SIZE(lm95241_reg_address)]; u8 status, config, model, trutherm; @@ -118,7 +118,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev) data->status = i2c_smbus_read_byte_data(client, LM95241_REG_R_STATUS); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); @@ -257,7 +257,7 @@ static int lm95241_write_temp(struct device *dev, u32 attr, int channel, else data->config &= ~R2DF_MASK; } - data->valid = 0; + data->valid = false; ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); break; @@ -273,7 +273,7 @@ static int lm95241_write_temp(struct device *dev, u32 attr, int channel, else data->config &= ~R2DF_MASK; } - data->valid = 0; + data->valid = false; ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); break; diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c index 13b85367a21f..e3ac004c1ed1 100644 --- a/drivers/hwmon/ltc4151.c +++ b/drivers/hwmon/ltc4151.c @@ -77,7 +77,7 @@ static struct ltc4151_data *ltc4151_update_device(struct device *dev) data->regs[i] = val; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 1d18c212054f..fa43d26ddd4f 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c @@ -64,7 +64,7 @@ static struct ltc4215_data *ltc4215_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c index b81e9c3d297b..b91cc4fe84e5 100644 --- a/drivers/hwmon/ltc4261.c +++ b/drivers/hwmon/ltc4261.c @@ -73,13 +73,13 @@ static struct ltc4261_data *ltc4261_update_device(struct device *dev) "Failed to read ADC value: error %d\n", val); ret = ERR_PTR(val); - data->valid = 0; + data->valid = false; goto abort; } data->regs[i] = val; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index ae3a6a7bdaa2..daa5d8af1e69 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -166,7 +166,7 @@ static struct max16065_data *max16065_update_device(struct device *dev) = i2c_smbus_read_byte_data(client, MAX16065_FAULT(i)); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); return data; diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 8bd941cae4d1..eae9e68027bc 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -79,7 +79,7 @@ enum temp_index { struct max1619_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ @@ -124,7 +124,7 @@ static struct max1619_data *max1619_update_device(struct device *dev) data->alarms ^= 0x02; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index 5c41c78f0458..78688e6cb87d 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -58,7 +58,7 @@ struct max1668_data { enum chips type; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* 1x local and 4x remote */ @@ -120,7 +120,7 @@ static struct max1668_data *max1668_update_device(struct device *dev) data->alarms |= val; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index b71899c641fa..ccc0f047bd44 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -69,7 +69,7 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; struct max6639_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* Register values sampled regularly */ @@ -141,7 +141,7 @@ static struct max6639_data *max6639_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c index 23d93142b0b3..699d265aae2e 100644 --- a/drivers/hwmon/max6642.c +++ b/drivers/hwmon/max6642.c @@ -181,7 +181,7 @@ static struct max6642_data *max6642_update_device(struct device *dev) MAX6642_REG_R_STATUS); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 6a9ba23cd302..0828436a1f6c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -178,7 +178,7 @@ struct pc87360_data { struct device *hwmon_dev; struct mutex lock; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ int address[3]; @@ -1673,7 +1673,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c index a5cd4de36575..39ff1c9b1df5 100644 --- a/drivers/hwmon/sch5636.c +++ b/drivers/hwmon/sch5636.c @@ -56,7 +56,7 @@ struct sch5636_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[SCH5636_NO_INS]; u8 temp_val[SCH5636_NO_TEMPS]; @@ -140,7 +140,7 @@ static struct sch5636_data *sch5636_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; abort: mutex_unlock(&data->update_lock); return ret; diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 7d18ce5d3839..e23dbf287233 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -41,7 +41,7 @@ struct sht21 { unsigned long last_update; int temperature; int humidity; - char valid; + bool valid; char eic[18]; }; @@ -105,7 +105,7 @@ static int sht21_update_measurements(struct device *dev) goto out; sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret); sht21->last_update = jiffies; - sht21->valid = 1; + sht21->valid = true; } out: mutex_unlock(&sht21->lock); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 0c6741f949f5..018cb5a7651f 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -172,7 +172,7 @@ struct sis5595_data { struct mutex lock; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ char maxins; /* == 3 if temp enabled, otherwise == 4 */ u8 revision; /* Reg. value */ @@ -728,7 +728,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) sis5595_read_value(data, SIS5595_REG_ALARM1) | (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c index 62906d9c4b86..8c4ed72e5d68 100644 --- a/drivers/hwmon/smm665.c +++ b/drivers/hwmon/smm665.c @@ -265,7 +265,7 @@ static struct smm665_data *smm665_update_device(struct device *dev) data->adc[i] = val; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index f928b8d4ff48..c26d6eae0e4e 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -96,7 +96,7 @@ struct smsc47b397_data { struct mutex update_lock; unsigned long last_updated; /* in jiffies */ - int valid; + bool valid; /* register values */ u16 fan[4]; @@ -137,7 +137,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; dev_dbg(dev, "... device update complete\n"); } diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 03a87aa2017a..a5db15c087ae 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -86,7 +86,7 @@ struct smsc47m192_data { struct i2c_client *client; const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[8]; /* Register value */ @@ -157,7 +157,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) SMSC47M192_REG_ALARM2) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index fde5e2d0825a..6a804f5036f4 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -62,7 +62,7 @@ struct thmc50_data { enum chips type; unsigned long last_updated; /* In jiffies */ char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ /* Register values */ s8 temp_input[3]; @@ -107,7 +107,7 @@ static struct thmc50_data *thmc50_update_device(struct device *dev) data->alarms = i2c_smbus_read_byte_data(client, THMC50_REG_INTR); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index 9dc210b55e69..88007416c210 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c @@ -136,7 +136,7 @@ struct tmp401_data { struct i2c_client *client; const struct attribute_group *groups[3]; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ enum chips kind; @@ -267,7 +267,7 @@ static struct tmp401_data *tmp401_update_device(struct device *dev) data->temp_crit_hyst = val; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } abort: @@ -413,7 +413,7 @@ static ssize_t reset_temp_history_store(struct device *dev, } mutex_lock(&data->update_lock); i2c_smbus_write_byte_data(client, TMP401_TEMP_MSB_WRITE[5][0], val); - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return count; diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index a4ac6e16d592..356c96c3588b 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -94,7 +94,7 @@ struct tmp421_data { struct hwmon_channel_info temp_info; const struct hwmon_channel_info *info[2]; struct hwmon_chip_info chip; - char valid; + bool valid; unsigned long last_updated; unsigned long channels; u8 config; @@ -141,14 +141,14 @@ static int tmp421_update_device(struct tmp421_data *data) data->temp[i] |= ret; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } exit: mutex_unlock(&data->update_lock); if (ret < 0) { - data->valid = 0; + data->valid = false; return ret; } diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index a2eddd2c2538..55634110c2f9 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -304,7 +304,7 @@ struct via686a_data { const char *name; struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[5]; /* Register value */ @@ -800,7 +800,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) VIA686A_REG_ALARM1) | (via686a_read_value(data, VIA686A_REG_ALARM2) << 8); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 2fbdc532aed4..4a5e911d26eb 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -105,7 +105,7 @@ struct vt1211_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* Register values */ @@ -319,7 +319,7 @@ static struct vt1211_data *vt1211_update_device(struct device *dev) vt1211_read8(data, VT1211_REG_ALARM1); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 6603727e15a0..03275ac8ba72 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -145,7 +145,7 @@ struct vt8231_data { struct mutex update_lock; struct device *hwmon_dev; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[6]; /* Register value */ @@ -929,7 +929,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) data->alarms &= ~0x80; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 705a59663d42..af89b32a93a5 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -320,7 +320,7 @@ struct w83627ehf_data { const u16 *scale_in; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* Register values */ @@ -688,7 +688,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) W83627EHF_REG_CASEOPEN_DET); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); @@ -1099,7 +1099,7 @@ clear_caseopen(struct device *dev, struct w83627ehf_data *data, int channel, reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR); w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask); w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask); - data->valid = 0; /* Force cache refresh */ + data->valid = false; /* Force cache refresh */ mutex_unlock(&data->update_lock); return 0; @@ -2004,7 +2004,7 @@ static int __maybe_unused w83627ehf_resume(struct device *dev) w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat); /* Force re-reading all values */ - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return 0; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index a07b97400cba..9be277156ed2 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -355,7 +355,7 @@ struct w83627hf_data { enum chips type; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[9]; /* Register value */ @@ -448,7 +448,7 @@ static int w83627hf_resume(struct device *dev) w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2); /* Force re-reading all values */ - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return 0; @@ -1905,7 +1905,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index ce8e2c10e854..b3579721265f 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -203,7 +203,7 @@ struct w83781d_data { int isa_addr; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ struct i2c_client *lm75[2]; /* for secondary I2C addresses */ @@ -1554,7 +1554,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) W83781D_REG_BEEP_INTS3) << 16; } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 3c1be2c11fdf..80a9a78d7ce9 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -270,7 +270,7 @@ struct w83791d_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ /* volts */ @@ -1596,7 +1596,7 @@ static struct w83791d_data *w83791d_update_device(struct device *dev) << 4; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 1f175f381350..31a1cdc30877 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -261,7 +261,7 @@ struct w83792d_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ u8 in[9]; /* Register value */ @@ -740,7 +740,7 @@ intrusion0_alarm_store(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); - data->valid = 0; /* Force cache refresh */ + data->valid = false; /* Force cache refresh */ mutex_unlock(&data->update_lock); return count; @@ -1589,7 +1589,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) } data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 1d2854de1cfc..0a65d164c8f0 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -204,7 +204,7 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) struct w83793_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_nonvolatile; /* In jiffies, last time we update the * nonvolatile registers @@ -452,7 +452,7 @@ store_chassis_clear(struct device *dev, mutex_lock(&data->update_lock); reg = w83793_read_value(client, W83793_REG_CLR_CHASSIS); w83793_write_value(client, W83793_REG_CLR_CHASSIS, reg | 0x80); - data->valid = 0; /* Force cache refresh */ + data->valid = false; /* Force cache refresh */ mutex_unlock(&data->update_lock); return count; } @@ -2077,7 +2077,7 @@ static struct w83793_data *w83793_update_device(struct device *dev) data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB); w83793_update_nonvolatile(dev); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; END: mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 621b05afa837..45b12c4287df 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -379,7 +379,7 @@ struct w83795_data { u8 enable_beep; u8 beeps[6]; /* Register value */ - char valid; + bool valid; char valid_limits; char valid_pwm_config; }; @@ -684,7 +684,7 @@ static struct w83795_data *w83795_update_device(struct device *dev) tmp & ~ALARM_CTRL_RTSACS); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; END: mutex_unlock(&data->update_lock); @@ -764,7 +764,7 @@ store_chassis_clear(struct device *dev, /* Clear status and force cache refresh */ w83795_read(client, W83795_REG_ALARM(5)); - data->valid = 0; + data->valid = false; mutex_unlock(&data->update_lock); return count; } diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 656a77102ca6..a41f989d66e2 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -98,7 +98,7 @@ static struct i2c_driver w83l785ts_driver = { struct w83l785ts_data { struct device *hwmon_dev; struct mutex update_lock; - char valid; /* zero until following fields are valid */ + bool valid; /* false until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ @@ -270,7 +270,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) W83L785TS_REG_TEMP_OVER, data->temp[1]); data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 542afff1423b..11ba23c1af85 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -113,7 +113,7 @@ DIV_TO_REG(long val) struct w83l786ng_data { struct i2c_client *client; struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_updated; /* In jiffies */ unsigned long last_nonvolatile; /* In jiffies, last time we update the * nonvolatile registers */ @@ -209,7 +209,7 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) data->tolerance[1] = (reg_tmp >> 4) & 0x0f; data->last_updated = jiffies; - data->valid = 1; + data->valid = true; } -- cgit v1.2.3 From 8a0c75a1c3990ebe8383914781cec347c1576ae6 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Mon, 27 Sep 2021 00:10:44 +0200 Subject: hwmon: (dell-smm) Remove unnecessary includes sched.h and io.h are not used anywhere in dell-smm-hwmon.c. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://lore.kernel.org/r/20210926221044.14327-3-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 774c1b0715d9..5936f2f812d4 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -26,8 +26,6 @@ #include <linux/mutex.h> #include <linux/hwmon.h> #include <linux/uaccess.h> -#include <linux/io.h> -#include <linux/sched.h> #include <linux/ctype.h> #include <linux/smp.h> -- cgit v1.2.3 From beee7890c36320fe08d9cce82afa1db848360bfb Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Date: Mon, 11 Oct 2021 15:27:43 +0200 Subject: hwmon: (adt7x10) Make adt7x10_remove() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up to now adt7x10_remove() returns zero unconditionally. Make it return void instead which makes it easier to see in the callers that there is no error to handle. Also the return value of i2c and spi remove callbacks is ignored anyway. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20211011132754.2479853-3-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/adt7310.c | 3 ++- drivers/hwmon/adt7410.c | 3 ++- drivers/hwmon/adt7x10.c | 3 +-- drivers/hwmon/adt7x10.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c index 9fad01191620..c40cac16af68 100644 --- a/drivers/hwmon/adt7310.c +++ b/drivers/hwmon/adt7310.c @@ -90,7 +90,8 @@ static int adt7310_spi_probe(struct spi_device *spi) static int adt7310_spi_remove(struct spi_device *spi) { - return adt7x10_remove(&spi->dev, spi->irq); + adt7x10_remove(&spi->dev, spi->irq); + return 0; } static const struct spi_device_id adt7310_id[] = { diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c index 9d80895d0266..973db057427b 100644 --- a/drivers/hwmon/adt7410.c +++ b/drivers/hwmon/adt7410.c @@ -50,7 +50,8 @@ static int adt7410_i2c_probe(struct i2c_client *client) static int adt7410_i2c_remove(struct i2c_client *client) { - return adt7x10_remove(&client->dev, client->irq); + adt7x10_remove(&client->dev, client->irq); + return 0; } static const struct i2c_device_id adt7410_ids[] = { diff --git a/drivers/hwmon/adt7x10.c b/drivers/hwmon/adt7x10.c index 3f03b4cf5858..e9d33aa78a19 100644 --- a/drivers/hwmon/adt7x10.c +++ b/drivers/hwmon/adt7x10.c @@ -444,7 +444,7 @@ exit_restore: } EXPORT_SYMBOL_GPL(adt7x10_probe); -int adt7x10_remove(struct device *dev, int irq) +void adt7x10_remove(struct device *dev, int irq) { struct adt7x10_data *data = dev_get_drvdata(dev); @@ -457,7 +457,6 @@ int adt7x10_remove(struct device *dev, int irq) sysfs_remove_group(&dev->kobj, &adt7x10_group); if (data->oldconfig != data->config) adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig); - return 0; } EXPORT_SYMBOL_GPL(adt7x10_remove); diff --git a/drivers/hwmon/adt7x10.h b/drivers/hwmon/adt7x10.h index 21ad15ce3163..a1ae682eb32e 100644 --- a/drivers/hwmon/adt7x10.h +++ b/drivers/hwmon/adt7x10.h @@ -26,7 +26,7 @@ struct adt7x10_ops { int adt7x10_probe(struct device *dev, const char *name, int irq, const struct adt7x10_ops *ops); -int adt7x10_remove(struct device *dev, int irq); +void adt7x10_remove(struct device *dev, int irq); #ifdef CONFIG_PM_SLEEP extern const struct dev_pm_ops adt7x10_dev_pm_ops; -- cgit v1.2.3 From 5e3dbeac3795d60d9dc182abe6d0130a2a00142c Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Tue, 12 Oct 2021 11:26:55 +0200 Subject: hwmon: (tmp421) introduce a channel struct This is a preparatory change. Upcoming patches will introduce more per-channel parameters so it's worth organizing them into a struct. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/baf34d95983a6b58a3e39e4c098e5979e541572e.1634029538.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 356c96c3588b..707310d616a4 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -87,6 +87,10 @@ static const struct of_device_id __maybe_unused tmp421_of_match[] = { }; MODULE_DEVICE_TABLE(of, tmp421_of_match); +struct tmp421_channel { + s16 temp; +}; + struct tmp421_data { struct i2c_client *client; struct mutex update_lock; @@ -98,7 +102,7 @@ struct tmp421_data { unsigned long last_updated; unsigned long channels; u8 config; - s16 temp[MAX_CHANNELS]; + struct tmp421_channel channel[MAX_CHANNELS]; }; static int temp_from_raw(u16 reg, bool extended) @@ -133,12 +137,12 @@ static int tmp421_update_device(struct tmp421_data *data) ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_MSB[i]); if (ret < 0) goto exit; - data->temp[i] = ret << 8; + data->channel[i].temp = ret << 8; ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_LSB[i]); if (ret < 0) goto exit; - data->temp[i] |= ret; + data->channel[i].temp |= ret; } data->last_updated = jiffies; data->valid = true; @@ -167,7 +171,7 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, switch (attr) { case hwmon_temp_input: - *val = temp_from_raw(tmp421->temp[channel], + *val = temp_from_raw(tmp421->channel[channel].temp, tmp421->config & TMP421_CONFIG_RANGE); return 0; case hwmon_temp_fault: @@ -175,7 +179,7 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, * Any of OPEN or /PVLD bits indicate a hardware mulfunction * and the conversion result may be incorrect */ - *val = !!(tmp421->temp[channel] & 0x03); + *val = !!(tmp421->channel[channel].temp & 0x03); return 0; default: return -EOPNOTSUPP; -- cgit v1.2.3 From c1143d1bc5df2be7dafe90bfbc3cd18e9a199724 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:00:49 +0200 Subject: hwmon: (tmp421) add support for defining labels from DT tmp42x is a multichannel temperature sensor with several external channels. Since those channels can be used to connect diodes placed anywhere in the system, their meaning will vary depending on the project. For this case, the hwmon framework has an idea of labels which allows us to assign the meaning to each channel. The similar concept is already implemented in ina3221 - the label for each channel can be defined via device tree. See commit a9e9dd9c6de5 ("hwmon: (ina3221) Read channel input source info from DT") This patch adds support for similar feature to tmp421. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/dab0fda6ac0e8d7f163c3762a7fb1e595a4d8159.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 707310d616a4..89346ca6c9a9 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -88,6 +88,7 @@ static const struct of_device_id __maybe_unused tmp421_of_match[] = { MODULE_DEVICE_TABLE(of, tmp421_of_match); struct tmp421_channel { + const char *label; s16 temp; }; @@ -187,6 +188,16 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, } +static int tmp421_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + struct tmp421_data *data = dev_get_drvdata(dev); + + *str = data->channel[channel].label; + + return 0; +} + static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { @@ -194,6 +205,8 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, case hwmon_temp_fault: case hwmon_temp_input: return 0444; + case hwmon_temp_label: + return 0444; default: return 0; } @@ -286,9 +299,53 @@ static int tmp421_detect(struct i2c_client *client, return 0; } +static int tmp421_probe_child_from_dt(struct i2c_client *client, + struct device_node *child, + struct tmp421_data *data) + +{ + struct device *dev = &client->dev; + u32 i; + int err; + + err = of_property_read_u32(child, "reg", &i); + if (err) { + dev_err(dev, "missing reg property of %pOFn\n", child); + return err; + } + + if (i >= data->channels) { + dev_err(dev, "invalid reg %d of %pOFn\n", i, child); + return -EINVAL; + } + + of_property_read_string(child, "label", &data->channel[i].label); + if (data->channel[i].label) + data->temp_config[i] |= HWMON_T_LABEL; + + return 0; +} + +static int tmp421_probe_from_dt(struct i2c_client *client, struct tmp421_data *data) +{ + struct device *dev = &client->dev; + const struct device_node *np = dev->of_node; + struct device_node *child; + int err; + + for_each_child_of_node(np, child) { + err = tmp421_probe_child_from_dt(client, child, data); + if (err) + return err; + } + + return 0; +} + static const struct hwmon_ops tmp421_ops = { .is_visible = tmp421_is_visible, .read = tmp421_read, + .read_string = tmp421_read_string, }; static int tmp421_probe(struct i2c_client *client) @@ -317,6 +374,10 @@ static int tmp421_probe(struct i2c_client *client) for (i = 0; i < data->channels; i++) data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; + err = tmp421_probe_from_dt(client, data); + if (err) + return err; + data->chip.ops = &tmp421_ops; data->chip.info = data->info; -- cgit v1.2.3 From 45e9bda4ffc48f96e9811e158dcd610a5ec49e13 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:01:09 +0200 Subject: hwmon: (tmp421) support disabling channels from DT The previous patch introduced per channel subnodes in DT that let us specify some channel specific properties. This built a ground for easily disabling individual channels of the sensor that may not be connected to any external diode and thus are not returning any meaningful data. This patch adds support for parsing the "status" property of channels DT subnodes and makes sure the -ENODATA is returned when disabled channels value is read. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/a85d623f0792b862870933a875bdf802f4c017f1.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 89346ca6c9a9..af08bc985a13 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -89,6 +89,7 @@ MODULE_DEVICE_TABLE(of, tmp421_of_match); struct tmp421_channel { const char *label; + bool enabled; s16 temp; }; @@ -170,6 +171,9 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, if (ret) return ret; + if (!tmp421->channel[channel].enabled) + return -ENODATA; + switch (attr) { case hwmon_temp_input: *val = temp_from_raw(tmp421->channel[channel].temp, @@ -323,6 +327,8 @@ static int tmp421_probe_child_from_dt(struct i2c_client *client, if (data->channel[i].label) data->temp_config[i] |= HWMON_T_LABEL; + data->channel[i].enabled = of_device_is_available(child); + return 0; } @@ -371,8 +377,10 @@ static int tmp421_probe(struct i2c_client *client) if (err) return err; - for (i = 0; i < data->channels; i++) + for (i = 0; i < data->channels; i++) { data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; + data->channel[i].enabled = true; + } err = tmp421_probe_from_dt(client, data); if (err) -- cgit v1.2.3 From 3fba10dc0341462a907c2eb31e1dc60b83da23fa Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:01:28 +0200 Subject: hwmon: (tmp421) support specifying n-factor via DT Previous patches added a way to specify some channel specific parameters in DT and n-factor is definitely one of them. This calibration mechanism is board specific as its value depends on the diodes/transistors being connected to the sensor and thus the DT seems like a right fit for that information. It is very similar to the value of shunt resistor that some drivers allows specifying in DT. This patch adds a possibility to set n-factor for each channel via "n-factor" DT property in each channel subnode. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/69d0bfcc5ba27c67f21d3eabfb100656a14c75b9.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index af08bc985a13..4f3737d14ade 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -34,6 +34,7 @@ enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; #define TMP421_STATUS_REG 0x08 #define TMP421_CONFIG_REG_1 0x09 #define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_N_FACTOR_REG_1 0x21 #define TMP421_MANUFACTURER_ID_REG 0xFE #define TMP421_DEVICE_ID_REG 0xFF @@ -310,6 +311,7 @@ static int tmp421_probe_child_from_dt(struct i2c_client *client, { struct device *dev = &client->dev; u32 i; + s32 val; int err; err = of_property_read_u32(child, "reg", &i); @@ -329,6 +331,22 @@ static int tmp421_probe_child_from_dt(struct i2c_client *client, data->channel[i].enabled = of_device_is_available(child); + err = of_property_read_s32(child, "ti,n-factor", &val); + if (!err) { + if (i == 0) { + dev_err(dev, "n-factor can't be set for internal channel\n"); + return -EINVAL; + } + + if (val > 127 || val < -128) { + dev_err(dev, "n-factor for channel %d invalid (%d)\n", + i, val); + return -EINVAL; + } + i2c_smbus_write_byte_data(client, TMP421_N_FACTOR_REG_1 + i - 1, + val); + } + return 0; } -- cgit v1.2.3 From f3fbf4b81d30421d429c47b381353057c1fc1d68 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:09:08 +0200 Subject: hwmon: (tmp421) really disable channels Recent patch added possibility to disable selected channels. That would only make sure that the ENODATA is returned for those channels but would not configure the actual hardware. With this patch, the config register is written to make sure the channels are disabled also at hardware level. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/d451cacdf21bf8eff38a47c055aad8c0c6e8755a.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 4f3737d14ade..776464820a3d 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -33,6 +33,9 @@ enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; /* The TMP421 registers */ #define TMP421_STATUS_REG 0x08 #define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONFIG_REG_2 0x0A +#define TMP421_CONFIG_REG_REN(x) (BIT(3 + (x))) +#define TMP421_CONFIG_REG_REN_MASK GENMASK(6, 3) #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_N_FACTOR_REG_1 0x21 #define TMP421_MANUFACTURER_ID_REG 0xFE @@ -162,6 +165,34 @@ exit: return 0; } +static int tmp421_enable_channels(struct tmp421_data *data) +{ + int err; + struct i2c_client *client = data->client; + struct device *dev = &client->dev; + int old = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_2); + int new, i; + + if (old < 0) { + dev_err(dev, "error reading register, can't disable channels\n"); + return old; + } + + new = old & ~TMP421_CONFIG_REG_REN_MASK; + for (i = 0; i < data->channels; i++) + if (data->channel[i].enabled) + new |= TMP421_CONFIG_REG_REN(i); + + if (new == old) + return 0; + + err = i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_2, new); + if (err < 0) + dev_err(dev, "error writing register, can't disable channels\n"); + + return err; +} + static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { @@ -217,9 +248,10 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, } } -static int tmp421_init_client(struct i2c_client *client) +static int tmp421_init_client(struct tmp421_data *data) { int config, config_orig; + struct i2c_client *client = data->client; /* Set the conversion rate to 2 Hz */ i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05); @@ -240,7 +272,7 @@ static int tmp421_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config); } - return 0; + return tmp421_enable_channels(data); } static int tmp421_detect(struct i2c_client *client, @@ -391,10 +423,6 @@ static int tmp421_probe(struct i2c_client *client) data->channels = i2c_match_id(tmp421_id, client)->driver_data; data->client = client; - err = tmp421_init_client(client); - if (err) - return err; - for (i = 0; i < data->channels; i++) { data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; data->channel[i].enabled = true; @@ -404,6 +432,10 @@ static int tmp421_probe(struct i2c_client *client) if (err) return err; + err = tmp421_init_client(data); + if (err) + return err; + data->chip.ops = &tmp421_ops; data->chip.info = data->info; -- cgit v1.2.3 From 1a98068c71f9b6ca28ad645e169940756d76a294 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:09:58 +0200 Subject: hwmon: (tmp421) support HWMON_T_ENABLE Since the recent patches added possibility of disabling sensor channels via DT, it only make sense to allow controlling that from userspace via HWMON_T_ENABLE mechanism. This patches adds support for that. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/a64c22e7323bd5a083f37aaaca91a745ac1beef3.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 776464820a3d..277628e2a510 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -203,21 +203,25 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, if (ret) return ret; - if (!tmp421->channel[channel].enabled) - return -ENODATA; - switch (attr) { case hwmon_temp_input: + if (!tmp421->channel[channel].enabled) + return -ENODATA; *val = temp_from_raw(tmp421->channel[channel].temp, tmp421->config & TMP421_CONFIG_RANGE); return 0; case hwmon_temp_fault: + if (!tmp421->channel[channel].enabled) + return -ENODATA; /* * Any of OPEN or /PVLD bits indicate a hardware mulfunction * and the conversion result may be incorrect */ *val = !!(tmp421->channel[channel].temp & 0x03); return 0; + case hwmon_temp_enable: + *val = tmp421->channel[channel].enabled; + return 0; default: return -EOPNOTSUPP; } @@ -234,6 +238,24 @@ static int tmp421_read_string(struct device *dev, enum hwmon_sensor_types type, return 0; } +static int tmp421_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct tmp421_data *data = dev_get_drvdata(dev); + int ret; + + switch (attr) { + case hwmon_temp_enable: + data->channel[channel].enabled = val; + ret = tmp421_enable_channels(data); + break; + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { @@ -243,6 +265,8 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, return 0444; case hwmon_temp_label: return 0444; + case hwmon_temp_enable: + return 0644; default: return 0; } @@ -402,6 +426,7 @@ static const struct hwmon_ops tmp421_ops = { .is_visible = tmp421_is_visible, .read = tmp421_read, .read_string = tmp421_read_string, + .write = tmp421_write, }; static int tmp421_probe(struct i2c_client *client) @@ -424,7 +449,7 @@ static int tmp421_probe(struct i2c_client *client) data->client = client; for (i = 0; i < data->channels; i++) { - data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT; + data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_ENABLE; data->channel[i].enabled = true; } -- cgit v1.2.3 From 3e4dd2e8bcf2780e5d421a5d9e833b6ac4e70b11 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski <krzysztof.adamski@nokia.com> Date: Thu, 14 Oct 2021 15:11:02 +0200 Subject: hwmon: (tmp421) ignore non-channel related DT nodes In case the DT contains some nodes not describing the input channels, ignore them instead of exiting with error. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Link: https://lore.kernel.org/r/8e9e332b18dc2cf545f8e8255157e408d356f916.1634206677.git.krzysztof.adamski@nokia.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 277628e2a510..31e95b5749c8 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -414,6 +414,9 @@ static int tmp421_probe_from_dt(struct i2c_client *client, struct tmp421_data *d int err; for_each_child_of_node(np, child) { + if (strcmp(child->name, "channel")) + continue; + err = tmp421_probe_child_from_dt(client, child, data); if (err) return err; -- cgit v1.2.3 From b1986c8e31a3e5f119a52aab50234fc65cf01f30 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Mon, 27 Sep 2021 00:10:43 +0200 Subject: hwmon: (dell-smm) Add support for fanX_min, fanX_max and fanX_target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nominal speed of each fan can be obtained with i8k_get_fan_nominal_speed(), however the result is not available from userspace. Change that by adding fanX_min, fanX_max and fanX_target attributes. All are RO since fan control happens over pwm. Tested on a Dell Inspiron 3505 and a Dell Latitude C600. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Reviewed-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20210926221044.14327-2-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/dell-smm-hwmon.rst | 3 ++ drivers/hwmon/dell-smm-hwmon.c | 61 ++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/dell-smm-hwmon.rst b/Documentation/hwmon/dell-smm-hwmon.rst index 3bf77a5df995..beec88491171 100644 --- a/Documentation/hwmon/dell-smm-hwmon.rst +++ b/Documentation/hwmon/dell-smm-hwmon.rst @@ -34,6 +34,9 @@ Name Perm Description =============================== ======= ======================================= fan[1-3]_input RO Fan speed in RPM. fan[1-3]_label RO Fan label. +fan[1-3]_min RO Minimal Fan speed in RPM +fan[1-3]_max RO Maximal Fan speed in RPM +fan[1-3]_target RO Expected Fan speed in RPM pwm[1-3] RW Control the fan PWM duty-cycle. pwm1_enable WO Enable or disable automatic BIOS fan control (not supported on all laptops, diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 5936f2f812d4..af0d0d2b6e99 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -74,6 +74,7 @@ struct dell_smm_data { int temp_type[DELL_SMM_NO_TEMP]; bool fan[DELL_SMM_NO_FANS]; int fan_type[DELL_SMM_NO_FANS]; + int *fan_nominal_speed[DELL_SMM_NO_FANS]; }; MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); @@ -671,6 +672,13 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types if (data->fan[channel] && !data->disallow_fan_type_call) return 0444; + break; + case hwmon_fan_min: + case hwmon_fan_max: + case hwmon_fan_target: + if (data->fan_nominal_speed[channel]) + return 0444; + break; default: break; @@ -738,6 +746,25 @@ static int dell_smm_read(struct device *dev, enum hwmon_sensor_types type, u32 a *val = ret; + return 0; + case hwmon_fan_min: + *val = data->fan_nominal_speed[channel][0]; + + return 0; + case hwmon_fan_max: + *val = data->fan_nominal_speed[channel][data->i8k_fan_max]; + + return 0; + case hwmon_fan_target: + ret = i8k_get_fan_status(data, channel); + if (ret < 0) + return ret; + + if (ret > data->i8k_fan_max) + ret = data->i8k_fan_max; + + *val = data->fan_nominal_speed[channel][ret]; + return 0; default: break; @@ -887,9 +914,12 @@ static const struct hwmon_channel_info *dell_smm_info[] = { HWMON_T_INPUT | HWMON_T_LABEL ), HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_LABEL, - HWMON_F_INPUT | HWMON_F_LABEL + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | + HWMON_F_TARGET ), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, @@ -908,7 +938,7 @@ static int __init dell_smm_init_hwmon(struct device *dev) { struct dell_smm_data *data = dev_get_drvdata(dev); struct device *dell_smm_hwmon_dev; - int i, err; + int i, state, err; for (i = 0; i < DELL_SMM_NO_TEMP; i++) { data->temp_type[i] = i8k_get_temp_type(i); @@ -924,8 +954,27 @@ static int __init dell_smm_init_hwmon(struct device *dev) err = i8k_get_fan_status(data, i); if (err < 0) err = i8k_get_fan_type(data, i); - if (err >= 0) - data->fan[i] = true; + + if (err < 0) + continue; + + data->fan[i] = true; + data->fan_nominal_speed[i] = devm_kmalloc_array(dev, data->i8k_fan_max + 1, + sizeof(*data->fan_nominal_speed[i]), + GFP_KERNEL); + if (!data->fan_nominal_speed[i]) + continue; + + for (state = 0; state <= data->i8k_fan_max; state++) { + err = i8k_get_fan_nominal_speed(data, i, state); + if (err < 0) { + /* Mark nominal speed table as invalid in case of error */ + devm_kfree(dev, data->fan_nominal_speed[i]); + data->fan_nominal_speed[i] = NULL; + break; + } + data->fan_nominal_speed[i][state] = err; + } } dell_smm_hwmon_dev = devm_hwmon_device_register_with_info(dev, "dell_smm", data, -- cgit v1.2.3 From 2c59a32d12201b4aeaef5c0cc04698670e164dc3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> Date: Wed, 13 Oct 2021 18:04:09 +0200 Subject: hwmon: (acpi_power_meter) Use acpi_bus_get_acpi_device() In read_domain_devices(), acpi_bus_get_device() is called to obtain the ACPI device object attached to the given ACPI handle and subsequently that object is passed to get_device() for reference counting, but there is a window between the acpi_bus_get_device() and get_device() calls in which the ACPI device object in question may go away. To address this issue, make read_domain_devices() use acpi_bus_get_acpi_device() to reference count and return the given ACPI device object in one go and export that function to modules. While at it, also make read_domain_devices() and remove_domain_devices() use acpi_dev_put() instead of calling put_device() directly on the ACPI device objects returned by acpi_bus_get_acpi_device(). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/11871063.O9o76ZdvQC@kreacher Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/acpi/scan.c | 1 + drivers/hwmon/acpi_power_meter.c | 13 +++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5b54c80b9d32..f456ba7c1060 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -608,6 +608,7 @@ struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle) { return handle_to_device(handle, get_acpi_device); } +EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device); static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id) { diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 014505b1faf7..c405a5869581 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -535,7 +535,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) sysfs_remove_link(resource->holders_dir, kobject_name(&obj->dev.kobj)); - put_device(&obj->dev); + acpi_dev_put(obj); } kfree(resource->domain_devices); @@ -597,18 +597,15 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource) continue; /* Create a symlink to domain objects */ - resource->domain_devices[i] = NULL; - if (acpi_bus_get_device(element->reference.handle, - &resource->domain_devices[i])) + obj = acpi_bus_get_acpi_device(element->reference.handle); + resource->domain_devices[i] = obj; + if (!obj) continue; - obj = resource->domain_devices[i]; - get_device(&obj->dev); - res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj, kobject_name(&obj->dev.kobj)); if (res) { - put_device(&obj->dev); + acpi_dev_put(obj); resource->domain_devices[i] = NULL; } } -- cgit v1.2.3 From efb389b8c34fa7da673eb0a598b223bd891daa9d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Date: Tue, 12 Oct 2021 17:39:29 +0200 Subject: hwmon: (max31722) Warn about failure to put device in stand-by in .remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an spi driver's remove function returns a non-zero error code nothing happens apart from emitting a generic error message. Make this error message more device specific and return zero instead. Acked-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20211012153945.2651412-5-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/max31722.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c index 613338cbcb17..4cf4fe6809a3 100644 --- a/drivers/hwmon/max31722.c +++ b/drivers/hwmon/max31722.c @@ -103,10 +103,16 @@ static int max31722_probe(struct spi_device *spi) static int max31722_remove(struct spi_device *spi) { struct max31722_data *data = spi_get_drvdata(spi); + int ret; hwmon_device_unregister(data->hwmon_dev); - return max31722_set_mode(data, MAX31722_MODE_STANDBY); + ret = max31722_set_mode(data, MAX31722_MODE_STANDBY); + if (ret) + /* There is nothing we can do about this ... */ + dev_warn(&spi->dev, "Failed to put device in stand-by mode\n"); + + return 0; } static int __maybe_unused max31722_suspend(struct device *dev) -- cgit v1.2.3 From 66ae4d562b6a8eb2e54d051f31350b1bd5fa3d9c Mon Sep 17 00:00:00 2001 From: Wan Jiabing <wanjiabing@vivo.com> Date: Mon, 18 Oct 2021 08:15:37 -0400 Subject: hwmon: (tmp421) Add of_node_put() before return Fix following coccicheck warning: ./drivers/hwmon/tmp421.c:416:1-23: WARNING: Function for_each_child_of_node should have of_node_put() before return. Early exits from for_each_child_of_node should decrement the node reference counter. Signed-off-by: Wan Jiabing <wanjiabing@vivo.com> Link: https://lore.kernel.org/r/20211018121538.16482-1-wanjiabing@vivo.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/tmp421.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 31e95b5749c8..1fd8d41d90c8 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -418,8 +418,10 @@ static int tmp421_probe_from_dt(struct i2c_client *client, struct tmp421_data *d continue; err = tmp421_probe_child_from_dt(client, child, data); - if (err) + if (err) { + of_node_put(child); return err; + } } return 0; -- cgit v1.2.3 From 6105870f794ded0306dbff4ab017063e4d0f631a Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Thu, 21 Oct 2021 21:05:27 +0200 Subject: hwmon: (dell-smm) Sort includes in alphabetical order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort includes for better overview. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Acked-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20211021190531.17379-2-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index af0d0d2b6e99..9773d6c0477a 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -12,22 +12,22 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/capability.h> #include <linux/cpu.h> +#include <linux/ctype.h> #include <linux/delay.h> +#include <linux/dmi.h> #include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/init.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <linux/dmi.h> -#include <linux/capability.h> -#include <linux/mutex.h> -#include <linux/hwmon.h> -#include <linux/uaccess.h> -#include <linux/ctype.h> #include <linux/smp.h> +#include <linux/types.h> +#include <linux/uaccess.h> #include <linux/i8k.h> -- cgit v1.2.3 From 38c5b0dd7d3092c24fc3dbd9ca963fd0e11752f5 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Thu, 21 Oct 2021 21:05:28 +0200 Subject: hwmon: (dell-smm) Use strscpy_pad() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using strscpy_pad() allows for fewer memory accesses since memset() will not unconditionally zero-out the whole buffer. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Acked-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20211021190531.17379-3-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 9773d6c0477a..b0c591bb761a 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -25,6 +25,7 @@ #include <linux/platform_device.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/string.h> #include <linux/smp.h> #include <linux/types.h> #include <linux/uaccess.h> @@ -472,8 +473,7 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd if (restricted && !capable(CAP_SYS_ADMIN)) return -EPERM; - memset(buff, 0, sizeof(buff)); - strscpy(buff, data->bios_machineid, sizeof(buff)); + strscpy_pad(buff, data->bios_machineid, sizeof(buff)); break; case I8K_FN_STATUS: -- cgit v1.2.3 From e64325e8c56e73bf6e143d0a621be9a0b9bcf21a Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Thu, 21 Oct 2021 21:05:29 +0200 Subject: hwmon: (dell-smm) Return -ENOIOCTLCMD instead of -EINVAL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returning -ENOIOCTLCMD gives the callers a better hint of what went wrong and is the recommended behavior. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Acked-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20211021190531.17379-4-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index b0c591bb761a..5f0338b4a717 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/dmi.h> #include <linux/err.h> +#include <linux/errno.h> #include <linux/hwmon.h> #include <linux/init.h> #include <linux/module.h> @@ -516,7 +517,7 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd break; default: - return -EINVAL; + return -ENOIOCTLCMD; } if (val < 0) -- cgit v1.2.3 From 927d89ee96b3b08cf738eeae5853368d92504164 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Thu, 21 Oct 2021 21:05:30 +0200 Subject: hwmon: (dell-smm) Add comment explaining usage of i8k_config_data[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i8k_config_data[] should only be used for applying device specific quirks in case autoconfig does not work properly on certain devices. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Reviewed-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20211021190531.17379-5-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 5f0338b4a717..0e1bc3a2dd12 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -996,6 +996,11 @@ enum i8k_configs { DELL_XPS, }; +/* + * Only use for machines which need some special configuration + * in order to work correctly (e.g. if autoconfig fails on this machines). + */ + static const struct i8k_config_data i8k_config_data[] __initconst = { [DELL_LATITUDE_D520] = { .fan_mult = 1, -- cgit v1.2.3 From c0d79987a0d82671bff374c07f2201f9bdf4aaa2 Mon Sep 17 00:00:00 2001 From: Armin Wolf <W_Armin@gmx.de> Date: Thu, 21 Oct 2021 21:05:31 +0200 Subject: hwmon: (dell-smm) Speed up setting of fan speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When setting the fan speed, i8k_set_fan() calls i8k_get_fan_status(), causing an unnecessary SMM call since from the two users of this function, only i8k_ioctl_unlocked() needs to know the new fan status while dell_smm_write() ignores the new fan status. Since SMM calls can be very slow while also making error reporting difficult for dell_smm_write(), remove the function call from i8k_set_fan() and call it separately in i8k_ioctl_unlocked(). Tested on a Dell Inspiron 3505. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Reviewed-by: Pali Rohár <pali@kernel.org> Link: https://lore.kernel.org/r/20211021190531.17379-6-W_Armin@gmx.de Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/dell-smm-hwmon.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 0e1bc3a2dd12..eaace478f508 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -327,7 +327,7 @@ static int i8k_enable_fan_auto_mode(const struct dell_smm_data *data, bool enabl } /* - * Set the fan speed (off, low, high). Returns the new fan status. + * Set the fan speed (off, low, high, ...). */ static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed) { @@ -339,7 +339,7 @@ static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed) speed = (speed < 0) ? 0 : ((speed > data->i8k_fan_max) ? data->i8k_fan_max : speed); regs.ebx = (fan & 0xff) | (speed << 8); - return i8k_smm(®s) ? : i8k_get_fan_status(data, fan); + return i8k_smm(®s); } static int __init i8k_get_temp_type(int sensor) @@ -453,7 +453,7 @@ static int i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd, unsigned long arg) { int val = 0; - int speed; + int speed, err; unsigned char buff[16]; int __user *argp = (int __user *)arg; @@ -513,7 +513,11 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd if (copy_from_user(&speed, argp + 1, sizeof(int))) return -EFAULT; - val = i8k_set_fan(data, val, speed); + err = i8k_set_fan(data, val, speed); + if (err < 0) + return err; + + val = i8k_get_fan_status(data, val); break; default: -- cgit v1.2.3 From 0e346a86a51debe23755dae3b89957c1ba8ffbfd Mon Sep 17 00:00:00 2001 From: Oskar Senft <osk@google.com> Date: Wed, 20 Oct 2021 12:42:13 -0400 Subject: hwmon: (nct7802) Make temperature/voltage sensors configurable This change allows LTD and RTD inputs to be configured via device tree bindings. If the DT bindings are not present or invalid, the input configuration is not modified and left at HW defaults. Signed-off-by: Oskar Senft <osk@google.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20211020164213.174597-2-osk@google.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct7802.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index 604af2f6103a..d56f78327619 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -51,6 +51,23 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = { #define REG_CHIP_ID 0xfe #define REG_VERSION_ID 0xff +/* + * Resistance temperature detector (RTD) modes according to 7.2.32 Mode + * Selection Register + */ +#define RTD_MODE_CURRENT 0x1 +#define RTD_MODE_THERMISTOR 0x2 +#define RTD_MODE_VOLTAGE 0x3 + +#define MODE_RTD_MASK 0x3 +#define MODE_LTD_EN 0x40 + +/* + * Bit offset for sensors modes in REG_MODE. + * Valid for index 0..2, indicating RTD1..3. + */ +#define MODE_BIT_OFFSET_RTD(index) ((index) * 2) + /* * Data structures and manipulation thereof */ @@ -1038,7 +1055,112 @@ static const struct regmap_config nct7802_regmap_config = { .volatile_reg = nct7802_regmap_is_volatile, }; -static int nct7802_init_chip(struct nct7802_data *data) +static int nct7802_get_channel_config(struct device *dev, + struct device_node *node, u8 *mode_mask, + u8 *mode_val) +{ + u32 reg; + const char *type_str, *md_str; + u8 md; + + if (!node->name || of_node_cmp(node->name, "channel")) + return 0; + + if (of_property_read_u32(node, "reg", ®)) { + dev_err(dev, "Could not read reg value for '%s'\n", + node->full_name); + return -EINVAL; + } + + if (reg > 3) { + dev_err(dev, "Invalid reg (%u) in '%s'\n", reg, + node->full_name); + return -EINVAL; + } + + if (reg == 0) { + if (!of_device_is_available(node)) + *mode_val &= ~MODE_LTD_EN; + else + *mode_val |= MODE_LTD_EN; + *mode_mask |= MODE_LTD_EN; + return 0; + } + + /* At this point we have reg >= 1 && reg <= 3 */ + + if (!of_device_is_available(node)) { + *mode_val &= ~(MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1)); + *mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1); + return 0; + } + + if (of_property_read_string(node, "sensor-type", &type_str)) { + dev_err(dev, "No type for '%s'\n", node->full_name); + return -EINVAL; + } + + if (!strcmp(type_str, "voltage")) { + *mode_val |= (RTD_MODE_VOLTAGE & MODE_RTD_MASK) + << MODE_BIT_OFFSET_RTD(reg - 1); + *mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1); + return 0; + } + + if (strcmp(type_str, "temperature")) { + dev_err(dev, "Invalid type '%s' for '%s'\n", type_str, + node->full_name); + return -EINVAL; + } + + if (reg == 3) { + /* RTD3 only supports thermistor mode */ + md = RTD_MODE_THERMISTOR; + } else { + if (of_property_read_string(node, "temperature-mode", + &md_str)) { + dev_err(dev, "No mode for '%s'\n", node->full_name); + return -EINVAL; + } + + if (!strcmp(md_str, "thermal-diode")) + md = RTD_MODE_CURRENT; + else if (!strcmp(md_str, "thermistor")) + md = RTD_MODE_THERMISTOR; + else { + dev_err(dev, "Invalid mode '%s' for '%s'\n", md_str, + node->full_name); + return -EINVAL; + } + } + + *mode_val |= (md & MODE_RTD_MASK) << MODE_BIT_OFFSET_RTD(reg - 1); + *mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1); + + return 0; +} + +static int nct7802_configure_channels(struct device *dev, + struct nct7802_data *data) +{ + /* Enable local temperature sensor by default */ + u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN; + struct device_node *node; + int err; + + if (dev->of_node) { + for_each_child_of_node(dev->of_node, node) { + err = nct7802_get_channel_config(dev, node, &mode_mask, + &mode_val); + if (err) + return err; + } + } + + return regmap_update_bits(data->regmap, REG_MODE, mode_mask, mode_val); +} + +static int nct7802_init_chip(struct device *dev, struct nct7802_data *data) { int err; @@ -1047,8 +1169,7 @@ static int nct7802_init_chip(struct nct7802_data *data) if (err) return err; - /* Enable local temperature sensor */ - err = regmap_update_bits(data->regmap, REG_MODE, 0x40, 0x40); + err = nct7802_configure_channels(dev, data); if (err) return err; @@ -1074,7 +1195,7 @@ static int nct7802_probe(struct i2c_client *client) mutex_init(&data->access_lock); mutex_init(&data->in_alarm_lock); - ret = nct7802_init_chip(data); + ret = nct7802_init_chip(dev, data); if (ret < 0) return ret; -- cgit v1.2.3 From f4cbba74c3ec481af882c1057f911c237a5d37d5 Mon Sep 17 00:00:00 2001 From: Denis Pauk <pauk.denis@gmail.com> Date: Mon, 25 Oct 2021 22:47:48 +0300 Subject: hwmon: (nct6775) add ProArt X570-CREATOR WIFI. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ASUS ProArt X570-CREATOR WIFI board has got an nct6775 chip, but by default there's no use of it because of resource conflict with WMI method. This commit adds ProArt X570-CREATOR WIFI to the list of boards that can be monitored using ASUS WMI. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=204807 Signed-off-by: Denis Pauk <pauk.denis@gmail.com> Tested-by: Joel Wirāmu Pauling <jwp@redhat.com> Link: https://lore.kernel.org/r/20211025194748.6784-1-pauk.denis@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct6775.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index f345e1902ad9..93dca471972e 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -4986,6 +4986,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) static struct platform_device *pdev[2]; static const char * const asus_wmi_boards[] = { + "ProArt X570-CREATOR WIFI", "Pro WS X570-ACE", "PRIME B360-PLUS", "PRIME B460-PLUS", -- cgit v1.2.3 From f347e249fcf920ad6974cbd898e2ec0b366a1c34 Mon Sep 17 00:00:00 2001 From: Guenter Roeck <linux@roeck-us.net> Date: Thu, 21 Oct 2021 01:49:50 -0700 Subject: hwmon: (lm90) Introduce flag indicating extended temperature support A flag indicating extended temperature support makes it easier to add support for additional chips with this functionality. Cc: David T. Wilson <david.wilson@nasa.gov> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/lm90.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 567b7c521f38..1a1d7bfcb30b 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -182,7 +182,8 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ #define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ -#define LM90_PAUSE_FOR_CONFIG (1 << 8) /* Pause conversion for config */ +#define LM90_HAVE_EXTENDED_TEMP (1 << 8) /* extended temperature support*/ +#define LM90_PAUSE_FOR_CONFIG (1 << 9) /* Pause conversion for config */ /* LM90 status */ #define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */ @@ -350,7 +351,7 @@ static const struct lm90_params lm90_params[] = { }, [adt7461] = { .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT - | LM90_HAVE_BROKEN_ALERT, + | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, .alert_alarms = 0x7c, .max_convrate = 10, }, @@ -422,7 +423,7 @@ static const struct lm90_params lm90_params[] = { }, [tmp451] = { .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT - | LM90_HAVE_BROKEN_ALERT, + | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, .alert_alarms = 0x7c, .max_convrate = 9, .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, @@ -998,7 +999,7 @@ static int lm90_get_temp11(struct lm90_data *data, int index) s16 temp11 = data->temp11[index]; int temp; - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) temp = temp_from_u16_adt7461(data, temp11); else if (data->kind == max6646) temp = temp_from_u16(temp11); @@ -1035,7 +1036,7 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val) val -= 16000; } - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) data->temp11[index] = temp_to_u16_adt7461(data, val); else if (data->kind == max6646) data->temp11[index] = temp_to_u8(val) << 8; @@ -1062,7 +1063,7 @@ static int lm90_get_temp8(struct lm90_data *data, int index) s8 temp8 = data->temp8[index]; int temp; - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) temp = temp_from_u8_adt7461(data, temp8); else if (data->kind == max6646) temp = temp_from_u8(temp8); @@ -1098,7 +1099,7 @@ static int lm90_set_temp8(struct lm90_data *data, int index, long val) val -= 16000; } - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) data->temp8[index] = temp_to_u8_adt7461(data, val); else if (data->kind == max6646) data->temp8[index] = temp_to_u8(val); @@ -1116,7 +1117,7 @@ static int lm90_get_temphyst(struct lm90_data *data, int index) { int temp; - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) temp = temp_from_u8_adt7461(data, data->temp8[index]); else if (data->kind == max6646) temp = temp_from_u8(data->temp8[index]); @@ -1136,7 +1137,7 @@ static int lm90_set_temphyst(struct lm90_data *data, long val) int temp; int err; - if (data->kind == adt7461 || data->kind == tmp451) + if (data->flags & LM90_HAVE_EXTENDED_TEMP) temp = temp_from_u8_adt7461(data, data->temp8[LOCAL_CRIT]); else if (data->kind == max6646) temp = temp_from_u8(data->temp8[LOCAL_CRIT]); @@ -1685,7 +1686,7 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data) lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ /* Check Temperature Range Select */ - if (data->kind == adt7461 || data->kind == tmp451) { + if (data->flags & LM90_HAVE_EXTENDED_TEMP) { if (config & 0x04) data->flags |= LM90_FLAG_ADT7461_EXT; } -- cgit v1.2.3 From f8344f7693a25d9025a59d164450b50c6f5aa3c0 Mon Sep 17 00:00:00 2001 From: Guenter Roeck <linux@roeck-us.net> Date: Mon, 18 Oct 2021 20:03:32 -0700 Subject: hwmon: (lm90) Add basic support for TI TMP461 TMP461 is almost identical to TMP451 and was actually detected as TMP451 with the existing lm90 driver if its I2C address is 0x4c. Add support for it to the lm90 driver. At the same time, improve the chip detection function to at least try to distinguish between TMP451 and TMP461. As a side effect, this fixes commit 24333ac26d01 ("hwmon: (tmp401) use smb word operations instead of 2 smb byte operations"). TMP461 does not support word operations on temperature registers, which causes bad temperature readings with the tmp401 driver. The lm90 driver does not perform word operations on temperature registers and thus does not have this problem. Support is listed as basic because TMP461 supports a sensor resolution of 0.0625 degrees C, while the lm90 driver assumes a resolution of 0.125 degrees C. Also, the TMP461 supports negative temperatures with its default temperature range, which is not the case for similar chips supported by the lm90 and the tmp401 drivers. Those limitations will be addressed with follow-up patches. Fixes: 24333ac26d01 ("hwmon: (tmp401) use smb word operations instead of 2 smb byte operations") Reported-by: David T. Wilson <david.wilson@nasa.gov> Cc: David T. Wilson <david.wilson@nasa.gov> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/lm90.rst | 10 ++++++++ drivers/hwmon/Kconfig | 2 +- drivers/hwmon/lm90.c | 54 ++++++++++++++++++++++++++++++++------------ 3 files changed, 50 insertions(+), 16 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/lm90.rst b/Documentation/hwmon/lm90.rst index 3da8c6e06a36..05391fb4042d 100644 --- a/Documentation/hwmon/lm90.rst +++ b/Documentation/hwmon/lm90.rst @@ -265,6 +265,16 @@ Supported chips: https://www.ti.com/litv/pdf/sbos686 + * Texas Instruments TMP461 + + Prefix: 'tmp461' + + Addresses scanned: I2C 0x48 through 0x4F + + Datasheet: Publicly available at TI website + + https://www.ti.com/lit/gpn/tmp461 + Author: Jean Delvare <jdelvare@suse.de> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 7fde4c6e1e7f..8c776fb92445 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1327,7 +1327,7 @@ config SENSORS_LM90 Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658, MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG, - Philips SA56004, GMT G781, and Texas Instruments TMP451 + Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461 sensor chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 1a1d7bfcb30b..618052c6cdb6 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -69,10 +69,10 @@ * This driver also supports the G781 from GMT. This device is compatible * with the ADM1032. * - * This driver also supports TMP451 from Texas Instruments. This device is - * supported in both compatibility and extended mode. It's mostly compatible - * with ADT7461 except for local temperature low byte register and max - * conversion rate. + * This driver also supports TMP451 and TMP461 from Texas Instruments. + * Those devices are supported in both compatibility and extended mode. + * They are mostly compatible with ADT7461 except for local temperature + * low byte register and max conversion rate. * * Since the LM90 was the first chipset supported by this driver, most * comments will refer to this chipset, but are actually general and @@ -112,7 +112,7 @@ static const unsigned short normal_i2c[] = { 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, - max6646, w83l771, max6696, sa56004, g781, tmp451, max6654 }; + max6646, w83l771, max6696, sa56004, g781, tmp451, tmp461, max6654 }; /* * The LM90 registers @@ -168,8 +168,12 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ -/* TMP451 registers */ +/* TMP451/TMP461 registers */ #define TMP451_REG_R_LOCAL_TEMPL 0x15 +#define TMP451_REG_CONALERT 0x22 + +#define TMP461_REG_CHEN 0x16 +#define TMP461_REG_DFC 0x24 /* * Device flags @@ -230,6 +234,7 @@ static const struct i2c_device_id lm90_id[] = { { "w83l771", w83l771 }, { "sa56004", sa56004 }, { "tmp451", tmp451 }, + { "tmp461", tmp461 }, { } }; MODULE_DEVICE_TABLE(i2c, lm90_id); @@ -327,6 +332,10 @@ static const struct of_device_id __maybe_unused lm90_of_match[] = { .compatible = "ti,tmp451", .data = (void *)tmp451 }, + { + .compatible = "ti,tmp461", + .data = (void *)tmp461 + }, { }, }; MODULE_DEVICE_TABLE(of, lm90_of_match); @@ -428,6 +437,13 @@ static const struct lm90_params lm90_params[] = { .max_convrate = 9, .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, }, + [tmp461] = { + .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT + | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP, + .alert_alarms = 0x7c, + .max_convrate = 9, + .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL, + }, }; /* @@ -1628,18 +1644,26 @@ static int lm90_detect(struct i2c_client *client, && convrate <= 0x08) name = "g781"; } else - if (address == 0x4C - && man_id == 0x55) { /* Texas Instruments */ - int local_ext; + if (man_id == 0x55 && chip_id == 0x00 && + (config1 & 0x1B) == 0x00 && convrate <= 0x09) { + int local_ext, conalert, chen, dfc; local_ext = i2c_smbus_read_byte_data(client, TMP451_REG_R_LOCAL_TEMPL); - - if (chip_id == 0x00 /* TMP451 */ - && (config1 & 0x1B) == 0x00 - && convrate <= 0x09 - && (local_ext & 0x0F) == 0x00) - name = "tmp451"; + conalert = i2c_smbus_read_byte_data(client, + TMP451_REG_CONALERT); + chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN); + dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC); + + if ((local_ext & 0x0F) == 0x00 && + (conalert & 0xf1) == 0x01 && + (chen & 0xfc) == 0x00 && + (dfc & 0xfc) == 0x00) { + if (address == 0x4c && !(chen & 0x03)) + name = "tmp451"; + else if (address >= 0x48 && address <= 0x4f) + name = "tmp461"; + } } if (!name) { /* identification failed */ -- cgit v1.2.3 From 38d9f06c57403383d574727d9978ad049b011197 Mon Sep 17 00:00:00 2001 From: Guenter Roeck <linux@roeck-us.net> Date: Fri, 15 Oct 2021 17:34:25 -0700 Subject: hwmon: (tmp401) Drop support for TMP461 TMP461 is almost identical to TMP451, which is already supported by the lm90 driver. At the same time, unlike other sensors from the TMP401 compatible series, it only supports 8-bit temperature read operations, and it supports negative temperatures when configured for its default temperature range, and it supports a temperature offset register. Supporting this chip in the tmp401 driver adds unnecessary complexity. Remove its support from this driver and support the chip with the lm90 driver instead. Fixes: 24333ac26d01 ("hwmon: (tmp401) use smb word operations instead of 2 smb byte operations") Reported-by: David T. Wilson <david.wilson@nasa.gov> Cc: David T. Wilson <david.wilson@nasa.gov> Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- Documentation/hwmon/tmp401.rst | 15 +-------------- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/tmp401.c | 25 ++----------------------- 3 files changed, 4 insertions(+), 38 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/tmp401.rst b/Documentation/hwmon/tmp401.rst index 14bf1fbf4493..3aacf3d3bdf3 100644 --- a/Documentation/hwmon/tmp401.rst +++ b/Documentation/hwmon/tmp401.rst @@ -43,12 +43,6 @@ Supported chips: Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html - * Texas Instruments TMP461 - - Prefix: 'tmp461' - - Datasheet: https://www.ti.com/product/tmp461 - Authors: @@ -60,7 +54,7 @@ Description ----------- This driver implements support for Texas Instruments TMP401, TMP411, -TMP431, TMP432, TMP435, and TMP461 chips. These chips implement one or two +TMP431, TMP432, and TMP435 chips. These chips implement one or two remote and one local temperature sensors. Temperature is measured in degrees Celsius. Resolution of the remote sensor is 0.0625 degree. Local sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not @@ -84,10 +78,3 @@ some additional features. TMP432 is compatible with TMP401 and TMP431. It supports two external temperature sensors. - -TMP461 is compatible with TMP401. It supports offset correction -that is applied to the remote sensor. - -* Sensor offset values are temperature values - - Exported via sysfs attribute tempX_offset diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 8c776fb92445..64bd3dfba2c4 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1941,7 +1941,7 @@ config SENSORS_TMP401 depends on I2C help If you say yes here you get support for Texas Instruments TMP401, - TMP411, TMP431, TMP432, TMP435, and TMP461 temperature sensor chips. + TMP411, TMP431, TMP432, and TMP435 temperature sensor chips. This driver can also be built as a module. If so, the module will be called tmp401. diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index 88007416c210..b31f4964f852 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c @@ -34,7 +34,7 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; -enum chips { tmp401, tmp411, tmp431, tmp432, tmp435, tmp461 }; +enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 }; /* * The TMP401 registers, note some registers have different addresses for @@ -56,7 +56,6 @@ static const u8 TMP401_TEMP_MSB_READ[7][2] = { { 0x20, 0x19 }, /* therm (crit) limit */ { 0x30, 0x34 }, /* lowest */ { 0x32, 0x36 }, /* highest */ - { 0, 0x11 }, /* offset */ }; static const u8 TMP401_TEMP_MSB_WRITE[7][2] = { @@ -66,7 +65,6 @@ static const u8 TMP401_TEMP_MSB_WRITE[7][2] = { { 0x20, 0x19 }, /* therm (crit) limit */ { 0x30, 0x34 }, /* lowest */ { 0x32, 0x36 }, /* highest */ - { 0, 0x11 }, /* offset */ }; static const u8 TMP432_TEMP_MSB_READ[4][3] = { @@ -123,7 +121,6 @@ static const struct i2c_device_id tmp401_id[] = { { "tmp431", tmp431 }, { "tmp432", tmp432 }, { "tmp435", tmp435 }, - { "tmp461", tmp461 }, { } }; MODULE_DEVICE_TABLE(i2c, tmp401_id); @@ -570,21 +567,6 @@ static const struct attribute_group tmp432_group = { .attrs = tmp432_attributes, }; -/* - * Additional features of the TMP461 chip. - * The TMP461 temperature offset for the remote channel. - */ -static SENSOR_DEVICE_ATTR_2_RW(temp2_offset, temp, 6, 1); - -static struct attribute *tmp461_attributes[] = { - &sensor_dev_attr_temp2_offset.dev_attr.attr, - NULL -}; - -static const struct attribute_group tmp461_group = { - .attrs = tmp461_attributes, -}; - /* * Begin non sysfs callback code (aka Real code) */ @@ -686,7 +668,7 @@ static int tmp401_detect(struct i2c_client *client, static int tmp401_probe(struct i2c_client *client) { static const char * const names[] = { - "TMP401", "TMP411", "TMP431", "TMP432", "TMP435", "TMP461" + "TMP401", "TMP411", "TMP431", "TMP432", "TMP435" }; struct device *dev = &client->dev; struct device *hwmon_dev; @@ -717,9 +699,6 @@ static int tmp401_probe(struct i2c_client *client) if (data->kind == tmp432) data->groups[groups++] = &tmp432_group; - if (data->kind == tmp461) - data->groups[groups++] = &tmp461_group; - hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, data->groups); if (IS_ERR(hwmon_dev)) -- cgit v1.2.3 From 10f0d2ab9aa672707559d46601fd35544759ff70 Mon Sep 17 00:00:00 2001 From: Wan Jiabing <wanjiabing@vivo.com> Date: Thu, 28 Oct 2021 22:49:18 -0400 Subject: hwmon: (nct7802) Add of_node_put() before return Fix following coccicheck warning: ./drivers/hwmon/nct7802.c:1152:2-24: WARNING: Function for_each_child_of_node should have of_node_put() before return. Early exits from for_each_child_of_node should decrement the node reference counter. Signed-off-by: Wan Jiabing <wanjiabing@vivo.com> Link: https://lore.kernel.org/r/20211029024918.5161-1-wanjiabing@vivo.com Signed-off-by: Guenter Roeck <linux@roeck-us.net> --- drivers/hwmon/nct7802.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index d56f78327619..d1eeef02b6dc 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -1152,8 +1152,10 @@ static int nct7802_configure_channels(struct device *dev, for_each_child_of_node(dev->of_node, node) { err = nct7802_get_channel_config(dev, node, &mode_mask, &mode_val); - if (err) + if (err) { + of_node_put(node); return err; + } } } -- cgit v1.2.3