summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 13:13:57 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 13:13:57 -0700
commit9aebd3254c184fb6c731548b8347193bf882b6f7 (patch)
tree6e0a741ec6e349449410d95273ce1cb7da654ee9 /drivers
parent441977979a78bffe51b13932d353919b1fb20c14 (diff)
parente2f75e6b5d766195d2ca584d92995a0dfe467fc7 (diff)
Merge tag 'hwmon-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck: "Highlights: - New driver for Sparx5 SoC temperature sensot - New driver for Corsair Commander Pro - MAX20710 support added to max20730 driver Enhancements: - max6697: Allow max6581 to create tempX_offset attributes - gsc (Gateworks System Controller): add 16bit pre-scaled voltage mode - adm1275: Enable adm1278 ADM1278_TEMP1_EN - dell-smm: Add Latitude 5480 to fan control whitelist Fixes: - adc128d818: Fix advanced configuration register init - pmbus/core: Use s64 instead of long for calculations to fix overflow issues with 32-bit architectures Plus various cleanups in several drivers" * tag 'hwmon-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (32 commits) hwmon: (adc128d818) Fix advanced configuration register init hwmon: (axi-fan-control) remove duplicate macros hwmon: (i5k_amb, vt8231) Drop uses of pci_read_config_*() return value hwmon: (sparx5) Make symbol 's5_temp_match' static hwmon: (corsair-cpro) add reading pwm values hwmon: sparx5: Add Sparx5 SoC temperature driver dt-bindings: hwmon: Add Sparx5 temperature sensor hwmon: (tmp401) Replace HTTP links with HTTPS ones hwmon: (lm95234) Replace HTTP links with HTTPS ones hwmon: (lm90) Replace HTTP links with HTTPS ones hwmon: (k8temp) Replace HTTP links with HTTPS ones hwmon: (jc42) Replace HTTP links with HTTPS ones hwmon: (ina2xx) Replace HTTP links with HTTPS ones hwmon: (ina209) Replace HTTP links with HTTPS ones hwmon: Replace HTTP links with HTTPS ones docs: hwmon: Replace HTTP links with HTTPS ones hwmon: (adm1025) Replace HTTP links with HTTPS ones hwmon: add Corsair Commander Pro driver hwmon: (max6697) Allow max6581 to create tempX_offset hwmon: (tmmp513) Replace HTTP links with HTTPS links ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/Kconfig20
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/adc128d818.c24
-rw-r--r--drivers/hwmon/adm1025.c2
-rw-r--r--drivers/hwmon/adm1026.c2
-rw-r--r--drivers/hwmon/axi-fan-control.c4
-rw-r--r--drivers/hwmon/corsair-cpro.c582
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c8
-rw-r--r--drivers/hwmon/gsc-hwmon.c8
-rw-r--r--drivers/hwmon/hwmon-vid.c6
-rw-r--r--drivers/hwmon/i5k_amb.c14
-rw-r--r--drivers/hwmon/ina209.c2
-rw-r--r--drivers/hwmon/ina2xx.c10
-rw-r--r--drivers/hwmon/ina3221.c2
-rw-r--r--drivers/hwmon/lm87.c2
-rw-r--r--drivers/hwmon/max6697.c96
-rw-r--r--drivers/hwmon/nct6683.c8
-rw-r--r--drivers/hwmon/pmbus/Kconfig4
-rw-r--r--drivers/hwmon/pmbus/adm1275.c13
-rw-r--r--drivers/hwmon/pmbus/max20730.c49
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c66
-rw-r--r--drivers/hwmon/powr1220.c2
-rw-r--r--drivers/hwmon/sht21.c2
-rw-r--r--drivers/hwmon/sparx5-temp.c168
-rw-r--r--drivers/hwmon/tmp513.c4
-rw-r--r--drivers/hwmon/vt8231.c8
26 files changed, 1007 insertions, 101 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 288ae9f63588..8dc28b26916e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -439,6 +439,16 @@ config SENSORS_BT1_PVT_ALARMS
the data conversion will be periodically performed and the data will be
saved in the internal driver cache.
+config SENSORS_CORSAIR_CPRO
+ tristate "Corsair Commander Pro controller"
+ depends on HID
+ help
+ If you say yes here you get support for the Corsair Commander Pro
+ controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called corsair-cpro.
+
config SENSORS_DRIVETEMP
tristate "Hard disk drives with temperature sensors"
depends on SCSI && ATA
@@ -515,6 +525,16 @@ config SENSORS_I5K_AMB
This driver can also be built as a module. If so, the module
will be called i5k_amb.
+config SENSORS_SPARX5
+ tristate "Sparx5 SoC temperature sensor"
+ depends on ARCH_SPARX5 || COMPILE_TEST
+ help
+ If you say yes here you get support for temperature monitoring
+ with the Microchip Sparx5 SoC.
+
+ This driver can also be built as a module. If so, the module
+ will be called sparx5-temp.
+
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on !PPC
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3e32c21f5efe..a8f4b35b136b 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_AXI_FAN_CONTROL) += axi-fan-control.o
obj-$(CONFIG_SENSORS_BT1_PVT) += bt1-pvt.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
+obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o
@@ -167,6 +168,7 @@ obj-$(CONFIG_SENSORS_SMM665) += smm665.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
+obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_TC74) += tc74.o
diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c
index f9edec195c35..571d5454c6b2 100644
--- a/drivers/hwmon/adc128d818.c
+++ b/drivers/hwmon/adc128d818.c
@@ -393,6 +393,7 @@ static int adc128_init_client(struct adc128_data *data)
{
struct i2c_client *client = data->client;
int err;
+ u8 regval = 0x0;
/*
* Reset chip to defaults.
@@ -403,10 +404,17 @@ static int adc128_init_client(struct adc128_data *data)
return err;
/* Set operation mode, if non-default */
- if (data->mode != 0) {
- err = i2c_smbus_write_byte_data(client,
- ADC128_REG_CONFIG_ADV,
- data->mode << 1);
+ if (data->mode != 0)
+ regval |= data->mode << 1;
+
+ /* If external vref is selected, configure the chip to use it */
+ if (data->regulator)
+ regval |= 0x01;
+
+ /* Write advanced configuration register */
+ if (regval != 0x0) {
+ err = i2c_smbus_write_byte_data(client, ADC128_REG_CONFIG_ADV,
+ regval);
if (err)
return err;
}
@@ -416,14 +424,6 @@ static int adc128_init_client(struct adc128_data *data)
if (err)
return err;
- /* If external vref is selected, configure the chip to use it */
- if (data->regulator) {
- err = i2c_smbus_write_byte_data(client,
- ADC128_REG_CONFIG_ADV, 0x01);
- if (err)
- return err;
- }
-
return 0;
}
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index ae7b96945185..ed15185fa60f 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -13,7 +13,7 @@
* resolution of about 0.5% of the nominal value). Temperature values are
* reported with a 1 deg resolution and a 3 deg accuracy. Complete
* datasheet can be obtained from Analog's website at:
- * http://www.onsemi.com/PowerSolutions/product.do?id=ADM1025
+ * https://www.onsemi.com/PowerSolutions/product.do?id=ADM1025
*
* This driver also supports the ADM1025A, which differs from the ADM1025
* only in that it has "open-drain VID inputs while the ADM1025 has
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index e0f630c64152..af77096724fd 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -7,7 +7,7 @@
*
* Chip details at:
*
- * <http://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
+ * <https://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
*/
#include <linux/module.h>
diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c
index 38d9cdb3db1a..e3f6b03e6764 100644
--- a/drivers/hwmon/axi-fan-control.c
+++ b/drivers/hwmon/axi-fan-control.c
@@ -15,10 +15,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
-#define ADI_AXI_PCORE_VER_MAJOR(version) (((version) >> 16) & 0xff)
-#define ADI_AXI_PCORE_VER_MINOR(version) (((version) >> 8) & 0xff)
-#define ADI_AXI_PCORE_VER_PATCH(version) ((version) & 0xff)
-
/* register map */
#define ADI_REG_RSTN 0x0080
#define ADI_REG_PWM_WIDTH 0x0084
diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
new file mode 100644
index 000000000000..591929ec217a
--- /dev/null
+++ b/drivers/hwmon/corsair-cpro.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * corsair-cpro.c - Linux driver for Corsair Commander Pro
+ * Copyright (C) 2020 Marius Zachmann <mail@mariuszachmann.de>
+ *
+ * This driver uses hid reports to communicate with the device to allow hidraw userspace drivers
+ * still being used. The device does not use report ids. When using hidraw and this driver
+ * simultaniously, reports could be switched.
+ */
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/hid.h>
+#include <linux/hwmon.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define USB_VENDOR_ID_CORSAIR 0x1b1c
+#define USB_PRODUCT_ID_CORSAIR_COMMANDERPRO 0x0c10
+#define USB_PRODUCT_ID_CORSAIR_1000D 0x1d00
+
+#define OUT_BUFFER_SIZE 63
+#define IN_BUFFER_SIZE 16
+#define LABEL_LENGTH 11
+#define REQ_TIMEOUT 300
+
+#define CTL_GET_TMP_CNCT 0x10 /*
+ * returns in bytes 1-4 for each temp sensor:
+ * 0 not connected
+ * 1 connected
+ */
+#define CTL_GET_TMP 0x11 /*
+ * send: byte 1 is channel, rest zero
+ * rcv: returns temp for channel in centi-degree celsius
+ * in bytes 1 and 2
+ * returns 0x11 in byte 0 if no sensor is connected
+ */
+#define CTL_GET_VOLT 0x12 /*
+ * send: byte 1 is rail number: 0 = 12v, 1 = 5v, 2 = 3.3v
+ * rcv: returns millivolt in bytes 1,2
+ * returns error 0x10 if request is invalid
+ */
+#define CTL_GET_FAN_CNCT 0x20 /*
+ * returns in bytes 1-6 for each fan:
+ * 0 not connected
+ * 1 3pin
+ * 2 4pin
+ */
+#define CTL_GET_FAN_RPM 0x21 /*
+ * send: byte 1 is channel, rest zero
+ * rcv: returns rpm in bytes 1,2
+ */
+#define CTL_GET_FAN_PWM 0x22 /*
+ * send: byte 1 is channel, rest zero
+ * rcv: returns pwm in byte 1 if it was set
+ * returns error 0x12 if fan is controlled via
+ * fan_target or fan curve
+ */
+#define CTL_SET_FAN_FPWM 0x23 /*
+ * set fixed pwm
+ * send: byte 1 is fan number
+ * send: byte 2 is percentage from 0 - 100
+ */
+#define CTL_SET_FAN_TARGET 0x24 /*
+ * set target rpm
+ * send: byte 1 is fan number
+ * send: byte 2-3 is target
+ * device accepts all values from 0x00 - 0xFFFF
+ */
+
+#define NUM_FANS 6
+#define NUM_TEMP_SENSORS 4
+
+struct ccp_device {
+ struct hid_device *hdev;
+ struct device *hwmon_dev;
+ struct completion wait_input_report;
+ struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
+ u8 *buffer;
+ int target[6];
+ DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
+ DECLARE_BITMAP(fan_cnct, NUM_FANS);
+ char fan_label[6][LABEL_LENGTH];
+};
+
+/* converts response error in buffer to errno */
+static int ccp_get_errno(struct ccp_device *ccp)
+{
+ switch (ccp->buffer[0]) {
+ case 0x00: /* success */
+ return 0;
+ case 0x01: /* called invalid command */
+ return -EOPNOTSUPP;
+ case 0x10: /* called GET_VOLT / GET_TMP with invalid arguments */
+ return -EINVAL;
+ case 0x11: /* requested temps of disconnected sensors */
+ case 0x12: /* requested pwm of not pwm controlled channels */
+ return -ENODATA;
+ default:
+ hid_dbg(ccp->hdev, "unknown device response error: %d", ccp->buffer[0]);
+ return -EIO;
+ }
+}
+
+/* send command, check for error in response, response in ccp->buffer */
+static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, u8 byte3)
+{
+ unsigned long t;
+ int ret;
+
+ memset(ccp->buffer, 0x00, OUT_BUFFER_SIZE);
+ ccp->buffer[0] = command;
+ ccp->buffer[1] = byte1;
+ ccp->buffer[2] = byte2;
+ ccp->buffer[3] = byte3;
+
+ reinit_completion(&ccp->wait_input_report);
+
+ ret = hid_hw_output_report(ccp->hdev, ccp->buffer, OUT_BUFFER_SIZE);
+ if (ret < 0)
+ return ret;
+
+ t = wait_for_completion_timeout(&ccp->wait_input_report, msecs_to_jiffies(REQ_TIMEOUT));
+ if (!t)
+ return -ETIMEDOUT;
+
+ return ccp_get_errno(ccp);
+}
+
+static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)
+{
+ struct ccp_device *ccp = hid_get_drvdata(hdev);
+
+ /* only copy buffer when requested */
+ if (completion_done(&ccp->wait_input_report))
+ return 0;
+
+ memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
+ complete(&ccp->wait_input_report);
+
+ return 0;
+}
+
+/* requests and returns single data values depending on channel */
+static int get_data(struct ccp_device *ccp, int command, int channel, bool two_byte_data)
+{
+ int ret;
+
+ mutex_lock(&ccp->mutex);
+
+ ret = send_usb_cmd(ccp, command, channel, 0, 0);
+ if (ret)
+ goto out_unlock;
+
+ ret = ccp->buffer[1];
+ if (two_byte_data)
+ ret = (ret << 8) + ccp->buffer[2];
+
+out_unlock:
+ mutex_unlock(&ccp->mutex);
+ return ret;
+}
+
+static int set_pwm(struct ccp_device *ccp, int channel, long val)
+{
+ int ret;
+
+ if (val < 0 || val > 255)
+ return -EINVAL;
+
+ /* The Corsair Commander Pro uses values from 0-100 */
+ val = DIV_ROUND_CLOSEST(val * 100, 255);
+
+ mutex_lock(&ccp->mutex);
+
+ ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0);
+ if (!ret)
+ ccp->target[channel] = -ENODATA;
+
+ mutex_unlock(&ccp->mutex);
+ return ret;
+}
+
+static int set_target(struct ccp_device *ccp, int channel, long val)
+{
+ int ret;
+
+ val = clamp_val(val, 0, 0xFFFF);
+ ccp->target[channel] = val;
+
+ mutex_lock(&ccp->mutex);
+ ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val);
+
+ mutex_unlock(&ccp->mutex);
+ return ret;
+}
+
+static int ccp_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_label:
+ *str = ccp->fan_label[channel];
+ return 0;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ ret = get_data(ccp, CTL_GET_TMP, channel, true);
+ if (ret < 0)
+ return ret;
+ *val = ret * 10;
+ return 0;
+ default:
+ break;
+ }
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ ret = get_data(ccp, CTL_GET_FAN_RPM, channel, true);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return 0;
+ case hwmon_fan_target:
+ /* how to read target values from the device is unknown */
+ /* driver returns last set value or 0 */
+ if (ccp->target[channel] < 0)
+ return -ENODATA;
+ *val = ccp->target[channel];
+ return 0;
+ default:
+ break;
+ }
+ break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ ret = get_data(ccp, CTL_GET_FAN_PWM, channel, false);
+ if (ret < 0)
+ return ret;
+ *val = DIV_ROUND_CLOSEST(ret * 255, 100);
+ return 0;
+ default:
+ break;
+ }
+ break;
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ ret = get_data(ccp, CTL_GET_VOLT, channel, true);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return 0;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+};
+
+static int ccp_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct ccp_device *ccp = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ return set_pwm(ccp, channel, val);
+ default:
+ break;
+ }
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_target:
+ return set_target(ccp, channel, val);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+};
+
+static umode_t ccp_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct ccp_device *ccp = data;
+
+ switch (type) {
+ case hwmon_temp:
+ if (!test_bit(channel, ccp->temp_cnct))
+ break;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ case hwmon_temp_label:
+ return 0444;
+ default:
+ break;
+ }
+ break;
+ case hwmon_fan:
+ if (!test_bit(channel, ccp->fan_cnct))
+ break;
+
+ switch (attr) {
+ case hwmon_fan_input:
+ return 0444;
+ case hwmon_fan_label:
+ return 0444;
+ case hwmon_fan_target:
+ return 0644;
+ default:
+ break;
+ }
+ break;
+ case hwmon_pwm:
+ if (!test_bit(channel, ccp->fan_cnct))
+ break;
+
+ switch (attr) {
+ case hwmon_pwm_input:
+ return 0644;
+ default:
+ break;
+ }
+ break;
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_input:
+ return 0444;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+};
+
+static const struct hwmon_ops ccp_hwmon_ops = {
+ .is_visible = ccp_is_visible,
+ .read = ccp_read,
+ .read_string = ccp_read_string,
+ .write = ccp_write,
+};
+
+static const struct hwmon_channel_info *ccp_info[] = {
+ HWMON_CHANNEL_INFO(chip,
+ HWMON_C_REGISTER_TZ),
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT,
+ HWMON_T_INPUT,
+ HWMON_T_INPUT,
+ HWMON_T_INPUT
+ ),
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET
+ ),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT,
+ HWMON_PWM_INPUT
+ ),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT,
+ HWMON_I_INPUT,
+ HWMON_I_INPUT
+ ),
+ NULL
+};
+
+static const struct hwmon_chip_info ccp_chip_info = {
+ .ops = &ccp_hwmon_ops,
+ .info = ccp_info,
+};
+
+/* read fan connection status and set labels */
+static int get_fan_cnct(struct ccp_device *ccp)
+{
+ int channel;
+ int mode;
+ int ret;
+
+ ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0, 0);
+ if (ret)
+ return ret;
+
+ for (channel = 0; channel < NUM_FANS; channel++) {
+ mode = ccp->buffer[channel + 1];
+ if (mode == 0)
+ continue;
+
+ set_bit(channel, ccp->fan_cnct);
+ ccp->target[channel] = -ENODATA;
+
+ switch (mode) {
+ case 1:
+ scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
+ "fan%d 3pin", channel + 1);
+ break;
+ case 2:
+ scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
+ "fan%d 4pin", channel + 1);
+ break;
+ default:
+ scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
+ "fan%d other", channel + 1);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* read temp sensor connection status */
+static int get_temp_cnct(struct ccp_device *ccp)
+{
+ int channel;
+ int mode;
+ int ret;
+
+ ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0, 0);
+ if (ret)
+ return ret;
+
+ for (channel = 0; channel < NUM_TEMP_SENSORS; channel++) {
+ mode = ccp->buffer[channel + 1];
+ if (mode == 0)
+ continue;
+
+ set_bit(channel, ccp->temp_cnct);
+ }
+
+ return 0;
+}
+
+static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ struct ccp_device *ccp;
+ int ret;
+
+ ccp = devm_kzalloc(&hdev->dev, sizeof(*ccp), GFP_KERNEL);
+ if (!ccp)
+ return -ENOMEM;
+
+ ccp->buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
+ if (!ccp->buffer)
+ return -ENOMEM;
+
+ ret = hid_parse(hdev);
+ if (ret)
+ return ret;
+
+ ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ if (ret)
+ return ret;
+
+ ret = hid_hw_open(hdev);
+ if (ret)
+ goto out_hw_stop;
+
+ ccp->hdev = hdev;
+ hid_set_drvdata(hdev, ccp);
+ mutex_init(&ccp->mutex);
+ init_completion(&ccp->wait_input_report);
+
+ hid_device_io_start(hdev);
+
+ /* temp and fan connection status only updates when device is powered on */
+ ret = get_temp_cnct(ccp);
+ if (ret)
+ goto out_hw_close;
+
+ ret = get_fan_cnct(ccp);
+ if (ret)
+ goto out_hw_close;
+ ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
+ ccp, &ccp_chip_info, 0);
+ if (IS_ERR(ccp->hwmon_dev)) {
+ ret = PTR_ERR(ccp->hwmon_dev);
+ goto out_hw_close;
+ }
+
+ return 0;
+
+out_hw_close:
+ hid_hw_close(hdev);
+out_hw_stop:
+ hid_hw_stop(hdev);
+ return ret;
+}
+
+static void ccp_remove(struct hid_device *hdev)
+{
+ struct ccp_device *ccp = hid_get_drvdata(hdev);
+
+ hwmon_device_unregister(ccp->hwmon_dev);
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id ccp_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_PRODUCT_ID_CORSAIR_COMMANDERPRO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_PRODUCT_ID_CORSAIR_1000D) },
+ { }
+};
+
+static struct hid_driver ccp_driver = {
+ .name = "corsair-cpro",
+ .id_table = ccp_devices,
+ .probe = ccp_probe,
+ .remove = ccp_remove,
+ .raw_event = ccp_raw_event,
+};
+
+MODULE_DEVICE_TABLE(hid, ccp_devices);
+MODULE_LICENSE("GPL");
+
+static int __init ccp_init(void)
+{
+ return hid_register_driver(&ccp_driver);
+}
+
+static void __exit ccp_exit(void)
+{
+ hid_unregister_driver(&ccp_driver);
+}
+
+/*
+ * When compiling this driver as built-in, hwmon initcalls will get called before the
+ * hid driver and this driver would fail to register. late_initcall solves this.
+ */
+late_initcall(ccp_init);
+module_exit(ccp_exit);
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 16be012a95ed..ec448f5f2dc3 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -1188,6 +1188,14 @@ static struct dmi_system_id i8k_whitelist_fan_control[] __initdata = {
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3],
},
{
+ .ident = "Dell Latitude 5480",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Latitude 5480"),
+ },
+ .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3],
+ },
+ {
.ident = "Dell Latitude E6440",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index 2137bc65829d..3dfe2ca2f8c8 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -159,7 +159,7 @@ gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
return -EOPNOTSUPP;
}
- sz = (ch->mode == mode_voltage) ? 3 : 2;
+ sz = (ch->mode == mode_voltage_24bit) ? 3 : 2;
ret = regmap_bulk_read(hwmon->regmap, ch->reg, buf, sz);
if (ret)
return ret;
@@ -186,7 +186,8 @@ gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
/* adjust by uV offset */
tmp += ch->mvoffset;
break;
- case mode_voltage:
+ case mode_voltage_24bit:
+ case mode_voltage_16bit:
/* no adjustment needed */
break;
}
@@ -336,7 +337,8 @@ static int gsc_hwmon_probe(struct platform_device *pdev)
HWMON_T_LABEL;
i_temp++;
break;
- case mode_voltage:
+ case mode_voltage_24bit:
+ case mode_voltage_16bit:
case mode_voltage_raw:
if (i_in == GSC_HWMON_MAX_IN_CH) {
dev_err(gsc->dev, "too many input channels\n");
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 8ae68dfa75b2..eb72e390844e 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -49,15 +49,15 @@
* The 13 specification corresponds to the Intel Pentium M series. There
* doesn't seem to be any named specification for these. The conversion
* tables are detailed directly in the various Pentium M datasheets:
- * http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
+ * https://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
*
* The 14 specification corresponds to Intel Core series. There
* doesn't seem to be any named specification for these. The conversion
* tables are detailed directly in the various Pentium Core datasheets:
- * http://www.intel.com/design/mobile/datashts/309221.htm
+ * https://www.intel.com/design/mobile/datashts/309221.htm
*
* The 110 (VRM 11) specification corresponds to Intel Conroe based series.
- * http://www.intel.com/design/processor/applnots/313214.htm
+ * https://www.intel.com/design/processor/applnots/313214.htm
*/
/*
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index eeac4b04df27..783fa936e4d1 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -396,7 +396,7 @@ exit_remove:
static int i5k_amb_add(void)
{
- int res = -ENODEV;
+ int res;
/* only ever going to be one of these */
amb_pdev = platform_device_alloc(DRVNAME, 0);
@@ -427,11 +427,13 @@ static int i5k_find_amb_registers(struct i5k_amb_data *data,
if (!pcidev)
return -ENODEV;
- if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32))
+ pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32);
+ if (val32 == (u32)~0)
goto out;
data->amb_base = val32;
- if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32))
+ pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32);
+ if (val32 == (u32)~0)
goto out;
data->amb_len = val32;
@@ -458,11 +460,13 @@ static int i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
if (!pcidev)
return -ENODEV;
- if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16))
+ pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16);
+ if (val16 == (u16)~0)
goto out;
amb_present[0] = val16;
- if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16))
+ pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16);
+ if (val16 == (u16)~0)
goto out;
amb_present[1] = val16;
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index 70ad1efcb3de..08ee3a64a026 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -14,7 +14,7 @@
* Thanks to Jan Volkering
*
* Datasheet:
- * http://www.ti.com/lit/gpn/ina209
+ * https://www.ti.com/lit/gpn/ina209
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 55d474ec7c35..0fc6d5857993 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -4,19 +4,19 @@
*
* INA219:
* Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
- * Datasheet: http://www.ti.com/product/ina219
+ * Datasheet: https://www.ti.com/product/ina219
*
* INA220:
* Bi-Directional Current/Power Monitor with I2C Interface
- * Datasheet: http://www.ti.com/product/ina220
+ * Datasheet: https://www.ti.com/product/ina220
*
* INA226:
* Bi-Directional Current/Power Monitor with I2C Interface
- * Datasheet: http://www.ti.com/product/ina226
+ * Datasheet: https://www.ti.com/product/ina226
*
* INA230:
* Bi-directional Current/Power Monitor with I2C Interface
- * Datasheet: http://www.ti.com/product/ina230
+ * Datasheet: https://www.ti.com/product/ina230
*
* Copyright (C) 2012 Lothar Felten <lothar.felten@gmail.com>
* Thanks to Jan Volkering
@@ -148,7 +148,7 @@ static const struct ina2xx_config ina2xx_config[] = {
* Available averaging rates for ina226. The indices correspond with
* the bit values expected by the chip (according to the ina226 datasheet,
* table 3 AVG bit settings, found at
- * http://www.ti.com/lit/ds/symlink/ina226.pdf.
+ * https://www.ti.com/lit/ds/symlink/ina226.pdf.
*/
static const int ina226_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index f335d0cb0c77..7fc5b065ad8b 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -2,7 +2,7 @@
/*
* INA3221 Triple Current/Voltage Monitor
*
- * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
* Andrew F. Davis <afd@ti.com>
*/
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index ad501ac4a594..c96c4d807e38 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -40,7 +40,7 @@
* This driver also supports the ADM1024, a sensor chip made by Analog
* Devices. That chip is fully compatible with the LM87. Complete
* datasheet can be obtained from Analog's website at:
- * http://www.analog.com/en/prod/0,2877,ADM1024,00.html
+ * https://www.analog.com/en/prod/0,2877,ADM1024,00.html
*/
#include <linux/module.h>
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index 64122eb38060..58781d999caa 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -57,6 +57,8 @@ static const u8 MAX6697_REG_CRIT[] = {
#define MAX6581_REG_IDEALITY_SELECT 0x4c
#define MAX6581_REG_OFFSET 0x4d
#define MAX6581_REG_OFFSET_SELECT 0x4e
+#define MAX6581_OFFSET_MIN -31750
+#define MAX6581_OFFSET_MAX 31750
#define MAX6697_CONV_TIME 156 /* ms per channel, worst case */
@@ -172,6 +174,11 @@ static const struct max6697_chip_data max6697_chip_data[] = {
},
};
+static inline int max6581_offset_to_millic(int val)
+{
+ return sign_extend32(val, 7) * 250;
+}
+
static struct max6697_data *max6697_update_device(struct device *dev)
{
struct max6697_data *data = dev_get_drvdata(dev);
@@ -317,6 +324,70 @@ static ssize_t temp_store(struct device *dev,
return ret < 0 ? ret : count;
}
+static ssize_t offset_store(struct device *dev, struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ int val, ret, index, select;
+ struct max6697_data *data;
+ bool channel_enabled;
+ long temp;
+
+ index = to_sensor_dev_attr(devattr)->index;
+ data = dev_get_drvdata(dev);
+ ret = kstrtol(buf, 10, &temp);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&data->update_lock);
+ select = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET_SELECT);
+ if (select < 0) {
+ ret = select;
+ goto abort;
+ }
+ channel_enabled = (select & (1 << (index - 1)));
+ temp = clamp_val(temp, MAX6581_OFFSET_MIN, MAX6581_OFFSET_MAX);
+ val = DIV_ROUND_CLOSEST(temp, 250);
+ /* disable the offset for channel if the new offset is 0 */
+ if (val == 0) {
+ if (channel_enabled)
+ ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET_SELECT,
+ select & ~(1 << (index - 1)));
+ ret = ret < 0 ? ret : count;
+ goto abort;
+ }
+ if (!channel_enabled) {
+ ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET_SELECT,
+ select | (1 << (index - 1)));
+ if (ret < 0)
+ goto abort;
+ }
+ ret = i2c_smbus_write_byte_data(data->client, MAX6581_REG_OFFSET, val);
+ ret = ret < 0 ? ret : count;
+
+abort:
+ mutex_unlock(&data->update_lock);
+ return ret;
+}
+
+static ssize_t offset_show(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+ struct max6697_data *data;
+ int select, ret, index;
+
+ index = to_sensor_dev_attr(devattr)->index;
+ data = dev_get_drvdata(dev);
+ mutex_lock(&data->update_lock);
+ select = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET_SELECT);
+ if (select < 0)
+ ret = select;
+ else if (select & (1 << (index - 1)))
+ ret = i2c_smbus_read_byte_data(data->client, MAX6581_REG_OFFSET);
+ else
+ ret = 0;
+ mutex_unlock(&data->update_lock);
+ return ret < 0 ? ret : sprintf(buf, "%d\n", max6581_offset_to_millic(ret));
+}
+
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0);
static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp, 0, MAX6697_TEMP_MAX);
static SENSOR_DEVICE_ATTR_2_RW(temp1_crit, temp, 0, MAX6697_TEMP_CRIT);
@@ -375,6 +446,15 @@ static SENSOR_DEVICE_ATTR_RO(temp6_fault, alarm, 5);
static SENSOR_DEVICE_ATTR_RO(temp7_fault, alarm, 6);
static SENSOR_DEVICE_ATTR_RO(temp8_fault, alarm, 7);
+/* There is no offset for local temperature so starting from temp2 */
+static SENSOR_DEVICE_ATTR_RW(temp2_offset, offset, 1);
+static SENSOR_DEVICE_ATTR_RW(temp3_offset, offset, 2);
+static SENSOR_DEVICE_ATTR_RW(temp4_offset, offset, 3);
+static SENSOR_DEVICE_ATTR_RW(temp5_offset, offset, 4);
+static SENSOR_DEVICE_ATTR_RW(temp6_offset, offset, 5);
+static SENSOR_DEVICE_ATTR_RW(temp7_offset, offset, 6);
+static SENSOR_DEVICE_ATTR_RW(temp8_offset, offset, 7);
+
static DEVICE_ATTR(dummy, 0, NULL, NULL);
static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
@@ -383,8 +463,8 @@ static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
struct device *dev = container_of(kobj, struct device, kobj);
struct max6697_data *data = dev_get_drvdata(dev);
const struct max6697_chip_data *chip = data->chip;
- int channel = index / 6; /* channel number */
- int nr = index % 6; /* attribute index within channel */
+ int channel = index / 7; /* channel number */
+ int nr = index % 7; /* attribute index within channel */
if (channel >= chip->channels)
return 0;
@@ -393,6 +473,10 @@ static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
return 0;
if (nr == 5 && !(chip->have_fault & (1 << channel)))
return 0;
+ /* offset reg is only supported on max6581 remote channels */
+ if (nr == 6)
+ if (data->type != max6581 || channel == 0)
+ return 0;
return attr->mode;
}
@@ -409,6 +493,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
&dev_attr_dummy.attr,
+ &dev_attr_dummy.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
@@ -416,6 +501,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
+ &sensor_dev_attr_temp2_offset.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
@@ -423,6 +509,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
+ &sensor_dev_attr_temp3_offset.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
@@ -430,6 +517,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp4_crit.dev_attr.attr,
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
+ &sensor_dev_attr_temp4_offset.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
@@ -437,6 +525,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp5_crit.dev_attr.attr,
&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
+ &sensor_dev_attr_temp5_offset.dev_attr.attr,
&sensor_dev_attr_temp6_input.dev_attr.attr,
&sensor_dev_attr_temp6_max.dev_attr.attr,
@@ -444,6 +533,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp6_crit.dev_attr.attr,
&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp6_fault.dev_attr.attr,
+ &sensor_dev_attr_temp6_offset.dev_attr.attr,
&sensor_dev_attr_temp7_input.dev_attr.attr,
&sensor_dev_attr_temp7_max.dev_attr.attr,
@@ -451,6 +541,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp7_crit.dev_attr.attr,
&sensor_dev_attr_temp7_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp7_fault.dev_attr.attr,
+ &sensor_dev_attr_temp7_offset.dev_attr.attr,
&sensor_dev_attr_temp8_input.dev_attr.attr,
&sensor_dev_attr_temp8_max.dev_attr.attr,
@@ -458,6 +549,7 @@ static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp8_crit.dev_attr.attr,
&sensor_dev_attr_temp8_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp8_fault.dev_attr.attr,
+ &sensor_dev_attr_temp8_offset.dev_attr.attr,
NULL
};
diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c
index c0229152296f..2d299149f4d2 100644
--- a/drivers/hwmon/nct6683.c
+++ b/drivers/hwmon/nct6683.c
@@ -674,7 +674,7 @@ show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
static umode_t nct6683_in_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct nct6683_data *data = dev_get_drvdata(dev);
int nr = index % 4; /* attribute */
@@ -739,7 +739,7 @@ show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
static umode_t nct6683_fan_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct nct6683_data *data = dev_get_drvdata(dev);
int fan = index / 3; /* fan index */
int nr = index % 3; /* attribute index */
@@ -857,7 +857,7 @@ show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
static umode_t nct6683_temp_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct nct6683_data *data = dev_get_drvdata(dev);
int temp = index / 7; /* temp index */
int nr = index % 7; /* attribute index */
@@ -944,7 +944,7 @@ SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, store_pwm, 0);
static umode_t nct6683_pwm_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct nct6683_data *data = dev_get_drvdata(dev);
int pwm = index; /* pwm index */
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index ea516cec1d35..e35db489b76f 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -156,10 +156,10 @@ config SENSORS_MAX16601
be called max16601.
config SENSORS_MAX20730
- tristate "Maxim MAX20730, MAX20734, MAX20743"
+ tristate "Maxim MAX20710, MAX20730, MAX20734, MAX20743"
help
If you say yes here you get hardware monitoring support for Maxim
- MAX20730, MAX20734, and MAX20743.
+ MAX20710, MAX20730, MAX20734, and MAX20743.
This driver can also be built as a module. If so, the module will
be called max20730.
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index 19317575d1c6..651846650a9c 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -683,11 +683,13 @@ static int adm1275_probe(struct i2c_client *client,
tindex = 3;
info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
- PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
- /* Enable VOUT if not enabled (it is disabled by default) */
- if (!(config & ADM1278_VOUT_EN)) {
- config |= ADM1278_VOUT_EN;
+ /* Enable VOUT & TEMP1 if not enabled (disabled by default) */
+ if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) !=
+ (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) {
+ config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN;
ret = i2c_smbus_write_byte_data(client,
ADM1275_PMON_CONFIG,
config);
@@ -698,9 +700,6 @@ static int adm1275_probe(struct i2c_client *client,
}
}
- if (config & ADM1278_TEMP1_EN)
- info->func[0] |=
- PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
if (config & ADM1278_VIN_EN)
info->func[0] |= PMBUS_HAVE_VIN;
break;
diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c
index c0bb05487e0e..a151a2b588a5 100644
--- a/drivers/hwmon/pmbus/max20730.c
+++ b/drivers/hwmon/pmbus/max20730.c
@@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Driver for MAX20730, MAX20734, and MAX20743 Integrated, Step-Down
- * Switching Regulators
+ * Driver for MAX20710, MAX20730, MAX20734, and MAX20743 Integrated,
+ * Step-Down Switching Regulators
*
* Copyright 2019 Google LLC.
+ * Copyright 2020 Maxim Integrated
*/
#include <linux/bits.h>
@@ -19,6 +20,7 @@
#include "pmbus.h"
enum chips {
+ max20710,
max20730,
max20734,
max20743
@@ -80,6 +82,7 @@ static long direct_to_val(u16 w, enum pmbus_sensor_classes class,
}
static u32 max_current[][5] = {
+ [max20710] = { 6200, 8000, 9700, 11600 },
[max20730] = { 13000, 16600, 20100, 23600 },
[max20734] = { 21000, 27000, 32000, 38000 },
[max20743] = { 18900, 24100, 29200, 34100 },
@@ -164,6 +167,35 @@ static int max20730_write_word_data(struct i2c_client *client, int page,
}
static const struct pmbus_driver_info max20730_info[] = {
+ [max20710] = {
+ .pages = 1,
+ .read_word_data = max20730_read_word_data,
+ .write_word_data = max20730_write_word_data,
+
+ /* Source : Maxim AN6140 and AN6042 */
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_TEMPERATURE] = 21,
+ .b[PSC_TEMPERATURE] = 5887,
+ .R[PSC_TEMPERATURE] = -1,
+
+ .format[PSC_VOLTAGE_IN] = direct,
+ .m[PSC_VOLTAGE_IN] = 3609,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = -2,
+
+ .format[PSC_CURRENT_OUT] = direct,
+ .m[PSC_CURRENT_OUT] = 153,
+ .b[PSC_CURRENT_OUT] = 4976,
+ .R[PSC_CURRENT_OUT] = -1,
+
+ .format[PSC_VOLTAGE_OUT] = linear,
+
+ .func[0] = PMBUS_HAVE_VIN |
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_INPUT,
+ },
[max20730] = {
.pages = 1,
.read_word_data = max20730_read_word_data,
@@ -200,7 +232,8 @@ static const struct pmbus_driver_info max20730_info[] = {
.func[0] = PMBUS_HAVE_VIN |
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
- PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_INPUT,
},
[max20734] = {
.pages = 1,
@@ -228,7 +261,8 @@ static const struct pmbus_driver_info max20730_info[] = {
.func[0] = PMBUS_HAVE_VIN |
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
- PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_INPUT,
},
[max20743] = {
.pages = 1,
@@ -256,7 +290,8 @@ static const struct pmbus_driver_info max20730_info[] = {
.func[0] = PMBUS_HAVE_VIN |
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
- PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
+ PMBUS_HAVE_STATUS_INPUT,
},
};
@@ -339,6 +374,7 @@ static int max20730_probe(struct i2c_client *client,
}
static const struct i2c_device_id max20730_id[] = {
+ { "max20710", max20710 },
{ "max20730", max20730 },
{ "max20734", max20734 },
{ "max20743", max20743 },
@@ -348,6 +384,7 @@ static const struct i2c_device_id max20730_id[] = {
MODULE_DEVICE_TABLE(i2c, max20730_id);
static const struct of_device_id max20730_of_match[] = {
+ { .compatible = "maxim,max20710", .data = (void *)max20710 },
{ .compatible = "maxim,max20730", .data = (void *)max20730 },
{ .compatible = "maxim,max20734", .data = (void *)max20734 },
{ .compatible = "maxim,max20743", .data = (void *)max20743 },
@@ -369,5 +406,5 @@ static struct i2c_driver max20730_driver = {
module_i2c_driver(max20730_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("PMBus driver for Maxim MAX20730 / MAX20734 / MAX20743");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX20710 / MAX20730 / MAX20734 / MAX20743");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 2191575a448b..44535add3a4a 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -628,12 +628,12 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
* Convert linear sensor values to milli- or micro-units
* depending on sensor type.
*/
-static long pmbus_reg2data_linear(struct pmbus_data *data,
- struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_linear(struct pmbus_data *data,
+ struct pmbus_sensor *sensor)
{
s16 exponent;
s32 mantissa;
- long val;
+ s64 val;
if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */
exponent = data->exponent[sensor->page];
@@ -647,11 +647,11 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
/* scale result to milli-units for all sensors except fans */
if (sensor->class != PSC_FAN)
- val = val * 1000L;
+ val = val * 1000LL;
/* scale result to micro-units for power sensors */
if (sensor->class == PSC_POWER)
- val = val * 1000L;
+ val = val * 1000LL;
if (exponent >= 0)
val <<= exponent;
@@ -665,8 +665,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data,
* Convert direct sensor values to milli- or micro-units
* depending on sensor type.
*/
-static long pmbus_reg2data_direct(struct pmbus_data *data,
- struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_direct(struct pmbus_data *data,
+ struct pmbus_sensor *sensor)
{
s64 b, val = (s16)sensor->data;
s32 m, R;
@@ -702,15 +702,15 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
}
val = div_s64(val - b, m);
- return clamp_val(val, LONG_MIN, LONG_MAX);
+ return val;
}
/*
* Convert VID sensor values to milli- or micro-units
* depending on sensor type.
*/
-static long pmbus_reg2data_vid(struct pmbus_data *data,
- struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data_vid(struct pmbus_data *data,
+ struct pmbus_sensor *sensor)
{
long val = sensor->data;
long rv = 0;
@@ -740,9 +740,9 @@ static long pmbus_reg2data_vid(struct pmbus_data *data,
return rv;
}
-static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
+static s64 pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
{
- long val;
+ s64 val;
if (!sensor->convert)
return sensor->data;
@@ -766,7 +766,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
#define MIN_MANTISSA (511 * 1000)
static u16 pmbus_data2reg_linear(struct pmbus_data *data,
- struct pmbus_sensor *sensor, long val)
+ struct pmbus_sensor *sensor, s64 val)
{
s16 exponent = 0, mantissa;
bool negative = false;
@@ -788,8 +788,8 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
val <<= -data->exponent[sensor->page];
else
val >>= data->exponent[sensor->page];
- val = DIV_ROUND_CLOSEST(val, 1000);
- return val & 0xffff;
+ val = DIV_ROUND_CLOSEST_ULL(val, 1000);
+ return clamp_val(val, 0, 0xffff);
}
if (val < 0) {
@@ -799,14 +799,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
/* Power is in uW. Convert to mW before converting. */
if (sensor->class == PSC_POWER)
- val = DIV_ROUND_CLOSEST(val, 1000L);
+ val = DIV_ROUND_CLOSEST_ULL(val, 1000);
/*
* For simplicity, convert fan data to milli-units
* before calculating the exponent.
*/
if (sensor->class == PSC_FAN)
- val = val * 1000;
+ val = val * 1000LL;
/* Reduce large mantissa until it fits into 10 bit */
while (val >= MAX_MANTISSA && exponent < 15) {
@@ -820,11 +820,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
}
/* Convert mantissa from milli-units to units */
- mantissa = DIV_ROUND_CLOSEST(val, 1000);
-
- /* Ensure that resulting number is within range */
- if (mantissa > 0x3ff)
- mantissa = 0x3ff;
+ mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
/* restore sign */
if (negative)
@@ -835,9 +831,9 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
}
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
- struct pmbus_sensor *sensor, long val)
+ struct pmbus_sensor *sensor, s64 val)
{
- s64 b, val64 = val;
+ s64 b;
s32 m, R;
m = data->info->m[sensor->class];
@@ -855,30 +851,30 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
R -= 3; /* Adjust R and b for data in milli-units */
b *= 1000;
}
- val64 = val64 * m + b;
+ val = val * m + b;
while (R > 0) {
- val64 *= 10;
+ val *= 10;
R--;
}
while (R < 0) {
- val64 = div_s64(val64 + 5LL, 10L); /* round closest */
+ val = div_s64(val + 5LL, 10L); /* round closest */
R++;
}
- return (u16)clamp_val(val64, S16_MIN, S16_MAX);
+ return (u16)clamp_val(val, S16_MIN, S16_MAX);
}
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
- struct pmbus_sensor *sensor, long val)
+ struct pmbus_sensor *sensor, s64 val)
{
val = clamp_val(val, 500, 1600);
- return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625);
+ return 2 + DIV_ROUND_CLOSEST_ULL((1600LL - val) * 100LL, 625);
}
static u16 pmbus_data2reg(struct pmbus_data *data,
- struct pmbus_sensor *sensor, long val)
+ struct pmbus_sensor *sensor, s64 val)
{
u16 regval;
@@ -944,7 +940,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
return 0;
} else {
- long v1, v2;
+ s64 v1, v2;
if (s1->data < 0)
return s1->data;
@@ -981,7 +977,7 @@ static ssize_t pmbus_show_sensor(struct device *dev,
if (sensor->data < 0)
return sensor->data;
- return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
+ return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
}
static ssize_t pmbus_set_sensor(struct device *dev,
@@ -992,11 +988,11 @@ static ssize_t pmbus_set_sensor(struct device *dev,
struct pmbus_data *data = i2c_get_clientdata(client);
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
ssize_t rv = count;
- long val = 0;
+ s64 val;
int ret;
u16 regval;
- if (kstrtol(buf, 10, &val) < 0)
+ if (kstrtos64(buf, 10, &val) < 0)
return -EINVAL;
mutex_lock(&data->update_lock);
diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c
index 65997421ee3c..a5d1a890d0be 100644
--- a/drivers/hwmon/powr1220.c
+++ b/drivers/hwmon/powr1220.c
@@ -4,7 +4,7 @@
* and monitor. Users can read all ADC inputs along with their labels
* using the sysfs nodes.
*
- * Copyright (c) 2014 Echo360 http://www.echo360.com
+ * Copyright (c) 2014 Echo360 https://www.echo360.com
* Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com>
*/
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index bc70c8332d9a..8ea5534455f2 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2010 Urs Fleisch <urs.fleisch@sensirion.com>
*
- * Data sheet available at http://www.sensirion.com/file/datasheet_sht21
+ * Data sheet available at https://www.sensirion.com/file/datasheet_sht21
*/
#include <linux/module.h>
diff --git a/drivers/hwmon/sparx5-temp.c b/drivers/hwmon/sparx5-temp.c
new file mode 100644
index 000000000000..1a2b1026b026
--- /dev/null
+++ b/drivers/hwmon/sparx5-temp.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Sparx5 SoC temperature sensor driver
+ *
+ * Copyright (C) 2020 Lars Povlsen <lars.povlsen@microchip.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/hwmon.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define TEMP_CTRL 0
+#define TEMP_CFG 4
+#define TEMP_CFG_CYCLES GENMASK(24, 15)
+#define TEMP_CFG_ENA BIT(0)
+#define TEMP_STAT 8
+#define TEMP_STAT_VALID BIT(12)
+#define TEMP_STAT_TEMP GENMASK(11, 0)
+
+struct s5_hwmon {
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static void s5_temp_clk_disable(void *data)
+{
+ struct clk *clk = data;
+
+ clk_disable_unprepare(clk);
+}
+
+static void s5_temp_enable(struct s5_hwmon *hwmon)
+{
+ u32 val = readl(hwmon->base + TEMP_CFG);
+ u32 clk = clk_get_rate(hwmon->clk) / USEC_PER_SEC;
+
+ val &= ~TEMP_CFG_CYCLES;
+ val |= FIELD_PREP(TEMP_CFG_CYCLES, clk);
+ val |= TEMP_CFG_ENA;
+
+ writel(val, hwmon->base + TEMP_CFG);
+}
+
+static int s5_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *temp)
+{
+ struct s5_hwmon *hwmon = dev_get_drvdata(dev);
+ int rc = 0, value;
+ u32 stat;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ stat = readl_relaxed(hwmon->base + TEMP_STAT);
+ if (!(stat & TEMP_STAT_VALID))
+ return -EIO;
+ value = stat & TEMP_STAT_TEMP;
+ /*
+ * From register documentation:
+ * Temp(C) = TEMP_SENSOR_STAT.TEMP / 4096 * 352.2 - 109.4
+ */
+ value = DIV_ROUND_CLOSEST(value * 3522, 4096) - 1094;
+ /*
+ * Scale down by 10 from above and multiply by 1000 to
+ * have millidegrees as specified by the hwmon sysfs
+ * interface.
+ */
+ value *= 100;
+ *temp = value;
+ break;
+ default:
+ rc = -EOPNOTSUPP;
+ break;
+ }
+
+ return rc;
+}
+
+static umode_t s5_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;
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_channel_info *s5_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops s5_hwmon_ops = {
+ .is_visible = s5_is_visible,
+ .read = s5_read,
+};
+
+static const struct hwmon_chip_info s5_chip_info = {
+ .ops = &s5_hwmon_ops,
+ .info = s5_info,
+};
+
+static int s5_temp_probe(struct platform_device *pdev)
+{
+ struct device *hwmon_dev;
+ struct s5_hwmon *hwmon;
+ int ret;
+
+ hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ hwmon->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(hwmon->base))
+ return PTR_ERR(hwmon->base);
+
+ hwmon->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(hwmon->clk))
+ return PTR_ERR(hwmon->clk);
+
+ ret = clk_prepare_enable(hwmon->clk);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&pdev->dev, s5_temp_clk_disable,
+ hwmon->clk);
+ if (ret)
+ return ret;
+
+ s5_temp_enable(hwmon);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
+ "s5_temp",
+ hwmon,
+ &s5_chip_info,
+ NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct of_device_id s5_temp_match[] = {
+ { .compatible = "microchip,sparx5-temp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s5_temp_match);
+
+static struct platform_driver s5_temp_driver = {
+ .probe = s5_temp_probe,
+ .driver = {
+ .name = "sparx5-temp",
+ .of_match_table = s5_temp_match,
+ },
+};
+
+module_platform_driver(s5_temp_driver);
+
+MODULE_AUTHOR("Lars Povlsen <lars.povlsen@microchip.com>");
+MODULE_DESCRIPTION("Sparx5 SoC temperature sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c
index df66e0bc1253..23908dc5611b 100644
--- a/drivers/hwmon/tmp513.c
+++ b/drivers/hwmon/tmp513.c
@@ -5,12 +5,12 @@
* TMP513:
* Thermal/Power Management with Triple Remote and
* Local Temperature Sensor and Current Shunt Monitor
- * Datasheet: http://www.ti.com/lit/gpn/tmp513
+ * Datasheet: https://www.ti.com/lit/gpn/tmp513
*
* TMP512:
* Thermal/Power Management with Dual Remote
* and Local Temperature Sensor and Current Shunt Monitor
- * Datasheet: http://www.ti.com/lit/gpn/tmp512
+ * Datasheet: https://www.ti.com/lit/gpn/tmp512
*
* Copyright (C) 2019 Eric Tremblay <etremblay@distech-controls.com>
*
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 2335d440f72d..6603727e15a0 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -992,8 +992,8 @@ static int vt8231_pci_probe(struct pci_dev *dev,
return -ENODEV;
}
- if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
- &val))
+ pci_read_config_word(dev, VT8231_BASE_REG, &val);
+ if (val == (u16)~0)
return -ENODEV;
address = val & ~(VT8231_EXTENT - 1);
@@ -1002,8 +1002,8 @@ static int vt8231_pci_probe(struct pci_dev *dev,
return -ENODEV;
}
- if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_ENABLE_REG,
- &val))
+ pci_read_config_word(dev, VT8231_ENABLE_REG, &val);
+ if (val == (u16)~0)
return -ENODEV;
if (!(val & 0x0001)) {