summaryrefslogtreecommitdiffstats
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/